• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "bmbase.c"
2 #include <db.h>
3 
4 #define DEFAULT_DB "bdb_bench.db"
5 
6 
7 typedef struct BM_BDB {
8   DB *dbp;
9 } BM_BDB;
10 
env_setup()11 static void env_setup() {
12   fprintf(stderr, " engine: %s\n", DB_VERSION_STRING);
13 }
14 
db_size_bytes(BMCTX * ctx)15 static uint64_t db_size_bytes(BMCTX *ctx) {
16   const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
17   IWP_FILE_STAT fst;
18   iwrc rc = iwp_fstat(path, &fst);
19   if (rc) {
20     iwlog_ecode_error3(rc);
21     return 0;
22   }
23   return fst.size;
24 }
25 
val_free(void * data)26 static void val_free(void *data) {
27   free(data);
28 }
29 
db_open(BMCTX * ctx)30 static void *db_open(BMCTX *ctx) {
31   if (ctx->db) {
32     return 0; // db is not closed properly
33   }
34   const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
35   BM_BDB *bmdb = malloc(sizeof(*bmdb));
36   int ret = db_create(&bmdb->dbp, 0, 0);
37   if (ret) {
38     fprintf(stderr, "db_create: %s\n", db_strerror(ret));
39     free(bmdb);
40     return 0;
41   }
42   int32_t mode = DB_CREATE;
43   if (ctx->freshdb) {
44     mode |= DB_TRUNCATE;
45   }
46   ret = bmdb->dbp->open(bmdb->dbp, 0, path, 0, DB_BTREE, mode, 0664);
47   if (ret) {
48     fprintf(stderr, "db_open: %s\n", db_strerror(ret));
49     free(bmdb);
50     return 0;
51   }
52   return bmdb;
53 }
54 
db_close(BMCTX * ctx)55 static bool db_close(BMCTX *ctx) {
56   if (!ctx->db) {
57     return false;
58   }
59   BM_BDB *bmdb = ctx->db;
60   int ret = bmdb->dbp->close(bmdb->dbp, 0);
61   if (ret) {
62     fprintf(stderr, "db_close: %s\n", db_strerror(ret));
63     return false;
64   }
65   free(bmdb);
66   return true;
67 }
68 
db_put(BMCTX * ctx,const IWKV_val * key,const IWKV_val * val,bool sync)69 static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
70   BM_BDB *bmdb = ctx->db;
71   DBT bkey = {.data = key->data, .size = key->size};
72   DBT bval = {.data = val->data, .size = val->size};
73   int ret = bmdb->dbp->put(bmdb->dbp, 0, &bkey, &bval, 0);
74   if (ret) {
75     fprintf(stderr, "db_put: %s\n", db_strerror(ret));
76     return false;
77   }
78   if (sync) {
79     ret = bmdb->dbp->sync(bmdb->dbp, 0);
80     if (ret) {
81       fprintf(stderr, "db_sync: %s\n", db_strerror(ret));
82       return false;
83     }
84   }
85   return true;
86 }
87 
db_get(BMCTX * ctx,const IWKV_val * key,IWKV_val * val,bool * found)88 static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
89   BM_BDB *bmdb = ctx->db;
90   DBT bkey = {.data = key->data, .size = key->size};
91   DBT bval = {.flags =  DB_DBT_MALLOC};
92   int ret = bmdb->dbp->get(bmdb->dbp, 0, &bkey, &bval, 0);
93   val->data = bval.data;
94   val->size = bval.size;
95   if (ret == DB_NOTFOUND) {
96     *found = false;
97     ret = 0;
98   } else if (ret) {
99     *found = false;
100     fprintf(stderr, "db_get: %s\n", db_strerror(ret));
101   } else {
102     *found = true;
103   }
104   return ret == 0;
105 }
106 
107 
db_del(BMCTX * ctx,const IWKV_val * key,bool sync)108 static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
109   BM_BDB *bmdb = ctx->db;
110   DBT bkey = {.data = key->data, .size = key->size};
111   int ret = bmdb->dbp->del(bmdb->dbp, 0, &bkey, 0);
112   if (ret == DB_NOTFOUND) {
113     ret = 0;
114   } else if (ret) {
115     fprintf(stderr, "db_del: %s\n", db_strerror(ret));
116     return false;
117   }
118   if (sync) {
119     ret = bmdb->dbp->sync(bmdb->dbp, 0);
120     if (ret) {
121       fprintf(stderr, "db_del: %s\n", db_strerror(ret));
122       return false;
123     }
124   }
125   return true;
126 }
127 
db_read_seq(BMCTX * ctx,bool reverse)128 static bool db_read_seq(BMCTX *ctx, bool reverse) {
129   BM_BDB *bmdb = ctx->db;
130   DBC *curp;
131   DBT bkey = {.flags =  DB_DBT_MALLOC};
132   DBT bval = {.flags =  DB_DBT_MALLOC};
133   int ret = bmdb->dbp->cursor(bmdb->dbp, 0, &curp, 0);
134   if (ret) {
135     fprintf(stderr, "db_read_seq: %s\n", db_strerror(ret));
136     return false;
137   }
138   ret = curp->get(curp, &bkey, &bval, reverse ? DB_LAST : DB_FIRST);
139   if (ret == DB_NOTFOUND) {
140     ret = 0;
141   }
142   if (bkey.data) free(bkey.data);
143   if (bval.data) free(bval.data);
144 
145   for (int i = 0; i < bm.param_num - 1 && !ret; ++i) {
146     bkey.data = 0;
147     bval.data = 0;
148     ret = curp->get(curp, &bkey, &bval, reverse ? DB_PREV : DB_NEXT);
149     if (ret == DB_NOTFOUND) {
150       ret = 0;
151       break;
152     } else if (ret) {
153       fprintf(stderr, "db_read_seq: %s\n", db_strerror(ret));
154     }
155     if (bkey.data) free(bkey.data);
156     if (bval.data) free(bval.data);
157   }
158 
159   curp->close(curp);
160   return ret == 0;
161 }
162 
db_cursor_to_key(BMCTX * ctx,const IWKV_val * key,IWKV_val * val,bool * found)163 static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
164   BM_BDB *bmdb = ctx->db;
165   DBC *curp;
166   DBT bkey = {.data = key->data, .size = key->size};
167   DBT bval = {.flags =  DB_DBT_MALLOC};
168   int ret = bmdb->dbp->cursor(bmdb->dbp, 0, &curp, 0);
169   if (ret) {
170     fprintf(stderr, "db_cursor_to_key: %s\n", db_strerror(ret));
171     return false;
172   }
173   ret = curp->get(curp, &bkey, &bval, DB_SET);
174   if (ret == DB_NOTFOUND) {
175     *found = false;
176     ret = 0;
177   } else if (ret) {
178     *found = false;
179     fprintf(stderr, "db_cursor_to_key: %s\n", db_strerror(ret));
180   } else {
181     *found = true;
182     val->data = bval.data;
183     val->size = bval.size;
184   }
185   curp->close(curp);
186   return ret == 0;
187 }
188 
main(int argc,char ** argv)189 int main(int argc, char **argv) {
190   if (argc < 1) return -1;
191   g_program = argv[0];
192   bm.env_setup = env_setup;
193   bm.db_size_bytes = db_size_bytes;
194   bm.val_free = val_free;
195   bm.db_open = db_open;
196   bm.db_close = db_close;
197   bm.db_put = db_put;
198   bm.db_get = db_get;
199   bm.db_del = db_del;
200   bm.db_read_seq = db_read_seq;
201   bm.db_cursor_to_key = db_cursor_to_key;
202   if (!bm_bench_run(argc, argv)) {
203     return 1;
204   }
205   return 0;
206 }
207