1
0
mirror of https://github.com/fumiama/fumidb.git synced 2026-06-10 05:04:18 +08:00

finish int32 int64

This commit is contained in:
源文雨
2022-10-09 16:23:12 +08:00
parent 2dd269b364
commit b410f26bf4
12 changed files with 782 additions and 48 deletions

View File

@@ -2,6 +2,8 @@
#include "../include/types.h"
#include "../include/types/int8.h"
#include "../include/types/int16.h"
#include "../include/types/int32.h"
#include "../include/types/int64.h"
// ptr = init(fd)
typedef void* (*_type_init_t)(int, void*);
@@ -63,70 +65,70 @@ static uint64_t remove_item_by_not_impl_key(int fd, void* index, key_t k) {
static _type_init_t _types_init[] = {
create_int8_index,
create_int16_index,
create_not_impl_index,
create_not_impl_index,
create_not_impl_index,
create_not_impl_index,
create_int32_index,
create_int64_index,
create_int32_index, // float
create_int64_index, // double
create_not_impl_index
};
static _type_load_t _types_load[] = {
load_int8_index,
load_int16_index,
load_not_impl_index,
load_not_impl_index,
load_not_impl_index,
load_not_impl_index,
load_int32_index,
load_int64_index,
load_int32_index, // float
load_int64_index, // double
load_not_impl_index
};
static _type_remove_t _types_remove[] = {
remove_int8_index,
remove_int16_index,
remove_not_impl_index,
remove_not_impl_index,
remove_not_impl_index,
remove_not_impl_index,
remove_int32_index,
remove_int64_index,
remove_int32_index, // float
remove_int64_index, // double
remove_not_impl_index
};
static _type_count_t _types_count[] = {
count_int8_items,
count_int16_items,
count_not_impl_items,
count_not_impl_items,
count_not_impl_items,
count_not_impl_items,
count_int32_items,
count_int64_items,
count_int32_items, // float
count_int64_items, // double
count_not_impl_items
};
static _insert_item_t _insert_item[] = {
insert_int8_item,
insert_int16_item,
insert_not_impl_item,
insert_not_impl_item,
insert_not_impl_item,
insert_not_impl_item,
insert_int32_item,
insert_int64_item,
insert_int32_item, // float
insert_int64_item, // double
insert_not_impl_item
};
static _find_by_key_t _find_item_by_key[] = {
find_item_by_int8_key,
find_item_by_int16_key,
find_item_by_not_impl_key,
find_item_by_not_impl_key,
find_item_by_not_impl_key,
find_item_by_not_impl_key,
find_item_by_int32_key,
find_item_by_int64_key,
find_item_by_int32_key, // float
find_item_by_int64_key, // double
find_item_by_not_impl_key
};
static _remove_by_key_t _remove_item_by_key[] = {
remove_item_by_int8_key,
remove_item_by_int16_key,
remove_item_by_not_impl_key,
remove_item_by_not_impl_key,
remove_item_by_not_impl_key,
remove_item_by_not_impl_key,
remove_item_by_int32_key,
remove_item_by_int64_key,
remove_item_by_int32_key, // float
remove_item_by_int64_key, // double
remove_item_by_not_impl_key
};

View File

@@ -9,13 +9,15 @@
#include "../../include/page.h"
#include "../../include/types/int32.h"
//#define DEBUG
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);
page = alloc_page(fd, buf+i*(PAGESZ+8));
if(unlikely(page == NULL)) {
for(int j = 0; j < i; j++) free_page(fd, buf+j*(PAGESZ+8)+8);
return NULL;
@@ -34,13 +36,16 @@ void* create_int32_index(int fd, void* buf) {
for(int i = 0; i < INT32_BUCKET_SZ; i++) free_page(fd, buf+i*(PAGESZ+8)+8);
return NULL;
}
#ifdef DEBUG
puts("alloc finish");
#endif
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++) {
for(int i = 1; i < INT32_BUCKET_SZ; i++) {
page = get_page(fd, le64(page+PAGESZ-8), buf+i*(PAGESZ+8));
if(unlikely(page == NULL)) return NULL;
}
@@ -52,27 +57,213 @@ int remove_int32_index(int fd, void* index) {
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);
void* p = get_page(fd, ptr, index-8+INT32_INDEX_SZ-PAGESZ-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;
}
return 0;
}
uint64_t count_int32_items(int fd, void* index) {
uint64_t sum = 0;
for(int i = 0; i < INT32_BUCKET_SZ; i++) {
void* page = index+i*(PAGESZ+8);
uint64_t ptr = 1;
for(int j = 0; j < INT32_BUCKET_MAX_ITEM_SZ && ptr; j++) {
ptr = le64(page+j*(8+4));
sum += !!ptr;
}
ptr = le64(page+PAGESZ-16); // 查看是否有溢出桶
while(ptr) {
#ifdef DEBUG
//printf("%x ", ptr);
//fflush(stdout);
#endif
page = get_page(fd, ptr, index-8+INT32_INDEX_SZ-PAGESZ-8);
for(int j = 0; j < INT32_BUCKET_MAX_ITEM_SZ && ptr; j++) {
ptr = le64(page+j*(8+4));
sum += !!ptr;
}
ptr = le64(page+PAGESZ-16); // 查看是否有溢出桶
}
}
return sum;
}
int insert_int32_item(int fd, void* index, key_t k, uint64_t ptr) {
uint32_t key = (uint32_t)k;
uint64_t digest = (k*(k+INT32_DIGEST_FACTOR))%256;
// 访问digest指向的存储桶
void* page = index+digest*(PAGESZ+8);
uint64_t p = 1;
while(1) {
for(int j = 0; j < INT32_BUCKET_MAX_ITEM_SZ && p; j++) {
void* slot = page+j*(8+4);
p = le64(slot);
if(p && key == le32(slot+8)) { // 已存在值, 替换之
putle64(slot, ptr);
return sync_page(fd, page);
} else if(!p) { // 不存在值, 新建
putle64(slot, ptr);
putle32(slot+8, key);
return sync_page(fd, page);
}
}
// 溢出
p = le64(page+PAGESZ-16); // 查看是否有溢出桶
if(!p) { // 无溢出桶, 新建
void* ovpage = alloc_page(fd, index-8+INT32_INDEX_SZ-PAGESZ-8);
if(unlikely(ovpage == NULL)) return EOF;
memset(ovpage, 0, PAGESZ);
putle64(page+PAGESZ-16, le64(ovpage-8));
#ifdef DEBUG
printf("new ovpage: %x, this page: %x\n", le64(page+PAGESZ-16), le64(page-8));
#endif
int r = sync_page(fd, page);
if(unlikely(r)) return r;
putle64(ovpage, ptr);
putle32(ovpage+8, key);
#ifdef DEBUG
printf("write ptr: %x, key: %x\n", ptr, key);
#endif
return sync_page(fd, ovpage);
}
// 有溢出桶, 进入下一轮搜索
page = get_page(fd, p, index-8+INT32_INDEX_SZ-PAGESZ-8);
}
}
uint64_t find_item_by_int32_key(int fd, void* index, key_t k) {
uint32_t key = (uint32_t)k;
uint64_t digest = (k*(k+INT32_DIGEST_FACTOR))%256;
// 访问digest指向的存储桶
void* page = index+digest*(PAGESZ+8);
uint64_t p = 1;
while(1) {
for(int j = 0; j < INT32_BUCKET_MAX_ITEM_SZ && p; j++) {
void* slot = page+j*(8+4);
p = le64(slot);
if(!p || (p && key == le32(slot+8))) { // 找到项目 or 不存在值, 无该项目
return p;
}
}
// 桶已满
p = le64(page+PAGESZ-16); // 查看是否有溢出桶
if(!p) { // 无溢出桶, 无该项目
return 0;
}
// 有溢出桶, 进入下一轮搜索
page = get_page(fd, p, index-8+INT32_INDEX_SZ-PAGESZ-8);
}
}
uint64_t remove_item_by_int32_key(int fd, void* index, key_t k) {
uint32_t key = (uint32_t)k;
uint64_t digest = (k*(k+INT32_DIGEST_FACTOR))%256;
// 访问digest指向的存储桶
void* page = index+digest*(PAGESZ+8);
uint64_t p = 1;
while(1) {
for(int j = 0; j < INT32_BUCKET_MAX_ITEM_SZ && p; j++) {
void* slot = page+j*(8+4);
p = le64(slot);
if(!p) { // 不存在值, 无该项目
return 0;
}
if(p && key == le32(slot+8)) { // 找到项
int i = j;
for(; i < INT32_BUCKET_MAX_ITEM_SZ && le64(page+i*(8+4)); i++) {
#ifdef DEBUG
//printf("lookup %03d: %x\n", i, le64(page+i*(8+4)));
#endif
}
#ifdef DEBUG
printf("page: %x(%x), i: %d, p: %x\n", page, le64(page-8), i, p);
#endif
void *next_page = page, *prev_page;
while(i == INT32_BUCKET_MAX_ITEM_SZ) { // 本桶已满
int next = le64(next_page+PAGESZ-16); // 查看是否有溢出桶
if(!next) { // 无溢出桶, 将最后一个值搬移至slot并为其补0
// 不是最后一项, 搬移
if(j+1 != INT32_BUCKET_MAX_ITEM_SZ || next_page!=page) memcpy(slot, next_page-8-8-8-4, 8+4);
memset(next_page-8-8-8-4, 0, 8+4);
int r = sync_page(fd, next_page);
if(unlikely(r)) return r;
if(next_page!=page) {
r = sync_page(fd, page);
if(unlikely(r)) return r;
}
return p;
}
// 有溢出桶, 加载
prev_page = next_page;
#ifdef DEBUG
printf("%x have next bucket at: %x, ", le64(prev_page-8), next);
#endif
void* buf = index-8+INT32_INDEX_SZ-PAGESZ-8-PAGESZ-8;
#ifdef DEBUG
printf("buf: %p, ", buf);
fflush(stdout);
#endif
next_page = get_page(fd, next, buf);
#ifdef DEBUG
printf("next page: %p\n", next_page);
#endif
for(i = 0; i < INT32_BUCKET_MAX_ITEM_SZ && le64(next_page+i*(8+4)); i++);
#ifdef DEBUG
printf("new i: %d\n", i);
#endif
}
// 转至新桶第一个, 但发现为空, 即最后一项在上个桶末尾
if(!i) {
#ifdef DEBUG
puts("i == 0");
#endif
memcpy(slot, prev_page+PAGESZ-8-8-8-4, 8+4);
memset(prev_page+PAGESZ-8-8-8-4, 0, 8+4);
#ifdef DEBUG
printf("prev_page: %x(%x), page: %x(%x)\n", prev_page, le64(prev_page-8), page, le64(page-8));
printf("slot@%016x+%03d, last@%016x+339, ptr: %x, key: %x\n", le64(page-8), (slot-page)/12, le64(prev_page-8), le64(slot), le64(slot+8));
#endif
int r = sync_page(fd, prev_page);
if(unlikely(r)) return r;
if(prev_page!=page) {
r = sync_page(fd, page);
if(unlikely(r)) return r;
}
return p;
}
// 本桶未满
if(--i == j && page == next_page) { // 是最后一项, 直接删除
memset(slot, 0, 8+4);
int r = sync_page(fd, page);
if(unlikely(r)) return r;
return p;
}
// 不是最后一项, 搬移
memcpy(slot, next_page+i*(8+4), 8+4);
memset(next_page+i*(8+4), 0, 8+4);
int r = sync_page(fd, next_page);
if(unlikely(r)) return r;
if(next_page!=page) {
r = sync_page(fd, page);
if(unlikely(r)) return r;
}
#ifdef DEBUG
printf("slot@%016x+%03d, last@%016x+%03d\n", le64(page-8), (slot-page)/12, le64(next_page-8), i);
#endif
return p;
}
}
// 桶已满
p = le64(page+PAGESZ-16); // 查看是否有溢出桶
if(!p) { // 无溢出桶, 无该项目
return 0;
}
// 有溢出桶, 进入下一轮搜索
page = get_page(fd, p, index-8+INT32_INDEX_SZ-PAGESZ-8);
}
}

269
src/types/int64.c Normal file
View File

@@ -0,0 +1,269 @@
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../../include/binary.h"
#include "../../include/page.h"
#include "../../include/types/int64.h"
//#define DEBUG
void* create_int64_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 < INT64_BUCKET_SZ; i++) {
page = alloc_page(fd, buf+i*(PAGESZ+8));
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 < INT64_BUCKET_SZ; i++) free_page(fd, buf+i*(PAGESZ+8)+8);
return NULL;
}
#ifdef DEBUG
puts("alloc finish");
#endif
return buf+8;
}
void* load_int64_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 < INT64_BUCKET_SZ; i++) {
page = get_page(fd, le64(page+PAGESZ-8), buf+i*(PAGESZ+8));
if(unlikely(page == NULL)) return NULL;
}
return buf+8;
}
int remove_int64_index(int fd, void* index) {
for(int i = 0; i < INT64_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-8+INT64_INDEX_SZ-PAGESZ-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;
}
return 0;
}
uint64_t count_int64_items(int fd, void* index) {
uint64_t sum = 0;
for(int i = 0; i < INT64_BUCKET_SZ; i++) {
void* page = index+i*(PAGESZ+8);
uint64_t ptr = 1;
for(int j = 0; j < INT64_BUCKET_MAX_ITEM_SZ && ptr; j++) {
ptr = le64(page+j*(8+8));
sum += !!ptr;
}
ptr = le64(page+PAGESZ-16); // 查看是否有溢出桶
while(ptr) {
#ifdef DEBUG
//printf("%x ", ptr);
//fflush(stdout);
#endif
page = get_page(fd, ptr, index-8+INT64_INDEX_SZ-PAGESZ-8);
for(int j = 0; j < INT64_BUCKET_MAX_ITEM_SZ && ptr; j++) {
ptr = le64(page+j*(8+8));
sum += !!ptr;
}
ptr = le64(page+PAGESZ-16); // 查看是否有溢出桶
}
}
return sum;
}
int insert_int64_item(int fd, void* index, key_t k, uint64_t ptr) {
uint64_t key = (uint64_t)k;
uint64_t digest = (k*(k+INT64_DIGEST_FACTOR))%256;
// 访问digest指向的存储桶
void* page = index+digest*(PAGESZ+8);
uint64_t p = 1;
while(1) {
for(int j = 0; j < INT64_BUCKET_MAX_ITEM_SZ && p; j++) {
void* slot = page+j*(8+8);
p = le64(slot);
if(p && key == le64(slot+8)) { // 已存在值, 替换之
putle64(slot, ptr);
return sync_page(fd, page);
} else if(!p) { // 不存在值, 新建
putle64(slot, ptr);
putle64(slot+8, key);
return sync_page(fd, page);
}
}
// 溢出
p = le64(page+PAGESZ-16); // 查看是否有溢出桶
if(!p) { // 无溢出桶, 新建
void* ovpage = alloc_page(fd, index-8+INT64_INDEX_SZ-PAGESZ-8);
if(unlikely(ovpage == NULL)) return EOF;
memset(ovpage, 0, PAGESZ);
putle64(page+PAGESZ-16, le64(ovpage-8));
#ifdef DEBUG
printf("new ovpage: %x, this page: %x\n", le64(page+PAGESZ-16), le64(page-8));
#endif
int r = sync_page(fd, page);
if(unlikely(r)) return r;
putle64(ovpage, ptr);
putle64(ovpage+8, key);
#ifdef DEBUG
printf("write ptr: %x, key: %x\n", ptr, key);
#endif
return sync_page(fd, ovpage);
}
// 有溢出桶, 进入下一轮搜索
page = get_page(fd, p, index-8+INT64_INDEX_SZ-PAGESZ-8);
}
}
uint64_t find_item_by_int64_key(int fd, void* index, key_t k) {
uint64_t key = (uint64_t)k;
uint64_t digest = (k*(k+INT64_DIGEST_FACTOR))%256;
// 访问digest指向的存储桶
void* page = index+digest*(PAGESZ+8);
uint64_t p = 1;
while(1) {
for(int j = 0; j < INT64_BUCKET_MAX_ITEM_SZ && p; j++) {
void* slot = page+j*(8+8);
p = le64(slot);
if(!p || (p && key == le64(slot+8))) { // 找到项目 or 不存在值, 无该项目
return p;
}
}
// 桶已满
p = le64(page+PAGESZ-16); // 查看是否有溢出桶
if(!p) { // 无溢出桶, 无该项目
return 0;
}
// 有溢出桶, 进入下一轮搜索
page = get_page(fd, p, index-8+INT64_INDEX_SZ-PAGESZ-8);
}
}
uint64_t remove_item_by_int64_key(int fd, void* index, key_t k) {
uint64_t key = (uint64_t)k;
uint64_t digest = (k*(k+INT64_DIGEST_FACTOR))%256;
// 访问digest指向的存储桶
void* page = index+digest*(PAGESZ+8);
uint64_t p = 1;
while(1) {
for(int j = 0; j < INT64_BUCKET_MAX_ITEM_SZ && p; j++) {
void* slot = page+j*(8+8);
p = le64(slot);
if(!p) { // 不存在值, 无该项目
return 0;
}
if(p && key == le64(slot+8)) { // 找到项
int i = j;
for(; i < INT64_BUCKET_MAX_ITEM_SZ && le64(page+i*(8+8)); i++) {
#ifdef DEBUG
//printf("lookup %03d: %x\n", i, le64(page+i*(8+8)));
#endif
}
#ifdef DEBUG
printf("page: %x(%x), i: %d, p: %x\n", page, le64(page-8), i, p);
#endif
void *next_page = page, *prev_page;
while(i == INT64_BUCKET_MAX_ITEM_SZ) { // 本桶已满
int next = le64(next_page+PAGESZ-16); // 查看是否有溢出桶
if(!next) { // 无溢出桶, 将最后一个值搬移至slot并为其补0
// 不是最后一项, 搬移
if(j+1 != INT64_BUCKET_MAX_ITEM_SZ || next_page!=page) memcpy(slot, next_page-8-8-8-8, 8+8);
memset(next_page-8-8-8-8, 0, 8+8);
int r = sync_page(fd, next_page);
if(unlikely(r)) return r;
if(next_page!=page) {
r = sync_page(fd, page);
if(unlikely(r)) return r;
}
return p;
}
// 有溢出桶, 加载
prev_page = next_page;
#ifdef DEBUG
printf("%x have next bucket at: %x, ", le64(prev_page-8), next);
#endif
void* buf = index-8+INT64_INDEX_SZ-PAGESZ-8-PAGESZ-8;
#ifdef DEBUG
printf("buf: %p, ", buf);
fflush(stdout);
#endif
next_page = get_page(fd, next, buf);
#ifdef DEBUG
printf("next page: %p\n", next_page);
#endif
for(i = 0; i < INT64_BUCKET_MAX_ITEM_SZ && le64(next_page+i*(8+8)); i++);
#ifdef DEBUG
printf("new i: %d\n", i);
#endif
}
// 转至新桶第一个, 但发现为空, 即最后一项在上个桶末尾
if(!i) {
#ifdef DEBUG
puts("i == 0");
#endif
memcpy(slot, prev_page+PAGESZ-8-8-8-8, 8+8);
memset(prev_page+PAGESZ-8-8-8-8, 0, 8+8);
#ifdef DEBUG
printf("prev_page: %x(%x), page: %x(%x)\n", prev_page, le64(prev_page-8), page, le64(page-8));
printf("slot@%016x+%03d, last@%016x+339, ptr: %x, key: %x\n", le64(page-8), (slot-page)/12, le64(prev_page-8), le64(slot), le64(slot+8));
#endif
int r = sync_page(fd, prev_page);
if(unlikely(r)) return r;
if(prev_page!=page) {
r = sync_page(fd, page);
if(unlikely(r)) return r;
}
return p;
}
// 本桶未满
if(--i == j && page == next_page) { // 是最后一项, 直接删除
memset(slot, 0, 8+8);
int r = sync_page(fd, page);
if(unlikely(r)) return r;
return p;
}
// 不是最后一项, 搬移
memcpy(slot, next_page+i*(8+8), 8+8);
memset(next_page+i*(8+8), 0, 8+8);
int r = sync_page(fd, next_page);
if(unlikely(r)) return r;
if(next_page!=page) {
r = sync_page(fd, page);
if(unlikely(r)) return r;
}
#ifdef DEBUG
printf("slot@%016x+%03d, last@%016x+%03d\n", le64(page-8), (slot-page)/12, le64(next_page-8), i);
#endif
return p;
}
}
// 桶已满
p = le64(page+PAGESZ-16); // 查看是否有溢出桶
if(!p) { // 无溢出桶, 无该项目
return 0;
}
// 有溢出桶, 进入下一轮搜索
page = get_page(fd, p, index-8+INT64_INDEX_SZ-PAGESZ-8);
}
}