diff --git a/api/index.md b/api/index.md index bb08fc5..602a0aa 100644 --- a/api/index.md +++ b/api/index.md @@ -50,8 +50,8 @@ ## int32/float > 查找速度为O(logn) -使用B+树建立索引,每个节点大小为`4096`字节,最多可有`n=341`个扇出,`340`个值;最少则有`170`个值(根节点不遵守最少值规则)。 -> 下面每格4字节 +- 使用B+树建立索引,每个节点大小为`4096`字节,最多可有`n=341`个扇出,`340`个值;最少则有`170`个值(根节点不遵守最少值规则)。 +> 下面每格4字节, next node ptr 将所有块连接起来以便全部遍历(如删除)。 ``` 0 8 12 20 ┌───────────────────┬─────────┬───────────────────┬─────────┐ @@ -69,11 +69,31 @@ └───────────────────┴───────────────────┘ 4088 4096 ``` +> 备选方案 + +- 使用哈希桶作索引,允许溢出桶,同样每个桶大小为`4096`字节,可装`340`个值。共`256`个桶,初始占用`1M`空间,后续由于溢出可能会增加。 +``` + 0 8 12 20 + ┌───────────────────┬─────────┬───────────────────┬─────────┐ + 0│ pointer 001 │ key 001 │ pointer 002 │ key 002 │ + ├───────────────────┼─────────┼───────────────────┼─────────┤ + 24│ pointer 003 │ key 003 │ pointer 004 │ key 004 │ + ├───────────────────┼─────────┼───────────────────┼─────────┤ + 48│ pointer 005 │ key 005 │ pointer 006 │ key 006 │ + ├───────────────────┼─────────┼───────────────────┼─────────┤ + xxx│ pointer xxx │ key xxx │ pointer xxx │ key xxx │ + ├───────────────────┼─────────┼───────────────────┼─────────┤ +4056│ pointer 339 │ key 339 │ pointer 340 │ key 340 │ + ├───────────────────┼─────────┴─────────┬─────────┴─────────┘ +4080│ overflow ptr │ next node ptr │ + └───────────────────┴───────────────────┘ + 4088 4096 +``` ## int64/double > 查找速度为O(logn) -使用B+树建立索引,每个节点大小为`4096`字节,最多可有`n=256`个扇出,`255`个值;最少则有`128`个值(根节点不遵守最少值规则)。 -> 下面每格8字节 +- 使用B+树建立索引,每个节点大小为`4096`字节,最多可有`n=256`个扇出,`255`个值;最少则有`128`个值(根节点不遵守最少值规则)。 +> 下面每格8字节, next node ptr 将所有块连接起来以便全部遍历(如删除)。 ``` 0 8 ┌───────────────────┬───────────────────┐ @@ -91,7 +111,27 @@ └───────────────────┴───────────────────┘ 4088 4096 ``` +> 备选方案 + +- 使用哈希桶作索引,允许溢出桶,同样每个桶大小为`4096`字节,可装`255`个值。共`1024`个桶,初始占用`4M`空间,后续由于溢出可能会增加。 +``` + 0 8 + ┌───────────────────┬───────────────────┐ + 0│ pointer 001 │ key 001 │ + ├───────────────────┼───────────────────┤ + 16│ pointer 002 │ key 002 │ + ├───────────────────┼───────────────────┤ + 32│ pointer 003 │ key 003 │ + ├───────────────────┼───────────────────┤ + xxx│ pointer xxx │ key xxx │ + ├───────────────────┼───────────────────┤ +4064│ pointer 255 │ key 255 │ + ├───────────────────┼───────────────────┤ +4080│ overflow ptr │ next node ptr │ + └───────────────────┴───────────────────┘ + 4088 4096 +``` ## string > 查找速度为O(logn) -先将其哈希为int64再按int64进行查找。具体哈希方法为取字符串`md5`的前8位作为小段`uint64`。冲突时,根据string表项附带存储的[下一个哈希相同的数据项的指针(uint64)](/api/types.md#字符串)可依次遍历到所有项目,然后找到真正与查询内容相同的项。 +先将其哈希为int64再按int64进行查找。具体哈希方法为取字符串`md5`的前8位作为小端`uint64`。冲突时,根据string表项附带存储的[下一个哈希相同的数据项的指针(uint64)](/api/types.md#字符串)可依次遍历到所有项目,然后找到真正与查询内容相同的项。 diff --git a/include/binary.h b/include/binary.h index 81790e6..bd20e3d 100644 --- a/include/binary.h +++ b/include/binary.h @@ -5,6 +5,10 @@ #include #include +#ifndef __null +# define __null 0 +#endif + #ifdef __linux__ # include #endif diff --git a/include/types/int32.h b/include/types/int32.h new file mode 100644 index 0000000..d588d7f --- /dev/null +++ b/include/types/int32.h @@ -0,0 +1,26 @@ +#ifndef _TYPE_INT32_H_ +#define _TYPE_INT32_H_ + +#include +#include "../types.h" + +#define INT32_BUCKET_SZ (256) +#define INT32_INDEX_SZ ((INT32_BUCKET_SZ+1)*(PAGESZ+8)) + +// len(buf) >= INT32_INDEX_SZ = (PAGESZ+8)*(256+1) = 4104*257 = 1054728 (1M) +// 256个哈希桶, 多出来一个是机动空间, 用于加载溢出桶 +void* create_int32_index(int fd, void* buf); + +void* load_int32_index(int fd, uint64_t ptr, void* buf); + +int remove_int32_index(int fd, void* index); + +uint64_t count_int32_items(int fd, void* index); + +int insert_int32_item(int fd, void* index, key_t k, uint64_t ptr); + +uint64_t find_item_by_int32_key(int fd, void* index, key_t k); + +uint64_t remove_item_by_int32_key(int fd, void* index, key_t k); + +#endif \ No newline at end of file diff --git a/src/types/int32.c b/src/types/int32.c new file mode 100644 index 0000000..6d20744 --- /dev/null +++ b/src/types/int32.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include + +#include "../../include/binary.h" +#include "../../include/page.h" +#include "../../include/types/int32.h" + +void* create_int32_index(int fd, void* buf) { + void* page = alloc_page(fd, buf); + if(unlikely(page == NULL)) return NULL; + memset(page, 0, PAGESZ); + void* prev_page = page; + for(int i = 1; i < INT32_BUCKET_SZ; i++) { + page = alloc_page(fd, buf); + if(unlikely(page == NULL)) { + for(int j = 0; j < i; j++) free_page(fd, buf+j*(PAGESZ+8)+8); + return NULL; + } + memset(page, 0, PAGESZ); + putle64(prev_page+PAGESZ-8, le64(page-8)); + if(unlikely(sync_page(fd, prev_page))) { + free_page(fd, page); + for(int j = 0; j < i; j++) free_page(fd, buf+j*(PAGESZ+8)+8); + return NULL; + } + prev_page = page; + } + if(unlikely(sync_page(fd, page))) { + free_page(fd, page); + for(int i = 0; i < INT32_BUCKET_SZ; i++) free_page(fd, buf+i*(PAGESZ+8)+8); + return NULL; + } + return buf+8; +} + +void* load_int32_index(int fd, uint64_t ptr, void* buf) { + void* page = get_page(fd, ptr, buf); + if(unlikely(page == NULL)) return NULL; + for(int i = 1; i < INT32_BUCKET_SZ-1; i++) { + page = get_page(fd, le64(page+PAGESZ-8), buf+i*(PAGESZ+8)); + if(unlikely(page == NULL)) return NULL; + } + return buf+8; +} + +int remove_int32_index(int fd, void* index) { + for(int i = 0; i < INT32_BUCKET_SZ; i++) { + void* page = index+i*(PAGESZ+8); + uint64_t ptr = le64(page+PAGESZ-16); + while(unlikely(ptr)) { + void* p = get_page(fd, ptr, index+INT32_INDEX_SZ-BUFSIZ-8); + if(unlikely(p == NULL)) return EOF; + ptr = le64(p+PAGESZ-16); + if(unlikely(free_page(fd, p))) return EOF; + } + if(unlikely(free_page(fd, page))) return EOF; + } +} + +uint64_t count_int32_items(int fd, void* index) { + +} + +int insert_int32_item(int fd, void* index, key_t k, uint64_t ptr) { + +} + +uint64_t find_item_by_int32_key(int fd, void* index, key_t k) { + +} + +uint64_t remove_item_by_int32_key(int fd, void* index, key_t k) { + +}