Joedb 10.5.0
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Server_Connection.cpp
Go to the documentation of this file.
5
6namespace joedb
7{
8 ////////////////////////////////////////////////////////////////////////////
9 size_t Server_Connection::pread(char *data, size_t size, int64_t offset) const
10 ////////////////////////////////////////////////////////////////////////////
11 {
12 buffer.index = 0;
13 buffer.write<char>('r');
14 buffer.write<int64_t>(offset);
15 buffer.write<int64_t>(offset + int64_t(size));
16
18 lock->write(buffer.data, buffer.index);
19 lock->read(buffer.data, 9);
20
21 buffer.index = 1;
22 const int64_t until = buffer.read<int64_t>();
23
24 if (until < offset || until > offset + int64_t(size))
25 throw Disconnection("bad pread size from server");
26
27 const size_t returned_size = size_t(until - offset);
28
29 lock->read(data, returned_size);
30
31 return returned_size;
32 }
33
34 ////////////////////////////////////////////////////////////////////////////
36 ////////////////////////////////////////////////////////////////////////////
37 (
38 const Readonly_Journal &client_journal,
39 Content_Check content_check
40 )
41 {
43 (
44 client_journal,
45 content_check,
47 std::min(server_checkpoint, client_journal.get_checkpoint())
48 );
49
50 return server_checkpoint;
51 }
52
53 ////////////////////////////////////////////////////////////////////////////
55 ////////////////////////////////////////////////////////////////////////////
56 (
57 const Readonly_Journal &client_journal,
58 Content_Check content_check,
59 int64_t from,
60 int64_t until
61 )
62 {
63 log("checking hash, from = " + std::to_string(from) + ", until = " + std::to_string(until));
64
65 if (content_check == Content_Check::none || from >= until)
66 return;
67
68 buffer.index = 0;
69 buffer.write<char>(content_check == Content_Check::fast ? 'H' : 'I');
70 buffer.write<int64_t>(from);
71 buffer.write<int64_t>(until);
72
73 buffer.write
74 (
75 content_check == Content_Check::fast
76 ? get_fast_hash(client_journal.get_file(), from, until)
77 : get_full_hash(client_journal.get_file(), from, until)
78 );
79
80 {
82 lock->write(buffer.data, buffer.index);
83 lock->read(buffer.data, 1);
84 }
85
86 log(std::string("hash result: ") + buffer.data[0]);
87
88 if (buffer.data[0] == 'h')
90 }
91
92 ////////////////////////////////////////////////////////////////////////////
94 ////////////////////////////////////////////////////////////////////////////
95 (
96 Lock_Action lock_action,
97 Data_Transfer data_transfer,
98 Writable_Journal &client_journal,
99 std::chrono::milliseconds wait
100 )
101 {
103
104 const char pull_type = char('D' + int(lock_action) + 2*int(data_transfer));
105
106 log("pulling, lock = " + std::to_string(int(lock_action)) +
107 ", data = " + std::to_string(int(data_transfer)) +
108 ", wait = " + std::to_string(double(wait.count()) * 0.001) + 's');
109
110 buffer.index = 0;
111 buffer.write<char>(pull_type);
112 buffer.write<int64_t>(wait.count());
113 buffer.write<int64_t>(client_journal.get_checkpoint());
114 lock->write(buffer.data, buffer.index);
115
116 buffer.index = 0;
117 lock->read(buffer.data, 9);
118 {
119 const char reply = buffer.read<char>();
120 if (reply == 'R')
121 throw Disconnection("pull error: server is pull-only, cannot lock");
122 else if (reply != pull_type)
123 throw Disconnection("pull error: unexpected server reply");
124 }
125 server_checkpoint = buffer.read<int64_t>();
126
127 if (bool(data_transfer))
128 {
129 buffer.index = 0;
130 const int64_t size = server_checkpoint - client_journal.get_checkpoint();
131 Async_Writer writer = client_journal.get_async_tail_writer();
132 download(writer, lock, size);
133 client_journal.soft_checkpoint_at(writer.get_position());
134 }
135 else
136 log("!data_transfer");
137
138 return server_checkpoint;
139 }
140
141 ////////////////////////////////////////////////////////////////////////////
143 ////////////////////////////////////////////////////////////////////////////
144 (
145 const Readonly_Journal &client_journal,
146 int64_t from,
147 int64_t until,
148 Unlock_Action unlock_action
149 )
150 {
152
153 const char push_type = char('N' + int(unlock_action));
154 buffer.index = 0;
155 buffer.write<char>(push_type);
156 buffer.write<int64_t>(from);
157 buffer.write<int64_t>(until);
158
159 {
160 Async_Reader reader = client_journal.get_async_reader(from, until);
161
162 log
163 (
164 std::string("pushing(") + push_type +
165 ")... from = " + std::to_string(from) +
166 ", until = " + std::to_string(until)
167 );
168
169 Progress_Bar progress_bar(reader.get_remaining(), *this);
170
171 size_t offset = buffer.index;
172
173 while (offset + reader.get_remaining() > 0)
174 {
175 const size_t size = reader.read(buffer.data + offset, buffer.size - offset);
176 if (reader.is_end_of_file())
177 throw Disconnection("push error: unexpected end of file");
178 lock->write(buffer.data, size + offset);
179 offset = 0;
180 progress_bar.print_remaining(reader.get_remaining());
181 }
182 }
183
184 lock->read(buffer.data, 1);
185
186 if (buffer.data[0] == 'R')
187 throw Disconnection("push error: server is pull-only");
188 else if (buffer.data[0] == 'C')
189 throw Disconnection("push error: conflict");
190 else if (buffer.data[0] == 't')
191 throw Exception("push error: time out");
192 else if (buffer.data[0] != push_type)
193 throw Disconnection("push error: unexpected reply");
194
195 server_checkpoint = until;
196
197 return server_checkpoint;
198 }
199
200 ////////////////////////////////////////////////////////////////////////////
202 ////////////////////////////////////////////////////////////////////////////
203 {
204 log("joedb::Server_Connection::unlock");
205
206 {
208 buffer.data[0] = 'M';
209 lock->write(buffer.data, 1);
210 lock->read(buffer.data, 1);
211 }
212
213 log(std::string() + buffer.data[0]);
214
215 if (buffer.data[0] != 'M')
216 throw Disconnection("unlock error: unexpected reply");
217 }
218}
int64_t get_remaining() const
size_t read(char *buffer, size_t capacity)
bool is_end_of_file() const
int64_t get_position() const
static void content_mismatch()
Called by handshake when the file and the connection do not match.
Definition Connection.cpp:9
joedb::Robust_Connection does not try to reconnect when thrown
bool print_remaining(int64_t remaining)
void log(beman::cstring_view message) noexcept override
Thread_Safe< Channel & > channel
void download(Async_Writer &writer, Lock< Channel & > &lock, int64_t size) const
int64_t pull(Lock_Action lock_action, Data_Transfer data_transfer, Writable_Journal &client_journal, std::chrono::milliseconds wait=std::chrono::milliseconds(0)) override
Pull from the connection.
void unlock() override
Unlock the connection.
int64_t handshake(const Readonly_Journal &client_journal, Content_Check content_check) override
Called during Client construction.
size_t pread(char *data, size_t size, int64_t offset) const
int64_t push(const Readonly_Journal &client_journal, int64_t from, int64_t until, Unlock_Action unlock_action) override
Push new data to the connection.
void check_matching_content(const Readonly_Journal &client_journal, Content_Check content_check, int64_t from, int64_t until) override
Compare content of file and connection. Throw if mismatch.
Data_Transfer
Definition Connection.h:28
Lock_Action
Definition Connection.h:35
Content_Check
Definition Connection.h:20
Unlock_Action
Definition Connection.h:42
SHA_256::Hash get_full_hash(const Abstract_File &file, int64_t from, int64_t until)
Definition get_hash.cpp:11
SHA_256::Hash get_fast_hash(const Abstract_File &file, int64_t from, int64_t until)
Definition get_hash.cpp:69
static constexpr int64_t ssize
Definition Header.h:18