mirror of
https://github.com/fumiama/fumidb.git
synced 2026-06-08 03:53:48 +08:00
int16
This commit is contained in:
39
src/page.c
39
src/page.c
@@ -14,8 +14,13 @@ static const uint8_t nullpage[PAGESZ];
|
||||
void* alloc_page(int fd, void* page) {
|
||||
uint64_t ptr = 8, prev_ptr = 0, prev_prev_ptr = 0;
|
||||
uint8_t buf[8];
|
||||
if(page == NULL) return NULL;
|
||||
// 对于 page,只关心位于第一页 8~15 字节的 ptr of unused blk
|
||||
while(ptr) {
|
||||
if(unlikely(ptr == prev_ptr)) { // 文件损坏
|
||||
errno = ESPIPE;
|
||||
return NULL;
|
||||
}
|
||||
if(!(ptr%PAGESZ)) { // 找到符合要求的页
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return NULL;
|
||||
if(read(fd, buf, 8) != 8) return NULL;
|
||||
@@ -46,7 +51,7 @@ void* alloc_page(int fd, void* page) {
|
||||
readle64(fd, ptr);
|
||||
}
|
||||
ptr = lseek(fd, 0, SEEK_END);
|
||||
if(ptr < 0) return NULL;
|
||||
if((int)ptr < 0) return NULL;
|
||||
if(ptr%PAGESZ) { // 文件没有页对齐
|
||||
errno = ESPIPE;
|
||||
return NULL;
|
||||
@@ -57,6 +62,7 @@ void* alloc_page(int fd, void* page) {
|
||||
}
|
||||
|
||||
void* get_page(int fd, uint64_t ptr, void* page) {
|
||||
if(page == NULL) return NULL;
|
||||
if(ptr%PAGESZ) return NULL;
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return NULL;
|
||||
putle64(page, ptr);
|
||||
@@ -66,16 +72,21 @@ void* get_page(int fd, uint64_t ptr, void* page) {
|
||||
}
|
||||
|
||||
int sync_page(int fd, void* page) {
|
||||
if(page == NULL) return EOF;
|
||||
uint64_t ptr = le64(page-8);
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
|
||||
return write(fd, page, PAGESZ) != PAGESZ;
|
||||
}
|
||||
|
||||
int free_page(int fd, void* page) {
|
||||
if(page == NULL) return EOF;
|
||||
uint64_t ptr = 8, prev_ptr = 0, prev_prev_ptr = 0, page_ptr = le64(page-8);
|
||||
uint8_t buf[8];
|
||||
while(ptr && ptr < page_ptr) {
|
||||
if(prev_ptr == ptr) return EOF;
|
||||
if(unlikely(ptr == prev_ptr)) { // 文件损坏
|
||||
errno = ESPIPE;
|
||||
return EOF;
|
||||
}
|
||||
if(prev_prev_ptr && ptr < prev_ptr) { // 不符合顺序,进行一次调整
|
||||
lseek(fd, prev_prev_ptr, SEEK_SET);
|
||||
putle64(buf, ptr);
|
||||
@@ -110,11 +121,16 @@ void* alloc_block(int fd, uint16_t size, void* blk) {
|
||||
uint8_t buf[8];
|
||||
uint16_t blksz;
|
||||
|
||||
if(blk == NULL) return NULL;
|
||||
if(size > PAGESZ) return NULL;
|
||||
// 对于 page,只关心位于第一页 8~15 字节的 ptr of unused blk
|
||||
while(ptr) {
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return NULL;
|
||||
if(read(fd, buf, 8) != 8) return NULL;
|
||||
if(unlikely(lseek(fd, ptr, SEEK_SET) < 0)) return NULL;
|
||||
if(unlikely(read(fd, buf, 8) != 8)) return NULL;
|
||||
if(unlikely(ptr == prev_ptr)) { // 文件损坏
|
||||
errno = ESPIPE;
|
||||
return NULL;
|
||||
}
|
||||
readle16(fd, blksz);
|
||||
if(blksz >= size) { // 找到符合要求的块
|
||||
if(blksz - size > 10) { // 分裂块
|
||||
@@ -153,7 +169,7 @@ void* alloc_block(int fd, uint16_t size, void* blk) {
|
||||
readle64(fd, ptr);
|
||||
}
|
||||
ptr = lseek(fd, 0, SEEK_END);
|
||||
if(ptr < 0) return NULL;
|
||||
if((int)ptr < 0) return NULL;
|
||||
if(ptr%PAGESZ) { // 文件没有页对齐
|
||||
errno = ESPIPE;
|
||||
return NULL;
|
||||
@@ -173,6 +189,7 @@ void* alloc_block(int fd, uint16_t size, void* blk) {
|
||||
}
|
||||
|
||||
void* get_block(int fd, uint16_t size, uint64_t ptr, void* blk) {
|
||||
if(blk == NULL) return NULL;
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return NULL;
|
||||
putle64(blk, ptr);
|
||||
putle16(blk+8, size);
|
||||
@@ -182,6 +199,7 @@ void* get_block(int fd, uint16_t size, uint64_t ptr, void* blk) {
|
||||
}
|
||||
|
||||
int sync_block(int fd, void* blk) {
|
||||
if(blk == NULL) return EOF;
|
||||
uint64_t off = le64(blk-10);
|
||||
uint16_t size = le16(blk-2);
|
||||
if(size > PAGESZ) {
|
||||
@@ -193,11 +211,15 @@ int sync_block(int fd, void* blk) {
|
||||
}
|
||||
|
||||
int free_block(int fd, void* blk) {
|
||||
if(blk == NULL) return EOF;
|
||||
uint64_t ptr = 8, prev_ptr = 0, prev_prev_ptr = 0, off = le64(blk-10);
|
||||
uint8_t buf[8];
|
||||
uint16_t size = le16(blk-2), sz;
|
||||
while(ptr && ptr < off) {
|
||||
if(prev_ptr == ptr) return EOF;
|
||||
if(unlikely(ptr == prev_ptr)) { // 文件损坏
|
||||
errno = ESPIPE;
|
||||
return EOF;
|
||||
}
|
||||
if(prev_prev_ptr && ptr < prev_ptr) { // 不符合顺序,进行一次调整
|
||||
lseek(fd, prev_prev_ptr, SEEK_SET);
|
||||
putle64(buf, ptr);
|
||||
@@ -247,7 +269,10 @@ int add_block(int fd, uint16_t size, uint64_t off) {
|
||||
uint8_t buf[8];
|
||||
uint16_t sz;
|
||||
while(ptr && ptr < off) {
|
||||
if(prev_ptr == ptr) return EOF;
|
||||
if(unlikely(ptr == prev_ptr)) { // 文件损坏
|
||||
errno = ESPIPE;
|
||||
return EOF;
|
||||
}
|
||||
if(prev_prev_ptr && ptr < prev_ptr) { // 不符合顺序,进行一次调整
|
||||
lseek(fd, prev_prev_ptr, SEEK_SET);
|
||||
putle64(buf, ptr);
|
||||
|
||||
61
src/types.c
61
src/types.c
@@ -1,16 +1,21 @@
|
||||
#include "../include/types.h"
|
||||
#include "../include/types/int8.h"
|
||||
#include "../include/types/int16.h"
|
||||
|
||||
// ptr = init(fd)
|
||||
typedef void* (*_type_init_t)(int, void*);
|
||||
// ptr = load(fd, ptr)
|
||||
typedef void* (*_type_load_t)(int, uint64_t, void*);
|
||||
// ret = rm(fd, index)
|
||||
typedef int (*_type_remove_t)(int, void*);
|
||||
// n = count(fd, index)
|
||||
typedef uint64_t (*_type_count_t)(int, void*);
|
||||
// ret = insert_item(fd, index, k, ptr)
|
||||
typedef int (*_insert_item_t)(int, void*, key_t, uint64_t);
|
||||
// ptr = find_by_key(fd, index, k)
|
||||
typedef uint64_t (*_find_by_key_t)(int, void*, key_t);
|
||||
// ret = remove_by_key(fd, index, k)
|
||||
typedef int (*_remove_by_key_t)(int, void*, key_t);
|
||||
typedef uint64_t (*_remove_by_key_t)(int, void*, key_t);
|
||||
|
||||
// Function not implemented
|
||||
static void* create_not_impl_index(int fd, void* buf) {
|
||||
@@ -24,6 +29,18 @@ static void* load_not_impl_index(int fd, uint64_t ptr, void* buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Function not implemented
|
||||
static int remove_not_impl_index(int fd, void* index) {
|
||||
errno = ENOSYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Function not implemented
|
||||
static uint64_t count_not_impl_items(int fd, void* index) {
|
||||
errno = ENOSYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Function not implemented
|
||||
static int insert_not_impl_item(int fd, void* index, key_t k, uint64_t ptr) {
|
||||
errno = ENOSYS;
|
||||
@@ -37,14 +54,14 @@ static uint64_t find_item_by_not_impl_key(int fd, void* index, key_t k) {
|
||||
}
|
||||
|
||||
// Function not implemented
|
||||
static int remove_item_by_not_impl_key(int fd, void* index, key_t k) {
|
||||
static uint64_t remove_item_by_not_impl_key(int fd, void* index, key_t k) {
|
||||
errno = ENOSYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static _type_init_t _types_init[] = {
|
||||
create_int8_index,
|
||||
create_not_impl_index,
|
||||
create_int16_index,
|
||||
create_not_impl_index,
|
||||
create_not_impl_index,
|
||||
create_not_impl_index,
|
||||
@@ -54,7 +71,7 @@ static _type_init_t _types_init[] = {
|
||||
|
||||
static _type_load_t _types_load[] = {
|
||||
load_int8_index,
|
||||
load_not_impl_index,
|
||||
load_int16_index,
|
||||
load_not_impl_index,
|
||||
load_not_impl_index,
|
||||
load_not_impl_index,
|
||||
@@ -62,9 +79,29 @@ static _type_load_t _types_load[] = {
|
||||
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_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_not_impl_items
|
||||
};
|
||||
|
||||
static _insert_item_t _insert_item[] = {
|
||||
insert_int8_item,
|
||||
insert_not_impl_item,
|
||||
insert_int16_item,
|
||||
insert_not_impl_item,
|
||||
insert_not_impl_item,
|
||||
insert_not_impl_item,
|
||||
@@ -74,7 +111,7 @@ static _insert_item_t _insert_item[] = {
|
||||
|
||||
static _find_by_key_t _find_item_by_key[] = {
|
||||
find_item_by_int8_key,
|
||||
find_item_by_not_impl_key,
|
||||
find_item_by_int16_key,
|
||||
find_item_by_not_impl_key,
|
||||
find_item_by_not_impl_key,
|
||||
find_item_by_not_impl_key,
|
||||
@@ -84,7 +121,7 @@ static _find_by_key_t _find_item_by_key[] = {
|
||||
|
||||
static _remove_by_key_t _remove_item_by_key[] = {
|
||||
remove_item_by_int8_key,
|
||||
remove_item_by_not_impl_key,
|
||||
remove_item_by_int16_key,
|
||||
remove_item_by_not_impl_key,
|
||||
remove_item_by_not_impl_key,
|
||||
remove_item_by_not_impl_key,
|
||||
@@ -100,6 +137,14 @@ void* load_index(int fd, type_t t, uint64_t ptr, void* buf) {
|
||||
return _types_load[t&7](fd, ptr, buf);
|
||||
}
|
||||
|
||||
int remove_index(int fd, type_t t, void* index) {
|
||||
return _types_remove[t&7](fd, index);
|
||||
}
|
||||
|
||||
uint64_t count_items(int fd, type_t t, void* index) {
|
||||
return _types_count[t&7](fd, index);
|
||||
}
|
||||
|
||||
int insert_item(int fd, type_t t, void* index, key_t k, uint64_t ptr) {
|
||||
return _insert_item[t&7](fd, index, k, ptr);
|
||||
}
|
||||
@@ -108,6 +153,6 @@ uint64_t find_item_by_key(int fd, type_t t, void* index, key_t k) {
|
||||
return _find_item_by_key[t&7](fd, index, k);
|
||||
}
|
||||
|
||||
int remove_item_by_key(int fd, type_t t, void* index, key_t k) {
|
||||
uint64_t remove_item_by_key(int fd, type_t t, void* index, key_t k) {
|
||||
return _remove_item_by_key[t&7](fd, index, k);
|
||||
}
|
||||
|
||||
420
src/types/int16.c
Normal file
420
src/types/int16.c
Normal file
@@ -0,0 +1,420 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "../../include/binary.h"
|
||||
#include "../../include/page.h"
|
||||
#include "../../include/types/int16.h"
|
||||
|
||||
// len(buf) >= INT16_INDEX_SZ+10 + INT16_BITMAP_SZ+8*2 = 10290
|
||||
// &buf[0] ~ &buf[2081] is index, index = buf+10
|
||||
// &buf[2082] ~ &buf[6185] is the first page of bitmap, ptr = buf+2090
|
||||
// &buf[6186] ~ &buf[10289] is the second page of bitmap, ptr = buf+6194
|
||||
// 返回:index = buf+10
|
||||
void* create_int16_index(int fd, void* buf) {
|
||||
buf = alloc_block(fd, INT16_INDEX_SZ, buf);
|
||||
if(buf == NULL) return NULL;
|
||||
memset(buf, 0, INT16_INDEX_SZ);
|
||||
|
||||
void* page = alloc_page(fd, buf+INT16_INDEX_SZ);
|
||||
if(page == NULL) {
|
||||
free_block(fd, buf);
|
||||
return NULL;
|
||||
}
|
||||
memset(page, 0, PAGESZ);
|
||||
sync_page(fd, page);
|
||||
|
||||
void* page2 = alloc_page(fd, page+PAGESZ);
|
||||
if(page2 == NULL) {
|
||||
free_block(fd, buf);
|
||||
free_page(fd, page);
|
||||
return NULL;
|
||||
}
|
||||
memset(page2, 0, PAGESZ);
|
||||
sync_page(fd, page2);
|
||||
|
||||
putle64(buf, le64(page-8));
|
||||
putle64(buf+8, le64(page2-8));
|
||||
sync_block(fd, buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// len(buf) >= INT16_INDEX_SZ+10 + INT16_BITMAP_SZ+8*2 = 10290
|
||||
// &buf[0] ~ &buf[2081] is index, index = buf+10
|
||||
// &buf[2082] ~ &buf[6185] is the first page of bitmap, ptr = buf+2090
|
||||
// &buf[6186] ~ &buf[10289] is the second page of bitmap, ptr = buf+6194
|
||||
// 返回:index = buf+10
|
||||
void* load_int16_index(int fd, uint64_t ptr, void* buf) {
|
||||
buf = get_block(fd, INT16_INDEX_SZ, ptr, buf);
|
||||
if(get_page(fd, le64(buf+8), get_page(fd, le64(buf), buf+INT16_INDEX_SZ)+PAGESZ) == NULL) return NULL;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int remove_int16_index(int fd, void* index) {
|
||||
uint64_t ptr = le64(index+16); // 链表头
|
||||
while(ptr) {
|
||||
uint64_t tmp;
|
||||
if(unlikely(lseek(fd, ptr, SEEK_SET) < 0)) return EOF;
|
||||
readle64(fd, tmp);
|
||||
add_block(fd, INT16_CHAIN_SZ, ptr);
|
||||
ptr = tmp;
|
||||
}
|
||||
if(free_page(fd, index+INT16_INDEX_SZ+8)) return 2; // 第一页位图
|
||||
if(free_page(fd, index+INT16_INDEX_SZ+8+PAGESZ+8)) return 3; // 第二页位图
|
||||
return free_block(fd, index); // 位图索引
|
||||
}
|
||||
|
||||
uint64_t count_int16_items(int fd, void* index) {
|
||||
int total = 0;
|
||||
// 计算总的条目数
|
||||
for(int i = 0; i < 128; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8))[i*32])) {
|
||||
total += 256;
|
||||
continue;
|
||||
}
|
||||
total += s;
|
||||
}
|
||||
for(int i = 128; i < 256; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8+8))[i*32])) {
|
||||
total += 256;
|
||||
continue;
|
||||
}
|
||||
total += s;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
int insert_int16_item(int fd, void* index, key_t k, uint64_t ptr) {
|
||||
int isexist, sum = 0, total = count_int16_items(fd, index);
|
||||
uint16_t key = (uint16_t)k;
|
||||
char buf[8];
|
||||
char tmp[10+INT16_CHAIN_SZ];
|
||||
putle64(buf, ptr);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("No.%u: ", (int)key);
|
||||
#endif
|
||||
|
||||
if(key < 32768) {
|
||||
// key是否已存在
|
||||
isexist = ((uint8_t*)(index+INT16_INDEX_SZ+8))[key/8] & (128>>(key%8));
|
||||
// 查找 key 之前共有多少索引
|
||||
for(int i = key/256*32; i < key/8; i++) { // 从未计算的32位组开始算起
|
||||
sum += __builtin_popcount(((uint8_t*)(index+INT16_INDEX_SZ+8))[i]);
|
||||
}
|
||||
sum += __builtin_popcount(((uint8_t*)(index+INT16_INDEX_SZ+8))[key/8] & ~(0xff>>(key%8)));
|
||||
#ifdef DEBUG
|
||||
printf("popc: %d, ", sum);
|
||||
#endif
|
||||
for(int i = 0; i < key/256; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("sum: %d, totl: %d, ", sum, total);
|
||||
#endif
|
||||
} else {
|
||||
// key是否已存在
|
||||
isexist = ((uint8_t*)(index+INT16_INDEX_SZ+8+8))[key/8] & (128>>(key%8));
|
||||
// 查找 key 之前共有多少索引
|
||||
for(int i = key/256*32; i < key/8; i++) { // 从未计算的32位组开始算起
|
||||
sum += __builtin_popcount(((uint8_t*)(index+INT16_INDEX_SZ+8+8))[i]);
|
||||
}
|
||||
sum += __builtin_popcount(((uint8_t*)(index+INT16_INDEX_SZ+8+8))[key/8] & ~(0xff>>(key%8)));
|
||||
#ifdef DEBUG
|
||||
printf("popc: %d, ", sum);
|
||||
#endif
|
||||
for(int i = 0; i < 128; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
for(int i = 128; i < key/256; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("sum: %d, totl: %d, ", sum, total);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!isexist) {
|
||||
// 写入位图
|
||||
if(key<32768) {
|
||||
((uint8_t*)(index+INT16_INDEX_SZ+8))[key/8] |= 128>>(key%8);
|
||||
if(unlikely(sync_page(fd, index+INT16_INDEX_SZ+8))) { // 失败,撤销更改
|
||||
((uint8_t*)(index+INT16_INDEX_SZ+8))[key/8] &= ~(128>>(key%8));
|
||||
return EOF;
|
||||
}
|
||||
} else {
|
||||
((uint8_t*)(index+INT16_INDEX_SZ+8+8))[key/8] |= 128>>(key%8);
|
||||
if(unlikely(sync_page(fd, index+INT16_INDEX_SZ+8+PAGESZ+8))) { // 失败,撤销更改
|
||||
((uint8_t*)(index+INT16_INDEX_SZ+8+8))[key/8] &= ~(128>>(key%8));
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
((uint8_t*)(index+24))[key/256]++; // 写入位图索引
|
||||
if(unlikely(sync_block(fd, index))) { // 失败,撤销更改
|
||||
((uint8_t*)(index+24))[key/256]--;
|
||||
return EOF;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("i: %d, sumblk: %d, map: %02x, ", key/256, ((uint8_t*)(index+24))[key/256], ((uint8_t*)(index+INT16_INDEX_SZ+8+((key<32768)?0:8)))[key/8]);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(unlikely(!le64(index+16))) { // 插入的是本索引的第一个值
|
||||
if(alloc_block(fd, INT16_CHAIN_SZ, tmp) == NULL) return EOF;
|
||||
memcpy(index+16, tmp, 8); // 记录第一个链表的指针
|
||||
sync_block(fd, index); // 同步索引到文件
|
||||
memset(tmp+10, 0, INT16_CHAIN_SZ); // 清空
|
||||
memcpy(tmp+10+8, buf, 8); // 写入 item 位置
|
||||
return sync_block(fd, tmp+10); // 同步链表到文件
|
||||
}
|
||||
|
||||
if(isexist) { // 索引已存在,仅替换指针
|
||||
ptr = le64(index+16);
|
||||
for(int i = 0; i < sum/256; i++) {
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
|
||||
readle64(fd, ptr);
|
||||
if(unlikely(!ptr)) {
|
||||
errno = ESPIPE;
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
lseek(fd, 8*(sum%256+1), SEEK_CUR);
|
||||
#ifdef DEBUG
|
||||
puts("replace");
|
||||
#endif
|
||||
return write(fd, buf, 8) != 8;
|
||||
}
|
||||
|
||||
// 索引不存在,需要搬移,统一向后移一个指针
|
||||
uint64_t prev_ptr, first_ptr = 1;
|
||||
ptr = le64(index+16);
|
||||
if(total%256 == 255) { // 旧链表刚好装满,需要新分配一个
|
||||
while(ptr && first_ptr) { // 遍历到末尾
|
||||
prev_ptr = ptr;
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
|
||||
readle64(fd, ptr);
|
||||
readle64(fd, first_ptr);
|
||||
if(unlikely(ptr == prev_ptr)) { // 文件损坏
|
||||
errno = ESPIPE;
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
if(first_ptr) { // 需要分配
|
||||
if(alloc_block(fd, INT16_CHAIN_SZ, tmp) == NULL) return EOF;
|
||||
lseek(fd, prev_ptr, SEEK_SET);
|
||||
write(fd, tmp, 8); // 将新分配的块附加到链表
|
||||
prev_ptr = ptr;
|
||||
ptr = le64(tmp);
|
||||
memset(tmp+10, 0, INT16_CHAIN_SZ); // 清空新链表
|
||||
sync_block(fd, tmp+10);
|
||||
}
|
||||
// 存在之前分配好的,但是由于删除索引而弃用的块,因此无需新分配
|
||||
}
|
||||
if(sum == total) { // 恰好在最后添加
|
||||
while(ptr && first_ptr) { // 遍历到末尾
|
||||
prev_ptr = ptr;
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
|
||||
readle64(fd, ptr);
|
||||
readle64(fd, first_ptr);
|
||||
if(unlikely(ptr == prev_ptr)) { // 文件损坏
|
||||
errno = ESPIPE;
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
// 定位到最后一个未满块或第一个空块上的最后
|
||||
lseek(fd, prev_ptr+8*(sum%256+1), SEEK_SET);
|
||||
#ifdef DEBUG
|
||||
puts("append");
|
||||
#endif
|
||||
return write(fd, buf, 8) != 8; // 写入
|
||||
}
|
||||
// 定位回链表头
|
||||
lseek(fd, le64(index+16), SEEK_SET);
|
||||
// 跳转到应当存入的块
|
||||
for(int i = 0; i < sum/256; i++) {
|
||||
readle64(fd, ptr);
|
||||
if(unlikely(!ptr)) {
|
||||
errno = ESPIPE;
|
||||
return EOF; // 不应当出现,如果出现说明文件损坏
|
||||
}
|
||||
lseek(fd, ptr, SEEK_SET);
|
||||
}
|
||||
// 搬移
|
||||
int offset = sum%256; // 搬移开始的位置,也是应当存入的位置
|
||||
readle64(fd, ptr); // 下一个块指针
|
||||
#ifdef DEBUG
|
||||
printf("off: %d, ", offset);
|
||||
#endif
|
||||
if(offset) { // 具有偏移,先定位到偏移
|
||||
lseek(fd, offset*8, SEEK_CUR);
|
||||
}
|
||||
readle64(fd, prev_ptr); // 读取第一个 item 指针
|
||||
#ifdef DEBUG
|
||||
printf("first item: %llu\n", prev_ptr);
|
||||
#endif
|
||||
lseek(fd, -8, SEEK_CUR); // 返回
|
||||
write(fd, buf, 8); // 插入
|
||||
while(prev_ptr) { // 一直搬移到末尾
|
||||
if(unlikely(offset && !(offset++%256))) { // 进入新的块
|
||||
lseek(fd, ptr, SEEK_SET);
|
||||
readle64(fd, first_ptr); // 下一个块指针
|
||||
if(unlikely(first_ptr == ptr)) { // 文件损坏
|
||||
errno = ESPIPE;
|
||||
return EOF;
|
||||
}
|
||||
ptr = first_ptr;
|
||||
}
|
||||
putle64(buf, prev_ptr); // 以备写入
|
||||
readle64(fd, prev_ptr); // 读取下一个 item 指针
|
||||
lseek(fd, -8, SEEK_CUR); // 返回
|
||||
write(fd, buf, 8); // 搬移一个指针
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t find_item_by_int16_key(int fd, void* index, key_t k) {
|
||||
uint64_t ptr;
|
||||
uint16_t key = (uint16_t)k;
|
||||
uint16_t sum;
|
||||
if(key < 32768) {
|
||||
int isexist = ((uint8_t*)(index+INT16_INDEX_SZ+8))[key/8] & (128>>(key%8));
|
||||
if(!isexist) return 0;
|
||||
sum = __builtin_popcount(((uint8_t*)(index+INT16_INDEX_SZ+8))[key/8] & ~(0xff>>(key%8)));
|
||||
for(int i = 0; i < key/256; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
} else {
|
||||
int isexist = ((uint8_t*)(index+INT16_INDEX_SZ+8+8))[key/8] & (128>>(key%8));
|
||||
if(!isexist) return 0;
|
||||
sum = __builtin_popcount(((uint8_t*)(index+INT16_INDEX_SZ+8+8))[key/8] & ~(0xff>>(key%8)));
|
||||
for(int i = 0; i < 128; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
for(int i = 128; i < key/256; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
}
|
||||
ptr = le64(index+16);
|
||||
for(int i = 0; i < sum/256 && ptr; i++) {
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
|
||||
readle64(fd, ptr);
|
||||
}
|
||||
if(!ptr) return EOF;
|
||||
ptr += 8*(sum%256+1);
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
|
||||
readle64(fd, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint64_t remove_item_by_int16_key(int fd, void* index, key_t k) {
|
||||
uint64_t ptr;
|
||||
uint16_t key = (uint16_t)k;
|
||||
uint16_t sum;
|
||||
char buf[8];
|
||||
if(key < 32768) {
|
||||
int isexist = ((uint8_t*)(index+INT16_INDEX_SZ+8))[key/8] & (128>>(key%8));
|
||||
if(!isexist) return 0;
|
||||
sum = __builtin_popcount(((uint8_t*)(index+INT16_INDEX_SZ+8))[key/8] & ~(0xff>>(key%8)));
|
||||
for(int i = 0; i < key/256; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
} else {
|
||||
int isexist = ((uint8_t*)(index+INT16_INDEX_SZ+8+8))[key/8] & (128>>(key%8));
|
||||
if(!isexist) return 0;
|
||||
sum = __builtin_popcount(((uint8_t*)(index+INT16_INDEX_SZ+8+8))[key/8] & ~(0xff>>(key%8)));
|
||||
for(int i = 0; i < 128; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
for(int i = 128; i < key/256; i++) {
|
||||
int s = ((uint8_t*)(index+24))[i];
|
||||
if(unlikely(!s && ((uint8_t*)(index+INT16_INDEX_SZ+8+8))[i*32])) {
|
||||
sum += 256;
|
||||
continue;
|
||||
}
|
||||
sum += s;
|
||||
}
|
||||
}
|
||||
ptr = le64(index+16);
|
||||
for(int i = 0; i < sum/256 && ptr; i++) {
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
|
||||
readle64(fd, ptr);
|
||||
}
|
||||
if(!ptr) return EOF;
|
||||
|
||||
int offset = sum%256;
|
||||
uint64_t cur_ptr = ptr+8*(offset+1), next_ptr, first_ptr = 0;
|
||||
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
|
||||
readle64(fd, next_ptr);
|
||||
lseek(fd, cur_ptr, SEEK_SET); // 回到开头
|
||||
readle64(fd, ptr); // 返回值
|
||||
cur_ptr += 8;
|
||||
|
||||
do { // 一直循环到末尾
|
||||
if(unlikely(offset++%256 == 255)) { // 当前位于末尾,需要从下一页取值
|
||||
// 换下一页
|
||||
if(lseek(fd, next_ptr+8, SEEK_SET) < 0) return EOF;
|
||||
readle64(fd, first_ptr); // 读后一个值
|
||||
// 回上一页
|
||||
lseek(fd, cur_ptr, SEEK_SET);
|
||||
putle64(buf, first_ptr);
|
||||
write(fd, buf, 8); // 覆盖
|
||||
// 换下一页
|
||||
cur_ptr = lseek(fd, next_ptr, SEEK_SET)+8;
|
||||
readle64(fd, next_ptr);
|
||||
lseek(fd, 8, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
// 当前后方至少还有一个指针,可以直接取值
|
||||
readle64(fd, first_ptr); // 读下一个值
|
||||
lseek(fd, -16, SEEK_CUR); // 回原处
|
||||
putle64(buf, first_ptr);
|
||||
write(fd, buf, 8); // 覆盖
|
||||
cur_ptr += 8;
|
||||
lseek(fd, 8, SEEK_CUR);
|
||||
} while(first_ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@@ -16,6 +16,16 @@ void* load_int8_index(int fd, uint64_t ptr, void* buf) {
|
||||
return get_block(fd, INT8_INDEX_SZ, ptr, buf);
|
||||
}
|
||||
|
||||
int remove_int8_index(int fd, void* index) {
|
||||
return free_block(fd, index);
|
||||
}
|
||||
|
||||
uint64_t count_int8_items(int fd, void* index) {
|
||||
uint64_t cnt = 0;
|
||||
for(int i = 0; i < 256; i++) cnt += !!(((uint64_t*)index)[i]);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int insert_int8_item(int fd, void* index, key_t k, uint64_t ptr) {
|
||||
uint8_t key = (uint8_t)k;
|
||||
((uint64_t*)index)[key] = ptr;
|
||||
@@ -27,8 +37,9 @@ uint64_t find_item_by_int8_key(int fd, void* index, key_t k) {
|
||||
return ((uint64_t*)index)[key];
|
||||
}
|
||||
|
||||
int remove_item_by_int8_key(int fd, void* index, key_t k) {
|
||||
uint64_t remove_item_by_int8_key(int fd, void* index, key_t k) {
|
||||
uint8_t key = (uint8_t)k;
|
||||
uint64_t ptr = ((uint64_t*)index)[key];
|
||||
((uint64_t*)index)[key] = 0;
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user