diff --git a/CMakeLists.txt b/CMakeLists.txt index c1cac0f..34d906e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,9 @@ include_directories(inc) add_library(YeltsinDB STATIC src/ydb.c inc/YeltsinDB/ydb.h - inc/YeltsinDB/error_code.h src/table_page.c - inc/YeltsinDB/table_page.h + inc/YeltsinDB/error_code.h + src/table_page.c inc/YeltsinDB/table_page.h inc/YeltsinDB/constants.h - inc/YeltsinDB/types.h inc/YeltsinDB/macro.h) \ No newline at end of file + inc/YeltsinDB/types.h + inc/YeltsinDB/macro.h + ) \ No newline at end of file diff --git a/cmake/FindCheck.cmake b/cmake/FindCheck.cmake new file mode 100644 index 0000000..8e12e94 --- /dev/null +++ b/cmake/FindCheck.cmake @@ -0,0 +1,56 @@ +# - Try to find the CHECK libraries +# Once done this will define +# +# CHECK_FOUND - system has check +# CHECK_INCLUDE_DIR - the check include directory +# CHECK_LIBRARIES - check library +# +# This configuration file for finding libcheck is originally from +# the opensync project. The originally was downloaded from here: +# opensync.org/browser/branches/3rd-party-cmake-modules/modules/FindCheck.cmake +# +# Copyright (c) 2007 Daniel Gollub +# Copyright (c) 2007 Bjoern Ricks +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +INCLUDE( FindPkgConfig ) + +# Take care about check.pc settings +PKG_SEARCH_MODULE( CHECK check ) + +# Look for CHECK include dir and libraries +IF( NOT CHECK_FOUND ) + IF ( CHECK_INSTALL_DIR ) + MESSAGE ( STATUS "Using override CHECK_INSTALL_DIR to find check" ) + SET ( CHECK_INCLUDE_DIR "${CHECK_INSTALL_DIR}/include" ) + SET ( CHECK_INCLUDE_DIRS "${CHECK_INCLUDE_DIR}" ) + FIND_LIBRARY( CHECK_LIBRARY NAMES check PATHS "${CHECK_INSTALL_DIR}/lib" ) + FIND_LIBRARY( COMPAT_LIBRARY NAMES compat PATHS "${CHECK_INSTALL_DIR}/lib" ) + SET ( CHECK_LIBRARIES "${CHECK_LIBRARY}" "${COMPAT_LIBRARY}" ) + ELSE ( CHECK_INSTALL_DIR ) + FIND_PATH( CHECK_INCLUDE_DIR check.h ) + FIND_LIBRARY( CHECK_LIBRARIES NAMES check ) + ENDIF ( CHECK_INSTALL_DIR ) + + IF ( CHECK_INCLUDE_DIR AND CHECK_LIBRARIES ) + SET( CHECK_FOUND 1 ) + IF ( NOT Check_FIND_QUIETLY ) + MESSAGE ( STATUS "Found CHECK: ${CHECK_LIBRARIES}" ) + ENDIF ( NOT Check_FIND_QUIETLY ) + ELSE ( CHECK_INCLUDE_DIR AND CHECK_LIBRARIES ) + IF ( Check_FIND_REQUIRED ) + MESSAGE( FATAL_ERROR "Could NOT find CHECK" ) + ELSE ( Check_FIND_REQUIRED ) + IF ( NOT Check_FIND_QUIETLY ) + MESSAGE( STATUS "Could NOT find CHECK" ) + ENDIF ( NOT Check_FIND_QUIETLY ) + ENDIF ( Check_FIND_REQUIRED ) + ENDIF ( CHECK_INCLUDE_DIR AND CHECK_LIBRARIES ) +ENDIF( NOT CHECK_FOUND ) + +# Hide advanced variables from CMake GUIs +MARK_AS_ADVANCED( CHECK_INCLUDE_DIR CHECK_LIBRARIES ) \ No newline at end of file diff --git a/inc/YeltsinDB/constants.h b/inc/YeltsinDB/constants.h index 78c3d72..5344e63 100644 --- a/inc/YeltsinDB/constants.h +++ b/inc/YeltsinDB/constants.h @@ -21,31 +21,6 @@ // TODO static_assert for sizes -// v0 -enum YDB_v0_sizes { - YDB_v0_first_page_size = 8, - YDB_v0_last_page_size = 8, - YDB_v0_last_free_page_size = 8, - YDB_v0_page_flags_size = 1, - YDB_v0_page_next_size = 8, - YDB_v0_page_row_count_size = 2, -}; - -enum YDB_v0_offsets { - YDB_v0_first_page_offset = YDB_TABLE_FILE_DATA_START_OFFSET, - YDB_v0_last_page_offset = YDB_v0_first_page_offset + YDB_v0_first_page_size, - YDB_v0_last_free_page_offset = YDB_v0_last_page_offset + YDB_v0_last_page_size, - YDB_v0_data_offset = YDB_v0_last_free_page_offset + YDB_v0_last_free_page_size, -}; - -enum YDB_v0_page_offsets { - YDB_v0_page_flags_offset = 0, - YDB_v0_page_next_offset = YDB_v0_page_flags_offset + YDB_v0_page_flags_size, - YDB_v0_page_row_count_offset = YDB_v0_page_next_offset + YDB_v0_page_next_size, - YDB_v0_page_data_offset = YDB_v0_page_row_count_offset + YDB_v0_page_row_count_size, -}; - -// v1 enum YDB_v1_sizes { YDB_v1_first_page_size = 8, YDB_v1_last_page_size = 8, @@ -56,6 +31,13 @@ enum YDB_v1_sizes { YDB_v1_page_row_count_size = 2, }; +enum YDB_v1_offsets { + YDB_v1_first_page_offset = YDB_TABLE_FILE_DATA_START_OFFSET, + YDB_v1_last_page_offset = YDB_v1_first_page_offset + YDB_v1_first_page_size, + YDB_v1_last_free_page_offset = YDB_v1_last_page_offset + YDB_v1_last_page_size, + YDB_v1_data_offset = YDB_v1_last_free_page_offset + YDB_v1_last_free_page_size, +}; + enum YDB_v1_page_offsets { YDB_v1_page_flags_offset = 0, YDB_v1_page_next_offset = YDB_v1_page_flags_offset + YDB_v1_page_flags_size, diff --git a/inc/YeltsinDB/ydb.h b/inc/YeltsinDB/ydb.h index 13652c1..1096290 100644 --- a/inc/YeltsinDB/ydb.h +++ b/inc/YeltsinDB/ydb.h @@ -68,26 +68,13 @@ YDB_Error ydb_create_table(YDB_Engine* instance, const char *path); YDB_Error ydb_unload_table(YDB_Engine* instance); /** - * @brief Seek to `index`th page. + * @brief Switch to previous page. * @param instance A YeltsinDB instance. - * @param index Page index. * @return Operation status. * - * If an error was returned, the state of instance remains the same as it was before execution. * @todo Possible error codes. */ -YDB_Error ydb_seek_page(YDB_Engine* instance, int64_t index); - -/** - * @brief Get current page index. - * @param instance A YeltsinDB instance. - * @return Current page index. - * @sa error_code.h - * - * Could return error codes (negative values). - * @todo Possible error codes. - */ -int64_t ydb_tell_page(YDB_Engine* instance); +YDB_Error ydb_prev_page(YDB_Engine* instance); /** * @brief Switch to next page. @@ -134,6 +121,15 @@ YDB_TablePage* ydb_get_current_page(YDB_Engine* instance); */ YDB_Error ydb_delete_current_page(YDB_Engine* instance); +/** + * @brief Seek to the last page. + * @param instance A YeltsinDB instance + * @return Operation status. + * + * @warning Could break an instance if ydb_ + */ +YDB_Error ydb_seek_to_end(YDB_Engine* instance); + // TODO: rebuild page offsets, etc. /** @@ -151,7 +147,7 @@ YDB_Error ydb_delete_current_page(YDB_Engine* instance); * * - types.h * - * And in some cases even [table file structure](table_file_v0.md) + * And in some cases even [table file structure](table_file_v1.md) */ #ifdef __cplusplus diff --git a/src/ydb.c b/src/ydb.c index b493baa..d384df4 100644 --- a/src/ydb.c +++ b/src/ydb.c @@ -24,8 +24,6 @@ struct __YDB_Engine { YDB_Offset curr_page_offset; /**< A location of current page in file. */ YDB_Offset next_page_offset; /**< A location of next page in file. */ - int64_t current_page_index; /**< Current page index in range [0, page_count). */ - YDB_TablePage *curr_page; /**< A pointer to the current page. */ uint8_t in_use; /**< "In use" flag. */ @@ -46,8 +44,7 @@ void ydb_terminate_instance(YDB_Engine *instance) { } // Internal usage only! -// Its only purpose to read current page data and set next_page offset. -// You should write prev_page offset on your own. +// Its only purpose to read current page data and set next_page and prev_page offsets. static YDB_Error __ydb_read_page(YDB_Engine *inst) { THROW_IF_NULL(inst, YDB_ERR_INSTANCE_NOT_INITIALIZED); @@ -62,16 +59,19 @@ static YDB_Error __ydb_read_page(YDB_Engine *inst) { return YDB_ERR_TABLE_DATA_CORRUPTED; } - // Read page flags, next page offset and row count + // Read page flags, next and prev page offset and row count YDB_Flags page_flags = p_data[0]; YDB_Offset next; + YDB_Offset prev; YDB_PageSize row_count; - memcpy(&next, p_data + YDB_v0_page_next_offset, sizeof(next)); + memcpy(&next, p_data + YDB_v1_page_next_offset, sizeof(next)); REASSIGN_FROM_LE(next); - memcpy(&row_count, p_data + YDB_v0_page_row_count_offset, sizeof(row_count)); + memcpy(&prev, p_data + YDB_v1_page_prev_offset, sizeof(prev)); + REASSIGN_FROM_LE(prev); + memcpy(&row_count, p_data + YDB_v1_page_row_count_offset, sizeof(row_count)); REASSIGN_FROM_LE(row_count); - const YDB_PageSize meta_size = YDB_v0_page_data_offset; + const YDB_PageSize meta_size = YDB_v1_page_data_offset; const YDB_PageSize data_size = YDB_TABLE_PAGE_SIZE - meta_size; YDB_TablePage *p = ydb_page_alloc(data_size); @@ -83,6 +83,7 @@ static YDB_Error __ydb_read_page(YDB_Engine *inst) { if (write_status) return write_status; inst->curr_page = p; + inst->prev_page_offset = prev; inst->next_page_offset = next; return YDB_ERR_SUCCESS; @@ -101,17 +102,21 @@ static YDB_Offset __ydb_allocate_page_and_seek(YDB_Engine *inst) { // Allocate an empty chunk char* new_page_data = calloc(1, YDB_TABLE_PAGE_SIZE); + // Write last page offset as prev page offset in this page + YDB_Offset last_page_offset_le = TO_LE(inst->last_page_offset); + memcpy(new_page_data + YDB_v1_page_prev_offset, &last_page_offset_le, sizeof(YDB_Offset)); + // Write it to file fwrite(new_page_data, YDB_TABLE_PAGE_SIZE, 1, inst->fd); free(new_page_data); // TODO throw error on fail - // Write next page offset in the previous page - fseek(inst->fd, inst->last_page_offset + YDB_v0_page_next_offset, SEEK_SET); // Skip page flag + // Write next page offset in the previous (last) page + fseek(inst->fd, inst->last_page_offset + YDB_v1_page_next_offset, SEEK_SET); fwrite(&allocated_page_offset_le, sizeof(YDB_Offset), 1, inst->fd); // Write last page offset inst->last_page_offset = result; - fseek(inst->fd, YDB_v0_last_page_offset, SEEK_SET); + fseek(inst->fd, YDB_v1_last_page_offset, SEEK_SET); fwrite(&allocated_page_offset_le, sizeof(YDB_Offset), 1, inst->fd); fflush(inst->fd); } else { @@ -119,19 +124,22 @@ static YDB_Offset __ydb_allocate_page_and_seek(YDB_Engine *inst) { result = inst->last_free_page_offset; // Read last free page offset after allocation - fseek(inst->fd, result + YDB_v0_page_next_offset, SEEK_SET); // Skip flag + fseek(inst->fd, result + YDB_v1_page_next_offset, SEEK_SET); // Skip flag fread(&inst->last_free_page_offset, sizeof(YDB_Offset), 1, inst->fd); REASSIGN_FROM_LE(inst->last_free_page_offset); - fseek(inst->fd, -(long)(sizeof(YDB_Offset) + 1), SEEK_CUR); //FIXME magic - // Rewrite page header - char page_header[] = "\x00" // No flags - "\x00\x00\x00\x00\x00\x00\x00\x00" // No next page - "\x00\x00"; // No rows - fwrite(page_header, sizeof(page_header)-1, 1, inst->fd); + // Go back to our almost allocated page + fseek(inst->fd, result, SEEK_SET); + + // Rewrite page header with last page offset as previous page + char* page_header = calloc(1, YDB_v1_data_offset); + YDB_Offset last_page_offset_le = TO_LE(inst->last_page_offset); + memcpy(page_header + YDB_v1_page_prev_offset, &last_page_offset_le, sizeof(YDB_Offset)); + fwrite(page_header, YDB_v1_data_offset, 1, inst->fd); + free(page_header); // Write last free page offset after allocation in file - fseek(inst->fd, YDB_v0_last_free_page_offset, SEEK_SET); + fseek(inst->fd, YDB_v1_last_free_page_offset, SEEK_SET); YDB_Offset lfp_offset_le = TO_LE(inst->last_free_page_offset); fwrite(&lfp_offset_le, sizeof(YDB_Offset), 1, inst->fd); } @@ -152,9 +160,9 @@ YDB_Error ydb_load_table(YDB_Engine *instance, const char *path) { instance->fd = fopen(path, "rb+"); THROW_IF_NULL(instance->fd, YDB_ERR_UNKNOWN); // TODO file open error - // FIXME magic - char signature[4]; - fread(signature, 1, 4, instance->fd); + // Check file signature + char signature[YDB_TABLE_FILE_SIGN_SIZE]; + fread(signature, 1, YDB_TABLE_FILE_SIGN_SIZE, instance->fd); int signature_match = memcmp(signature, YDB_TABLE_FILE_SIGN, 3) == 0; if (!signature_match) { return YDB_ERR_TABLE_DATA_CORRUPTED; @@ -163,18 +171,18 @@ YDB_Error ydb_load_table(YDB_Engine *instance, const char *path) { fread(&(instance->ver_major), sizeof(instance->ver_major), 1, instance->fd); fread(&(instance->ver_minor), sizeof(instance->ver_minor), 1, instance->fd); - if (instance->ver_major != 0) { // TODO proper version check + if (instance->ver_major != 1) { // TODO proper version check! return YDB_ERR_TABLE_DATA_VERSION_MISMATCH; } + // Check consistency of a page switch (signature[3]) { case '!': break; case '?': - if (instance->ver_minor < 2) { - return YDB_ERR_TABLE_DATA_CORRUPTED; - } // TODO mark table as possibly corrupted and start rollback from journal + // FIXME + return YDB_ERR_TABLE_DATA_CORRUPTED; break; default: return YDB_ERR_TABLE_DATA_CORRUPTED; @@ -210,7 +218,6 @@ YDB_Error ydb_unload_table(YDB_Engine *instance) { i->prev_page_offset = 0; i->curr_page_offset = 0; i->next_page_offset = 0; - i->current_page_index = 0; ydb_page_free(i->curr_page); i->curr_page = NULL; free(i->filename); @@ -226,7 +233,7 @@ YDB_Error ydb_create_table(YDB_Engine *instance, const char *path) { THROW_IF_NULL(instance, YDB_ERR_INSTANCE_NOT_INITIALIZED); THROW_IF_NULL(!instance->in_use, YDB_ERR_INSTANCE_IN_USE); - if (access(instance->filename, F_OK) != -1) { + if (access(path, F_OK) != -1) { // TODO: Windows does not check W_OK correctly, use other methods. // TODO: if can't read/write, throw other error return YDB_ERR_TABLE_EXIST; @@ -234,11 +241,11 @@ YDB_Error ydb_create_table(YDB_Engine *instance, const char *path) { FILE *f = fopen(path, "wb"); - char tpl[] = YDB_TABLE_FILE_SIGN - "\x00\x02" - "\x1E\x00\x00\x00\x00\x00\x00\x00" - "\x1E\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00"; + char tpl[] = YDB_TABLE_FILE_SIGN // File signature + "\x01\x00" // File version FIXME magic + "\x1E\x00\x00\x00\x00\x00\x00\x00" // First page offset + "\x1E\x00\x00\x00\x00\x00\x00\x00" // Last page offset + "\x00\x00\x00\x00\x00\x00\x00\x00"; // Last free page offset fwrite(tpl, sizeof(tpl)-1, 1, f); char *first_page = calloc(1, YDB_TABLE_PAGE_SIZE); @@ -250,10 +257,13 @@ YDB_Error ydb_create_table(YDB_Engine *instance, const char *path) { return ydb_load_table(instance, path); } -int64_t ydb_tell_page(YDB_Engine *instance) { +YDB_Error ydb_prev_page(YDB_Engine *instance) { THROW_IF_NULL(instance, YDB_ERR_INSTANCE_NOT_INITIALIZED); THROW_IF_NULL(instance->in_use, YDB_ERR_INSTANCE_NOT_IN_USE); - return instance->current_page_index; + THROW_IF_NULL(instance->prev_page_offset, YDB_ERR_NO_MORE_PAGES); + + instance->curr_page_offset = instance->prev_page_offset; + return __ydb_read_page(instance); } YDB_Error ydb_next_page(YDB_Engine *instance) { @@ -261,48 +271,10 @@ YDB_Error ydb_next_page(YDB_Engine *instance) { THROW_IF_NULL(instance->in_use, YDB_ERR_INSTANCE_NOT_IN_USE); THROW_IF_NULL(instance->next_page_offset, YDB_ERR_NO_MORE_PAGES); - instance->prev_page_offset = instance->curr_page_offset; instance->curr_page_offset = instance->next_page_offset; - ++instance->current_page_index; return __ydb_read_page(instance); } -YDB_Error ydb_seek_page(YDB_Engine *instance, int64_t index) { - THROW_IF_NULL(instance, YDB_ERR_INSTANCE_NOT_INITIALIZED); - THROW_IF_NULL(instance->in_use, YDB_ERR_INSTANCE_NOT_IN_USE); - if (index < 0) { - return YDB_ERR_PAGE_INDEX_OUT_OF_RANGE; - } - - // Save current state - YDB_Offset prev_page_offset = instance->prev_page_offset; - YDB_Offset curr_page_offset = instance->curr_page_offset; - YDB_Offset next_page_offset = instance->next_page_offset; - int64_t curr_page_index = instance->current_page_index; - - if (index < instance->current_page_index) { - instance->prev_page_offset = 0; - instance->curr_page_offset = instance->first_page_offset; - instance->current_page_index = 0; - __ydb_read_page(instance); - } - - while (instance->current_page_index != index) { - YDB_Error status = ydb_next_page(instance); - - if (status != YDB_ERR_SUCCESS) { - instance->prev_page_offset = prev_page_offset; - instance->curr_page_offset = curr_page_offset; - instance->next_page_offset = next_page_offset; - instance->current_page_index = curr_page_index; - __ydb_read_page(instance); - return status; - } - } - - return YDB_ERR_SUCCESS; -} - YDB_TablePage* ydb_get_current_page(YDB_Engine *instance) { THROW_IF_NULL(instance, NULL); THROW_IF_NULL(instance->in_use, NULL); @@ -314,21 +286,20 @@ YDB_Error ydb_append_page(YDB_Engine* instance, YDB_TablePage* page) { THROW_IF_NULL(instance, YDB_ERR_INSTANCE_NOT_INITIALIZED); THROW_IF_NULL(instance->in_use, YDB_ERR_INSTANCE_NOT_IN_USE); - __ydb_allocate_page_and_seek(instance); + YDB_Offset new_page_offset = __ydb_allocate_page_and_seek(instance); YDB_PageSize rc = ydb_page_row_count_get(page); + YDB_PageSize rc_le = TO_LE(rc); YDB_Flags f = ydb_page_flags_get(page); - YDB_Offset next = 0; - char d[YDB_TABLE_PAGE_SIZE - YDB_v0_page_data_offset]; + + char d[YDB_TABLE_PAGE_SIZE - YDB_v1_page_data_offset]; ydb_page_data_seek(page, 0); if (ydb_page_data_read(page, d, sizeof(d))) { return YDB_ERR_UNKNOWN; // FIXME } - YDB_PageSize rc_le = TO_LE(rc); - fwrite(&f, sizeof(f), 1, instance->fd); - fwrite(&next, sizeof(next), 1, instance->fd); + fseek(instance->fd, new_page_offset + YDB_v1_page_row_count_offset, SEEK_SET); fwrite(&rc_le, sizeof(rc), 1, instance->fd); fwrite(d, sizeof(d), 1, instance->fd); @@ -355,8 +326,8 @@ YDB_Error ydb_replace_current_page(YDB_Engine *instance, YDB_TablePage *page) { YDB_Flags page_flags = ydb_page_flags_get(page); fwrite(&page_flags, sizeof(YDB_Flags), 1, instance->fd); - // Skip next page offset - fseek(instance->fd, sizeof(YDB_Offset), SEEK_CUR); + // Skip next and prev page offsets + fseek(instance->fd, YDB_v1_page_next_size + YDB_v1_page_prev_size, SEEK_CUR); // Write row count YDB_PageSize row_cnt = ydb_page_row_count_get(page); @@ -364,7 +335,7 @@ YDB_Error ydb_replace_current_page(YDB_Engine *instance, YDB_TablePage *page) { fwrite(&row_cnt_le, sizeof(row_cnt), 1, instance->fd); // Write data - char page_data[YDB_TABLE_PAGE_SIZE - YDB_v0_page_data_offset]; + char page_data[YDB_TABLE_PAGE_SIZE - YDB_v1_page_data_offset]; ydb_page_data_seek(page, 0); if (ydb_page_data_read(page, page_data, sizeof(page_data))) { return YDB_ERR_UNKNOWN; // FIXME @@ -385,9 +356,11 @@ YDB_Error ydb_delete_current_page(YDB_Engine *instance) { THROW_IF_NULL(instance->in_use, YDB_ERR_INSTANCE_NOT_IN_USE); if (instance->prev_page_offset == 0 && instance->next_page_offset == 0) { - fseek(instance->fd, instance->curr_page_offset + 9, SEEK_SET); // Skip page flags + next ptr - YDB_PageSize tmp = 0; - fwrite(&tmp, sizeof(YDB_PageSize), 1, instance->fd); + // Just clear page header. That's all. + fseek(instance->fd, instance->curr_page_offset, SEEK_SET); + char* empty_header = calloc(1, YDB_v1_page_data_offset); + fwrite(empty_header, YDB_v1_page_data_offset, 1, instance->fd); + free(empty_header); return YDB_ERR_SUCCESS; } @@ -400,32 +373,51 @@ YDB_Error ydb_delete_current_page(YDB_Engine *instance) { fwrite(&lfp_le, sizeof(YDB_Offset), 1, instance->fd); // Link the previous page with next one (could be null ptr) - fseek(instance->fd, instance->prev_page_offset + 1, SEEK_SET); // Skip flags + if (instance->prev_page_offset != 0) { + fseek(instance->fd, instance->prev_page_offset + YDB_v1_page_next_offset, SEEK_SET); + } else { + // If it was the first page, rewrite first_page_offset with next_page_offset + fseek(instance->fd, YDB_v1_first_page_offset, SEEK_SET); + } YDB_Offset np_le = TO_LE(instance->next_page_offset); fwrite(&np_le, sizeof(YDB_Offset), 1, instance->fd); - // If it was the last page, rewrite last_page_offset with prev_page_offset - if (instance->next_page_offset == 0) { - fseek(instance->fd, 14, SEEK_SET); - YDB_Offset pp_le = TO_LE(instance->prev_page_offset); - fwrite(&pp_le, sizeof(YDB_Offset), 1, instance->fd); + // Link the next page with previous one (could be null ptr) + if (instance->next_page_offset != 0) { + fseek(instance->fd, instance->next_page_offset + YDB_v1_page_prev_offset, SEEK_SET); + } else { + // If it was the last page, rewrite last_page_offset with prev_page_offset + fseek(instance->fd, YDB_v1_last_page_offset, SEEK_SET); } + YDB_Offset pp_le = TO_LE(instance->prev_page_offset); + fwrite(&pp_le, sizeof(YDB_Offset), 1, instance->fd); // Rewrite last_free_page_offset with current offset - fseek(instance->fd, 22, SEEK_SET); + fseek(instance->fd, YDB_v1_last_free_page_offset, SEEK_SET); YDB_Offset cp_le = TO_LE(instance->curr_page_offset); fwrite(&cp_le, sizeof(YDB_Offset), 1, instance->fd); // Flush buffer fflush(instance->fd); - // Set previous page - int64_t ind = --instance->current_page_index; - if (ydb_seek_page(instance, ind + 1)) { - return YDB_ERR_UNKNOWN; + // Seek to the next page if it's not the last, else seek to the previous one + if (instance->next_page_offset != 0) { + instance->curr_page_offset = instance->next_page_offset; + } else { + instance->curr_page_offset = instance->prev_page_offset; } + return __ydb_read_page(instance); +} - return YDB_ERR_SUCCESS; +YDB_Error ydb_seek_to_end(YDB_Engine *instance) { + THROW_IF_NULL(instance, YDB_ERR_INSTANCE_NOT_INITIALIZED); + THROW_IF_NULL(instance->in_use, YDB_ERR_INSTANCE_NOT_IN_USE); + + if (instance->next_page_offset == 0) + return YDB_ERR_SUCCESS; + + instance->curr_page_offset = instance->next_page_offset; + return __ydb_read_page(instance); } #ifdef __cplusplus diff --git a/table_file_v0.md b/table_file_v0.md index 1432606..1109d86 100644 --- a/table_file_v0.md +++ b/table_file_v0.md @@ -1,5 +1,7 @@ # Table file structure (v0) +Notice that this version is not supported now. Use v1 documentation instead. + ## Table file version changelog ### v0.2