Created
March 24, 2013 03:31
-
-
Save qxj/5230372 to your computer and use it in GitHub Desktop.
test multiple secondary index of berkeley db g++ -o test_secondary_db test_secondary_db.cpp -g -O2 -Wall -Wextra -ldb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -*- mode: c++ -*- | |
// @(#) test_secondary_db.cpp Time-stamp: <Julian Qian 2013-03-23 22:16:12> | |
// Copyright 2013 Julian Qian | |
// Author: Julian Qian <[email protected]> | |
// Version: $Id: test_secondary_db.cpp,v 0.1 2013-03-23 21:31:19 jqian Exp $ | |
// | |
// test multiple secondary index of berkeley db | |
// g++ -o test_secondary_db test_secondary_db.cpp -g -O2 -Wall -Wextra -ldb | |
#include <stdint.h> | |
#include <string.h> | |
#include <stdlib.h> // strtoul | |
#include <unistd.h> | |
#include <sys/time.h> // gettimeofday | |
#include <sys/stat.h> // mkdir | |
#include <sys/types.h> // mkdir | |
#include <db.h> | |
typedef uint32_t KEY; | |
typedef struct combo | |
{ | |
uint32_t head; | |
uint32_t tail; | |
} COMBO; | |
int | |
my_callback(DB *, const DBT *, const DBT *pdata, DBT *skey) | |
{ | |
COMBO* combo = (COMBO*)pdata->data; | |
uint32_t& head = combo->head; | |
uint32_t& tail = combo->tail; | |
DBT *tmpdbt; | |
if(head == tail){ | |
tmpdbt = (DBT*)malloc(sizeof(DBT) * 1); | |
memset(tmpdbt, 0, sizeof(DBT) * 1); | |
tmpdbt[0].data = &head; | |
tmpdbt[0].size = sizeof(uint32_t); | |
skey->size = 1; | |
}else{ | |
tmpdbt = (DBT*)malloc(sizeof(DBT) * 2); | |
memset(tmpdbt, 0, sizeof(DBT) * 2); | |
tmpdbt[0].data = &head; | |
tmpdbt[0].size = sizeof(uint32_t); | |
tmpdbt[1].data = &tail; | |
tmpdbt[1].size = sizeof(uint32_t); | |
skey->size = 2; | |
} | |
skey->flags = DB_DBT_MULTIPLE | DB_DBT_APPMALLOC; | |
skey->data = tmpdbt; | |
return (0); | |
} | |
#if 0 | |
int | |
my_callback(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey) | |
{ | |
COMBO* combo = (COMBO*)pdata->data; | |
memset(skey, 0, sizeof(DBT)); | |
skey->data = &combo->head; | |
skey->size = sizeof(uint32_t); | |
return (0); | |
} | |
#endif | |
int main(int argc, char *argv[]){ | |
DB_ENV* envp = NULL; | |
DB *pri_dbp = NULL, *sec_dbp = NULL; | |
DBC* pri_cur = NULL, *sec_cur = NULL; | |
u_int32_t flags; | |
u_int32_t env_flags = DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOG; | |
int ret; | |
KEY keyid; | |
COMBO cmb; | |
DBT pkey, pdata, skey; | |
uint32_t sign = 200; | |
if ((ret = db_env_create(&envp, 0)) != 0) { | |
fprintf(stderr, "Error creating env handle: %s\n", db_strerror(ret)); | |
return -1; | |
} | |
mkdir("bdb", S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR ); | |
if ((ret = envp->open(envp, "bdb", env_flags, 0)) != 0) { | |
fprintf(stderr, "Environment open failed: %s", db_strerror(ret)); | |
return -1; | |
} | |
if ((ret = db_create(&pri_dbp, envp, 0)) != 0) { | |
fprintf(stderr, "error: %s\n", db_strerror(ret)); | |
return -1; | |
} | |
if ((ret = db_create(&sec_dbp, envp, 0)) != 0) { | |
fprintf(stderr, "error: %s\n", db_strerror(ret)); | |
return -1; | |
} | |
pri_dbp->set_errfile(pri_dbp, stderr); | |
pri_dbp->set_errpfx(pri_dbp, argv[0]); | |
if ((ret = sec_dbp->set_flags(sec_dbp, DB_DUPSORT)) != 0) { | |
pri_dbp->err(pri_dbp, ret, "set_flags"); | |
goto err; | |
} | |
flags = DB_CREATE; | |
if ((ret = pri_dbp->open(pri_dbp, NULL, "my_db.db", NULL, DB_BTREE, flags, 0)) != 0) { | |
pri_dbp->err(pri_dbp, ret, "open primary db"); | |
goto err; | |
} | |
if ((ret = sec_dbp->open(sec_dbp, NULL, "my_secdb.db", NULL, DB_BTREE, flags, 0)) != 0) { | |
pri_dbp->err(pri_dbp, ret, "open secondary db"); | |
goto err; | |
} | |
if ((ret = pri_dbp->associate(pri_dbp, NULL, sec_dbp, my_callback, 0)) != 0) { | |
pri_dbp->err(pri_dbp, ret, "associate"); | |
goto err; | |
} | |
if((ret = pri_dbp->cursor(pri_dbp, NULL, &pri_cur, 0)) != 0){ | |
pri_dbp->err(pri_dbp, ret, "primary cursor"); | |
goto err; | |
} | |
if((ret = sec_dbp->cursor(sec_dbp, NULL, &sec_cur, 0)) != 0){ | |
pri_dbp->err(pri_dbp, ret, "secondary cursor"); | |
goto err; | |
} | |
memset(&pkey, 0, sizeof(DBT)); | |
memset(&pdata, 0, sizeof(DBT)); | |
// write data | |
for(int i = 0; i< 10; ++i){ | |
keyid = i; | |
cmb.head = 100*i; | |
cmb.tail = 100*(i+1); | |
pkey.data = &keyid; | |
pkey.size = sizeof(uint32_t); | |
pdata.data = &cmb; | |
pdata.size = sizeof(COMBO); | |
if((ret = pri_cur->put(pri_cur, &pkey, &pdata, DB_KEYFIRST)) != 0){ | |
pri_dbp->err(pri_dbp, ret, "put data"); | |
} | |
} | |
// show data | |
printf("all data:\n"); | |
pkey.data = &keyid; | |
pkey.ulen = sizeof(KEY); | |
pkey.flags = DB_DBT_USERMEM; | |
pdata.data = &cmb; | |
pdata.ulen = sizeof(COMBO); | |
pdata.flags = DB_DBT_USERMEM; | |
ret = pri_cur->get(pri_cur, &pkey, &pdata, DB_FIRST); | |
while(ret == 0){ | |
printf("primary key: %u,\thead: %u,\ttail: %u\n", keyid, cmb.head, cmb.tail); | |
ret = pri_cur->get(pri_cur, &pkey, &pdata, DB_NEXT); | |
} | |
// search in primary | |
keyid = 1; | |
printf("search in primary, pri_key=%u:\n", keyid); | |
pkey.data = &keyid; | |
pkey.size = sizeof(uint32_t); | |
pdata.data = &cmb; | |
pdata.ulen = sizeof(COMBO); | |
pdata.flags = DB_DBT_USERMEM; | |
if((ret = pri_cur->get(pri_cur, &pkey, &pdata, DB_SET)) == 0){ | |
printf("found combo, head: %u, tail: %u\n", cmb.head, cmb.tail); | |
}else{ | |
pri_dbp->err(pri_dbp, ret, "get by primary id"); | |
} | |
// search in secondary | |
struct timeval start, end; | |
gettimeofday(&start, NULL); | |
if(argc > 1){ | |
sign = strtoul(argv[1], NULL, 10); | |
} | |
printf("search in secondary, sec_key=%u:\n", sign); | |
memset(&skey, 0, sizeof(DBT)); | |
skey.data = &sign; | |
skey.size = sizeof(uint32_t); | |
pkey.data = &keyid; | |
pkey.ulen = sizeof(uint32_t); | |
pkey.flags = DB_DBT_USERMEM; | |
pdata.data = &cmb; | |
pdata.ulen = sizeof(COMBO); | |
pdata.flags = DB_DBT_USERMEM; | |
ret = sec_cur->pget(sec_cur, &skey, &pkey, &pdata, DB_SET); | |
while(ret != DB_NOTFOUND){ | |
if(ret != 0){ | |
pri_dbp->err(pri_dbp, ret, "get by secondary key"); | |
break; | |
} | |
printf("found combo by second key: %u, primary key: %u, head: %u, tail: %u\n", | |
sign, keyid, cmb.head, cmb.tail); | |
ret = sec_cur->pget(sec_cur, &skey, &pkey, &pdata, DB_NEXT_DUP); | |
} | |
gettimeofday(&end, NULL); | |
printf("time: %.6f s.\n", (end.tv_sec - start.tv_sec) + (double) (end.tv_usec - start.tv_usec) / 1000000 ); | |
err: | |
if(sec_cur != NULL) sec_cur->close(sec_cur); | |
if(pri_cur != NULL) pri_cur->close(pri_cur); | |
if(sec_dbp != NULL) sec_dbp->close(sec_dbp, 0); | |
if(pri_dbp != NULL) pri_dbp->close(pri_dbp, 0); | |
if(envp != NULL) envp->close(envp, 0); | |
// if(sec_dbp != NULL) sec_dbp->remove(sec_dbp, "my_secdb.db", NULL, 0); | |
// if(pri_dbp != NULL) pri_dbp->remove(sec_dbp, "my_db.db", NULL, 0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment