From ef435631cbe64237c2195fd8f08da6083c2c2967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Tue, 3 May 2022 23:45:45 +0800 Subject: [PATCH] finish load table --- include/table.h | 8 +++---- src/page.c | 22 +++++++++++++----- src/table.c | 40 +++++++++++++++++++++++--------- tests/CMakeLists.txt | 6 +++-- tests/page_test.c | 2 +- tests/table_test.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ tests/types_test.c | 2 +- 7 files changed, 110 insertions(+), 25 deletions(-) create mode 100644 tests/table_test.c diff --git a/include/table.h b/include/table.h index 8cb4e86..bd2a5ff 100644 --- a/include/table.h +++ b/include/table.h @@ -11,7 +11,7 @@ // 返回: // NULL 失败,详见 errno // table 指向表头的指针 -void* create_table(int fd, char* buf, const char* name, uint16_t row_len, ...); +void* create_table(int fd, char* buf, const char* name, int row_len, ...); // 加载 ptr 位置的表 // len(buf) >= 4096+8+2=4106 @@ -47,7 +47,7 @@ int remove_table_index(int fd, void* table, uint16_t pos); // 返回: // 0 失败,详见 errno // ptr 本行插入的位置 -uint64_t insert_row(int fd, void* table, uint16_t row_len, ...); +uint64_t insert_row(int fd, void* table, int row_len, ...); // 根据主键的匹配值查找行 // 如果主键不为 string,k 直接装填其值 @@ -65,7 +65,7 @@ uint64_t find_row_by_pk(int fd, void* table, key_t k); // 返回: // 非 0 失败,详见 errno // 0 成功 -int find_row_by(int fd, void* table, int (*f)(uint64_t), uint16_t row_len, ...); +int find_row_by(int fd, void* table, int (*f)(uint64_t), int row_len, ...); // 根据主键的匹配值删除行 // 如果主键不为 string,k 直接装填其值 @@ -82,6 +82,6 @@ int remove_row_by_pk(int fd, void* table, key_t k); // 返回: // 非 0 失败,详见 errno // 0 成功 -int remove_row_by(int fd, void* table, uint16_t row_len, ...); +int remove_row_by(int fd, void* table, int row_len, ...); #endif \ No newline at end of file diff --git a/src/page.c b/src/page.c index 116e14c..72f4c12 100644 --- a/src/page.c +++ b/src/page.c @@ -30,7 +30,7 @@ void* alloc_page(int fd, void* page) { if(write(fd, buf, 8) != 8) return NULL; // 从空闲块链表移除本块 return page; } - if(prev_prev_ptr && ptr < prev_ptr) { // 不符合顺序,进行一次调整 + if(prev_prev_ptr && ptr < prev_ptr && ptr != 8) { // 不符合顺序,进行一次调整 lseek(fd, prev_prev_ptr, SEEK_SET); putle64(buf, ptr); if(write(fd, buf, 8) != 8) return NULL; // 1->next = 3 @@ -87,7 +87,7 @@ int free_page(int fd, void* page) { errno = ESPIPE; return EOF; } - if(prev_prev_ptr && ptr < prev_ptr) { // 不符合顺序,进行一次调整 + if(prev_prev_ptr && ptr < prev_ptr && ptr != 8) { // 不符合顺序,进行一次调整 lseek(fd, prev_prev_ptr, SEEK_SET); putle64(buf, ptr); if(write(fd, buf, 8) != 8) return EOF; // 1->next = 3 @@ -140,7 +140,11 @@ void* alloc_block(int fd, uint16_t size, void* blk) { errno = ESPIPE; return NULL; } - readle16(fd, blksz); + if(ptr == 8) blksz = 0; + else readle16(fd, blksz); + #ifdef DEBUG + printf("ptr: %016llx, blksize: %d\n", ptr, blksz); + #endif if(blksz >= size) { // 找到符合要求的块 if(blksz - size > 10) { // 分裂块 lseek(fd, ptr+size, SEEK_SET); @@ -152,6 +156,9 @@ void* alloc_block(int fd, uint16_t size, void* blk) { } putle64(blk, ptr); putle16(blk+8, size); + #ifdef DEBUG + printf("find match: ptr: %016llx, size: %d\n", ptr, size); + #endif blk += 10; if(lseek(fd, prev_ptr, SEEK_SET) < 0) return NULL; if(write(fd, buf, 8) != 8) { // 从空闲块链表移除本块 @@ -160,7 +167,7 @@ void* alloc_block(int fd, uint16_t size, void* blk) { } return blk; } - if(prev_prev_ptr && ptr < prev_ptr) { // 不符合顺序,进行一次调整 + if(prev_prev_ptr && ptr < prev_ptr && ptr != 8) { // 不符合顺序,进行一次调整 lseek(fd, prev_prev_ptr, SEEK_SET); putle64(buf, ptr); if(write(fd, buf, 8) != 8) return NULL; // 1->next = 3 @@ -221,6 +228,9 @@ int sync_block(int fd, void* blk) { errno = EFBIG; return EOF; } + #ifdef DEBUG + printf("off: %016llx, size: %d\n", off, size); + #endif if(lseek(fd, off, SEEK_SET) < 0) return EOF; return write(fd, blk, size) != size; } @@ -235,7 +245,7 @@ int free_block(int fd, void* blk) { errno = ESPIPE; return EOF; } - if(prev_prev_ptr && ptr < prev_ptr) { // 不符合顺序,进行一次调整 + if(prev_prev_ptr && ptr < prev_ptr && ptr != 8) { // 不符合顺序,进行一次调整 lseek(fd, prev_prev_ptr, SEEK_SET); putle64(buf, ptr); if(write(fd, buf, 8) != 8) return EOF; // 1->next = 3 @@ -288,7 +298,7 @@ int add_block(int fd, uint16_t size, uint64_t off) { errno = ESPIPE; return EOF; } - if(prev_prev_ptr && ptr < prev_ptr) { // 不符合顺序,进行一次调整 + if(prev_prev_ptr && ptr < prev_ptr && ptr != 8) { // 不符合顺序,进行一次调整 lseek(fd, prev_prev_ptr, SEEK_SET); putle64(buf, ptr); if(write(fd, buf, 8) != 8) return EOF; // 1->next = 3 diff --git a/src/table.c b/src/table.c index 91b3208..d15c340 100644 --- a/src/table.c +++ b/src/table.c @@ -35,7 +35,7 @@ static int _calc_index_size(type_t t) { // 返回: // 1 失败,详见 errno // 0 成功 -static void* _add_index_type(int fd, uint64_t* index_ptr, type_t t) { +static int _add_index_type(int fd, uint64_t* index_ptr, type_t t) { int sz = _calc_index_size(t); if(sz <= 0) { errno = EINVAL; @@ -56,10 +56,8 @@ static void* _add_index_type(int fd, uint64_t* index_ptr, type_t t) { // 返回: // NULL 失败,详见 errno // table 指向表头的指针 -void* create_table(int fd, char* buf, const char* name, uint16_t row_len, ...) { - va_list list; - - if(!row_len || row_len > 128) { +void* create_table(int fd, char* buf, const char* name, int row_len, ...) { + if(row_len <= 0 || row_len > 128) { errno = EINVAL; return NULL; } @@ -88,9 +86,10 @@ void* create_table(int fd, char* buf, const char* name, uint16_t row_len, ...) { len += 2; int foreign_cnt = 0; + va_list list; va_start(list, row_len); - type_t t = va_arg(list, type_t); // 是主键,检查是否有 unique + nonnull 类型修饰符 + type_t t = va_arg(list, int); // 是主键,检查是否有 unique + nonnull 类型修饰符 if(!(t&EXTYPE_NONNULL) || !(t&EXTYPE_UNIQUE)) { errno = EINVAL; return NULL; @@ -104,7 +103,7 @@ void* create_table(int fd, char* buf, const char* name, uint16_t row_len, ...) { // 为 pk 创建索引 if(_add_index_type(fd, table+len+(int)row_len, t)) return NULL; for(int i = 1; i < (int)row_len; i++) { - t = va_arg(list, type_t); + t = va_arg(list, int); ((type_t*)table)[len+i] = t; // 填充 type of row No.i if(t & EXTYPE_FOREIGNKEY) { // 是外键,还有一个参数 ptr = va_arg(list, uint64_t); @@ -137,7 +136,26 @@ void* create_table(int fd, char* buf, const char* name, uint16_t row_len, ...) { // NULL 失败,详见 errno // table 指向表头的指针 void* load_table(int fd, char* buf, uint64_t ptr) { - return NULL; + uint64_t tmp; + int len = 8; + putle64(buf, ptr); // this blk ptr + if(lseek(fd, ptr+8, SEEK_SET) < 0) return NULL; // skip next table ptr + readle16(fd, tmp); // table name length + len += 2+(int)tmp; + if(lseek(fd, tmp, SEEK_CUR) < 0) return NULL; + readle16(fd, tmp); // table row length + len += 2+((int)tmp)*(8+1); + for(int i = 0; i < (int)tmp; i++) { + type_t t; + read(fd, &t, 1); + if(t&EXTYPE_FOREIGNKEY) { // 外键有额外 ptr 长度 + len += 8; + } + } + putle16(buf+8, len); // this blk len + lseek(fd, ptr, SEEK_SET); + if(read(fd, buf+10, len) != len) return NULL; + return buf+10; } // 获得表名长度,包含结尾0 @@ -178,7 +196,7 @@ int remove_table_index(int fd, void* table, uint16_t pos) { // 返回: // 0 失败,详见 errno // ptr 本行插入的位置 -uint64_t insert_row(int fd, void* table, uint16_t row_len, ...) { +uint64_t insert_row(int fd, void* table, int row_len, ...) { return 0; } @@ -200,7 +218,7 @@ uint64_t find_row_by_pk(int fd, void* table, key_t k) { // 返回: // 非 0 失败,详见 errno // 0 成功 -int find_row_by(int fd, void* table, int (*f)(uint64_t), uint16_t row_len, ...) { +int find_row_by(int fd, void* table, int (*f)(uint64_t), int row_len, ...) { return 1; } @@ -221,6 +239,6 @@ int remove_row_by_pk(int fd, void* table, key_t k) { // 返回: // 非 0 失败,详见 errno // 0 成功 -int remove_row_by(int fd, void* table, uint16_t row_len, ...) { +int remove_row_by(int fd, void* table, int row_len, ...) { return 1; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 185c054..ee7eee6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,8 +3,10 @@ project(fumidb_test VERSION 1.0) add_executable(binary_test binary_test.c) add_executable(page_test page_test.c ../src/page.c ../src/file.c) -add_executable(types_test types_test.c ../src/types.c ../src/types/int8.c ../src/types/int16.c ../src/page.c ../src/file.c) +#add_executable(types_test types_test.c ../src/types.c ../src/types/int8.c ../src/types/int16.c ../src/page.c ../src/file.c) +add_executable(table_test table_test.c ../src/table.c ../src/types.c ../src/types/int8.c ../src/types/int16.c ../src/page.c ../src/file.c) add_test(test_binary binary_test COMMAND binary_test) add_test(test_page page_test COMMAND page_test) -add_test(test_types types_test COMMAND types_test) \ No newline at end of file +#add_test(test_types types_test COMMAND types_test) +add_test(test_table table_test COMMAND table_test) diff --git a/tests/page_test.c b/tests/page_test.c index 1f3c99e..bb49d7f 100644 --- a/tests/page_test.c +++ b/tests/page_test.c @@ -24,7 +24,7 @@ int main() { perror("create"); return 1; } - if(init_file_header_page(fd) < 0) return 2; + if(init_file_header_page(fd)) return 2; for(int i = 0; i < 16; i++) { void* page = alloc_page(fd, nullpages[i]); if(page == NULL) { diff --git a/tests/table_test.c b/tests/table_test.c new file mode 100644 index 0000000..d60eb71 --- /dev/null +++ b/tests/table_test.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include "../include/binary.h" +#include "../include/file.h" +#include "../include/page.h" +#include "../include/table.h" +#include "../include/types.h" + +char buf[4106]; + +int main() { + int fd = open("table_test_tmp.bin", O_RDWR | O_CREAT | O_TRUNC, 0644); + if(fd < 0) { + perror("create"); + return 1; + } + if(init_file_header_page(fd)) return 2; + void* table = create_table( + fd, buf, "test_table", 5, + TYPE_INT16|EXTYPE_NONNULL|EXTYPE_UNIQUE, + TYPE_INT64, + TYPE_INT8, + TYPE_STRING, + TYPE_BINARY + ); + if(table == NULL) { + perror("create_table"); + return 3; + } + int len = get_table_name_length(table); + if(len != sizeof("test_table")) return 4; + char namebuf[len]; + if(strcmp(get_table_name(table, namebuf), "test_table")) return 5; + close(fd); + fd = open("table_test_tmp.bin", O_RDWR, 0644); + if(fd < 0) { + perror("open"); + return 1; + } + memset(buf, 0, sizeof(buf)); + table = load_table(fd, buf, get_first_table(fd)); + if(table == NULL) { + perror("load_table"); + return 3; + } + len = get_table_name_length(table); + if(len != sizeof("test_table")) { + printf("%d\n", len); + return 4; + } + if(strcmp(get_table_name(table, namebuf), "test_table")) return 5; + close(fd); +} diff --git a/tests/types_test.c b/tests/types_test.c index 005cc6f..4331a4d 100644 --- a/tests/types_test.c +++ b/tests/types_test.c @@ -17,7 +17,7 @@ int main() { perror("create"); return 1; } - if(init_file_header_page(fd) < 0) return 2; + if(init_file_header_page(fd)) return 2; void* index = create_index(fd, TYPE_INT8, buf); if(!index) { perror("create_int8_index");