Skip to content
Snippets Groups Projects
Unverified Commit f6fc3659 authored by Dmitriy A. Gerasimov's avatar Dmitriy A. Gerasimov Committed by GitHub
Browse files

Merge pull request #4 from cellframe/feature-2304-beta

Feature 2304
parents 739a61ab a0559816
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,7 @@ file(GLOB DAP_CHAIN_GLOBAL_DB_HDR *.h)
add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_GLOBAL_DB_SRC} ${DAP_CHAIN_GLOBAL_DB_HDR})
target_link_libraries(dap_chain_global_db dap_core dap_crypto dap_chain dap_chain_crypto ldb talloc tevent sqlite3)
target_link_libraries(dap_chain_global_db dap_core dap_crypto dap_chain dap_chain_crypto ldb talloc tevent sqlite3 ${CMAKE_CURRENT_SOURCE_DIR}/libcuttdb.a)
target_include_directories(dap_chain_global_db INTERFACE .)
set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
......
cuttdb.h 0 → 100644
/*
* CuttDB - a fast key-value storage engine
*
*
* http://code.google.com/p/cuttdb/
*
* Copyright (c) 2012, Siyuan Fu. All rights reserved.
* Use and distribution licensed under the BSD license.
* See the LICENSE file for full text
*
* Author: Siyuan Fu <fusiyuan2010@gmail.com>
*
*/
#ifndef _CUTTDB_H_
#define _CUTTDB_H_
#include <stdint.h>
#include <stdbool.h>
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct CDB CDB;
typedef void (*CDB_ERRCALLBACK)(void *, int, const char *, int);
typedef bool (*CDB_ITERCALLBACK)(void *, const char *, int, const char *, int, uint32_t, uint64_t);
/* performance statistical information of an database instance */
typedef struct {
/* number of records in db */
uint64_t rnum;
/* number of records in cache */
uint64_t rcnum;
/* number of pages in db */
uint64_t pnum;
/* number of pages in cache */
uint64_t pcnum;
/* cache hit of record cache */
uint64_t rchit;
/* cache miss of record cache */
uint64_t rcmiss;
/* cache hit of page cache */
uint64_t pchit;
/* cache miss of page cache */
uint64_t pcmiss;
/* average disk read latency */
uint32_t rlatcy;
/* average disk write latency */
uint32_t wlatcy;
} CDBSTAT;
/* options to open a database*/
enum {
/* create an database if not exist */
CDB_CREAT = 0x1,
/* clean the database if already exist */
CDB_TRUNC = 0x2,
/* fill the cache when start up */
CDB_PAGEWARMUP = 0x4,
};
/* error codes */
enum {
CDB_SUCCESS = 0,
CDB_NOTFOUND,
CDB_EXIST,
CDB_DIRNOEXIST,
CDB_OPENERR,
CDB_PIDEXIST,
CDB_DATAERRDAT,
CDB_DATAERRIDX,
CDB_WRITEERR,
CDB_READERR,
CDB_NOFID,
CDB_INTERNALERR,
CDB_DATAERRMETA,
CDB_MEMDBNOCACHE,
};
/* record insertion options */
enum {
CDB_OVERWRITE = 0,
CDB_INSERTIFEXIST = 0x1,
CDB_INSERTIFNOEXIST = 0x2,
CDB_INSERTCACHE = 0x8,
};
/* if database path is CDB_MEMDB, records are never written to disk, they stay in cache only */
#define CDB_MEMDB ":memory:"
/*
WARNING:
the library has auxiliary thread, which means do fork() after open a database will cause
unpredictable situation.
*/
/* create an cuttdb object, which should be freed by cdb_destory() */
CDB *cdb_new();
/* cdb_option() must be called before cdb_open()
the second parameter 'hsize' indicates the size of main hash table, which can't be
modified after the database be created. To get better performance, it is suggest to
set the 'hsize' to 10% - 1% of the total number of records. The default value 1 million
should be proper for about 100 million records. Too large or small of the value would
lead to drop in speed or waste of memory
the third parameter 'rcacheMB' indicates the size limit of record cache (measured by
MegaBytes), every record in cache would have about 40 bytes overhead.
the fourth parameter 'pcacheMB' indicates the size limit of index page cache (measured
by MegaBytes). If a record is not in record cache, it will be read by only 1 disk seek
with enough page cache, or it have to make an extra disk seek to load the page.
cuttdb will use about {10 * number of records} bytes to cache all index pages, which
ensures fastest 'set' operation.
the default parameter is (_db, 1000000, 128, 1024)
return 0 if success, or -1 at failure. */
int cdb_option(CDB *db, int hsize, int rcacheMB, int pcacheMB);
/* Enable bloomfilter, size should be the estimated number of records in database
must be called before cdb_open(),
The value is 100000 at minimum. Memory cost of bloomfilter is size/8 bytes */
void cdb_option_bloomfilter(CDB *db, uint64_t size);
/* this is an advanced parameter. It is the size for cuttdb making a read from disk.
CuttDB do not know the record size even if the index is in memory,
so at least a read with default size will performed while in cdb_get().
The value is recommended to be larger than the size of most records in database,
unless the records are mostly larger than tens of KB.
If the value is much larger than recommended, it will be a waste of computing.
The value can only be 65536 at maximum, 1024 at minimum */
void cdb_option_areadsize(CDB *db, uint32_t size);
/* open an database, 'file' should be an existing directory, or CDB_MEMDB for temporary store,
'mode' should be combination of CDB_CREAT / CDB_TRUNC / CDB_PAGEWARMUP
CDB_PAGEWARMUP means to warm up page cache while opening
If there is a file called 'force_recovery' in the data directory, even if it might be made by 'touch force_recovery',
a force recovery will happen to rebuild the index (be aware that some deleted records would reappear after this)
*/
int cdb_open(CDB *db, const char *file, int mode);
/* simplified cdb_set2, insert a record with CDB_OVERWRITE and never expire */
int cdb_set(CDB *db, const char *key, int ksize, const char *val, int vsize);
/* set a record by 'key' and 'value',
opt could be bit combination of CDB_INSERTCACHE and one in {CDB_INSERTIFEXIST, CDB_INSERTNOEXIST,
CDB_OVERWRITE}
expire is the time for the record be valid, measured by second. 0 means never expire.
return 0 if success, or -1 at failure. */
int cdb_set2(CDB *db, const char *key, int ksize, const char *val, int vsize, int opt, int expire);
/* get an record by 'key', the value will be allocated and passed out by 'val', its size is
'vsize'. return 0 if success, or -1 at failure. */
int cdb_get(CDB *db, const char *key, int ksize, void **val, int *vsize);
/* the val got by cdb_get should be freed by this for safety.
If there is more than one memory allocator */
void cdb_free_val(void **val);
/* delete an record by 'key'. However ,the space of the record would not be recycled.
'vsize'. return 0 if success, or -1 at failure. */
int cdb_del(CDB *db, const char *key, int ksize);
/* create a new iterator begins at given operation id */
void *cdb_iterate_new(CDB *db, uint64_t oid);
/* iterate through the database with a callback, the function would stop if callback returned false
The callback should accept key, ksize, value, vsize, expire time, oid
Returns the number of records have been visited */
uint64_t cdb_iterate(CDB *db, CDB_ITERCALLBACK itcb, void *arg, void *iter);
/* destroy the iterator */
void cdb_iterate_destroy(CDB *db, void *iter);
/* get the current statistic information of db. 'stat' should be the struct already allocated.
if 'stat' is NULL, the statistic will be reset to zero. */
void cdb_stat(CDB *db, CDBSTAT *stat);
/* close the database. IT MUST BE CALLED BEFORE PROGRAM EXITS TO ENSURE DATA COMPLETION */
int cdb_close(CDB *db);
/* close the database if it opened, and free the object */
int cdb_destroy(CDB *db);
/* get last error number in current thread */
int cdb_errno(CDB *db);
/* get the description of an error number */
const char *cdb_errmsg(int ecode);
/* set callback when error happened, 'cdb_deferrorcb' is optional, which shows the error to stderr */
void cdb_seterrcb(CDB *db, CDB_ERRCALLBACK errcb, void *arg);
/* a possible error callback */
void cdb_deferrorcb(void *arg, int errno, const char *file, int line);
#if defined(__cplusplus)
}
#endif
#endif
......@@ -139,8 +139,8 @@ void dap_chain_global_db_objs_delete(dap_global_db_obj_t **objs)
int dap_chain_global_db_init(dap_config_t * g_config)
{
const char *l_storage_path = dap_config_get_item_str(g_config, "resources", "dap_global_db_path");
const char *l_driver_name = dap_config_get_item_str_default(g_config, "resources", "dap_global_db_driver",
"sqlite");
//const char *l_driver_name = dap_config_get_item_str_default(g_config, "resources", "dap_global_db_driver", "sqlite");
const char *l_driver_name = dap_config_get_item_str_default(g_config, "resources", "dap_global_db_driver", "cdb");
lock();
int res = dap_db_driver_init(l_driver_name, l_storage_path);
//int res = dap_db_init(a_storage_path);
......
......@@ -34,6 +34,7 @@
#include "dap_hash.h"
#include "dap_chain_global_db_driver_sqlite.h"
#include "dap_chain_global_db_driver_cdb.h"
#include "dap_chain_global_db_driver.h"
#define LOG_TAG "db_driver"
......@@ -79,6 +80,8 @@ int dap_db_driver_init(const char *a_driver_name, const char *a_filename_db)
l_ret = -1;
if(!dap_strcmp(s_used_driver, "sqlite"))
l_ret = dap_db_driver_sqlite_init(a_filename_db, &s_drv_callback);
if(!dap_strcmp(s_used_driver, "cdb"))
l_ret = dap_db_driver_cdb_init(a_filename_db, &s_drv_callback);
if(!l_ret) {
pthread_condattr_t l_condattr;
pthread_condattr_init(&l_condattr);
......
/*
* Authors:
* Konstantin Papizh <konstantin.papizh@demlabs.net>
* DeM Labs Inc. https://demlabs.net
* Kelvin Project https://github.com/kelvinblockchain
* Copyright (c) 2019
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <uthash.h>
#include "dap_common.h"
#include "dap_hash.h"
#include "dap_strfuncs.h"
#include "dap_chain_global_db_driver_cdb.h"
#define LOG_TAG "db_cdb"
#define uint64_size sizeof(uint64_t)
typedef struct _obj_arg {
pdap_store_obj_t o;
uint64_t q;
uint64_t n;
} obj_arg, *pobj_arg;
typedef struct _cdb_instance {
CDB *cdb;
char *local_group;
UT_hash_handle hh;
} cdb_instance, *pcdb_instance;
static char *s_cdb_path = NULL;
static pcdb_instance s_cdb = NULL;
static inline void dap_cdb_uint_to_hex(char *arr, uint64_t val, short size) {
short i = 0;
for (i = 0; i < size; ++i) {
arr[i] = (char)(((uint64_t) val >> (8 * (size - 1 - i))) & 0xFFu);
}
}
static inline uint64_t dap_cdb_hex_to_uint(char *arr, short size) {
uint64_t val = 0;
short i = 0;
for (i = 0; i < size; ++i){
uint8_t byte = *arr++;
if (byte >= 'a' && byte <='f'){
byte = byte - 'a' + 10;
} else if (byte >= 'A' && byte <='F') {
byte = byte - 'A' + 10;
}
val = (val << 8) | (byte & 0xFFu);
}
return val;
}
static void cdb_serialize_val_to_dap_store_obj(pdap_store_obj_t a_obj, char *key, char *val) {
if (!key || !val) {
a_obj = NULL;
return;
}
int offset = 0;
a_obj->key = dap_strdup(key);
unsigned char l_id[uint64_size] = {'\0'};
memcpy(l_id, val, uint64_size);
a_obj->id = dap_cdb_hex_to_uint(l_id, uint64_size);
offset += uint64_size;
unsigned char l_val_size[sizeof(unsigned long)] = {'\0'};
memcpy(l_val_size, val + offset, sizeof(unsigned long));
a_obj->value_len = dap_cdb_hex_to_uint(l_val_size, sizeof(unsigned long));
offset += sizeof(unsigned long);
a_obj->value = DAP_NEW_SIZE(uint8_t, a_obj->value_len);
memcpy(a_obj->value, val + offset, a_obj->value_len);
offset += a_obj->value_len;
unsigned char l_rawtime[sizeof(time_t)] = {'\0'};
memcpy(l_rawtime, val + offset, sizeof(time_t));
a_obj->timestamp = dap_cdb_hex_to_uint(l_rawtime, sizeof(time_t));
}
pcdb_instance *dap_cdb_init_group(char *a_group, int a_flags) {
pcdb_instance l_cdb_i = DAP_NEW(cdb_instance);
l_cdb_i->local_group = dap_strdup(a_group);
l_cdb_i->cdb = cdb_new();
char l_cdb_path[strlen(s_cdb_path) + strlen(a_group) + 2];
memset(l_cdb_path, '\0', strlen(s_cdb_path) + strlen(a_group) + 2);
strcat(l_cdb_path, s_cdb_path);
strcat(l_cdb_path, "/");
strcat(l_cdb_path, a_group);
cdb_options l_opts = { 1000000, 128, 1024 };
if ((dap_db_driver_cdb_options(&l_opts, l_cdb_i->cdb) != CDB_SUCCESS) ||
cdb_open(l_cdb_i->cdb, l_cdb_path, a_flags) < 0)
{
log_it(L_ERROR, "An error occured while opening CDB: \"%s\"", cdb_errmsg(cdb_errno(l_cdb_i->cdb)));
DAP_DELETE(l_cdb_i->local_group);
DAP_DELETE(l_cdb_i);
return NULL;
}
HASH_ADD_KEYPTR(hh, s_cdb, l_cdb_i->local_group, strlen(l_cdb_i->local_group), l_cdb_i);
return l_cdb_i;
}
int dap_db_driver_cdb_init(const char *a_cdb_path, dap_db_driver_callbacks_t *a_drv_callback) {
s_cdb_path = dap_strdup(a_cdb_path);
if(s_cdb_path[strlen(s_cdb_path)] == '/') {
s_cdb_path[strlen(s_cdb_path)] = '\0';
}
mkdir(s_cdb_path, 0755);
struct dirent *d;
DIR *dir = opendir(s_cdb_path);
if (!dir) {
log_it(L_ERROR, "Couldn't open db directory");
return -1;
}
for (d = readdir(dir); d; d = readdir(dir)) {
if (!dap_strcmp(d->d_name, ".") || !dap_strcmp(d->d_name, "..")) {
continue;
}
pcdb_instance l_cdb_i = dap_cdb_init_group(d->d_name, CDB_CREAT | CDB_PAGEWARMUP);
if (!l_cdb_i) {
dap_db_driver_cdb_deinit();
DAP_DELETE(s_cdb_path);
closedir(dir);
return -2;
}
CDBSTAT l_cdb_stat;
cdb_stat(l_cdb_i->cdb, &l_cdb_stat);
log_it(L_INFO, "Group \"%s\" found" , l_cdb_i->local_group);
log_it(L_INFO, "Records: %-24u" , l_cdb_stat.rnum);
log_it(L_INFO, "Average read latency: %-24u" , l_cdb_stat.rlatcy);
log_it(L_INFO, "Average write latency: %-24u" , l_cdb_stat.wlatcy);
}
a_drv_callback->read_last_store_obj = dap_db_driver_cdb_read_last_store_obj;
a_drv_callback->apply_store_obj = dap_db_driver_cdb_apply_store_obj;
a_drv_callback->read_store_obj = dap_db_driver_cdb_read_store_obj;
a_drv_callback->read_cond_store_obj = dap_db_driver_cdb_read_cond_store_obj;
a_drv_callback->deinit = dap_db_driver_cdb_deinit;
closedir(dir);
return CDB_SUCCESS;
}
CDB *dap_cdb_get_db_by_group(const char *a_group) {
pcdb_instance l_cdb_i = NULL;
HASH_FIND_STR(s_cdb, a_group, l_cdb_i);
if (!l_cdb_i) {
return NULL;
}
return l_cdb_i->cdb;
}
int dap_cdb_add_group(const char *a_group) {
char l_cdb_path[strlen(s_cdb_path) + strlen(a_group) + 2];
memset(l_cdb_path, '\0', strlen(s_cdb_path) + strlen(a_group) + 2);
strcat(l_cdb_path, s_cdb_path);
strcat(l_cdb_path, "/");
strcat(l_cdb_path, a_group);
mkdir(l_cdb_path, 0755);
return 0;
}
bool dap_cdb_get_last_obj_iter_callback(void *arg, const char *key, int ksize, const char *val, int vsize, uint32_t expire, uint64_t oid) {
/* this is wrong! TODO: instead of 'oid' must checkout real 'arg->id' */
/*if (oid != ((pobj_arg)arg)->q) {
return true;
}*/
cdb_serialize_val_to_dap_store_obj((pdap_store_obj_t)(((pobj_arg)arg)->o), key, val);
return false;
}
bool dap_cdb_get_some_obj_iter_callback(void *arg, const char *key, int ksize, const char *val, int vsize, uint32_t expire, uint64_t oid) {
((pobj_arg)arg)->q--;
uint64_t q = ((pobj_arg)arg)->q;
uint64_t n = ((pobj_arg)arg)->n;
pdap_store_obj_t l_obj = (pdap_store_obj_t)((pobj_arg)arg)->o;
cdb_serialize_val_to_dap_store_obj(&l_obj[n-q-1], key, val);
if (q == 0) {
return false;
}
return true;
}
bool dap_cdb_get_cond_obj_iter_callback(void *arg, const char *key, int ksize, const char *val, int vsize, uint32_t expire, uint64_t oid) {
/* No need due to this implementation design */
}
int dap_db_driver_cdb_deinit() {
cdb_instance *cur_cdb, *tmp;
HASH_ITER(hh, s_cdb, cur_cdb, tmp) {
HASH_DEL(s_cdb, cur_cdb);
cdb_destroy(cur_cdb->cdb);
}
return CDB_SUCCESS;
}
int dap_db_driver_cdb_options(pcdb_options l_opts, CDB* a_cdb) {
if (cdb_option(a_cdb,
l_opts->hsize,
l_opts->pcacheMB,
l_opts->rcacheMB) != CDB_SUCCESS) return -1;
return CDB_SUCCESS;
}
dap_store_obj_t *dap_db_driver_cdb_read_last_store_obj(const char* a_group) {
if (!a_group) {
return NULL;
}
CDB *l_cdb = dap_cdb_get_db_by_group(a_group);
if (!l_cdb) {
return NULL;
}
CDBSTAT l_cdb_stat;
cdb_stat(l_cdb, &l_cdb_stat);
void *l_iter = cdb_iterate_new(l_cdb, l_cdb_stat.rnum);
obj_arg l_arg;
l_arg.o = DAP_NEW_Z(dap_store_obj_t);
l_arg.q = l_cdb_stat.rnum;
cdb_iterate(l_cdb, dap_cdb_get_last_obj_iter_callback, (void*)&l_arg, l_iter);
cdb_iterate_destroy(l_cdb, l_iter);
l_arg.o->group = dap_strdup(a_group);
return l_arg.o;
}
dap_store_obj_t *dap_db_driver_cdb_read_store_obj(const char *a_group, const char *a_key, size_t *a_count_out) {
if (!a_group) {
return NULL;
}
//CDB_group l_group = dap_db_cdb_define_group(a_group);
CDB *l_cdb = dap_cdb_get_db_by_group(a_group);
if (!l_cdb) {
return NULL;
}
dap_store_obj_t *l_obj = NULL;
if (a_key) {
char *l_value;
int l_vsize;
cdb_get(l_cdb, a_key, strlen(a_key), (void**)&l_value, &l_vsize);
if (!l_value) {
return NULL;
}
l_obj = DAP_NEW_Z(dap_store_obj_t);
cdb_serialize_val_to_dap_store_obj(l_obj, a_key, l_value);
l_obj->group = dap_strdup(a_group);
cdb_free_val((void**)&l_value);
} else {
uint64_t l_count_out = 0;
if(a_count_out) {
l_count_out = *a_count_out;
}
CDBSTAT l_cdb_stat;
cdb_stat(l_cdb, &l_cdb_stat);
if ((l_count_out == 0) || (l_count_out > l_cdb_stat.rnum)) {
l_count_out = l_cdb_stat.rnum;
}
obj_arg l_arg;
l_arg.o = DAP_NEW_Z_SIZE(dap_store_obj_t, l_count_out * sizeof(dap_store_obj_t));
l_arg.q = l_count_out;
l_arg.n = l_count_out;
void *l_iter = cdb_iterate_new(l_cdb, 0);
l_count_out = cdb_iterate(l_cdb, dap_cdb_get_some_obj_iter_callback, (void*)&l_arg, l_iter);
cdb_iterate_destroy(l_cdb, l_iter);
if(a_count_out) {
*a_count_out = l_count_out;
}
for (ulong i = 0; i < l_count_out; ++i) {
l_arg.o[i].group = dap_strdup(a_group);
}
l_obj = l_arg.o;
}
return l_obj;
}
dap_store_obj_t* dap_db_driver_cdb_read_cond_store_obj(const char *a_group, uint64_t a_id, size_t *a_count_out) {
if (!a_group) {
return NULL;
}
CDB *l_cdb = dap_cdb_get_db_by_group(a_group);
if (!l_cdb) {
return NULL;
}
dap_store_obj_t *l_obj = NULL;
uint64_t l_count_out = 0;
if(a_count_out) {
l_count_out = *a_count_out;
}
CDBSTAT l_cdb_stat;
cdb_stat(l_cdb, &l_cdb_stat);
if ((l_count_out == 0) || (l_count_out > l_cdb_stat.rnum)) {
l_count_out = l_cdb_stat.rnum;
}
obj_arg l_arg;
l_arg.o = DAP_NEW_Z_SIZE(dap_store_obj_t, l_count_out * sizeof(dap_store_obj_t));
l_arg.q = l_count_out;
l_arg.q = l_count_out;
void *l_iter = cdb_iterate_new(l_cdb, a_id + 1); // wrong! TODO: make use of obj->id
l_count_out = cdb_iterate(l_cdb, dap_cdb_get_some_obj_iter_callback, (void*)&l_arg, l_iter);
cdb_iterate_destroy(l_cdb, l_iter);
if(a_count_out) {
*a_count_out = l_count_out;
}
for (ulong i = 0; i < l_count_out; ++i) {
l_arg.o[i].group = dap_strdup(a_group);
}
l_obj = l_arg.o;
}
int dap_db_driver_cdb_apply_store_obj(pdap_store_obj_t a_store_obj) {
if(!a_store_obj || !a_store_obj->group) {
return -1;
}
CDB *l_cdb = dap_cdb_get_db_by_group(a_store_obj->group);
if (!l_cdb) {
dap_cdb_add_group(a_store_obj->group);
pcdb_instance l_cdb_i = dap_cdb_init_group(a_store_obj->group, CDB_CREAT | CDB_PAGEWARMUP);
l_cdb = l_cdb_i->cdb;
}
if(a_store_obj->type == 'a') {
if(!a_store_obj->key || !a_store_obj->value || !a_store_obj->value_len) return -2;
cdb_record l_rec;
l_rec.key = dap_strdup(a_store_obj->key);
int offset = 0;
char *l_val = DAP_NEW_Z_SIZE(char, uint64_size + sizeof(unsigned long) + a_store_obj->value_len + sizeof(time_t));
dap_cdb_uint_to_hex(l_val, a_store_obj->id, uint64_size);
offset += uint64_size;
dap_cdb_uint_to_hex(l_val + offset, a_store_obj->value_len, sizeof(unsigned long));
offset += sizeof(unsigned long);
memcpy(l_val + offset, a_store_obj->value, a_store_obj->value_len);
offset += a_store_obj->value_len;
unsigned long l_time = (unsigned long)a_store_obj->timestamp;
dap_cdb_uint_to_hex(l_val + offset, l_time, sizeof(time_t));
offset += sizeof(time_t);
l_rec.val = l_val;
cdb_set(l_cdb, l_rec.key, strlen(l_rec.key), l_rec.val, offset);
DAP_DELETE(l_rec.key);
DAP_DELETE(l_rec.val);
} else if(a_store_obj->type == 'd') {
if(a_store_obj->key) {
cdb_del(l_cdb, a_store_obj->key, strlen(a_store_obj->key));
} else {
cdb_destroy(l_cdb);
dap_cdb_init_group(a_store_obj->group, CDB_TRUNC | CDB_PAGEWARMUP);
}
}
return 0;
}
/*
* Authors:
* Konstantin Papizh <konstantin.papizh@demlabs.net>
* DeM Labs Inc. https://demlabs.net
* Kelvin Project https://github.com/kelvinblockchain
* Copyright (c) 2019
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#include "cuttdb.h"
#include "dap_chain_global_db_driver.h"
typedef struct _cdb_options {
int hsize; // Main hash table size, 1%-10% of total records, immutable
int rcacheMB; // Record cache in MBytes
int pcacheMB; // Index page cache in MBytes
} cdb_options, *pcdb_options;
typedef struct _cdb_record {
char *key;
char *val;
} cdb_record, *pcdb_record;
int dap_db_driver_cdb_init(const char*, dap_db_driver_callbacks_t*);
int dap_db_driver_cdb_deinit();
int dap_db_driver_cdb_apply_store_obj(pdap_store_obj_t);
dap_store_obj_t *dap_db_driver_cdb_read_last_store_obj(const char*);
dap_store_obj_t *dap_db_driver_cdb_read_store_obj(const char*, const char*, size_t*);
dap_store_obj_t* dap_db_driver_cdb_read_cond_store_obj(const char*, uint64_t, size_t*);
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment