#include "lsmtest.h"
#include <stdlib.h>
#ifdef HAVE_KYOTOCABINET
#include "kcpolydb.h"
extern "C" {
struct KcDb {
TestDb base;
kyotocabinet::TreeDB* db;
char *pVal;
};
}
int test_kc_open(const char *zFilename, int bClear, TestDb **ppDb){
KcDb *pKcDb;
int ok;
int rc = 0;
if( bClear ){
char *zCmd = sqlite3_mprintf("rm -rf %s\n", zFilename);
system(zCmd);
sqlite3_free(zCmd);
}
pKcDb = (KcDb *)malloc(sizeof(KcDb));
memset(pKcDb, 0, sizeof(KcDb));
pKcDb->db = new kyotocabinet::TreeDB();
pKcDb->db->tune_page(TESTDB_DEFAULT_PAGE_SIZE);
pKcDb->db->tune_page_cache(
TESTDB_DEFAULT_PAGE_SIZE * TESTDB_DEFAULT_CACHE_SIZE
);
ok = pKcDb->db->open(zFilename,
kyotocabinet::PolyDB::OWRITER | kyotocabinet::PolyDB::OCREATE
);
if( ok==0 ){
free(pKcDb);
pKcDb = 0;
rc = 1;
}
*ppDb = (TestDb *)pKcDb;
return rc;
}
int test_kc_close(TestDb *pDb){
KcDb *pKcDb = (KcDb *)pDb;
if( pKcDb->pVal ){
delete [] pKcDb->pVal;
}
pKcDb->db->close();
delete pKcDb->db;
free(pKcDb);
return 0;
}
int test_kc_write(TestDb *pDb, void *pKey, int nKey, void *pVal, int nVal){
KcDb *pKcDb = (KcDb *)pDb;
int ok;
ok = pKcDb->db->set((const char *)pKey, nKey, (const char *)pVal, nVal);
return (ok ? 0 : 1);
}
int test_kc_delete(TestDb *pDb, void *pKey, int nKey){
KcDb *pKcDb = (KcDb *)pDb;
int ok;
ok = pKcDb->db->remove((const char *)pKey, nKey);
return (ok ? 0 : 1);
}
int test_kc_delete_range(
TestDb *pDb,
void *pKey1, int nKey1,
void *pKey2, int nKey2
){
int res;
KcDb *pKcDb = (KcDb *)pDb;
kyotocabinet::DB::Cursor* pCur = pKcDb->db->cursor();
if( pKey1 ){
res = pCur->jump((const char *)pKey1, nKey1);
}else{
res = pCur->jump();
}
while( 1 ){
const char *pKey; size_t nKey;
const char *pVal; size_t nVal;
pKey = pCur->get(&nKey, &pVal, &nVal);
if( pKey==0 ) break;
#ifndef NDEBUG
if( pKey1 ){
res = memcmp(pKey, pKey1, MIN((size_t)nKey1, nKey));
assert( res>0 || (res==0 && nKey>nKey1) );
}
#endif
if( pKey2 ){
res = memcmp(pKey, pKey2, MIN((size_t)nKey2, nKey));
if( res>0 || (res==0 && (size_t)nKey2<nKey) ){
delete [] pKey;
break;
}
}
pCur->remove();
delete [] pKey;
}
delete pCur;
return 0;
}
int test_kc_fetch(
TestDb *pDb,
void *pKey,
int nKey,
void **ppVal,
int *pnVal
){
KcDb *pKcDb = (KcDb *)pDb;
size_t nVal;
if( pKcDb->pVal ){
delete [] pKcDb->pVal;
pKcDb->pVal = 0;
}
pKcDb->pVal = pKcDb->db->get((const char *)pKey, nKey, &nVal);
if( pKcDb->pVal ){
*ppVal = pKcDb->pVal;
*pnVal = nVal;
}else{
*ppVal = 0;
*pnVal = -1;
}
return 0;
}
int test_kc_scan(
TestDb *pDb,
void *pCtx,
int bReverse,
void *pKey1, int nKey1,
void *pKey2, int nKey2,
void (*xCallback)(void *pCtx, void *pKey, int nKey, void *pVal, int nVal)
){
KcDb *pKcDb = (KcDb *)pDb;
kyotocabinet::DB::Cursor* pCur = pKcDb->db->cursor();
int res;
if( bReverse==0 ){
if( pKey1 ){
res = pCur->jump((const char *)pKey1, nKey1);
}else{
res = pCur->jump();
}
}else{
if( pKey2 ){
res = pCur->jump_back((const char *)pKey2, nKey2);
}else{
res = pCur->jump_back();
}
}
while( res ){
const char *pKey; size_t nKey;
const char *pVal; size_t nVal;
pKey = pCur->get(&nKey, &pVal, &nVal);
if( bReverse==0 && pKey2 ){
res = memcmp(pKey, pKey2, MIN((size_t)nKey2, nKey));
if( res>0 || (res==0 && (size_t)nKey2<nKey) ){
delete [] pKey;
break;
}
}else if( bReverse!=0 && pKey1 ){
res = memcmp(pKey, pKey1, MIN((size_t)nKey1, nKey));
if( res<0 || (res==0 && (size_t)nKey1>nKey) ){
delete [] pKey;
break;
}
}
xCallback(pCtx, (void *)pKey, (int)nKey, (void *)pVal, (int)nVal);
delete [] pKey;
if( bReverse ){
res = pCur->step_back();
}else{
res = pCur->step();
}
}
delete pCur;
return 0;
}
#endif
#ifdef HAVE_MDB
#include "lmdb.h"
extern "C" {
struct MdbDb {
TestDb base;
MDB_env *env;
MDB_dbi dbi;
};
}
int test_mdb_open(
const char *zSpec,
const char *zFilename,
int bClear,
TestDb **ppDb
){
MDB_txn *txn;
MdbDb *pMdb;
int rc;
if( bClear ){
char *zCmd = sqlite3_mprintf("rm -rf %s\n", zFilename);
system(zCmd);
sqlite3_free(zCmd);
}
pMdb = (MdbDb *)malloc(sizeof(MdbDb));
memset(pMdb, 0, sizeof(MdbDb));
rc = mdb_env_create(&pMdb->env);
if( rc==0 ) rc = mdb_env_set_mapsize(pMdb->env, 1*1024*1024*1024);
if( rc==0 ) rc = mdb_env_open(pMdb->env, zFilename, MDB_NOSYNC|MDB_NOSUBDIR, 0600);
if( rc==0 ) rc = mdb_txn_begin(pMdb->env, NULL, 0, &txn);
if( rc==0 ){
rc = mdb_open(txn, NULL, 0, &pMdb->dbi);
mdb_txn_commit(txn);
}
*ppDb = (TestDb *)pMdb;
return rc;
}
int test_mdb_close(TestDb *pDb){
MdbDb *pMdb = (MdbDb *)pDb;
mdb_close(pMdb->env, pMdb->dbi);
mdb_env_close(pMdb->env);
free(pMdb);
return 0;
}
int test_mdb_write(TestDb *pDb, void *pKey, int nKey, void *pVal, int nVal){
int rc;
MdbDb *pMdb = (MdbDb *)pDb;
MDB_val val;
MDB_val key;
MDB_txn *txn;
val.mv_size = nVal;
val.mv_data = pVal;
key.mv_size = nKey;
key.mv_data = pKey;
rc = mdb_txn_begin(pMdb->env, NULL, 0, &txn);
if( rc==0 ){
rc = mdb_put(txn, pMdb->dbi, &key, &val, 0);
if( rc==0 ){
rc = mdb_txn_commit(txn);
}else{
mdb_txn_abort(txn);
}
}
return rc;
}
int test_mdb_delete(TestDb *pDb, void *pKey, int nKey){
int rc;
MdbDb *pMdb = (MdbDb *)pDb;
MDB_val key;
MDB_txn *txn;
key.mv_size = nKey;
key.mv_data = pKey;
rc = mdb_txn_begin(pMdb->env, NULL, 0, &txn);
if( rc==0 ){
rc = mdb_del(txn, pMdb->dbi, &key, 0);
if( rc==0 ){
rc = mdb_txn_commit(txn);
}else{
mdb_txn_abort(txn);
}
}
return rc;
}
int test_mdb_fetch(
TestDb *pDb,
void *pKey,
int nKey,
void **ppVal,
int *pnVal
){
int rc;
MdbDb *pMdb = (MdbDb *)pDb;
MDB_val key;
MDB_txn *txn;
key.mv_size = nKey;
key.mv_data = pKey;
rc = mdb_txn_begin(pMdb->env, NULL, MDB_RDONLY, &txn);
if( rc==0 ){
MDB_val val = {0, 0};
rc = mdb_get(txn, pMdb->dbi, &key, &val);
if( rc==MDB_NOTFOUND ){
rc = 0;
*ppVal = 0;
*pnVal = -1;
}else{
*ppVal = val.mv_data;
*pnVal = val.mv_size;
}
mdb_txn_commit(txn);
}
return rc;
}
int test_mdb_scan(
TestDb *pDb,
void *pCtx,
int bReverse,
void *pKey1, int nKey1,
void *pKey2, int nKey2,
void (*xCallback)(void *pCtx, void *pKey, int nKey, void *pVal, int nVal)
){
MdbDb *pMdb = (MdbDb *)pDb;
int rc;
MDB_cursor_op op = bReverse ? MDB_PREV : MDB_NEXT;
MDB_txn *txn;
rc = mdb_txn_begin(pMdb->env, NULL, MDB_RDONLY, &txn);
if( rc==0 ){
MDB_cursor *csr;
MDB_val key = {0, 0};
MDB_val val = {0, 0};
rc = mdb_cursor_open(txn, pMdb->dbi, &csr);
if( rc==0 ){
while( mdb_cursor_get(csr, &key, &val, op)==0 ){
xCallback(pCtx, key.mv_data, key.mv_size, val.mv_data, val.mv_size);
}
mdb_cursor_close(csr);
}
}
return rc;
}
#endif