#include "kvstore.h" #include "kvs_rw_tools.h" #include "mem_pool/mem_pool.h" #include "diskuring/diskuring.h" // singleton kvs_array_t global_array = {0}; int kvs_array_create(kvs_array_t *inst) { if (!inst) return -1; if (inst->table) { printf("table has alloc\n"); return -1; } inst->table = kvs_malloc(KVS_ARRAY_SIZE * sizeof(kvs_array_item_t)); if (!inst->table) { return -1; } memset(inst->table, 0, (size_t)KVS_ARRAY_SIZE * sizeof(kvs_array_item_t)); inst->total = 0; return 0; } void kvs_array_destroy(kvs_array_t *inst) { if (!inst) return ; if (inst->table) { kvs_free(inst->table); } } /** * return: ==-2 not exist, == -1 error, >= 0 exist idx */ int kvs_array_find_index(kvs_array_t *inst, const void *key, uint32_t key_len) { if (!inst || !inst->table || !key) return -1; for (int i = 0; i < inst->total; i++) { kvs_array_item_t *it = &inst->table[i]; if (!it->key) continue; if (it->key_len == key_len && memcmp(it->key, key, key_len) == 0) { return i; } } return -2; // not found } /* * @return: <0 error; 0 success; 1 exist */ int kvs_array_set_bin(kvs_array_t *inst, const void *key, uint32_t key_len, const void *value, uint32_t value_len) { if (!inst || !inst->table || !key || key_len == 0 || !value) return -1; if (inst->total >= KVS_ARRAY_SIZE) return -1; int idx = kvs_array_find_index(inst, key, key_len); // -2 not exist if (idx >= 0) return 1; // exist if (idx == -1) return -1; // error uint8_t *kcopy = (uint8_t *)kvs_malloc(key_len); if (!kcopy) return -2; memcpy(kcopy, key, key_len); uint8_t *vcopy = NULL; if (value_len > 0) { vcopy = (uint8_t *)kvs_malloc(value_len); if (!vcopy) { kvs_free(kcopy); return -2; } memcpy(vcopy, value, value_len); } else { // 允许空 value(长度0),value 指针置 NULL vcopy = NULL; } int i = 0; for (i = 0;i < inst->total;i ++) { if (inst->table[i].key == NULL) { inst->table[i].key = kcopy; inst->table[i].key_len = key_len; inst->table[i].value = vcopy; inst->table[i].value_len = value_len; inst->total ++; return 0; } } if (i == inst->total && i < KVS_ARRAY_SIZE) { inst->table[i].key = kcopy; inst->table[i].key_len = key_len; inst->table[i].value = vcopy; inst->table[i].value_len = value_len; inst->total ++; } return 0; } /* * @return: NULL notexist, NOTNULL exist。out_value_len 是长度。 */ void *kvs_array_get_bin(kvs_array_t *inst, const void *key, uint32_t key_len, uint32_t *out_value_len) { if (out_value_len) *out_value_len = 0; if (!inst || !inst->table || !key || key_len == 0) return NULL; int idx = kvs_array_find_index(inst, key, key_len); if (idx < 0) return NULL; kvs_array_item_t *it = &inst->table[idx]; if (out_value_len) *out_value_len = it->value_len; return it->value; // 注意:由 store 持有 } /* * @return <0 error; =0 success; >0 no exist */ int kvs_array_del_bin(kvs_array_t *inst, const void *key, uint32_t key_len) { if (!inst || !inst->table || !key || key_len == 0) return -1; int idx = kvs_array_find_index(inst, key, key_len); if (idx == -2) return 1; // not exist if (idx < 0) return -1; kvs_array_item_t *it = &inst->table[idx]; if (it->key) kvs_free(it->key); if (it->value) kvs_free(it->value); // 用末尾元素填洞,保证 total 连续,避免 “total 只增不减” 问题 int last = inst->total - 1; if (idx != last) { inst->table[idx] = inst->table[last]; } // 清理末尾(已被移动或删除) memset(&inst->table[last], 0, sizeof(kvs_array_item_t)); inst->total--; return 0; } /* * @return < 0 error; =0 success; >0 no exist */ int kvs_array_mod_bin(kvs_array_t *inst, const void *key, uint32_t key_len, const void *value, uint32_t value_len) { if (!inst || !inst->table || !key || key_len == 0 || !value) return -1; int idx = kvs_array_find_index(inst, key, key_len); if (idx == -2) return 1; // not exist if (idx < 0) return -1; kvs_array_item_t *it = &inst->table[idx]; uint8_t *vcopy = NULL; if (value_len > 0) { vcopy = (uint8_t *)kvs_malloc(value_len); if (!vcopy) return -2; memcpy(vcopy, value, value_len); } else { vcopy = NULL; } if (it->value) kvs_free(it->value); it->value = vcopy; it->value_len = value_len; return 0; } /* * @return =0 exist, =1 no exist */ int kvs_array_exist_bin(kvs_array_t *inst, const void *key, uint32_t key_len) { if (!inst || !inst->table || !key || key_len == 0) return -1; int idx = kvs_array_find_index(inst, key, key_len); return (idx >= 0) ? 0 : 1; } // return: 0 success, <0 error int kvs_array_save(kvs_array_t *inst, const char* filename){ if(!inst || !filename) return -1; int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); if(fd < 0) return -2; off_t current_off = 0; for(int i = 0;i < inst->total; ++ i){ kvs_array_item_t *it = &inst->table[i]; if(!it->key || it->key_len == 0) continue; // 跳过空槽 if(it->value_len > 0 && !it->value) { close(fd); return -3; } uint32_t klen = htonl(it->key_len); uint32_t vlen = htonl(it->value_len); void *bufs[4]; size_t lens[4]; int count = 0; bufs[count] = &klen; lens[count] = sizeof(klen); count++; bufs[count] = &vlen; lens[count] = sizeof(vlen); count++; if (it->key_len > 0){ bufs[count] = it->key; lens[count] = it->key_len; count++; } if (it->value_len > 0) { bufs[count] = it->value; lens[count] = it->value_len; count++; } size_t total = 0; for (int i = 0; i < count; i++) total += lens[i]; task_t *t = submit_write(&global_uring_ctx, fd, bufs, lens, count, current_off); if (!t) { close(fd); return -4; } int res = task_wait(t); task_destroy(t); if (res < 0) { close(fd); return -5; } current_off += (off_t) total; } close(fd); return 0; } int kvs_array_load(kvs_array_t *inst, const char* filename) { if (!inst || !filename) return -1; if (!inst->table) return -1; FILE *fp = fopen(filename, "rb"); if (!fp) return -2; int idx = 0; while(1){ uint32_t klen_n = 0, vlen_n = 0; if (kvs_read_file(fp, &klen_n, 4) < 0) { fclose(fp); return -3; } if (kvs_read_file(fp, &vlen_n, 4) < 0) { fclose(fp); return -3; } uint32_t klen = ntohl(klen_n); uint32_t vlen = ntohl(vlen_n); if (klen == 0) { fclose(fp); return -3; } kvs_array_item_t *it = &inst->table[idx]; memset(it, 0, sizeof(*it)); it->key = (uint8_t *)kvs_malloc(klen); if (!it->key) { fclose(fp); return -3; } it->key_len = klen; if (kvs_read_file(fp, it->key, klen) < 0) { fclose(fp); return -3; } if (vlen > 0) { it->value = (uint8_t *)kvs_malloc(vlen); if (!it->value) { fclose(fp); return -4; } it->value_len = vlen; if (kvs_read_file(fp, it->value, vlen) < 0) { fclose(fp); return -3; } } else { it->value = NULL; it->value_len = 0; } inst->total ++; idx++; if(idx >= KVS_ARRAY_SIZE){ break; } } fclose(fp); return 0; }