8#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
9void joedb::Readonly_Journal::perform_update_##type_id(Writable &writable)\
11 const cpp_type value = read_method();\
12 writable.update_##type_id\
14 table_of_last_operation,\
15 record_of_last_operation,\
16 field_of_last_update,\
37 checkpoint_position(
Header::size)
48 throw Exception(
"missing joedb signature");
51 throw Exception(
"unsupported file format version");
59 throw Exception(
"Checkpoint is bigger than file size");
68void joedb::Readonly_Journal::read_checkpoint
71 const std::array<int64_t, 4> &pos
74 int64_t hard_checkpoint = 0;
75 int64_t soft_checkpoint = 0;
77 for (
int i = 0; i < 2; i++)
79 if (pos[2 * i] == pos[2 * i + 1] && pos[2 * i] >= hard_checkpoint)
81 hard_checkpoint = pos[2 * i];
85 for (
int j = 0; j < 2; j++)
87 if (-pos[2 * i + j] >= soft_checkpoint)
89 soft_checkpoint = -pos[2 * i + j];
96 if (hard_checkpoint > checkpoint_position)
97 checkpoint_position = hard_checkpoint;
99 if (soft_checkpoint > checkpoint_position)
100 checkpoint_position = soft_checkpoint;
104void joedb::Readonly_Journal::pull_without_locking()
107 std::array<int64_t, 4> pos;
108 file.pread((
char *)&pos,
sizeof(pos), 0);
109 read_checkpoint(pos);
116 const int64_t old_checkpoint = checkpoint_position;
119 pull_without_locking();
121 return checkpoint_position - old_checkpoint;
129 play_until_checkpoint(writable);
140 writable.start_writing(get_position());
141 while(get_position() < checkpoint_position)
144 writable.comment(std::to_string(get_position()));
146 writable.soft_checkpoint_at(get_position());
162 while(get_position() < end)
170 if (get_position() < end)
172 const int64_t writable_position = writable.
get_position();
173 if (get_position() < writable_position)
176 play_until(dummy_writable, writable_position);
179 while(get_position() < end)
184 file.flush_for_writing();
193 case operation_t::create_table:
195 const std::string name = safe_read_string();
200 case operation_t::drop_table:
207 case operation_t::rename_table:
210 const std::string name = safe_read_string();
215 case operation_t::add_field:
218 const std::string name = safe_read_string();
219 const Type type = read_type();
220 writable.
add_field(table_id, name, type);
224 case operation_t::drop_field:
232 case operation_t::rename_field:
236 const std::string name = safe_read_string();
241 case operation_t::insert_into:
246 table_of_last_operation = table_id;
247 record_of_last_operation = record_id;
251 case operation_t::delete_from:
259 case operation_t::insert_vector:
263 const size_t size = file.compact_read<
size_t>();
265 table_of_last_operation = table_id;
266 record_of_last_operation = record_id;
270 case operation_t::delete_vector:
274 const size_t size = file.compact_read<
size_t>();
279 case operation_t::append:
280 writable.
insert_into(table_of_last_operation, ++record_of_last_operation);
283 #define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
284 case operation_t::update_##type_id:\
285 table_of_last_operation = file.read_strong_type<Table_Id>();\
286 record_of_last_operation = file.read_strong_type<Record_Id>();\
287 field_of_last_update = file.read_strong_type<Field_Id>();\
288 perform_update_##type_id(writable);\
291 case operation_t::update_last_##type_id:\
292 field_of_last_update = file.read_strong_type<Field_Id>();\
293 perform_update_##type_id(writable);\
296 case operation_t::update_next_##type_id:\
297 ++record_of_last_operation;\
298 perform_update_##type_id(writable);\
302 #define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
303 case operation_t::update_vector_##type_id:\
305 table_of_last_operation = file.read_strong_type<Table_Id>();\
306 record_of_last_operation = file.read_strong_type<Record_Id>();\
307 field_of_last_update = file.read_strong_type<Field_Id>();\
308 const size_t size = file.compact_read<size_t>();\
309 if (int64_t(size) > checkpoint_position)\
310 throw Exception("update_vector too big");\
312 cpp_type *data = writable.get_own_##type_id##_storage\
314 table_of_last_operation,\
315 record_of_last_operation,\
316 field_of_last_update,\
319 std::vector<cpp_type> buffer;\
322 buffer.resize(size);\
325 else if (to_underlying(record_of_last_operation) <= 0 || to_underlying(record_of_last_operation) + size - 1 > capacity)\
326 throw Exception("update_vector out of range");\
327 read_vector_of_##type_id(data, size);\
328 writable.update_vector_##type_id\
330 table_of_last_operation,\
331 record_of_last_operation,\
332 field_of_last_update,\
340 case operation_t::custom:
342 const std::string name = safe_read_string();
347 case operation_t::comment:
349 const std::string comment = safe_read_string();
354 case operation_t::timestamp:
356 const int64_t timestamp = file.read<int64_t>();
361 case operation_t::valid_data:
365 case operation_t::blob:
367 const int64_t size = file.compact_read<int64_t>();
372 std::string s(
size_t(size), 0);
374 file.read_data(s.data(), s.size());
384 throw Exception(
"Unexpected operation: get_position() = " + std::to_string(get_position()));
394 if (type_id == Type::Type_Id::reference)
397 return Type(type_id);
404 return file.safe_read_string(checkpoint_position);
407#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
408void joedb::Readonly_Journal::read_vector_of_##type_id(cpp_type *data, size_t size)\
410 for (size_t i = 0; i < size; i++)\
411 data[i] = read_method();\
413#define TYPE_MACRO_NO_INT
414#define TYPE_MACRO_NO_FLOAT
417#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
418void joedb::Readonly_Journal::read_vector_of_##type_id(cpp_type *data, size_t size)\
420 file.read_data((char *)data, size * sizeof(cpp_type));\
422#define TYPE_MACRO_NO_STRING
423#define TYPE_MACRO_NO_REFERENCE
424#define TYPE_MACRO_NO_BLOB
virtual size_t pread(char *data, size_t size, int64_t offset) const
Read a range of bytes.
void set_position(int64_t position)
static void reading_past_end_of_file()
bool is_for_writable_journal() const
void play_until(Writable &writable, int64_t end)
void one_step(Writable &writable)
static constexpr uint32_t format_version
std::string safe_read_string()
Record_Id record_of_last_operation
void replay_with_checkpoint_comments(Writable &writable)
void append_until(Writable &writable, int64_t end)
void replay_log(Writable &writable)
Field_Id field_of_last_update
int64_t checkpoint_position
Readonly_Journal(Journal_Construction_Lock &lock)
Table_Id table_of_last_operation
static Type reference(Table_Id table_id)
virtual Blob write_blob(const std::string &data)
virtual void insert_into(Table_Id table_id, Record_Id record_id)
virtual void drop_table(Table_Id table_id)
virtual void create_table(const std::string &name)
virtual void drop_field(Table_Id table_id, Field_Id field_id)
virtual void rename_table(Table_Id table_id, const std::string &name)
virtual void insert_vector(Table_Id table_id, Record_Id record_id, size_t size)
virtual bool wants_blob_data() const
virtual void custom(const std::string &name)
virtual void start_writing(int64_t position)
virtual void delete_vector(Table_Id table_id, Record_Id record_id, size_t size)
virtual void add_field(Table_Id table_id, const std::string &name, Type type)
virtual void delete_from(Table_Id table_id, Record_Id record_id)
virtual void soft_checkpoint_at(int64_t position)
virtual int64_t get_position() const
virtual void comment(const std::string &comment)
virtual void on_blob(Blob blob)
virtual void valid_data()
virtual void rename_field(Table_Id table_id, Field_Id field_id, const std::string &name)
virtual void timestamp(int64_t timestamp)