36 throw Exception(
"Cannot create Writable_Journal with read-only file");
37 else if (lock.
size == 0)
55 ") is smaller than file size (" + std::to_string(lock.
size) +
56 "). This file may contain an aborted transaction. "
57 "'joedb_push file.joedb file fixed.joedb' can be used to truncate it."
70 if (checkpoint_position < until)
72 const int64_t size = until - checkpoint_position;
73 journal.get_file().copy_to(file, checkpoint_position, size);
74 soft_checkpoint_at(until);
77 return checkpoint_position;
92 throw Exception(
"writing must start at checkpoint position");
100 throw Exception(
"end_writing position is not matching file position");
123 reinterpret_cast<const char *
>(&neg),
197 const std::string &name
200 file_buffer.write<
operation_t>(operation_t::rename_table);
202 file_buffer.write_string(name);
210 const std::string &name,
214 file_buffer.write<
operation_t>(operation_t::add_field);
216 file_buffer.write_string(name);
218 if (type.get_type_id() == Type::Type_Id::reference)
219 file_buffer.compact_write<>(
to_underlying(type.get_table_id()));
230 file_buffer.write<
operation_t>(operation_t::drop_field);
241 const std::string &name
244 file_buffer.write<
operation_t>(operation_t::rename_field);
247 file_buffer.write_string(name);
289 if (table_id == table_of_last_operation &&
290 record_id == record_of_last_operation + 1)
292 file_buffer.write<
operation_t>(operation_t::append);
296 file_buffer.write<
operation_t>(operation_t::insert_into);
298 file_buffer.write_reference(record_id);
301 table_of_last_operation = table_id;
302 record_of_last_operation = record_id;
313 file_buffer.write<
operation_t>(operation_t::delete_from);
315 file_buffer.write_reference(record_id);
327 file_buffer.write<
operation_t>(operation_t::insert_vector);
329 file_buffer.write_reference(record_id);
330 file_buffer.compact_write<>(size);
332 table_of_last_operation = table_id;
333 record_of_last_operation = record_id;
345 file_buffer.write<
operation_t>(operation_t::delete_vector);
347 file_buffer.write_reference(record_id);
348 file_buffer.compact_write<>(size);
352 void Writable_Journal::generic_update
358 operation_t operation
363 table_id == table_of_last_operation &&
364 record_id == record_of_last_operation
368 int(operation_t::update_last_int8) -
369 int(operation_t::update_int8);
371 file_buffer.write<operation_t>(operation_t(
int(operation) + last));
373 field_of_last_update = field_id;
377 table_id == table_of_last_operation &&
378 record_id == record_of_last_operation + 1 &&
379 field_id == field_of_last_update
383 int(operation_t::update_next_int8) -
384 int(operation_t::update_int8);
385 file_buffer.write<operation_t>(operation_t(
int(operation) + next));
386 ++record_of_last_operation;
390 file_buffer.write<operation_t>(operation);
392 file_buffer.write_reference(record_id);
394 table_of_last_operation = table_id;
395 record_of_last_operation = record_id;
396 field_of_last_update = field_id;
401 #define TYPE_MACRO(type, return_type, type_id, R, write_method)\
402 void Writable_Journal::update_##type_id\
405 Record_Id record_id,\
410 generic_update(table_id, record_id, field_id, operation_t::update_##type_id);\
411 file_buffer.write_method(value);\
413 void Writable_Journal::update_vector_##type_id\
416 Record_Id record_id,\
422 file_buffer.write<operation_t>(operation_t::update_vector_##type_id);\
423 file_buffer.compact_write<>(to_underlying(table_id));\
424 file_buffer.write_reference(record_id);\
425 file_buffer.compact_write<>(to_underlying(field_id));\
426 file_buffer.compact_write<>(size);\
427 table_of_last_operation = table_id;\
428 record_of_last_operation = record_id;\
429 field_of_last_update = field_id;\
433 Type::Type_Id::type_id == Type::Type_Id::blob ||\
434 Type::Type_Id::type_id == Type::Type_Id::string ||\
435 Type::Type_Id::type_id == Type::Type_Id::reference\
438 for (size_t i = 0; i < size; i++)\
439 file_buffer.write_method(value[i]);\
442 file_buffer.write_data((const char *)value, size * sizeof(type));\
450 const std::string &data
454 file_buffer.compact_write<
size_t>(data.size());
455 const int64_t blob_position = get_position();
457 file_buffer.File_Iterator::write(data.data(), data.size());
458 return Blob(blob_position, int64_t(data.size()));
468 pull_without_locking();
488 offsetof(
Header, signature)
506 throw Exception(
"locking journal with uncheckpointed data (try rollback?)");
virtual int64_t get_size() const
Get the size of the file, or -1 if it is unknown.
virtual void datasync()
Write data durably (no file-size change)
virtual void unlock(int64_t start, int64_t size) noexcept
Remove a lock. The range should match the range of a corresponding lock.
bool is_readonly() const noexcept
virtual void sync()
Write data durably (including file-size change)
bool is_shared() const noexcept
void exclusive_lock_tail()
void unlock_tail() noexcept
virtual void pwrite(const char *data, size_t size, int64_t offset)
Write a range of bytes. Extend file size if necessary.
virtual void exclusive_lock(int64_t start, int64_t size)
Lock a range of bytes for writing (prevents both writes and reads)
static void warning(const std::string &message) noexcept
int64_t get_position() const noexcept
void write_string(const std::string &s)
Head_Exclusive_Lock(Abstract_File &file)
Head_Exclusive_Lock(const Head_Exclusive_Lock &)=delete
Head_Exclusive_Lock & operator=(const Head_Exclusive_Lock &)=delete
static constexpr uint32_t format_version
friend class Writable_Journal
int64_t hard_checkpoint_position
int64_t checkpoint_position
int64_t get_checkpoint() const
Tail_Exclusive_Lock(Writable_Journal &journal)
int64_t pull_from(const Readonly_Journal &journal, int64_t until)
void valid_data() override
void soft_checkpoint() override
int64_t ahead_of_checkpoint() const noexcept
void soft_checkpoint_at(int64_t position)
void start_writing(int64_t position) override
int64_t get_position() const override
void end_writing(int64_t position) override
~Writable_Journal() override
void hard_checkpoint() override
Blob write_blob(const std::string &data) override
void hard_checkpoint_at(int64_t position)
#define JOEDB_DEBUG_ASSERT(x)
assertion tested in debug mode
@ overwrite
allow overwriting an uncheckpointed tail
constexpr index_t to_underlying(Record_Id id)