rocksdb-ruby 0.2.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,8 +3,15 @@ require "mkmf"
3
3
  dir_config('rocksdb')
4
4
  RbConfig::CONFIG["CPP"] = "g++ -E -std=gnu++11"
5
5
 
6
- if have_header('rocksdb/db.h') and have_library('rocksdb')
6
+ DEBUG_BUILD = have_library('rocksdb_debug') || ENV["DEBUG_LEVEL"]
7
+
8
+ if have_header('rocksdb/db.h') and (have_library('rocksdb') or have_library('rocksdb_debug'))
7
9
  $CPPFLAGS << " -std=gnu++11"
10
+
11
+ if DEBUG_BUILD
12
+ CONFIG["optflags"] = "-O0"
13
+ end
14
+
8
15
  create_makefile("RocksDB/RocksDB")
9
16
  else
10
17
  abort "can't find header or library of rocksdb"
@@ -1,8 +1,9 @@
1
1
  #include "rocksdb_batch_rb.h"
2
2
 
3
- extern "C" {
4
3
  #include <ruby.h>
5
4
 
5
+ extern "C" {
6
+
6
7
  VALUE batch_alloc(VALUE klass){
7
8
  rocksdb::WriteBatch *batch = ALLOC(rocksdb::WriteBatch);
8
9
  batch = new rocksdb::WriteBatch;
@@ -12,6 +13,7 @@ extern "C" {
12
13
  VALUE rocksdb_write_batch_init(){
13
14
  return Qtrue;
14
15
  }
16
+
15
17
  VALUE rocksdb_write_batch_put(VALUE self, VALUE v_key, VALUE v_value){
16
18
  Check_Type(v_key, T_STRING);
17
19
  Check_Type(v_value, T_STRING);
@@ -19,17 +21,18 @@ extern "C" {
19
21
  rocksdb::WriteBatch *batch;
20
22
  std::string key = std::string((char*)RSTRING_PTR(v_key), RSTRING_LEN(v_key));
21
23
  std::string value = std::string((char*)RSTRING_PTR(v_value), RSTRING_LEN(v_value));
22
-
24
+
23
25
  Data_Get_Struct(self, rocksdb::WriteBatch, batch);
24
26
  batch->Put(key, value);
25
27
  return Qnil;
26
28
  }
29
+
27
30
  VALUE rocksdb_write_batch_delete(VALUE self, VALUE v_key){
28
31
  Check_Type(v_key, T_STRING);
29
32
 
30
33
  rocksdb::WriteBatch *batch;
31
34
  std::string key = std::string((char*)RSTRING_PTR(v_key), RSTRING_LEN(v_key));
32
-
35
+
33
36
  Data_Get_Struct(self, rocksdb::WriteBatch, batch);
34
37
  batch->Delete(key);
35
38
 
@@ -1,10 +1,10 @@
1
1
  #include "rocksdb/db.h"
2
2
  #include "rocksdb/write_batch.h"
3
+ #include <ruby.h>
3
4
 
4
5
  extern "C" {
5
6
 
6
- #include <ruby.h>
7
-
7
+
8
8
  typedef VALUE (*METHOD)(...);
9
9
 
10
10
  VALUE rocksdb_write_batch_init();
@@ -2,39 +2,40 @@
2
2
  #include "rocksdb_db_rb.h"
3
3
  #include "ruby/encoding.h"
4
4
  #include <iostream>
5
+ #include <ruby.h>
5
6
 
6
7
  extern "C" {
7
- #include <ruby.h>
8
8
 
9
- VALUE rocksdb_db_init(int argc, VALUE* argv, VALUE self) {
10
- VALUE v_db_file_name;
11
- VALUE v_options;
9
+ VALUE rocksdb_db_init(VALUE self, VALUE v_db_path, VALUE v_readonly, VALUE v_db_options) {
12
10
  rocksdb_pointer* db_pointer;
13
11
  rocksdb::DB* db;
14
12
  rocksdb::Options options;
15
13
  rocksdb::Status status;
14
+
16
15
  std::string db_file_name;
17
- bool readonly;
18
-
16
+ std::string db_string_options;
17
+
19
18
  Data_Get_Struct(self, rocksdb_pointer, db_pointer);
20
- rb_scan_args(argc, argv, "11", &v_db_file_name, &v_options);
21
19
 
22
- Check_Type(v_db_file_name, T_STRING);
23
- db_file_name = std::string((char*)RSTRING_PTR(v_db_file_name));
20
+ // Initialize db_pointer
21
+ db_pointer->db = nullptr;
22
+ db_pointer->readonly = false;
24
23
 
25
- readonly = false;
26
- if (TYPE(v_options) == T_HASH) {
27
- VALUE v = rb_hash_aref(v_options, ID2SYM(rb_intern("readonly")));
28
- if(v == Qtrue){
29
- readonly = true;
30
- }
31
- set_opt(&options, &v_options);
32
- }
33
- //std::cout << options.max_bytes_for_level_base << "\n";
34
- //std::cout << options.max_grandparent_overlap_factor << "\n";
35
- //std::cout << options.delete_obsolete_files_period_micros << "\n";
24
+ bool readonly = RTEST(v_readonly);
36
25
 
26
+ db_file_name = STRING_FROM_RB_VALUE(v_db_path);
27
+ db_string_options = STRING_FROM_RB_VALUE(v_db_options);
28
+
29
+ // Set option before parsing string, so create_if_missing could be
30
+ // overwriten in option string
37
31
  options.create_if_missing = true;
32
+ status = GetOptionsFromString(options, db_string_options, &options);
33
+
34
+ if(!status.ok()) {
35
+ raise_status_error(&status);
36
+ return Qnil;
37
+ }
38
+
38
39
  if(readonly){
39
40
  status = rocksdb::DB::OpenForReadOnly(options, db_file_name, &db);
40
41
  }else{
@@ -43,303 +44,287 @@ extern "C" {
43
44
 
44
45
  db_pointer->db = db;
45
46
  db_pointer->readonly = readonly;
46
-
47
- return status.ok() ? Qtrue : Qfalse;
48
- }
49
- VALUE rocksdb_db_init2(int argc, VALUE* argv, VALUE self) {
50
- rocksdb_pointer* db_pointer;
51
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
52
- db_pointer->db = NULL;
53
47
 
54
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
48
+ if(!status.ok()) {
49
+ raise_status_error(&status);
50
+ return Qnil;
51
+ }
55
52
 
56
53
  return Qtrue;
57
54
  }
58
55
 
59
- void set_opt_unit_val(uint64_t* opt, char* name, VALUE *v_options){
56
+ VALUE db_alloc(VALUE klass){
57
+ rocksdb_pointer* db_pointer = ALLOC(rocksdb_pointer);
58
+ return Data_Wrap_Struct(klass, 0, db_free, db_pointer);
59
+ }
60
60
 
61
- VALUE v2 = rb_hash_aref(*v_options, ID2SYM(rb_intern(name)));
62
- if(RB_TYPE_P(v2, T_FIXNUM)){
63
- *opt = NUM2INT(v2);
61
+ void db_free(rocksdb_pointer* db_pointer){
62
+ if(db_pointer == nullptr) {
63
+ return;
64
64
  }
65
- }
66
- void set_opt_int_val(int* opt, char* name, VALUE *v_options){
67
- VALUE v2 = rb_hash_aref(*v_options, ID2SYM(rb_intern(name)));
68
- if(RB_TYPE_P(v2, T_FIXNUM)){
69
- *opt = NUM2INT(v2);
65
+
66
+ if(db_pointer->db != nullptr){
67
+ delete db_pointer->db;
68
+ db_pointer->db = nullptr;
70
69
  }
71
- }
72
70
 
73
- void set_opt(rocksdb::Options* options, VALUE *v_options){
74
- set_opt_unit_val(&options->max_bytes_for_level_base, (char *) "max_bytes_for_level_base", v_options);
75
- set_opt_unit_val(&options->delete_obsolete_files_period_micros, (char *) "delete_obsolete_files_period_micros", v_options);
71
+ delete db_pointer;
72
+ db_pointer = nullptr;
76
73
  }
77
74
 
78
- VALUE db_alloc(VALUE klass){
79
- rocksdb_pointer* db_pointer = ALLOC(rocksdb_pointer);
80
- return Data_Wrap_Struct(klass, 0, db_free, db_pointer);
75
+ VALUE rocksdb_db_close(VALUE self){
76
+ rocksdb_pointer* db_pointer = get_db(&self);
77
+
78
+ if(db_pointer == nullptr) {
79
+ return Qfalse;
80
+ }
81
+
82
+ if(db_pointer->db != nullptr){
83
+ delete db_pointer->db;
84
+ db_pointer->db = nullptr;
85
+ }
86
+
87
+ return Qtrue;
81
88
  }
82
89
 
83
90
  VALUE rocksdb_db_put(VALUE self, VALUE v_key, VALUE v_value) {
84
- Check_Type(v_key, T_STRING);
85
- Check_Type(v_value, T_STRING);
91
+ rocksdb_pointer* db_pointer = get_db_for_write(&self);
86
92
 
87
- rocksdb_pointer* db_pointer;
88
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
89
-
90
- std::string key = std::string((char*)RSTRING_PTR(v_key), RSTRING_LEN(v_key));
91
- std::string value = std::string((char*)RSTRING_PTR(v_value), RSTRING_LEN(v_value));
93
+ rocksdb::Slice key = SLICE_FROM_RB_VALUE(v_key);
94
+ std::string value = STRING_FROM_RB_VALUE(v_value);
92
95
 
93
- if (db_pointer->db == NULL) {
94
- rb_raise(rb_eRuntimeError, "db not open");
95
- }
96
- if (db_pointer->readonly) {
97
- rb_raise(rb_eRuntimeError, "readonly");
98
- }
99
96
  rocksdb::Status status = db_pointer->db->Put(rocksdb::WriteOptions(), key, value);
100
-
101
- return status.ok() ? Qtrue : Qfalse;
97
+
98
+ if(!status.ok()) {
99
+ raise_status_error(&status);
100
+ return Qnil;
101
+ }
102
+
103
+ return Qtrue;
102
104
  }
103
105
 
104
106
  VALUE rocksdb_db_write(VALUE self, VALUE v_write){
105
- rocksdb_pointer* db_pointer;
106
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
107
+ rocksdb_pointer* db_pointer = get_db_for_write(&self);
107
108
 
108
109
  rocksdb::WriteBatch *batch;
109
110
  Data_Get_Struct(v_write, rocksdb::WriteBatch, batch);
110
111
 
111
- if (db_pointer->db == NULL) {
112
- rb_raise(rb_eRuntimeError, "db not open");
113
- }
114
- if (db_pointer->readonly) {
115
- rb_raise(rb_eRuntimeError, "readonly");
116
- }
117
112
  rocksdb::Status status = db_pointer->db->Write(rocksdb::WriteOptions(), batch);
118
- return status.ok() ? Qtrue : Qfalse;
113
+
114
+ if(!status.ok()) {
115
+ raise_status_error(&status);
116
+ return Qnil;
117
+ }
118
+
119
+ return Qtrue;
120
+ }
121
+
122
+ VALUE rocksdb_db_property(VALUE self, VALUE v_key){
123
+ rocksdb_pointer* db_pointer = get_db_for_read(&self);
124
+
125
+ rocksdb::Slice key = SLICE_FROM_RB_VALUE(v_key);
126
+ std::string value = std::string();
127
+
128
+ bool result_ok = db_pointer->db->GetProperty(key, &value);
129
+
130
+ if(!result_ok) return Qnil;
131
+ return SLICE_TO_RB_STRING(value);
132
+ }
133
+
134
+ VALUE rocksdb_db_options(VALUE self){
135
+ rocksdb_pointer* db_pointer = get_db_for_read(&self);
136
+
137
+ VALUE v_result = rb_hash_new();
138
+ VALUE v_key = Qnil;
139
+ VALUE v_value = Qnil;
140
+
141
+ std::string options_str;
142
+ std::unordered_map<std::string, std::string> options_map;
143
+
144
+ GetStringFromDBOptions(&options_str, db_pointer->db->GetOptions());
145
+
146
+ v_key = rb_str_new_cstr("DBOptions");
147
+ v_value = rb_str_new_cstr(options_str.c_str());
148
+ rb_hash_aset(v_result, v_key, v_value);
149
+
150
+ GetStringFromColumnFamilyOptions(&options_str, db_pointer->db->GetOptions());
151
+
152
+ v_key = rb_str_new_cstr("CFOptions");
153
+ v_value = rb_str_new_cstr(options_str.c_str());
154
+ rb_hash_aset(v_result, v_key, v_value);
155
+
156
+ return v_result;
119
157
  }
120
158
 
121
159
  VALUE rocksdb_db_get(VALUE self, VALUE v_key){
122
- Check_Type(v_key, T_STRING);
160
+ rocksdb_pointer* db_pointer = get_db_for_read(&self);
123
161
 
124
- rocksdb_pointer* db_pointer;
125
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
126
- std::string key = std::string((char*)RSTRING_PTR(v_key), RSTRING_LEN(v_key));
162
+ rocksdb::Slice key = SLICE_FROM_RB_VALUE(v_key);
127
163
  std::string value;
128
- if (db_pointer->db == NULL) {
129
- rb_raise(rb_eRuntimeError, "db not open");
130
- }
131
- rocksdb::Status status = db_pointer->db->Get(rocksdb::ReadOptions(), key, &value);
132
164
 
133
- return (status.IsNotFound()) ? Qnil : rb_enc_str_new(value.data(), value.size(), rb_utf8_encoding());
165
+ rocksdb::Status status = db_pointer->db->Get(rocksdb::ReadOptions(), key, &value);
134
166
 
135
- }
167
+ if(status.IsNotFound()) {
168
+ return Qnil;
169
+ } else if (!status.ok()) {
170
+ raise_status_error(&status);
171
+ return Qnil;
172
+ }
136
173
 
174
+ return SLICE_TO_RB_STRING(value);
175
+ }
137
176
 
138
177
  VALUE rocksdb_db_multi_get(VALUE self, VALUE v_array){
139
178
  Check_Type(v_array, T_ARRAY);
140
179
 
141
- rocksdb_pointer* db_pointer;
142
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
180
+ rocksdb_pointer* db_pointer = get_db_for_read(&self);
143
181
 
144
182
  long i;
145
183
  long length = RARRAY_LEN(v_array);
146
184
  std::vector<std::string> values(length);
147
185
  std::vector<rocksdb::Slice> keys(length);
148
- std::vector<rocksdb::Status> status;
186
+ std::vector<rocksdb::Status> statuses;
149
187
 
150
188
  for(i=0; i < length; i++){
151
- VALUE op = rb_ary_entry(v_array, i);
152
- keys[i] = rocksdb::Slice((char*)RSTRING_PTR(op), RSTRING_LEN(op));
189
+ VALUE v_element = rb_ary_entry(v_array, i);
190
+ keys[i] = SLICE_FROM_RB_VALUE(v_element);
153
191
  }
154
192
 
155
- if (db_pointer->db == NULL) {
156
- rb_raise(rb_eRuntimeError, "db not open");
157
- }
158
- status = db_pointer->db->MultiGet(rocksdb::ReadOptions(),keys,&values);
193
+ statuses = db_pointer->db->MultiGet(rocksdb::ReadOptions(), keys, &values);
194
+
159
195
  for(i=0; i < length; i++){
160
- rb_ary_store(v_array, i, rb_enc_str_new(values[i].data(), values[i].size(), rb_utf8_encoding()));
196
+ rocksdb::Status status = statuses[i];
197
+
198
+ if(status.IsNotFound()) {
199
+ rb_ary_store(v_array, i, Qnil);
200
+ } else if(status.ok()) {
201
+ rb_ary_store(v_array, i, SLICE_TO_RB_STRING(values[i]));
202
+ } else {
203
+ rb_ary_store(v_array, i, Qfalse);
204
+ }
161
205
  }
206
+
162
207
  return v_array;
163
208
  }
164
-
209
+
165
210
  VALUE rocksdb_db_delete(VALUE self, VALUE v_key){
166
- Check_Type(v_key, T_STRING);
167
-
168
- rocksdb_pointer* db_pointer;
169
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
211
+ rocksdb_pointer* db_pointer = get_db_for_write(&self);
170
212
 
171
- std::string key = std::string((char*)RSTRING_PTR(v_key), RSTRING_LEN(v_key));
172
- if (db_pointer->db == NULL) {
173
- rb_raise(rb_eRuntimeError, "db not open");
174
- }
175
- if (db_pointer->readonly) {
176
- rb_raise(rb_eRuntimeError, "readonly");
177
- }
213
+ rocksdb::Slice key = SLICE_FROM_RB_VALUE(v_key);
178
214
  rocksdb::Status status = db_pointer->db->Delete(rocksdb::WriteOptions(), key);
179
-
180
- return status.ok() ? Qtrue : Qfalse;
215
+
216
+ // https://github.com/facebook/rocksdb/issues/4975
217
+ if (status.ok()) {
218
+ return Qtrue;
219
+ } else {
220
+ raise_status_error(&status);
221
+ return Qfalse;
222
+ }
181
223
  }
182
224
 
183
225
  VALUE rocksdb_db_exists(VALUE self, VALUE v_key){
184
- Check_Type(v_key, T_STRING);
185
-
186
- rocksdb_pointer* db_pointer;
187
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
226
+ rocksdb_pointer* db_pointer = get_db_for_read(&self);
188
227
 
189
- std::string key = std::string((char*)RSTRING_PTR(v_key), RSTRING_LEN(v_key));
228
+ rocksdb::Slice key = SLICE_FROM_RB_VALUE(v_key);
190
229
  std::string value = std::string();
191
-
192
- if (db_pointer->db == NULL) {
193
- rb_raise(rb_eRuntimeError, "db not open");
194
- }
195
- return db_pointer->db->KeyMayExist(rocksdb::ReadOptions(), key, &value) ? Qtrue : Qfalse;
196
- }
197
230
 
198
- VALUE rocksdb_db_close(VALUE self){
199
- rocksdb_pointer* db_pointer;
200
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
201
-
202
- if(db_pointer->db != NULL){
203
- delete db_pointer->db;
204
- db_pointer->db = NULL;
205
- }
206
- return Qnil;
231
+ return db_pointer->db->KeyMayExist(rocksdb::ReadOptions(), key, &value) ? Qtrue : Qfalse;
207
232
  }
208
233
 
209
- void db_free(rocksdb_pointer* db_pointer){
210
- if(db_pointer->db != NULL){
211
- delete db_pointer->db;
212
- db_pointer->db = NULL;
213
- }
214
- delete db_pointer;
215
- }
216
234
 
217
- VALUE rocksdb_db_new_iterator(VALUE self){
218
- rocksdb_pointer* db_pointer;
235
+ VALUE rocksdb_db_to_iterator(VALUE self){
236
+ rocksdb_pointer* db_pointer = get_db_for_read(&self);
219
237
  rocksdb_iterator_pointer* rocksdb_it;
220
238
 
221
- VALUE klass;
222
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
223
-
224
- if (db_pointer->db == NULL) {
225
- rb_raise(rb_eRuntimeError, "db not open");
226
- }
227
239
  rocksdb::Iterator* it = db_pointer->db->NewIterator(rocksdb::ReadOptions());
228
240
 
241
+ VALUE klass;
229
242
  klass = rb_class_new_instance(0, NULL, cRocksdb_iterator);
230
243
 
231
244
  Data_Get_Struct(klass, rocksdb_iterator_pointer , rocksdb_it);
232
245
  rocksdb_it->it = it;
246
+ rocksdb_it->db_pointer = db_pointer;
247
+
233
248
  return klass;
234
249
  }
235
250
 
251
+ VALUE rocksdb_db_debug(VALUE self){
252
+ return Qnil;
253
+ }
236
254
 
237
- VALUE rocksdb_db_each(VALUE self){
238
- if(!rb_block_given_p()){
239
- return rocksdb_db_new_iterator(self);
240
- }
241
-
242
- rocksdb_pointer* db_pointer;
243
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
244
- if (db_pointer->db == NULL) {
245
- rb_raise(rb_eRuntimeError, "db not open");
246
- }
247
- rocksdb::Iterator* it = db_pointer->db->NewIterator(rocksdb::ReadOptions());
255
+ VALUE rocksdb_db_is_writable(VALUE self){
256
+ rocksdb_pointer* db_pointer = get_db(&self);
248
257
 
249
- for (it->SeekToFirst(); it->Valid(); it->Next()) {
250
- rb_yield(rb_enc_str_new(it->value().data(), it->value().size(), rb_utf8_encoding()));
251
- }
252
-
253
- delete it;
254
- return self;
258
+ return (db_pointer->readonly) ? Qfalse : Qtrue;
255
259
  }
256
260
 
257
- VALUE rocksdb_db_each_index(VALUE self){
258
- if(!rb_block_given_p()){
259
- return rocksdb_db_new_iterator(self);
260
- }
261
-
262
- rocksdb_pointer* db_pointer;
263
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
264
- if (db_pointer->db == NULL) {
265
- rb_raise(rb_eRuntimeError, "db not open");
266
- }
267
- rocksdb::Iterator* it = db_pointer->db->NewIterator(rocksdb::ReadOptions());
261
+ VALUE rocksdb_db_is_open(VALUE self){
262
+ rocksdb_pointer* db_pointer = get_db(&self);
268
263
 
269
- for (it->SeekToFirst(); it->Valid(); it->Next()) {
270
- rb_yield(rb_enc_str_new(it->key().data(), it->key().size(), rb_utf8_encoding()));
271
- }
272
-
273
- delete it;
274
- return self;
264
+ return (db_pointer->db == NULL) ? Qfalse : Qtrue;
275
265
  }
276
266
 
277
- VALUE rocksdb_db_each_with_index(VALUE self){
278
- if(!rb_block_given_p()){
279
- return rocksdb_db_new_iterator(self);
280
- }
281
-
282
- rocksdb_pointer* db_pointer;
283
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
284
- if (db_pointer->db == NULL) {
285
- rb_raise(rb_eRuntimeError, "db not open");
267
+ VALUE rocksdb_db_compact(int argc, VALUE* argv, VALUE self) {
268
+ VALUE v_from, v_to;
269
+ rocksdb::Slice from, to;
270
+
271
+ rb_scan_args(argc, argv, "02", &v_from, &v_to);
272
+
273
+ if(!NIL_P(v_from)) {
274
+ from = SLICE_FROM_RB_VALUE(v_from);
286
275
  }
287
- rocksdb::Iterator* it = db_pointer->db->NewIterator(rocksdb::ReadOptions());
288
276
 
289
- for (it->SeekToFirst(); it->Valid(); it->Next()) {
290
- VALUE a = rb_enc_str_new(it->key().data(), it->key().size(), rb_utf8_encoding());
291
- VALUE b = rb_enc_str_new(it->value().data(), it->value().size(), rb_utf8_encoding());
292
- rb_yield_values(2, a, b);
277
+ if(!NIL_P(v_to)) {
278
+ to = SLICE_FROM_RB_VALUE(v_to);
293
279
  }
294
-
295
- delete it;
296
- return self;
280
+
281
+ rocksdb_pointer* db_pointer = get_db_for_read(&self);
282
+ rocksdb::Status status = db_pointer->db->CompactRange(rocksdb::CompactRangeOptions(), &from, &to);
283
+
284
+ return status.ok() ? Qtrue : Qfalse;
297
285
  }
298
286
 
299
-
287
+ VALUE raise_status_error(rocksdb::Status *status) {
288
+ char const *error_text = status->ToString().c_str();
289
+ rb_raise(cRocksdb_status_error, "%s", error_text);
300
290
 
301
- VALUE rocksdb_db_reverse_each(VALUE self){
302
- rocksdb_pointer* db_pointer;
303
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
304
- if (db_pointer->db == NULL) {
305
- rb_raise(rb_eRuntimeError, "db not open");
306
- }
307
- rocksdb::Iterator* it = db_pointer->db->NewIterator(rocksdb::ReadOptions());
291
+ return Qnil;
292
+ }
308
293
 
309
- for (it->SeekToLast(); it->Valid(); it->Prev()) {
310
- rb_yield(rb_enc_str_new(it->value().data(), it->value().size(), rb_utf8_encoding()));
311
- }
312
-
313
- delete it;
314
- return self;
294
+ rocksdb_pointer* get_db(VALUE *self) {
295
+ rocksdb_pointer *db_pointer;
296
+ Data_Get_Struct(*self, rocksdb_pointer, db_pointer);
297
+
298
+ return db_pointer;
315
299
  }
316
300
 
317
- VALUE rocksdb_db_debug(VALUE self){
318
- return Qnil;
301
+ rocksdb_pointer* get_db_for_read(VALUE *self) {
302
+ rocksdb_pointer *db_pointer = get_db(self);
303
+
304
+ check_is_db_ready(db_pointer);
305
+
306
+ return db_pointer;
319
307
  }
320
308
 
321
- VALUE rocksdb_db_compact(int argc, VALUE* argv, VALUE self) {
322
- VALUE v_from, v_to;
323
- rocksdb::Slice from, to;
309
+ rocksdb_pointer* get_db_for_write(VALUE *self) {
310
+ rocksdb_pointer *db_pointer = get_db(self);
324
311
 
325
- rb_scan_args(argc, argv, "02", &v_from, &v_to);
312
+ check_is_db_ready(db_pointer);
326
313
 
327
- if(!NIL_P(v_from)) {
328
- Check_Type(v_from, T_STRING);
329
- from = rocksdb::Slice((char*)RSTRING_PTR(v_from), RSTRING_LEN(v_from));
314
+ if (db_pointer->readonly) {
315
+ rb_raise(cRocksdb_readonly, "database is read-only");
330
316
  }
331
317
 
332
- if(!NIL_P(v_to)) {
333
- Check_Type(v_to, T_STRING);
334
- to = rocksdb::Slice((char*)RSTRING_PTR(v_to), RSTRING_LEN(v_to));
318
+ return db_pointer;
319
+ }
320
+
321
+ void check_is_db_ready(rocksdb_pointer *db_pointer) {
322
+ if (db_pointer == NULL) {
323
+ rb_raise(cRocksdb_database_closed, "database is not initialized");
335
324
  }
336
325
 
337
- rocksdb_pointer* db_pointer;
338
- Data_Get_Struct(self, rocksdb_pointer, db_pointer);
339
326
  if (db_pointer->db == NULL) {
340
- rb_raise(rb_eRuntimeError, "db not open");
327
+ rb_raise(cRocksdb_database_closed, "database is not opened");
341
328
  }
342
- rocksdb::Status status = db_pointer->db->CompactRange(rocksdb::CompactRangeOptions(), &from, &to);
343
- return status.ok() ? Qtrue : Qfalse;
344
329
  }
345
330
  }