• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "bmbase.c"
2 #include <dirent.h>
3 #include <leveldb/c.h>
4 
5 #define DEFAULT_DB "leveldb_bench.db"
6 
7 typedef struct BM_LEVELDB {
8   leveldb_t *db;
9   leveldb_options_t *options;
10 } BM_LEVELDB;
11 
env_setup()12 static void env_setup() {
13   fprintf(stderr, " engine: LevelDB %d.%d\n", leveldb_major_version(), leveldb_minor_version());
14 }
15 
db_size_bytes(BMCTX * ctx)16 uint64_t db_size_bytes(BMCTX *ctx) {
17   char buf[PATH_MAX + 1];
18   DIR *d;
19   uint64_t sz = 0;
20   struct dirent *dir;
21   const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
22   d = opendir(path);
23   if (d) {
24     while ((dir = readdir(d))) {
25       snprintf(buf, sizeof(buf), "%s/%s", path, dir->d_name);
26       IWP_FILE_STAT fst;
27       iwrc rc = iwp_fstat(buf, &fst);
28       if (rc) {
29         iwlog_ecode_error3(rc);
30         return 0;
31       }
32       if (fst.ftype == IWP_TYPE_FILE) {
33         sz += fst.size;
34       }
35     }
36     closedir(d);
37   }
38   return sz;
39 }
40 
db_open(BMCTX * ctx)41 static void *db_open(BMCTX *ctx) {
42   if (ctx->db) {
43     return 0; // db is not closed properly
44   }
45   char *err = 0;
46   const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
47   BM_LEVELDB *bmdb = malloc(sizeof(*bmdb));
48   bmdb->options = leveldb_options_create();
49   leveldb_options_set_create_if_missing(bmdb->options, 1);
50   if (ctx->freshdb) {
51     leveldb_destroy_db(bmdb->options, path, &err);
52     if (err) {
53       leveldb_free(err);
54       err = 0;
55     }
56     iwp_removedir(path);
57   }
58   bmdb->db = leveldb_open(bmdb->options, path, &err);
59   if (err) {
60     leveldb_options_destroy(bmdb->options);
61     fprintf(stderr, "ERROR db_open: %s\n", err);
62     leveldb_free(err);
63     free(bmdb);
64     return 0;
65   }
66   return bmdb;
67 }
68 
db_close(BMCTX * ctx)69 static bool db_close(BMCTX *ctx) {
70   if (!ctx->db) {
71     return false;
72   }
73   BM_LEVELDB *bmdb = ctx->db;
74   leveldb_close(bmdb->db);
75   leveldb_options_destroy(bmdb->options);
76   free(bmdb);
77   return true;
78 }
79 
db_put(BMCTX * ctx,const IWKV_val * key,const IWKV_val * val,bool sync)80 static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
81   BM_LEVELDB *bmdb = ctx->db;
82   char *err = 0;
83   bool ret = true;
84   leveldb_writeoptions_t *wopt = leveldb_writeoptions_create();
85   if (sync) {
86     leveldb_writeoptions_set_sync(wopt, 1);
87   }
88   leveldb_put(bmdb->db, wopt, key->data, key->size, val->data, val->size, &err);
89   if (err) {
90     fprintf(stderr, "ERROR db_put: %s\n", err);
91     leveldb_free(err);
92     ret = false;
93   }
94   leveldb_writeoptions_destroy(wopt);
95   return ret;
96 }
97 
db_get(BMCTX * ctx,const IWKV_val * key,IWKV_val * val,bool * found)98 static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
99   BM_LEVELDB *bmdb = ctx->db;
100   size_t sz;
101   char *data = 0;
102   char *err = 0;
103   bool ret = true;
104   leveldb_readoptions_t *ropt = leveldb_readoptions_create();
105   data = leveldb_get(bmdb->db, ropt, key->data, key->size, &sz, &err);
106   *found = (data != 0);
107   if (err) {
108     fprintf(stderr, "ERROR db_get: %s\n", err);
109     leveldb_free(err);
110     ret = false;
111   } else {
112     val->data = data;
113     val->size = sz;
114   }
115   leveldb_readoptions_destroy(ropt);
116   return ret;
117 }
118 
db_del(BMCTX * ctx,const IWKV_val * key,bool sync)119 static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
120   BM_LEVELDB *bmdb = ctx->db;
121   char *err = 0;
122   bool ret = true;
123   leveldb_writeoptions_t *wopt = leveldb_writeoptions_create();
124   if (sync) {
125     leveldb_writeoptions_set_sync(wopt, 1);
126   }
127   leveldb_delete(bmdb->db, wopt, key->data, key->size, &err);
128   if (err) {
129     fprintf(stderr, "ERROR db_del: %s\n", err);
130     leveldb_free(err);
131     ret = false;
132   }
133   leveldb_writeoptions_destroy(wopt);
134   return ret;
135 }
136 
db_read_seq(BMCTX * ctx,bool reverse)137 static bool db_read_seq(BMCTX *ctx, bool reverse) {
138   BM_LEVELDB *bmdb = ctx->db;
139   bool ret = true;
140   leveldb_readoptions_t *ropt = leveldb_readoptions_create();
141   leveldb_iterator_t *it = leveldb_create_iterator(bmdb->db, ropt);
142   if (reverse) {
143     leveldb_iter_seek_to_last(it);
144   } else {
145     leveldb_iter_seek_to_first(it);
146   }
147   for (int i = 0; i < bm.param_num && leveldb_iter_valid(it); ++i) {
148     size_t vlen, klen;
149     leveldb_iter_value(it, &vlen);
150     leveldb_iter_key(it, &klen);
151     if (reverse) {
152       leveldb_iter_prev(it);
153     } else {
154       leveldb_iter_next(it);
155     }
156   }
157   leveldb_iter_destroy(it);
158   leveldb_readoptions_destroy(ropt);
159   return ret;
160 }
161 
db_cursor_to_key(BMCTX * ctx,const IWKV_val * key,IWKV_val * val,bool * found)162 static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
163   BM_LEVELDB *bmdb = ctx->db;
164   bool ret = true;
165   leveldb_readoptions_t *ropt = leveldb_readoptions_create();
166   leveldb_iterator_t *it = leveldb_create_iterator(bmdb->db, ropt);
167   leveldb_iter_seek(it, key->data, key->size);
168   *found = leveldb_iter_valid(it);
169   val->data = 0;
170   val->size = 0;
171   if (*found) {
172     size_t vlen;
173     const char *v = leveldb_iter_value(it, &vlen);
174     val->data = malloc(vlen);
175     memcpy(val->data, v, vlen);
176   }
177   leveldb_iter_destroy(it);
178   leveldb_readoptions_destroy(ropt);
179   return ret;
180 }
181 
main(int argc,char ** argv)182 int main(int argc, char **argv) {
183   if (argc < 1) {
184     return -1;
185   }
186   g_program = argv[0];
187   bm.env_setup = env_setup;
188   bm.db_size_bytes = db_size_bytes;
189   bm.db_open = db_open;
190   bm.db_close = db_close;
191   bm.db_put = db_put;
192   bm.db_get = db_get;
193   bm.db_del = db_del;
194   bm.db_read_seq = db_read_seq;
195   bm.db_cursor_to_key = db_cursor_to_key;
196   if (!bm_bench_run(argc, argv)) {
197     return 1;
198   }
199   return 0;
200 }
201