32#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
33void joedb::Readonly_Journal::perform_update_##type_id(Writable &writable)\
35 const cpp_type value = read_method();\
36 writable.update_##type_id\
38 table_of_last_operation,\
39 record_of_last_operation,\
40 field_of_last_update,\
62 checkpoint_position(
Header::size),
63 hard_checkpoint_position(
Header::size)
81 throw Exception(
"missing joedb signature");
84 throw Exception(
"unsupported file format version");
89 throw Exception(
"Checkpoint is bigger than file size");
99void joedb::Readonly_Journal::read_checkpoint
102 const std::array<int64_t, 4> &pos,
106 for (
int i = 0; i < 2; i++)
108 if (pos[2 * i] == pos[2 * i + 1] && pos[2 * i] >= hard_checkpoint_position)
110 hard_checkpoint_position = pos[2 * i];
114 for (
int j = 0; j < 2; j++)
118 -pos[2 * i + j] >= checkpoint_position &&
119 (file_size < 0 || -pos[2 * i + j] <= file_size)
122 checkpoint_position = -pos[2 * i + j];
129 if (hard_checkpoint_position > checkpoint_position)
130 checkpoint_position = hard_checkpoint_position;
134void joedb::Readonly_Journal::pull_without_locking()
137 std::array<int64_t, 4> pos;
138 file.pread((
char *)&pos,
sizeof(pos), 0);
139 read_checkpoint(pos, -1);
146 const int64_t old_checkpoint = checkpoint_position;
149 pull_without_locking();
151 return checkpoint_position - old_checkpoint;
159 play_until_checkpoint(writable);
170 writable.start_writing(get_position());
171 while(get_position() < checkpoint_position)
174 writable.comment(std::to_string(get_position()));
176 writable.end_writing(get_position());
192 while (get_position() < end)
200 if (get_position() < end)
202 const int64_t writable_position = writable.
get_position();
203 if (get_position() < writable_position)
206 raw_play_until(dummy_writable, writable_position);
209 raw_play_until(writable, end);
223 case operation_t::create_table:
225 const std::string name = safe_read_string();
230 case operation_t::drop_table:
237 case operation_t::rename_table:
240 const std::string name = safe_read_string();
245 case operation_t::add_field:
248 const std::string name = safe_read_string();
249 const Type type = read_type();
250 writable.
add_field(table_id, name, type);
254 case operation_t::drop_field:
262 case operation_t::rename_field:
266 const std::string name = safe_read_string();
271 case operation_t::insert_into:
274 const Record_Id record_id = file_buffer.read_reference();
276 table_of_last_operation = table_id;
277 record_of_last_operation = record_id;
281 case operation_t::delete_from:
284 const Record_Id record_id = file_buffer.read_reference();
289 case operation_t::insert_vector:
292 const Record_Id record_id = file_buffer.read_reference();
293 const size_t size = file_buffer.compact_read<
size_t>();
295 table_of_last_operation = table_id;
296 record_of_last_operation = record_id;
300 case operation_t::delete_vector:
303 const Record_Id record_id = file_buffer.read_reference();
304 const size_t size = file_buffer.compact_read<
size_t>();
309 case operation_t::append:
310 writable.
insert_into(table_of_last_operation, ++record_of_last_operation);
313 #define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
314 case operation_t::update_##type_id:\
315 table_of_last_operation = file_buffer.read_strong_type<Table_Id>();\
316 record_of_last_operation = file_buffer.read_reference();\
317 field_of_last_update = file_buffer.read_strong_type<Field_Id>();\
318 perform_update_##type_id(writable);\
321 case operation_t::update_last_##type_id:\
322 field_of_last_update = file_buffer.read_strong_type<Field_Id>();\
323 perform_update_##type_id(writable);\
326 case operation_t::update_next_##type_id:\
327 ++record_of_last_operation;\
328 perform_update_##type_id(writable);\
332 #define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
333 case operation_t::update_vector_##type_id:\
335 table_of_last_operation = file_buffer.read_strong_type<Table_Id>();\
336 record_of_last_operation = file_buffer.read_reference();\
337 field_of_last_update = file_buffer.read_strong_type<Field_Id>();\
338 const size_t size = file_buffer.compact_read<size_t>();\
341 if (int64_t(size) > checkpoint_position)\
342 throw Exception("update_vector too big");\
344 cpp_type *data = writable.get_own_##type_id##_storage\
346 table_of_last_operation,\
347 record_of_last_operation,\
348 field_of_last_update,\
351 std::vector<cpp_type> buffer;\
354 buffer.resize(size);\
357 else if (to_underlying(record_of_last_operation) < 0 || to_underlying(record_of_last_operation) + size > capacity)\
358 throw Exception("update_vector out of range");\
359 read_vector_of_##type_id(data, size);\
360 writable.update_vector_##type_id\
362 table_of_last_operation,\
363 record_of_last_operation,\
364 field_of_last_update,\
372 case operation_t::custom:
374 const std::string name = safe_read_string();
379 case operation_t::comment:
381 const std::string comment = safe_read_string();
386 case operation_t::timestamp:
388 const int64_t timestamp = file_buffer.read<int64_t>();
393 case operation_t::valid_data:
397 case operation_t::blob:
399 const int64_t size = file_buffer.compact_read<int64_t>();
404 std::string s(
size_t(size), 0);
406 file_buffer.read_data(s.data(), s.size());
410 file_buffer.ignore(size);
416 throw Exception(
"Unexpected operation: get_position() = " + std::to_string(get_position()));
426 if (type_id == Type::Type_Id::reference)
429 return Type(type_id);
436 return file_buffer.safe_read_string(checkpoint_position);
439#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
440void joedb::Readonly_Journal::read_vector_of_##type_id(cpp_type *data, size_t size)\
442 for (size_t i = 0; i < size; i++)\
443 data[i] = read_method();\
445#define TYPE_MACRO_NO_INT
446#define TYPE_MACRO_NO_FLOAT
449#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
450void joedb::Readonly_Journal::read_vector_of_##type_id(cpp_type *data, size_t size)\
452 file_buffer.read_data((char *)data, size * sizeof(cpp_type));\
454#define TYPE_MACRO_NO_STRING
455#define TYPE_MACRO_NO_REFERENCE
456#define TYPE_MACRO_NO_BLOB
static void reading_past_end_of_file()
void unlock_head() noexcept
virtual size_t pread(char *data, size_t size, int64_t offset) const
Read a range of bytes.
Writable with empty insert_vector and delete_vector.
void set_position(int64_t position)
Head_Shared_Lock(const Head_Shared_Lock &)=delete
Head_Shared_Lock(Abstract_File &file)
Head_Shared_Lock & operator=(const Head_Shared_Lock &)=delete
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 replay_log(Writable &writable)
void raw_play_until(Writable &writable, int64_t end)
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)
Superclass with all joedb journal event listeners as virtual functions.
virtual void insert_vector(Table_Id table_id, Record_Id record_id, size_t size)=0
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 delete_vector(Table_Id table_id, Record_Id record_id, size_t size)=0
virtual void soft_checkpoint()
virtual bool wants_blob_data() const
virtual void custom(const std::string &name)
virtual void start_writing(int64_t position)
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 end_writing(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)
@ ignore_header
use file size as checkpoint