12 throw Exception(
"Cannot create Writable_Journal with read-only file");
13 else if (lock.
size == 0)
26 ") is smaller than file size (" + std::to_string(lock.
size) +
27 "). This file may contain an aborted transaction. "
28 "'joedb_push file.joedb file fixed.joedb' can be used to truncate it."
41 if (checkpoint_position < until)
43 const int64_t size = until - checkpoint_position;
44 journal.get_file().copy_to(file, checkpoint_position, size);
45 soft_checkpoint_at(until);
48 return checkpoint_position;
55 return file.get_position() - checkpoint_position;
62 if (position != checkpoint_position)
63 throw Exception(
"writing must start at checkpoint position");
70 if (checkpoint_position >= position)
76 checkpoint_position = position;
80 const int64_t neg = -checkpoint_position;
84 reinterpret_cast<const char *
>(&neg),
86 int64_t(
sizeof(neg)) * (2 * (hard_index ^ 1) + soft_index)
97 checkpoint_position = position;
103 reinterpret_cast<const char *
>(&checkpoint_position),
104 sizeof(checkpoint_position),
105 int64_t(
sizeof(checkpoint_position)) * (2 * hard_index)
112 reinterpret_cast<const char *
>(&checkpoint_position),
113 sizeof(checkpoint_position),
114 int64_t(
sizeof(checkpoint_position)) * (2 * hard_index + 1)
124 file.write<
operation_t>(operation_t::create_table);
125 file.write_string(name);
141 const std::string &name
144 file.write<
operation_t>(operation_t::rename_table);
146 file.write_string(name);
154 const std::string &name,
160 file.write_string(name);
162 if (type.get_type_id() == Type::Type_Id::reference)
185 const std::string &name
188 file.write<
operation_t>(operation_t::rename_field);
191 file.write_string(name);
199 file.write_string(name);
207 file.write_string(comment);
215 file.write<int64_t>(timestamp);
233 if (table_id == table_of_last_operation &&
234 record_id == record_of_last_operation + 1)
245 table_of_last_operation = table_id;
246 record_of_last_operation = record_id;
271 file.write<
operation_t>(operation_t::insert_vector);
274 file.compact_write<>(size);
276 table_of_last_operation = table_id;
277 record_of_last_operation = record_id;
289 file.write<
operation_t>(operation_t::delete_vector);
292 file.compact_write<>(size);
296void joedb::Writable_Journal::generic_update
302 operation_t operation
307 table_id == table_of_last_operation &&
308 record_id == record_of_last_operation
312 int(operation_t::update_last_int8) -
313 int(operation_t::update_int8);
315 file.write<operation_t>(operation_t(
int(operation) + last));
317 field_of_last_update = field_id;
321 table_id == table_of_last_operation &&
322 record_id == record_of_last_operation + 1 &&
323 field_id == field_of_last_update
327 int(operation_t::update_next_int8) -
328 int(operation_t::update_int8);
329 file.write<operation_t>(operation_t(
int(operation) + next));
330 ++record_of_last_operation;
334 file.write<operation_t>(operation);
338 table_of_last_operation = table_id;
339 record_of_last_operation = record_id;
340 field_of_last_update = field_id;
345#define TYPE_MACRO(type, return_type, type_id, R, write_method)\
346void joedb::Writable_Journal::update_##type_id\
349 Record_Id record_id,\
354 generic_update(table_id, record_id, field_id, operation_t::update_##type_id);\
355 file.write_method(value);\
357void joedb::Writable_Journal::update_vector_##type_id\
360 Record_Id record_id,\
366 file.write<operation_t>(operation_t::update_vector_##type_id);\
367 file.compact_write<>(to_underlying(table_id));\
368 file.compact_write<>(to_underlying(record_id));\
369 file.compact_write<>(to_underlying(field_id));\
370 file.compact_write<>(size);\
371 table_of_last_operation = table_id;\
372 record_of_last_operation = record_id;\
373 field_of_last_update = field_id;\
377 Type::Type_Id::type_id == Type::Type_Id::blob ||\
378 Type::Type_Id::type_id == Type::Type_Id::string ||\
379 Type::Type_Id::type_id == Type::Type_Id::reference\
382 for (size_t i = 0; i < size; i++)\
383 file.write_method(value[i]);\
386 file.write_data((const char *)value, size * sizeof(type));\
394 const std::string &data
398 file.compact_write<
size_t>(data.size());
399 const int64_t blob_position = get_position();
401 file.sequential_write(data.data(), data.size());
402 return Blob(blob_position, int64_t(data.size()));
409 if (file.is_shared())
411 file.exclusive_lock_tail();
412 pull_without_locking();
420 if (file.is_shared())
428 if (ahead_of_checkpoint() > 0)
bool is_readonly() const noexcept
static void write(const char *message) noexcept
static constexpr uint32_t format_version
friend class Writable_Journal
int64_t checkpoint_position
void sequential_write(const char *data, size_t size)
int64_t pull_from(const Readonly_Journal &journal, int64_t until)
void hard_checkpoint_at(int64_t position) override
void soft_checkpoint_at(int64_t position) override
int64_t ahead_of_checkpoint() const noexcept
Blob write_blob(const std::string &data) final
void start_writing(int64_t position) override
~Writable_Journal() override
constexpr std::underlying_type< Table_Id >::type to_underlying(Table_Id id)