-
Notifications
You must be signed in to change notification settings - Fork 14
/
rocks.ml
719 lines (606 loc) · 21.5 KB
/
rocks.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
open Ctypes
open Foreign
open Rocks_common
type bigarray = Rocks_intf.bigarray
module Views = Views
exception OperationOnInvalidObject = Rocks_common.OperationOnInvalidObject
module WriteBatch = struct
module C = CreateConstructors_(struct let name = "writebatch" end)
include C
let clear =
foreign
"rocksdb_writebatch_clear"
(t @-> returning void)
let count =
foreign
"rocksdb_writebatch_count"
(t @-> returning int)
let put_raw =
foreign
"rocksdb_writebatch_put"
(t @->
ptr char @-> Views.int_to_size_t @->
ptr char @-> Views.int_to_size_t @-> returning void)
let put_raw_string =
foreign
"rocksdb_writebatch_put"
(t @->
ocaml_string @-> Views.int_to_size_t @->
ocaml_string @-> Views.int_to_size_t @-> returning void)
let put ?(key_pos=0) ?key_len ?(value_pos=0) ?value_len batch key value =
let open Bigarray.Array1 in
let key_len = match key_len with None -> dim key - key_pos | Some len -> len in
let value_len = match value_len with None -> dim value - value_pos | Some len -> len in
put_raw
batch
(bigarray_start array1 key +@ key_pos) key_len
(bigarray_start array1 value +@ value_pos) value_len
let put_string ?(key_pos=0) ?key_len ?(value_pos=0) ?value_len batch key value =
let key_len = match key_len with None -> String.length key - key_pos | Some len -> len in
let value_len = match value_len with None -> String.length value - value_pos | Some len -> len in
put_raw_string batch
(ocaml_string_start key +@ key_pos) key_len
(ocaml_string_start value +@ value_pos) value_len
let delete_raw =
foreign
"rocksdb_writebatch_delete"
(t @-> ptr char @-> Views.int_to_size_t @-> returning void)
let delete_raw_string =
foreign
"rocksdb_writebatch_delete"
(t @-> ocaml_string @-> Views.int_to_size_t @-> returning void)
let delete ?(pos=0) ?len batch key =
let open Bigarray.Array1 in
let len = match len with None -> dim key - pos | Some len -> len in
delete_raw batch (bigarray_start array1 key +@ pos) len
let delete_string ?(pos=0) ?len batch key =
let len = match len with None -> String.length key - pos | Some len -> len in
delete_raw_string batch (ocaml_string_start key +@ pos) len
end
module Version = Rocks_version
let returning_error typ = ptr string_opt @-> returning typ
let with_err_pointer f =
let err_pointer = allocate string_opt None in
let res = f err_pointer in
match !@ err_pointer with
| None -> res
| Some err -> failwith err
module rec Iterator : Rocks_intf.ITERATOR with type db := RocksDb.t = struct
module ReadOptions = Rocks_options.ReadOptions
type nonrec t = t
let t = t
type db
let db = t
let get_pointer = get_pointer
exception InvalidIterator
let create_no_gc =
foreign
"rocksdb_create_iterator"
(db @-> ReadOptions.t @-> returning t)
let destroy =
let inner =
foreign
"rocksdb_iter_destroy"
(t @-> returning void)
in
fun t ->
inner t;
t.valid <- false
let create ?opts db =
let inner opts =
let t = create_no_gc db opts in
Gc.finalise destroy t;
t
in
match opts with
| None -> ReadOptions.with_t inner
| Some opts -> inner opts
let with_t ?opts db ~f =
let inner opts =
let t = create_no_gc db opts in
finalize (fun () -> f t) (fun () -> destroy t)
in
match opts with
| None -> ReadOptions.with_t inner
| Some opts -> inner opts
let is_valid =
foreign
"rocksdb_iter_valid"
(t @-> returning Views.bool_to_uchar)
let seek_to_first =
foreign
"rocksdb_iter_seek_to_first"
(t @-> returning void)
let seek_to_last =
foreign
"rocksdb_iter_seek_to_last"
(t @-> returning void)
let seek_raw =
foreign
"rocksdb_iter_seek"
(t @-> ptr char @-> Views.int_to_size_t @-> returning void)
let seek_raw_string =
foreign
"rocksdb_iter_seek"
(t @-> ocaml_string @-> Views.int_to_size_t @-> returning void)
let seek ?(pos=0) ?len t key =
let open Bigarray.Array1 in
let len = match len with None -> dim key - pos | Some len -> len in
seek_raw t (bigarray_start array1 key +@ pos) len
let seek_string ?(pos=0) ?len t key =
let len = match len with None -> String.length key - pos | Some len -> len in
seek_raw_string t (ocaml_string_start key +@ pos) len
let next =
foreign
"rocksdb_iter_next"
(t @-> returning void)
let prev =
foreign
"rocksdb_iter_prev"
(t @-> returning void)
let get_key_raw =
let inner =
foreign "rocksdb_iter_key" (t @-> ptr Views.int_to_size_t @-> returning (ptr char))
in
fun t size -> if is_valid t then inner t size else raise InvalidIterator
let get_key t =
let res_size = allocate Views.int_to_size_t 0 in
let res = get_key_raw t res_size in
if (to_voidp res) = null
then failwith (Printf.sprintf "could not get key, is_valid=%b" (is_valid t))
else bigarray_of_ptr array1 (!@res_size) Bigarray.char res
let get_key_string t =
let res_size = allocate Views.int_to_size_t 0 in
let res = get_key_raw t res_size in
if (to_voidp res) = null
then failwith (Printf.sprintf "could not get key, is_valid=%b" (is_valid t))
else string_from_ptr res (!@ res_size)
let get_value_raw =
let inner =
foreign "rocksdb_iter_value" (t @-> ptr Views.int_to_size_t @-> returning (ptr char))
in
fun t size -> if is_valid t then inner t size else raise InvalidIterator
let get_value t =
let res_size = allocate Views.int_to_size_t 0 in
let res = get_value_raw t res_size in
if (to_voidp res) = null
then failwith (Printf.sprintf "could not get value, is_valid=%b" (is_valid t))
else bigarray_of_ptr array1 (!@res_size) Bigarray.char res
let get_value_string t =
let res_size = allocate Views.int_to_size_t 0 in
let res = get_value_raw t res_size in
if (to_voidp res) = null
then failwith (Printf.sprintf "could not get value, is_valid=%b" (is_valid t))
else string_from_ptr res (!@ res_size)
let get_error_raw =
foreign
"rocksdb_iter_get_error"
(t @-> ptr string_opt @-> returning void)
let get_error t =
let err_pointer = allocate string_opt None in
get_error_raw t err_pointer;
!@err_pointer
end
and Transaction : Rocks_intf.TRANSACTION with type db := RocksDb.t and type iter := Iterator.t = struct
module ReadOptions = Rocks_options.ReadOptions
module WriteOptions = Rocks_options.WriteOptions
module TransactionOptions = Rocks_options.TransactionOptions
module Snapshot = Rocks_options.Snapshot
let name = "transaction"
let destructor = "rocksdb_" ^ name ^ "_destroy"
type db = t
let db = t
type nonrec t = t
let t = t
let txnbegin_raw =
foreign
"rocksdb_transaction_begin"
(db @-> WriteOptions.t @-> TransactionOptions.t @-> ptr void @->
returning t)
let destroy = make_destroy t destructor
let txnbegin_no_gc ?wopts ?txnopts db =
let inner wopts txnopts =
txnbegin_raw db wopts txnopts null in
match wopts, txnopts with
None, None -> TransactionOptions.with_t (fun txnopts ->
(WriteOptions.with_t (fun wopts ->
inner wopts txnopts)))
| Some wopts, None -> TransactionOptions.with_t (inner wopts)
| None, Some txnopts -> (WriteOptions.with_t (fun wopts ->
inner wopts txnopts))
| Some wopts, Some txnopts -> inner wopts txnopts
let txnbegin ?wopts ?txnopts db =
let t = txnbegin_no_gc ?wopts ?txnopts db in
Gc.finalise destroy t;
t
let commit_raw =
foreign "rocksdb_transaction_commit"
(t @-> returning_error void)
let commit t =
with_err_pointer (commit_raw t)
let rollback_raw =
foreign "rocksdb_transaction_rollback"
(t @-> returning_error void)
let rollback t =
with_err_pointer (rollback_raw t)
let with_t db f =
let t = txnbegin_no_gc db in
finalize
(fun () -> f t)
(fun () -> destroy t)
let put_raw =
foreign
"rocksdb_transaction_put"
(t @->
ptr char @-> Views.int_to_size_t @->
ptr char @-> Views.int_to_size_t @->
returning_error void)
let put_raw_string =
foreign
"rocksdb_transaction_put"
(t @->
ocaml_string @-> Views.int_to_size_t @->
ocaml_string @-> Views.int_to_size_t @->
returning_error void)
let put ?(key_pos=0) ?key_len ?(value_pos=0) ?value_len ?opts t key value =
let open Bigarray.Array1 in
let key_len = match key_len with None -> dim key - key_pos | Some len -> len in
let value_len = match value_len with None -> dim value - value_pos | Some len -> len in
with_err_pointer begin
put_raw t
(bigarray_start array1 key +@ key_pos) key_len
(bigarray_start array1 value +@ value_pos) value_len
end
let put_string ?(key_pos=0) ?key_len ?(value_pos=0) ?value_len ?opts t key value =
let key_len = match key_len with None -> String.length key - key_pos | Some len -> len in
let value_len = match value_len with None -> String.length value - value_pos | Some len -> len in
with_err_pointer begin
put_raw_string t
(ocaml_string_start key +@ key_pos) key_len
(ocaml_string_start value +@ value_pos) value_len
end
let delete_raw =
foreign
"rocksdb_transaction_delete"
(t @->
ptr char @-> Views.int_to_size_t @->
returning_error void)
let delete_raw_string =
foreign
"rocksdb_transaction_delete"
(t @->
ocaml_string @-> Views.int_to_size_t @->
returning_error void)
let delete ?(pos=0) ?len ?opts t key =
let open Bigarray.Array1 in
let len = match len with None -> dim key - pos | Some len -> len in
with_err_pointer (delete_raw t (bigarray_start array1 key +@ pos) len)
let delete_string ?(pos=0) ?len ?opts t key =
let len = match len with None -> String.length key - pos | Some len -> len in
with_err_pointer (delete_raw_string t (ocaml_string_start key +@ pos) len)
let get_raw =
foreign
"rocksdb_transaction_get"
(t @-> ReadOptions.t @->
ptr char @-> Views.int_to_size_t @-> ptr Views.int_to_size_t @->
returning_error (ptr char))
let get_raw_string =
foreign
"rocksdb_transaction_get"
(t @-> ReadOptions.t @->
ocaml_string @-> Views.int_to_size_t @-> ptr Views.int_to_size_t @->
returning_error (ptr char))
let get ?(pos=0) ?len ?opts t key =
let open Bigarray.Array1 in
let len = match len with None -> dim key - pos | Some len -> len in
let inner opts =
let res_size = allocate Views.int_to_size_t 0 in
let res = with_err_pointer
(get_raw t opts (bigarray_start array1 key +@ pos) len res_size)
in
if (to_voidp res) = null
then None
else begin
let res' = bigarray_of_ptr array1 (!@res_size) Bigarray.char res in
Gc.finalise_last (fun () -> free (to_voidp res)) res';
Some res'
end
in
match opts with
| Some opts -> inner opts
| None -> ReadOptions.with_t inner
let get_string ?(pos=0) ?len ?opts t key =
let len = match len with None -> String.length key - pos | Some len -> len in
let inner opts =
let res_size = allocate Views.int_to_size_t 0 in
let res = with_err_pointer
(get_raw_string t opts (ocaml_string_start key +@ pos) len res_size)
in
if (to_voidp res) = null
then None
else begin
let res' = string_from_ptr res (!@ res_size) in
Gc.finalise_last (fun () -> free (to_voidp res)) res';
Some res'
end
in
match opts with
| Some opts -> inner opts
| None -> ReadOptions.with_t inner
let get_snapshot =
foreign "rocksdb_transaction_get_snapshot"
(t @-> returning Snapshot.t)
let free_snapshot =
foreign "rocksdb_free"
(Snapshot.t @-> returning void)
let create_iterator_no_gc =
foreign
"rocksdb_transaction_create_iterator"
(t @-> ReadOptions.t @-> returning t)
let destroy_iterator =
let inner =
foreign
"rocksdb_iter_destroy"
(t @-> returning void)
in
fun t -> inner t;
t.valid <- false
let create_iterator ?opts txn =
let inner opts =
let t = create_iterator_no_gc txn opts in
Gc.finalise destroy_iterator t;
t
in
match opts with
| None -> ReadOptions.with_t inner
| Some opts -> inner opts
let with_iterator ?opts txn ~f =
let inner opts =
let t = create_iterator_no_gc txn opts in
finalize
(fun () -> f t)
(fun () -> destroy_iterator t)
in
match opts with
| None -> ReadOptions.with_t inner
| Some opts -> inner opts
end
and RocksDb : Rocks_intf.ROCKS with type batch := WriteBatch.t = struct
module ReadOptions = Rocks_options.ReadOptions
module WriteOptions = Rocks_options.WriteOptions
module FlushOptions = Rocks_options.FlushOptions
module Options = Rocks_options.Options
module Cache = Rocks_options.Cache
module Snapshot = Rocks_options.Snapshot
module BlockBasedTableOptions = Rocks_options.BlockBasedTableOptions
module TransactionDbOptions = Rocks_options.TransactionDbOptions
type nonrec t = t
type batch
let t = t
let get_pointer = get_pointer
let open_db_raw =
foreign
"rocksdb_open"
(Options.t @-> string @-> ptr string_opt @-> returning t)
let open_db_for_read_only_raw =
foreign
"rocksdb_open_for_read_only"
(Options.t @-> string @-> Views.bool_to_uchar @-> ptr string_opt @-> returning t)
let open_transactiondb_raw =
foreign
"rocksdb_transactiondb_open"
(Options.t @-> TransactionDbOptions.t @-> string @-> ptr string_opt @-> returning t)
let open_transactiondb ?opts ?txnopts name =
let inner opts txndbopts = with_err_pointer (open_transactiondb_raw opts txndbopts name) in
match opts, txnopts with
None, None -> TransactionDbOptions.with_t (fun txndbopts ->
(Options.with_t (fun opts ->
inner opts txndbopts)))
| Some opts, None -> TransactionDbOptions.with_t (inner opts)
| None, Some txndbopts -> Options.with_t (fun opts ->
inner opts txndbopts)
| Some opts, Some txndbopts -> inner opts txndbopts
let open_db ?opts name =
match opts with
| None -> Options.with_t (fun options -> with_err_pointer (open_db_raw options name))
| Some opts -> with_err_pointer (open_db_raw opts name)
let open_db_for_read_only ?opts name error_if_log_file_exists =
match opts with
| None -> Options.with_t (fun options -> with_err_pointer (open_db_for_read_only_raw options name error_if_log_file_exists))
| Some opts -> with_err_pointer (open_db_for_read_only_raw opts name error_if_log_file_exists)
let close =
let inner =
foreign
"rocksdb_close"
(t @-> returning void)
in
fun t ->
inner t;
t.valid <- false
let with_db ?opts name ~f =
let db = open_db ?opts name in
finalize (fun () -> f db) (fun () -> close db)
let put_raw =
foreign
"rocksdb_put"
(t @-> WriteOptions.t @->
ptr char @-> Views.int_to_size_t @->
ptr char @-> Views.int_to_size_t @->
returning_error void)
let put_raw_string =
foreign
"rocksdb_put"
(t @-> WriteOptions.t @->
ocaml_string @-> Views.int_to_size_t @->
ocaml_string @-> Views.int_to_size_t @->
returning_error void)
let put ?(key_pos=0) ?key_len ?(value_pos=0) ?value_len ?opts t key value =
let open Bigarray.Array1 in
let key_len = match key_len with None -> dim key - key_pos | Some len -> len in
let value_len = match value_len with None -> dim value - value_pos | Some len -> len in
let inner opts = with_err_pointer begin
put_raw t opts
(bigarray_start array1 key +@ key_pos) key_len
(bigarray_start array1 value +@ value_pos) value_len
end
in
match opts with
| None -> WriteOptions.with_t inner
| Some opts -> inner opts
let put_string ?(key_pos=0) ?key_len ?(value_pos=0) ?value_len ?opts t key value =
let key_len = match key_len with None -> String.length key - key_pos | Some len -> len in
let value_len = match value_len with None -> String.length value - value_pos | Some len -> len in
let inner opts = with_err_pointer begin
put_raw_string t opts
(ocaml_string_start key +@ key_pos) key_len
(ocaml_string_start value +@ value_pos) value_len
end
in
match opts with
| None -> WriteOptions.with_t inner
| Some opts -> inner opts
let delete_raw =
foreign
"rocksdb_delete"
(t @-> WriteOptions.t @->
ptr char @-> Views.int_to_size_t @->
returning_error void)
let delete_raw_string =
foreign
"rocksdb_delete"
(t @-> WriteOptions.t @->
ocaml_string @-> Views.int_to_size_t @->
returning_error void)
let delete ?(pos=0) ?len ?opts t key =
let open Bigarray.Array1 in
let len = match len with None -> dim key - pos | Some len -> len in
let inner opts =
with_err_pointer (delete_raw t opts (bigarray_start array1 key +@ pos) len) in
match opts with
| None -> WriteOptions.with_t inner
| Some opts -> inner opts
let delete_string ?(pos=0) ?len ?opts t key =
let len = match len with None -> String.length key - pos | Some len -> len in
let inner opts =
with_err_pointer (delete_raw_string t opts (ocaml_string_start key +@ pos) len) in
match opts with
| None -> WriteOptions.with_t inner
| Some opts -> inner opts
let write_raw =
foreign
"rocksdb_write"
(t @-> WriteOptions.t @-> WriteBatch.t @->
returning_error void)
let write ?opts t wb =
let inner opts = with_err_pointer (write_raw t opts wb) in
match opts with
| None -> WriteOptions.with_t inner
| Some opts -> with_err_pointer (write_raw t opts wb)
let get_raw =
foreign
"rocksdb_get"
(t @-> ReadOptions.t @->
ptr char @-> Views.int_to_size_t @-> ptr Views.int_to_size_t @->
returning_error (ptr char))
let get_raw_string =
foreign
"rocksdb_get"
(t @-> ReadOptions.t @->
ocaml_string @-> Views.int_to_size_t @-> ptr Views.int_to_size_t @->
returning_error (ptr char))
let get ?(pos=0) ?len ?opts t key =
let open Bigarray.Array1 in
let len = match len with None -> dim key - pos | Some len -> len in
let inner opts =
let res_size = allocate Views.int_to_size_t 0 in
let res = with_err_pointer
(get_raw t opts (bigarray_start array1 key +@ pos) len res_size)
in
if (to_voidp res) = null
then None
else begin
let res' = bigarray_of_ptr array1 (!@res_size) Bigarray.char res in
Gc.finalise_last (fun () -> free (to_voidp res)) res';
Some res'
end
in
match opts with
| Some opts -> inner opts
| None -> ReadOptions.with_t inner
let get_string ?(pos=0) ?len ?opts t key =
let len = match len with None -> String.length key - pos | Some len -> len in
let inner opts =
let res_size = allocate Views.int_to_size_t 0 in
let res = with_err_pointer
(get_raw_string t opts (ocaml_string_start key +@ pos) len res_size)
in
if (to_voidp res) = null
then None
else begin
let res' = string_from_ptr res (!@ res_size) in
Gc.finalise_last (fun () -> free (to_voidp res)) res';
Some res'
end
in
match opts with
| Some opts -> inner opts
| None -> ReadOptions.with_t inner
let flush_raw =
foreign
"rocksdb_flush"
(t @-> FlushOptions.t @-> returning_error void)
let flush ?opts t =
let inner opts = with_err_pointer (flush_raw t opts) in
match opts with
| None -> FlushOptions.with_t inner
| Some opts -> inner opts
let create_snapshot =
foreign "rocksdb_create_snapshot"
(t @-> returning Snapshot.t)
let release_snapshot =
foreign "rocksdb_release_snapshot"
(t @-> Snapshot.t @-> returning void)
module CheckpointObject = struct
let name = "checkpoint_object"
let constructor = "rocksdb_" ^ name ^ "_create"
let destructor = "rocksdb_" ^ name ^ "_destroy"
type db = t
let db = t
type nonrec t = t
let t = t
let create_no_gc =
foreign
constructor
(db @-> returning t)
let destroy = make_destroy t destructor
let create db =
let t = create_no_gc db in
Gc.finalise destroy t;
t
let with_t db f =
let t = create_no_gc db in
finalize
(fun () -> f t)
(fun () -> destroy t)
end
let checkpoint_create db dir log_size_for_flush =
let checkpoint_create_raw =
foreign "rocksdb_checkpoint_create"
(CheckpointObject.t @-> string @->
Views.int_to_uint64_t @-> ptr string_opt @-> returning void) in
CheckpointObject.with_t db (fun checkpoint_object ->
with_err_pointer (checkpoint_create_raw checkpoint_object dir
log_size_for_flush))
let property_value db name =
(* Ugly hack. Is there a better way to retrieve string from C? *)
let get = foreign "rocksdb_property_value"
(t @-> string @-> returning (ptr_opt char)) in
let free = foreign "free" ((ptr char) @-> returning void) in
let strlen = foreign "strlen" ((ptr char) @-> returning int) in
match get db name with
Some p -> let value = string_from_ptr p ~length:(strlen p) in
free p;
Some value
| None -> None
end
include RocksDb