Joedb 9.1.4
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Buffered_File.h
Go to the documentation of this file.
1#ifndef joedb_Buffered_File_declared
2#define joedb_Buffered_File_declared
3
6#include "joedb/Blob.h"
10#include "joedb/index_types.h"
11
12#include <string>
13
14namespace joedb
15{
16 /// @ingroup journal
18 {
19 friend class File_Hasher;
20
21 private:
22 Buffer<12> buffer;
23
24 size_t read_buffer_size;
25
26 //////////////////////////////////////////////////////////////////////////
27 static void reading_past_end_of_file()
28 //////////////////////////////////////////////////////////////////////////
29 {
30 throw Exception("Trying to read past the end of file");
31 }
32
33 //////////////////////////////////////////////////////////////////////////
34 bool buffer_has_write_data() const noexcept
35 //////////////////////////////////////////////////////////////////////////
36 {
37 return buffer.index > 0 && !read_buffer_size;
38 }
39
40 //////////////////////////////////////////////////////////////////////////
41 bool buffer_has_read_data() const
42 //////////////////////////////////////////////////////////////////////////
43 {
44 return read_buffer_size;
45 }
46
47 //////////////////////////////////////////////////////////////////////////
48 void read_buffer()
49 //////////////////////////////////////////////////////////////////////////
50 {
51 JOEDB_ASSERT(!buffer_has_write_data());
52 JOEDB_ASSERT(buffer.index <= read_buffer_size);
53
54 buffer.index = 0;
55 read_buffer_size = sequential_read(buffer.data, buffer.size);
56 if (read_buffer_size == 0)
57 reading_past_end_of_file();
58 }
59
60 //////////////////////////////////////////////////////////////////////////
61 void write_buffer()
62 //////////////////////////////////////////////////////////////////////////
63 {
64 JOEDB_ASSERT(!buffer_has_read_data());
65
66 sequential_write(buffer.data, buffer.index);
67 buffer.index = 0;
68 }
69
70 //////////////////////////////////////////////////////////////////////////
71 void check_write_buffer()
72 //////////////////////////////////////////////////////////////////////////
73 {
74 JOEDB_ASSERT(!buffer_has_read_data());
75
76 if (buffer.index >= buffer.size)
77 write_buffer();
78 }
79
80 Open_Mode mode;
81 bool locked_tail;
82
83 protected:
87
88 public:
90 void flush();
91
92 //////////////////////////////////////////////////////////////////////////
94 //////////////////////////////////////////////////////////////////////////
95 {
96 flush();
97 sync();
98 }
99
100 static constexpr int64_t last_position = (1ULL << 63) - 1;
101
103 {
105 locked_tail = true;
106 }
107
109 {
111 locked_tail = false;
112 }
113
114 bool tail_is_locked() const noexcept {return locked_tail;}
118
121
122 // set_position must be called when switching between write and read
123 void set_position(int64_t position);
124
126 {
127 return Sequential_File::get_position() - read_buffer_size + buffer.index;
128 }
129
130 //////////////////////////////////////////////////////////////////////////
131 virtual void copy_to
132 //////////////////////////////////////////////////////////////////////////
133 (
135 int64_t start,
136 int64_t size
137 );
138
139 //////////////////////////////////////////////////////////////////////////
141 //////////////////////////////////////////////////////////////////////////
142 {
144 }
145
146 //////////////////////////////////////////////////////////////////////////
147 template<typename T> void write(T x)
148 //////////////////////////////////////////////////////////////////////////
149 {
150 static_assert(sizeof(T) <= decltype(buffer)::extra_size);
151 buffer.write<T>(x);
152 check_write_buffer();
153 }
154
155 //////////////////////////////////////////////////////////////////////////
156 template<typename T> T read()
157 //////////////////////////////////////////////////////////////////////////
158 {
159 T result;
160 read_data(reinterpret_cast<char *>(&result), sizeof(result));
161 return result;
162 }
163
164 //////////////////////////////////////////////////////////////////////////
165 template<typename T> void compact_write(T x)
166 //////////////////////////////////////////////////////////////////////////
167 {
168 buffer.compact_write<T>(x);
169 check_write_buffer();
170 }
171
172 //////////////////////////////////////////////////////////////////////////
173 template<typename T> T compact_read()
174 //////////////////////////////////////////////////////////////////////////
175 {
176 if (buffer.index + 8 <= read_buffer_size)
177 return buffer.compact_read<T>();
178
180 int extra_bytes = first_byte >> 5;
181 T result = first_byte & 0x1f;
182 while (--extra_bytes >= 0)
183 result = T((result << 8) | read<uint8_t>());
184 return result;
185 }
186
187 template<typename T> T read_strong_type()
188 {
189 return T(compact_read<typename std::underlying_type<T>::type>());
190 }
191
193 {
195 }
196
198 {
199 return Record_Id(compact_read<std::underlying_type<Record_Id>::type>());
200 }
201
202 void write_string(const std::string &s);
203 std::string read_string();
206 std::string safe_read_string(int64_t max_size);
207
208 //////////////////////////////////////////////////////////////////////////
209 void write_data(const char *data, size_t n)
210 //////////////////////////////////////////////////////////////////////////
211 {
212 JOEDB_ASSERT(!buffer_has_read_data());
213
214 if (n <= buffer.extra_size)
215 {
216 std::copy_n(data, n, buffer.data + buffer.index);
217 buffer.index += n;
218 check_write_buffer();
219 }
220 else
221 {
222 const size_t remaining = buffer.size + buffer.extra_size - buffer.index;
223
224 if (n < remaining)
225 {
226 std::copy_n(data, n, buffer.data + buffer.index);
227 buffer.index += n;
228 check_write_buffer();
229 }
230 else
231 {
232 flush();
233 sequential_write(data, n);
234 }
235 }
236 }
237
238 //////////////////////////////////////////////////////////////////////////
239 size_t read_data(char *data, const size_t n)
240 //////////////////////////////////////////////////////////////////////////
241 {
242 JOEDB_ASSERT(!buffer_has_write_data());
243 JOEDB_ASSERT(buffer.index <= read_buffer_size);
244
245 if (buffer.index + n <= read_buffer_size)
246 {
247 std::copy_n(buffer.data + buffer.index, n, data);
248 buffer.index += n;
249 return n;
250 }
251 else
252 {
253 size_t n0 = read_buffer_size - buffer.index;
254 std::copy_n(buffer.data + buffer.index, n0, data);
255 buffer.index += n0;
256
257 if (n <= buffer.size)
258 {
259 read_buffer();
260
261 while (n0 < n && buffer.index < read_buffer_size)
262 data[n0++] = buffer.data[buffer.index++];
263 }
264
265 while (n0 < n)
266 {
267 const size_t actually_read = sequential_read(data + n0, n - n0);
268 if (actually_read == 0)
269 {
270 reading_past_end_of_file();
271 break;
272 }
273 n0 += actually_read;
274 }
275
276 return n0;
277 }
278 }
279
280 //////////////////////////////////////////////////////////////////////////
281 void ignore(const int64_t n)
282 //////////////////////////////////////////////////////////////////////////
283 {
284 if (buffer.index + n <= read_buffer_size)
285 buffer.index += n;
286 else
288 }
289
290 virtual std::string read_blob_data(Blob blob) const;
291 };
292}
293
294#endif
virtual void shared_lock(int64_t start, int64_t size)
virtual int64_t get_size() const
virtual void unlock(int64_t start, int64_t size) noexcept
virtual void sync()
virtual void exclusive_lock(int64_t start, int64_t size)
int64_t get_position() const noexcept
Definition Blob.h:28
T compact_read()
Definition Buffer.h:70
size_t index
Definition Buffer.h:21
void write(T x)
Definition Buffer.h:24
static constexpr size_t extra_size
Definition Buffer.h:18
char data[size+extra_size]
Definition Buffer.h:20
static constexpr size_t size
Definition Buffer.h:16
void compact_write(T x)
Definition Buffer.h:44
void ignore(const int64_t n)
void write_reference(Record_Id id)
void write_blob(Blob blob)
void set_position(int64_t position)
bool is_shared() const noexcept
void unlock_head() noexcept
bool tail_is_locked() const noexcept
static constexpr int64_t last_position
size_t read_data(char *data, const size_t n)
void write_string(const std::string &s)
virtual std::string read_blob_data(Blob blob) const
bool is_readonly() const noexcept
void unlock_tail() noexcept
std::string read_string()
void destructor_flush() noexcept
void write_data(const char *data, size_t n)
virtual void copy_to(Buffered_File &destination, int64_t start, int64_t size)
Record_Id read_reference()
std::string safe_read_string(int64_t max_size)
void copy_to(Buffered_File &destination)
int64_t get_position() const noexcept
size_t sequential_read(char *data, size_t size)
void sequential_write(const char *data, size_t size)
int64_t get_position() const
#define JOEDB_ASSERT(x)
Definition assert.h:18
Open_Mode
Definition Open_Mode.h:8
@ write_existing
fails if does not exist or locked, locks the file for writing
@ shared_write
like write_existing_or_create_new, but does not lock the file, and does not fail if locked
@ read_existing
fails if does not exist
Definition Blob.h:7
constexpr std::underlying_type< Table_Id >::type to_underlying(Table_Id id)
Definition index_types.h:15