From 6022eb75fc2acda6718eb871684f45c3a99f3bec 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: Wed, 4 May 2022 00:40:58 +0800 Subject: [PATCH] add more api --- api/types.md | 8 ++-- include/table.h | 17 ++++++--- src/page.c | 11 ++++++ src/table.c | 88 +++++++++++++++++++++++++++++++++++++++++--- tests/CMakeLists.txt | 4 +- tests/table_test.c | 1 + 6 files changed, 113 insertions(+), 16 deletions(-) diff --git a/api/types.md b/api/types.md index 181f1ba..74fc495 100644 --- a/api/types.md +++ b/api/types.md @@ -15,18 +15,18 @@ | 5 | double | 直接存储 | ## 字符串 -> 字符串为变长的可索引的字节数组,长度最大不超过uint32(65535字节)。 +> 字符串为变长的可索引的字节数组,长度最大不超过uint16(65535字节)。 ### 类型列表 | 类型代号 | 类型 | 存储方式 | | --- | --- | --- | -| 6 | string | 下一个哈希相同的数据项的指针+uint32长度+该长度的数据(字节数组) | +| 6 | string | 下一个哈希相同的数据项的指针+uint16长度+该长度的数据(字节数组) | ## 二进制数据块 -> 二进制数据块为变长的不参与索引的字节数组,长度最大不超过uint64。 +> 二进制数据块为变长的不参与索引的字节数组,长度最大不超过uint32。 ### 类型列表 | 类型代号 | 类型 | 存储方式 | | --- | --- | --- | -| 7 | binary | uint64长度+直接存储的数据(字节数组) | +| 7 | binary | uint32长度+直接存储的数据(字节数组) | ## 类型修饰符 > 类型修饰符占据类型代号的高2位,通过或运算与基础代号结合 diff --git a/include/table.h b/include/table.h index bd2a5ff..316f60a 100644 --- a/include/table.h +++ b/include/table.h @@ -16,8 +16,8 @@ void* create_table(int fd, char* buf, const char* name, int row_len, ...); // 加载 ptr 位置的表 // len(buf) >= 4096+8+2=4106 // 返回: -// NULL 失败,详见 errno -// table 指向表头的指针 +// 0 失败,详见 errno +// ptr 指向表头的指针 void* load_table(int fd, char* buf, uint64_t ptr); // 获得表名长度,包含结尾0 @@ -27,11 +27,14 @@ uint16_t get_table_name_length(void* table); // 返回:buf char* get_table_name(void* table, char* buf); +// 获得第 pos 项的索引 ptr +uint64_t get_index_ptr(void* table, uint16_t pos); + // 为 pos 位置的列创建索引。不可用于 0 列,即 pk 列,因为 pk 必有索引 // 返回: -// NULL 失败,详见 errno -// index 指向索引头的指针 -void* add_table_index(int fd, void* table, uint16_t pos); +// NULL 失败,详见 errno +// ptr 指向索引头的指针 +uint64_t add_table_index(int fd, void* table, uint16_t pos); // 删除 pos 位置的列的索引。不可用于 0 列,即 pk 列,因为 pk 必有索引 // 返回: @@ -44,6 +47,10 @@ int remove_table_index(int fd, void* table, uint16_t pos); // 加一个 int isavailable,标记本项是否有值 // 如果 isavailable==0,后面不再跟有本项数据 // 如果 isavailable!=0,则在后面附加数据 +// 如果 val 不为 string,直接装填其值 +// 否则,值是指向 string 的指针 (const char*) +// 如果是 binary,需要在指针之前提供一个 uint32 参数 +// 说明 binary 的大小 // 返回: // 0 失败,详见 errno // ptr 本行插入的位置 diff --git a/src/page.c b/src/page.c index 72f4c12..a3fe07d 100644 --- a/src/page.c +++ b/src/page.c @@ -326,13 +326,20 @@ int add_block(int fd, uint16_t size, uint64_t off) { lseek(fd, prev_ptr, SEEK_SET); putle64(buf, off); if(write(fd, buf, 8) != 8) return EOF; // 将本页附加到链表 + #ifdef DEBUG + printf("add blk: %016llx, next ptr: %016llx, size: %d\n", off, ptr, size); + #endif readle16(fd, sz); + putle16(buf, sz); if(prev_ptr+sz == off && prev_ptr%PAGESZ < off%PAGESZ) { // 可以和前一块合并 lseek(fd, prev_ptr, SEEK_SET); putle64(buf, ptr); write(fd, buf, 8); putle16(buf, size+sz); write(fd, buf, 2); + #ifdef DEBUG + printf("merge front: %016llx, size: %d\n", ptr, size+sz); + #endif return 0; } if(off+size == ptr && off%PAGESZ < ptr%PAGESZ) { // 可以和后一块合并 @@ -344,6 +351,10 @@ int add_block(int fd, uint16_t size, uint64_t off) { write(fd, buf, 8); putle16(buf, size+sz); write(fd, buf, 2); + #ifdef DEBUG + printf("merge rear: %016llx, size: %d\n", prev_ptr, size+sz); + #endif + return 0; } return 0; } diff --git a/src/table.c b/src/table.c index d15c340..8f1175f 100644 --- a/src/table.c +++ b/src/table.c @@ -44,11 +44,37 @@ static int _add_index_type(int fd, uint64_t* index_ptr, type_t t) { void* buf = malloc(sz); if(buf == NULL) return 1; void* index = create_index(fd, t, buf); + if(index == NULL) { + free(buf); + return 2; + } *index_ptr = le64(buf); free(buf); return 0; } +// 移除 t 类型索引 +// 返回: +// 1 失败,详见 errno +// 0 成功 +static int _remove_index_type(int fd, type_t t, uint64_t ptr) { + int sz = _calc_index_size(t); + if(sz <= 0) { + errno = EINVAL; + return EINVAL; + } + void* buf = malloc(sz); + if(buf == NULL) return 1; + void* index = load_index(fd, t, ptr, buf); + if(index == NULL) { + free(buf); + return 2; + } + sz = remove_index(fd, t, index); + free(buf); + return sz; +} + // 创建表,可变参数为本表的一行的 types,详见 types.h // 如果 types 为外键,需要紧跟一个 uint64_t ptr // 指示外键链接到的表位置 @@ -127,6 +153,9 @@ void* create_table(int fd, char* buf, const char* name, int row_len, ...) { // 将 page 变为 block putle64(buf, ptr); putle16(buf+8, len); + #ifdef DEBUG + printf("create len: %d\n", len); + #endif return buf+10; } @@ -155,6 +184,9 @@ void* load_table(int fd, char* buf, uint64_t ptr) { putle16(buf+8, len); // this blk len lseek(fd, ptr, SEEK_SET); if(read(fd, buf+10, len) != len) return NULL; + #ifdef DEBUG + printf("load len: %d\n", len); + #endif return buf+10; } @@ -172,12 +204,41 @@ char* get_table_name(void* table, char* buf) { return buf; } +uint64_t get_index_ptr(void* table, uint16_t pos) { + int len = 8+2+le16(table+8); + uint16_t rlen = le16(table+len); + if(pos >= rlen) { + errno = EINVAL; + return 0; + } + len += 2; + type_t t = ((type_t*)table)[len+(int)pos]; + len += (int)rlen+(int)pos*8; + return *(uint64_t*)(table+len); +} + // 为 pos 位置的列创建索引。不可用于 0 列,即 pk 列,因为 pk 必有索引 // 返回: -// NULL 失败,详见 errno -// index 指向索引头的指针 -void* add_table_index(int fd, void* table, uint16_t pos) { - return NULL; +// 0 失败,详见 errno +// ptr 指向索引头的指针 +uint64_t add_table_index(int fd, void* table, uint16_t pos) { + if(!pos) { + errno = EINVAL; + return 0; + } + int len = 8+2+le16(table+8); + uint16_t rlen = le16(table+len); + if(pos >= rlen) { + errno = EINVAL; + return 0; + } + len += 2; + type_t t = ((type_t*)table)[len+(int)pos]; + len += (int)rlen+(int)pos*8; + if(*(uint64_t*)(table+len)) return *(uint64_t*)(table+len); // 已经有索引 + if(_add_index_type(fd, table+len, t)) return 0; + if(sync_block(fd, table)) return 0; + return *(uint64_t*)(table+len); } // 删除 pos 位置的列的索引。不可用于 0 列,即 pk 列,因为 pk 必有索引 @@ -185,7 +246,24 @@ void* add_table_index(int fd, void* table, uint16_t pos) { // 非 0 失败,详见 errno // 0 成功 int remove_table_index(int fd, void* table, uint16_t pos) { - return 0; + if(!pos) { + errno = EINVAL; + return 0; + } + int len = 8+2+le16(table+8); + uint16_t rlen = le16(table+len); + if(pos >= rlen) { + errno = EINVAL; + return 0; + } + len += 2; + type_t t = ((type_t*)table)[len+(int)pos]; + len += (int)rlen+(int)pos*8; + uint64_t ptr = *(uint64_t*)(table+len); + if(ptr == 0) return 0; // 没有索引 + *(uint64_t*)(table+len) = 0; // 清除 + _remove_index_type(fd, t, ptr); + return sync_block(fd, table); } // 插入一行,如果 pk 有值则替换 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ee7eee6..4f56159 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,10 +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) +add_test(test_types types_test COMMAND types_test) add_test(test_table table_test COMMAND table_test) diff --git a/tests/table_test.c b/tests/table_test.c index d60eb71..663905b 100644 --- a/tests/table_test.c +++ b/tests/table_test.c @@ -51,5 +51,6 @@ int main() { return 4; } if(strcmp(get_table_name(table, namebuf), "test_table")) return 5; + if(get_index_ptr(table, 0) != 0x100) return 6; close(fd); }