rocksdb-ruby 0.2.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  }