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