1 #include "bmbase.c"
2 #include "iowow.h"
3
4 #define DEFAULT_DB "iwkv_bench.db"
5
6 typedef struct BM_IWKVDB {
7 IWKV iwkv;
8 IWDB db;
9 } BM_IWKVDB;
10
env_setup()11 static void env_setup() {
12 iwrc rc = iw_init();
13 if (rc) {
14 iwlog_ecode_error2(rc, "Failed to init iwkv: iwkv_init()");
15 exit(1);
16 }
17 fprintf(stderr, " engine: IWKV %s\n", iowow_version_full());
18 }
19
db_size_bytes(BMCTX * ctx)20 static uint64_t db_size_bytes(BMCTX *ctx) {
21 const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
22 IWP_FILE_STAT fst;
23 iwrc rc = iwp_fstat(path, &fst);
24 if (rc) {
25 iwlog_ecode_error3(rc);
26 return 0;
27 }
28 return fst.size;
29 }
30
db_open(BMCTX * ctx)31 static void *db_open(BMCTX *ctx) {
32 if (ctx->db) {
33 return 0; // db is not closed properly
34 }
35 bool wal_enabled = false;
36 for (int i = 0; i < bm.argc; ++i) {
37 if (!strcmp(bm.argv[i], "-w")) {
38 wal_enabled = true;
39 }
40 }
41 IWKV_OPTS opts = {
42 .wal = {
43 .enabled = wal_enabled,
44 .check_crc_on_checkpoint = false,
45 .savepoint_timeout_sec = 10, // 10 sec
46 .checkpoint_timeout_sec = 300, // 5 min
47 .wal_buffer_sz = 8 * 1024 * 1024, // 8M
48 .checkpoint_buffer_sz = 500ULL * 1024 * 1024 // 500MB
49 }
50 };
51 opts.path = bm.param_db ? bm.param_db : DEFAULT_DB;
52
53 if (ctx->freshdb) {
54 opts.oflags = IWKV_TRUNC;
55 }
56 BM_IWKVDB *bmdb = malloc(sizeof(*bmdb));
57 iwrc rc = iwkv_open(&opts, &bmdb->iwkv);
58 if (rc) {
59 iwlog_ecode_error2(rc, "Failed to open iwkv file");
60 return 0;
61 }
62 rc = iwkv_db(bmdb->iwkv, 1, 0, &bmdb->db);
63 if (rc) {
64 iwlog_ecode_error2(rc, "Failed to open iwkv db: 1");
65 return 0;
66 }
67 return bmdb;
68 }
69
db_close(BMCTX * ctx)70 static bool db_close(BMCTX *ctx) {
71 if (!ctx->db) {
72 return false;
73 }
74 BM_IWKVDB *bmdb = ctx->db;
75 iwrc rc = iwkv_close(&bmdb->iwkv);
76 if (rc) {
77 iwlog_ecode_error2(rc, "db_close");
78 return false;
79 }
80 free(bmdb);
81 return true;
82 }
83
db_put(BMCTX * ctx,const IWKV_val * key,const IWKV_val * val,bool sync)84 static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
85 BM_IWKVDB *bmdb = ctx->db;
86 iwrc rc = iwkv_put(bmdb->db, key, val, sync ? IWKV_SYNC : 0);
87 if (rc) {
88 iwlog_ecode_error2(rc, "db_put");
89 return false;
90 }
91 return true;
92 }
93
db_get(BMCTX * ctx,const IWKV_val * key,IWKV_val * val,bool * found)94 static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
95 BM_IWKVDB *bmdb = ctx->db;
96 *found = true;
97 iwrc rc = iwkv_get(bmdb->db, key, val);
98 if (rc == IWKV_ERROR_NOTFOUND) {
99 *found = false;
100 rc = 0;
101 }
102 if (rc) {
103 iwlog_ecode_error2(rc, "db_get");
104 return false;
105 }
106 return true;
107 }
108
db_del(BMCTX * ctx,const IWKV_val * key,bool sync)109 static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
110 BM_IWKVDB *bmdb = ctx->db;
111 iwrc rc = iwkv_del(bmdb->db, key, sync ? IWKV_SYNC : 0);
112 if (rc == IWKV_ERROR_NOTFOUND) {
113 rc = 0;
114 }
115 if (rc) {
116 iwlog_ecode_error2(rc, "db_del");
117 return false;
118 }
119 return true;
120 }
121
db_read_seq(BMCTX * ctx,bool reverse)122 static bool db_read_seq(BMCTX *ctx, bool reverse) {
123 BM_IWKVDB *bmdb = ctx->db;
124 bool ret = true;
125 IWKV_cursor cur;
126 iwrc rc = iwkv_cursor_open(bmdb->db, &cur,
127 (reverse ? IWKV_CURSOR_AFTER_LAST : IWKV_CURSOR_BEFORE_FIRST), 0);
128 if (rc) {
129 iwlog_ecode_error2(rc, "db_read_seq::iwkv_cursor_open failed");
130 return false;
131 }
132 for (int i = 0; i < bm.param_num && !rc; ++i) {
133 rc = iwkv_cursor_to(cur, reverse ? IWKV_CURSOR_PREV : IWKV_CURSOR_NEXT);
134 }
135 iwkv_cursor_close(&cur);
136 if (rc == IWKV_ERROR_NOTFOUND) {
137 rc = 0;
138 }
139 if (rc) {
140 ret = false;
141 iwlog_ecode_error2(rc, "db_read_seq");
142 }
143 return ret;
144 }
145
db_cursor_to_key(BMCTX * ctx,const IWKV_val * key,IWKV_val * val,bool * found)146 static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
147 BM_IWKVDB *bmdb = ctx->db;
148 bool ret = true;
149 IWKV_cursor cur;
150 *found = true;
151 iwrc rc = iwkv_cursor_open(bmdb->db, &cur, IWKV_CURSOR_EQ, key);
152 if (!rc) {
153 rc = iwkv_cursor_val(cur, val);
154 if (rc) {
155 ret = false;
156 iwlog_ecode_error2(rc, "db_cursor_to_key::iwkv_cursor_val failed");
157 }
158 iwkv_cursor_close(&cur);
159 } else if (rc == IWKV_ERROR_NOTFOUND) {
160 *found = false;
161 iwkv_cursor_close(&cur);
162 } else {
163 iwlog_ecode_error2(rc, "db_cursor_to_key::iwkv_cursor_open failed");
164 ret = false;
165 }
166 return ret;
167 }
168
main(int argc,char * argv[])169 int main(int argc, char *argv[]) {
170 if (argc < 1) return -1;
171 g_program = argv[0];
172 bm.env_setup = env_setup;
173 bm.db_size_bytes = db_size_bytes;
174 bm.db_open = db_open;
175 bm.db_close = db_close;
176 bm.db_put = db_put;
177 bm.db_get = db_get;
178 bm.db_del = db_del;
179 bm.db_read_seq = db_read_seq;
180 bm.db_cursor_to_key = db_cursor_to_key;
181 if (!bm_bench_run(argc, argv)) {
182 return 1;
183 }
184 return 0;
185 }
186