leveldb-ruby 0.10 → 0.11
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.
- data/ext/leveldb/extconf.rb +2 -6
- data/ext/leveldb/leveldb.cc +377 -33
- data/ext/leveldb/platform.rb +83 -0
- data/leveldb/Makefile +29 -28
- data/leveldb/build_detect_platform +23 -4
- data/leveldb/db/builder.cc +1 -1
- data/leveldb/db/builder.h +1 -1
- data/leveldb/db/corruption_test.cc +1 -1
- data/leveldb/db/db_bench.cc +2 -2
- data/leveldb/db/db_impl.cc +8 -16
- data/leveldb/db/db_impl.h +1 -1
- data/leveldb/db/db_iter.cc +1 -1
- data/leveldb/db/db_iter.h +1 -1
- data/leveldb/db/db_test.cc +180 -9
- data/leveldb/db/dbformat.cc +9 -7
- data/leveldb/db/dbformat.h +2 -2
- data/leveldb/db/dbformat_test.cc +1 -1
- data/leveldb/db/filename.cc +6 -2
- data/leveldb/db/filename.h +1 -1
- data/leveldb/db/filename_test.cc +1 -1
- data/leveldb/db/log_format.h +2 -2
- data/leveldb/db/log_reader.cc +2 -2
- data/leveldb/db/log_reader.h +2 -2
- data/leveldb/db/log_test.cc +2 -2
- data/leveldb/db/log_writer.cc +2 -2
- data/leveldb/db/log_writer.h +2 -2
- data/leveldb/db/memtable.cc +1 -1
- data/leveldb/db/memtable.h +1 -1
- data/leveldb/db/repair.cc +2 -2
- data/leveldb/db/skiplist.h +1 -1
- data/leveldb/db/skiplist_test.cc +1 -1
- data/leveldb/db/snapshot.h +1 -1
- data/leveldb/db/table_cache.cc +1 -1
- data/leveldb/db/table_cache.h +1 -1
- data/leveldb/db/version_edit.cc +1 -1
- data/leveldb/db/version_edit.h +1 -1
- data/leveldb/db/version_edit_test.cc +1 -1
- data/leveldb/db/version_set.cc +39 -14
- data/leveldb/db/version_set.h +1 -1
- data/leveldb/db/version_set_test.cc +1 -1
- data/leveldb/db/write_batch.cc +2 -2
- data/leveldb/db/write_batch_internal.h +1 -1
- data/leveldb/db/write_batch_test.cc +1 -1
- data/leveldb/helpers/memenv/memenv.cc +374 -0
- data/leveldb/helpers/memenv/memenv.h +20 -0
- data/leveldb/helpers/memenv/memenv_test.cc +232 -0
- data/leveldb/include/leveldb/cache.h +1 -1
- data/leveldb/include/leveldb/comparator.h +1 -1
- data/leveldb/include/leveldb/db.h +1 -1
- data/leveldb/include/leveldb/env.h +1 -1
- data/leveldb/include/leveldb/iterator.h +1 -1
- data/leveldb/include/leveldb/options.h +1 -1
- data/leveldb/include/leveldb/slice.h +1 -1
- data/leveldb/include/leveldb/status.h +1 -1
- data/leveldb/include/leveldb/table.h +1 -1
- data/leveldb/include/leveldb/table_builder.h +1 -1
- data/leveldb/include/leveldb/write_batch.h +1 -1
- data/leveldb/port/atomic_pointer.h +2 -2
- data/leveldb/port/port_android.cc +2 -2
- data/leveldb/port/port_android.h +2 -2
- data/leveldb/port/port_example.h +2 -2
- data/leveldb/port/port_posix.cc +2 -2
- data/leveldb/port/port_posix.h +11 -3
- data/leveldb/table/block.cc +1 -1
- data/leveldb/table/block.h +1 -1
- data/leveldb/table/block_builder.cc +1 -1
- data/leveldb/table/block_builder.h +1 -1
- data/leveldb/table/format.cc +1 -1
- data/leveldb/table/format.h +1 -1
- data/leveldb/table/iterator.cc +2 -2
- data/leveldb/table/merger.cc +2 -2
- data/leveldb/table/merger.h +1 -1
- data/leveldb/table/table.cc +1 -1
- data/leveldb/table/table_builder.cc +1 -1
- data/leveldb/table/table_test.cc +3 -3
- data/leveldb/table/two_level_iterator.cc +2 -2
- data/leveldb/table/two_level_iterator.h +1 -1
- data/leveldb/util/arena.cc +1 -1
- data/leveldb/util/arena.h +1 -1
- data/leveldb/util/arena_test.cc +1 -1
- data/leveldb/util/cache.cc +1 -1
- data/leveldb/util/cache_test.cc +1 -1
- data/leveldb/util/coding.cc +1 -1
- data/leveldb/util/coding.h +1 -1
- data/leveldb/util/coding_test.cc +1 -1
- data/leveldb/util/comparator.cc +7 -4
- data/leveldb/util/crc32c.cc +2 -2
- data/leveldb/util/crc32c.h +2 -2
- data/leveldb/util/crc32c_test.cc +2 -2
- data/leveldb/util/env.cc +17 -3
- data/leveldb/util/env_posix.cc +2 -2
- data/leveldb/util/env_test.cc +13 -11
- data/leveldb/util/hash.cc +1 -1
- data/leveldb/util/histogram.cc +1 -1
- data/leveldb/util/histogram.h +1 -1
- data/leveldb/util/logging.cc +1 -1
- data/leveldb/util/logging.h +1 -1
- data/leveldb/util/mutexlock.h +1 -1
- data/leveldb/util/options.cc +1 -1
- data/leveldb/util/posix_logger.h +1 -1
- data/leveldb/util/random.h +1 -1
- data/leveldb/util/status.cc +1 -1
- data/leveldb/util/testharness.cc +2 -2
- data/leveldb/util/testharness.h +2 -2
- data/leveldb/util/testutil.cc +2 -2
- data/leveldb/util/testutil.h +2 -2
- data/lib/leveldb.rb +34 -2
- metadata +7 -13
- data/leveldb/port/port_chromium.cc +0 -80
- data/leveldb/port/port_chromium.h +0 -97
- data/leveldb/port/port_osx.cc +0 -50
- data/leveldb/port/port_osx.h +0 -125
- data/leveldb/port/sha1_portable.cc +0 -298
- data/leveldb/port/sha1_portable.h +0 -25
- data/leveldb/port/sha1_test.cc +0 -39
- data/leveldb/util/env_chromium.cc +0 -612
data/ext/leveldb/extconf.rb
CHANGED
@@ -1,18 +1,14 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
require 'fileutils'
|
3
|
+
require "./platform.rb"
|
3
4
|
|
4
5
|
Dir.chdir "../../leveldb"
|
5
6
|
system "make libleveldb.a" or abort
|
6
7
|
Dir.chdir "../ext/leveldb"
|
7
8
|
|
8
|
-
|
9
|
+
set_platform_specific_variables!
|
9
10
|
|
10
11
|
$CFLAGS << " -I../../leveldb/include"
|
11
12
|
$LIBS << " -L../../leveldb -lleveldb"
|
12
|
-
if RUBY_PLATFORM =~ /darwin/
|
13
|
-
$CFLAGS.sub! "-arch i386", ""
|
14
|
-
$LDFLAGS.sub! "-arch i386", ""
|
15
|
-
$LIBS << " -lruby" # whyyyyy
|
16
|
-
end
|
17
13
|
|
18
14
|
create_makefile "leveldb/leveldb"
|
data/ext/leveldb/leveldb.cc
CHANGED
@@ -2,10 +2,23 @@
|
|
2
2
|
|
3
3
|
#include "leveldb/db.h"
|
4
4
|
#include "leveldb/slice.h"
|
5
|
+
#include "leveldb/write_batch.h"
|
5
6
|
|
6
7
|
static VALUE m_leveldb;
|
7
8
|
static VALUE c_db;
|
9
|
+
static VALUE c_iter;
|
10
|
+
static VALUE c_batch;
|
8
11
|
static VALUE c_error;
|
12
|
+
static VALUE k_fill;
|
13
|
+
static VALUE k_verify;
|
14
|
+
static VALUE k_sync;
|
15
|
+
static VALUE k_from;
|
16
|
+
static VALUE k_to;
|
17
|
+
static VALUE k_reversed;
|
18
|
+
static VALUE k_class;
|
19
|
+
static VALUE k_name;
|
20
|
+
static ID to_s;
|
21
|
+
static leveldb::ReadOptions uncached_read_options;
|
9
22
|
|
10
23
|
// support 1.9 and 1.8
|
11
24
|
#ifndef RSTRING_PTR
|
@@ -62,37 +75,89 @@ static VALUE db_close(VALUE self) {
|
|
62
75
|
return Qtrue;
|
63
76
|
}
|
64
77
|
|
78
|
+
static leveldb::ReadOptions parse_read_options(VALUE options) {
|
79
|
+
leveldb::ReadOptions readOptions;
|
80
|
+
|
81
|
+
if(!NIL_P(options)) {
|
82
|
+
Check_Type(options, T_HASH);
|
83
|
+
if(rb_hash_aref(options, k_fill) == Qfalse)
|
84
|
+
readOptions.fill_cache = false;
|
85
|
+
if(rb_hash_aref(options, k_verify) == Qtrue)
|
86
|
+
readOptions.verify_checksums = true;
|
87
|
+
}
|
88
|
+
|
89
|
+
return readOptions;
|
90
|
+
}
|
91
|
+
|
92
|
+
static leveldb::WriteOptions parse_write_options(VALUE options) {
|
93
|
+
leveldb::WriteOptions writeOptions;
|
94
|
+
|
95
|
+
if(!NIL_P(options)) {
|
96
|
+
Check_Type(options, T_HASH);
|
97
|
+
if(rb_hash_aref(options, k_sync) == Qtrue)
|
98
|
+
writeOptions.sync = true;
|
99
|
+
}
|
100
|
+
|
101
|
+
return writeOptions;
|
102
|
+
}
|
103
|
+
|
65
104
|
#define RUBY_STRING_TO_SLICE(x) leveldb::Slice(RSTRING_PTR(x), RSTRING_LEN(x))
|
66
105
|
#define SLICE_TO_RUBY_STRING(x) rb_str_new(x.data(), x.size())
|
67
106
|
#define STRING_TO_RUBY_STRING(x) rb_str_new(x.data(), x.size())
|
68
|
-
|
107
|
+
|
108
|
+
/*
|
109
|
+
* call-seq:
|
110
|
+
* get(key, options = nil)
|
111
|
+
*
|
112
|
+
* get data from db
|
113
|
+
*
|
114
|
+
* [key] key you want to get
|
115
|
+
* [options[ :fill_cache ]] Should the data read for this iteration be cached in memory?
|
116
|
+
* Callers may wish to set this field to false for bulk scans.
|
117
|
+
*
|
118
|
+
* true or false
|
119
|
+
*
|
120
|
+
* Default: true
|
121
|
+
* [options[ :verify_checksums ]] If true, all data read from underlying storage will be
|
122
|
+
* verified against corresponding checksums.
|
123
|
+
*
|
124
|
+
* Default: false
|
125
|
+
* [return] value of stored db
|
126
|
+
*/
|
127
|
+
static VALUE db_get(int argc, VALUE* argv, VALUE self) {
|
128
|
+
VALUE v_key, v_options;
|
129
|
+
rb_scan_args(argc, argv, "11", &v_key, &v_options);
|
69
130
|
Check_Type(v_key, T_STRING);
|
131
|
+
leveldb::ReadOptions readOptions = parse_read_options(v_options);
|
70
132
|
|
71
133
|
bound_db* db;
|
72
134
|
Data_Get_Struct(self, bound_db, db);
|
73
135
|
|
74
136
|
leveldb::Slice key = RUBY_STRING_TO_SLICE(v_key);
|
75
137
|
std::string value;
|
76
|
-
leveldb::Status status = db->db->Get(
|
138
|
+
leveldb::Status status = db->db->Get(readOptions, key, &value);
|
77
139
|
if(status.IsNotFound()) return Qnil;
|
78
140
|
|
79
141
|
RAISE_ON_ERROR(status);
|
80
142
|
return STRING_TO_RUBY_STRING(value);
|
81
143
|
}
|
82
144
|
|
83
|
-
static VALUE db_delete(VALUE
|
145
|
+
static VALUE db_delete(int argc, VALUE* argv, VALUE self) {
|
146
|
+
VALUE v_key, v_options;
|
147
|
+
rb_scan_args(argc, argv, "11", &v_key, &v_options);
|
84
148
|
Check_Type(v_key, T_STRING);
|
149
|
+
leveldb::WriteOptions writeOptions = parse_write_options(v_options);
|
85
150
|
|
86
151
|
bound_db* db;
|
87
152
|
Data_Get_Struct(self, bound_db, db);
|
88
153
|
|
89
154
|
leveldb::Slice key = RUBY_STRING_TO_SLICE(v_key);
|
90
155
|
std::string value;
|
91
|
-
leveldb::Status status = db->db->Get(
|
156
|
+
leveldb::Status status = db->db->Get(uncached_read_options, key, &value);
|
92
157
|
|
93
158
|
if(status.IsNotFound()) return Qnil;
|
94
159
|
|
95
|
-
status = db->db->Delete(
|
160
|
+
status = db->db->Delete(writeOptions, key);
|
96
161
|
RAISE_ON_ERROR(status);
|
97
162
|
|
98
163
|
return STRING_TO_RUBY_STRING(value);
|
@@ -112,16 +177,46 @@ static VALUE db_exists(VALUE self, VALUE v_key) {
|
|
112
177
|
return Qtrue;
|
113
178
|
}
|
114
179
|
|
115
|
-
|
180
|
+
/*
|
181
|
+
* call-seq:
|
182
|
+
* put(key, value, options = nil)
|
183
|
+
*
|
184
|
+
* store data into DB
|
185
|
+
*
|
186
|
+
* [key] key you want to store
|
187
|
+
* [value] data you want to store
|
188
|
+
* [options[ :sync ]] If true, the write will be flushed from the operating system
|
189
|
+
* buffer cache (by calling WritableFile::Sync()) before the write
|
190
|
+
* is considered complete. If this flag is true, writes will be
|
191
|
+
* slower.
|
192
|
+
*
|
193
|
+
* If this flag is false, and the machine crashes, some recent
|
194
|
+
* writes may be lost. Note that if it is just the process that
|
195
|
+
* crashes (i.e., the machine does not reboot), no writes will be
|
196
|
+
* lost even if sync==false.
|
197
|
+
*
|
198
|
+
* In other words, a DB write with sync==false has similar
|
199
|
+
* crash semantics as the "write()" system call. A DB write
|
200
|
+
* with sync==true has similar crash semantics to a "write()"
|
201
|
+
* system call followed by "fsync()".
|
202
|
+
*
|
203
|
+
* Default: false
|
204
|
+
* [return] stored value
|
205
|
+
*/
|
206
|
+
static VALUE db_put(int argc, VALUE* argv, VALUE self) {
|
207
|
+
VALUE v_key, v_value, v_options;
|
208
|
+
|
209
|
+
rb_scan_args(argc, argv, "21", &v_key, &v_value, &v_options);
|
116
210
|
Check_Type(v_key, T_STRING);
|
117
211
|
Check_Type(v_value, T_STRING);
|
212
|
+
leveldb::WriteOptions writeOptions = parse_write_options(v_options);
|
118
213
|
|
119
214
|
bound_db* db;
|
120
215
|
Data_Get_Struct(self, bound_db, db);
|
121
216
|
|
122
217
|
leveldb::Slice key = RUBY_STRING_TO_SLICE(v_key);
|
123
218
|
leveldb::Slice value = RUBY_STRING_TO_SLICE(v_value);
|
124
|
-
leveldb::Status status = db->db->Put(
|
219
|
+
leveldb::Status status = db->db->Put(writeOptions, key, value);
|
125
220
|
|
126
221
|
RAISE_ON_ERROR(status);
|
127
222
|
|
@@ -133,7 +228,7 @@ static VALUE db_size(VALUE self) {
|
|
133
228
|
|
134
229
|
bound_db* db;
|
135
230
|
Data_Get_Struct(self, bound_db, db);
|
136
|
-
leveldb::Iterator* it = db->db->NewIterator(
|
231
|
+
leveldb::Iterator* it = db->db->NewIterator(uncached_read_options);
|
137
232
|
|
138
233
|
// apparently this is how we have to do it. slow and painful!
|
139
234
|
for (it->SeekToFirst(); it->Valid(); it->Next()) count++;
|
@@ -142,45 +237,294 @@ static VALUE db_size(VALUE self) {
|
|
142
237
|
return INT2NUM(count);
|
143
238
|
}
|
144
239
|
|
145
|
-
static VALUE
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
240
|
+
static VALUE db_init(VALUE self, VALUE v_pathname) {
|
241
|
+
rb_iv_set(self, "@pathname", v_pathname);
|
242
|
+
return self;
|
243
|
+
}
|
244
|
+
|
245
|
+
typedef struct current_iteration {
|
246
|
+
leveldb::Iterator* iterator;
|
247
|
+
bool passed_limit;
|
248
|
+
bool check_limit;
|
249
|
+
bool reversed;
|
250
|
+
int checked_valid; // 0 = unchecked, 1 = valid, -1 = invalid
|
251
|
+
std::string key_to_str;
|
252
|
+
leveldb::Slice current_key;
|
253
|
+
} current_iteration;
|
254
|
+
|
255
|
+
static void current_iteration_free(current_iteration* iter) {
|
256
|
+
delete iter;
|
257
|
+
}
|
258
|
+
|
259
|
+
static VALUE iter_make(VALUE klass, VALUE db, VALUE options) {
|
260
|
+
if(c_db != rb_funcall(db, k_class, 0)) {
|
261
|
+
rb_raise(rb_eArgError, "db must be a LevelDB::DB");
|
157
262
|
}
|
158
263
|
|
159
|
-
|
160
|
-
|
264
|
+
bound_db* b_db;
|
265
|
+
Data_Get_Struct(db, bound_db, b_db);
|
266
|
+
|
267
|
+
current_iteration* iter = new current_iteration;
|
268
|
+
iter->passed_limit = false;
|
269
|
+
iter->check_limit = false;
|
270
|
+
iter->checked_valid = 0;
|
271
|
+
iter->iterator = b_db->db->NewIterator(uncached_read_options);
|
272
|
+
|
273
|
+
VALUE o_iter = Data_Wrap_Struct(klass, NULL, current_iteration_free, iter);
|
274
|
+
|
275
|
+
VALUE argv[2];
|
276
|
+
argv[0] = db;
|
277
|
+
argv[1] = options;
|
278
|
+
rb_obj_call_init(o_iter, 2, argv);
|
279
|
+
|
280
|
+
return o_iter;
|
281
|
+
}
|
282
|
+
|
283
|
+
static VALUE iter_init(VALUE self, VALUE db, VALUE options) {
|
284
|
+
if(c_db != rb_funcall(db, k_class, 0)) {
|
285
|
+
rb_raise(rb_eArgError, "db must be a LevelDB::DB");
|
286
|
+
}
|
287
|
+
|
288
|
+
rb_iv_set(self, "@db", db);
|
289
|
+
current_iteration* iter;
|
290
|
+
Data_Get_Struct(self, current_iteration, iter);
|
291
|
+
|
292
|
+
VALUE key_from = Qnil;
|
293
|
+
VALUE key_to = Qnil;
|
294
|
+
|
295
|
+
if(!NIL_P(options)) {
|
296
|
+
Check_Type(options, T_HASH);
|
297
|
+
key_from = rb_hash_aref(options, k_from);
|
298
|
+
key_to = rb_hash_aref(options, k_to);
|
299
|
+
|
300
|
+
if(RTEST(key_to)) {
|
301
|
+
iter->check_limit = true;
|
302
|
+
iter->key_to_str = RUBY_STRING_TO_SLICE(rb_funcall(key_to, to_s, 0)).ToString();
|
303
|
+
}
|
304
|
+
|
305
|
+
rb_iv_set(self, "@from", key_from);
|
306
|
+
rb_iv_set(self, "@to", key_to);
|
307
|
+
if(NIL_P(rb_hash_aref(options, k_reversed))) {
|
308
|
+
iter->reversed = false;
|
309
|
+
rb_iv_set(self, "@reversed", false);
|
310
|
+
} else {
|
311
|
+
iter->reversed = true;
|
312
|
+
rb_iv_set(self, "@reversed", true);
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
if(RTEST(key_from)) {
|
317
|
+
iter->iterator->Seek(RUBY_STRING_TO_SLICE(rb_funcall(key_from, to_s, 0)));
|
318
|
+
} else {
|
319
|
+
if(iter->reversed) {
|
320
|
+
iter->iterator->SeekToLast();
|
321
|
+
} else {
|
322
|
+
iter->iterator->SeekToFirst();
|
323
|
+
}
|
324
|
+
}
|
161
325
|
|
162
326
|
return self;
|
163
327
|
}
|
164
328
|
|
165
|
-
static
|
166
|
-
|
329
|
+
static bool iter_valid(current_iteration* iter) {
|
330
|
+
if(iter->checked_valid == 0) {
|
331
|
+
if(iter->passed_limit) {
|
332
|
+
iter->checked_valid = -2;
|
333
|
+
} else {
|
334
|
+
if(iter->iterator->Valid()) {
|
335
|
+
iter->current_key = iter->iterator->key();
|
336
|
+
|
337
|
+
if(iter->check_limit &&
|
338
|
+
(iter->reversed ?
|
339
|
+
(iter->current_key.ToString() < iter->key_to_str) :
|
340
|
+
(iter->current_key.ToString() > iter->key_to_str))) {
|
341
|
+
iter->passed_limit = true;
|
342
|
+
iter->checked_valid = -2;
|
343
|
+
} else {
|
344
|
+
iter->checked_valid = 1;
|
345
|
+
}
|
346
|
+
|
347
|
+
} else {
|
348
|
+
iter->checked_valid = -1;
|
349
|
+
}
|
350
|
+
}
|
351
|
+
}
|
352
|
+
|
353
|
+
if(iter->checked_valid == 1)
|
354
|
+
return true;
|
355
|
+
else
|
356
|
+
return false;
|
357
|
+
}
|
358
|
+
|
359
|
+
static VALUE iter_invalid_reason(VALUE self) {
|
360
|
+
current_iteration* iter;
|
361
|
+
Data_Get_Struct(self, current_iteration, iter);
|
362
|
+
if(iter_valid(iter)) {
|
363
|
+
return Qnil;
|
364
|
+
} else {
|
365
|
+
return INT2FIX(iter->checked_valid);
|
366
|
+
}
|
367
|
+
}
|
368
|
+
|
369
|
+
static VALUE iter_next_value(current_iteration* iter) {
|
370
|
+
VALUE arr = rb_ary_new2(2);
|
371
|
+
rb_ary_push(arr, SLICE_TO_RUBY_STRING(iter->current_key));
|
372
|
+
rb_ary_push(arr, SLICE_TO_RUBY_STRING(iter->iterator->value()));
|
373
|
+
}
|
374
|
+
|
375
|
+
static void iter_scan_iterator(current_iteration* iter) {
|
376
|
+
if(iter->reversed)
|
377
|
+
iter->iterator->Prev();
|
378
|
+
else
|
379
|
+
iter->iterator->Next();
|
380
|
+
iter->checked_valid = 0;
|
381
|
+
}
|
382
|
+
|
383
|
+
static VALUE iter_peek(VALUE self) {
|
384
|
+
current_iteration* iter;
|
385
|
+
Data_Get_Struct(self, current_iteration, iter);
|
386
|
+
if(iter_valid(iter)) {
|
387
|
+
return iter_next_value(iter);
|
388
|
+
} else {
|
389
|
+
return Qnil;
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
static VALUE iter_scan(VALUE self) {
|
394
|
+
current_iteration* iter;
|
395
|
+
Data_Get_Struct(self, current_iteration, iter);
|
396
|
+
if(iter_valid(iter))
|
397
|
+
iter_scan_iterator(iter);
|
398
|
+
return Qnil;
|
399
|
+
}
|
400
|
+
|
401
|
+
static VALUE iter_next(VALUE self) {
|
402
|
+
current_iteration* iter;
|
403
|
+
Data_Get_Struct(self, current_iteration, iter);
|
404
|
+
|
405
|
+
VALUE arr = Qnil;
|
406
|
+
|
407
|
+
if(iter_valid(iter)) {
|
408
|
+
arr = iter_next_value(iter);
|
409
|
+
iter_scan_iterator(iter);
|
410
|
+
}
|
411
|
+
|
412
|
+
return arr;
|
413
|
+
}
|
414
|
+
|
415
|
+
static VALUE iter_each(VALUE self) {
|
416
|
+
current_iteration* iter;
|
417
|
+
Data_Get_Struct(self, current_iteration, iter);
|
418
|
+
|
419
|
+
while(iter_valid(iter)) {
|
420
|
+
rb_yield(iter_next_value(iter));
|
421
|
+
iter_scan_iterator(iter);
|
422
|
+
}
|
423
|
+
|
424
|
+
RAISE_ON_ERROR(iter->iterator->status());
|
425
|
+
delete iter->iterator;
|
167
426
|
return self;
|
168
427
|
}
|
169
428
|
|
429
|
+
typedef struct bound_batch {
|
430
|
+
leveldb::WriteBatch batch;
|
431
|
+
} bound_batch;
|
432
|
+
|
433
|
+
static void batch_free(bound_batch* batch) {
|
434
|
+
delete batch;
|
435
|
+
}
|
436
|
+
|
437
|
+
static VALUE batch_make(VALUE klass) {
|
438
|
+
bound_batch* batch = new bound_batch;
|
439
|
+
batch->batch = leveldb::WriteBatch();
|
440
|
+
|
441
|
+
VALUE o_batch = Data_Wrap_Struct(klass, NULL, batch_free, batch);
|
442
|
+
VALUE argv[0];
|
443
|
+
rb_obj_call_init(o_batch, 0, argv);
|
444
|
+
|
445
|
+
return o_batch;
|
446
|
+
}
|
447
|
+
|
448
|
+
static VALUE batch_put(VALUE self, VALUE v_key, VALUE v_value) {
|
449
|
+
Check_Type(v_key, T_STRING);
|
450
|
+
Check_Type(v_value, T_STRING);
|
451
|
+
|
452
|
+
bound_batch* batch;
|
453
|
+
Data_Get_Struct(self, bound_batch, batch);
|
454
|
+
batch->batch.Put(RUBY_STRING_TO_SLICE(v_key), RUBY_STRING_TO_SLICE(v_value));
|
455
|
+
|
456
|
+
return v_value;
|
457
|
+
}
|
458
|
+
|
459
|
+
static VALUE batch_delete(VALUE self, VALUE v_key) {
|
460
|
+
Check_Type(v_key, T_STRING);
|
461
|
+
bound_batch* batch;
|
462
|
+
Data_Get_Struct(self, bound_batch, batch);
|
463
|
+
batch->batch.Delete(RUBY_STRING_TO_SLICE(v_key));
|
464
|
+
return Qtrue;
|
465
|
+
}
|
466
|
+
|
467
|
+
static VALUE db_batch(int argc, VALUE* argv, VALUE self) {
|
468
|
+
VALUE o_batch = batch_make(c_batch);
|
469
|
+
|
470
|
+
rb_yield(o_batch);
|
471
|
+
|
472
|
+
bound_batch* batch;
|
473
|
+
bound_db* db;
|
474
|
+
Data_Get_Struct(o_batch, bound_batch, batch);
|
475
|
+
Data_Get_Struct(self, bound_db, db);
|
476
|
+
|
477
|
+
VALUE v_options;
|
478
|
+
rb_scan_args(argc, argv, "01", &v_options);
|
479
|
+
leveldb::WriteOptions writeOptions = parse_write_options(v_options);
|
480
|
+
|
481
|
+
leveldb::Status status = db->db->Write(writeOptions, &batch->batch);
|
482
|
+
RAISE_ON_ERROR(status);
|
483
|
+
return Qtrue;
|
484
|
+
}
|
485
|
+
|
170
486
|
extern "C" {
|
171
487
|
void Init_leveldb() {
|
488
|
+
k_fill = ID2SYM(rb_intern("fill_cache"));
|
489
|
+
k_verify = ID2SYM(rb_intern("verify_checksums"));
|
490
|
+
k_sync = ID2SYM(rb_intern("sync"));
|
491
|
+
k_from = ID2SYM(rb_intern("from"));
|
492
|
+
k_to = ID2SYM(rb_intern("to"));
|
493
|
+
k_reversed = ID2SYM(rb_intern("reversed"));
|
494
|
+
k_class = rb_intern("class");
|
495
|
+
k_name = rb_intern("name");
|
496
|
+
to_s = rb_intern("to_s");
|
497
|
+
uncached_read_options = leveldb::ReadOptions();
|
498
|
+
uncached_read_options.fill_cache = false;
|
499
|
+
|
172
500
|
m_leveldb = rb_define_module("LevelDB");
|
173
501
|
|
502
|
+
printf("initialized the correct codebase\n");
|
503
|
+
|
174
504
|
c_db = rb_define_class_under(m_leveldb, "DB", rb_cObject);
|
175
|
-
rb_define_singleton_method(c_db, "make", (
|
176
|
-
rb_define_method(c_db, "initialize", (
|
177
|
-
rb_define_method(c_db, "get", (
|
178
|
-
rb_define_method(c_db, "delete", (
|
179
|
-
rb_define_method(c_db, "put", (
|
180
|
-
rb_define_method(c_db, "exists?", (
|
181
|
-
rb_define_method(c_db, "close", (
|
182
|
-
rb_define_method(c_db, "size", (
|
183
|
-
rb_define_method(c_db, "
|
505
|
+
rb_define_singleton_method(c_db, "make", RUBY_METHOD_FUNC(db_make), 3);
|
506
|
+
rb_define_method(c_db, "initialize", RUBY_METHOD_FUNC(db_init), 1);
|
507
|
+
rb_define_method(c_db, "get", RUBY_METHOD_FUNC(db_get), -1);
|
508
|
+
rb_define_method(c_db, "delete", RUBY_METHOD_FUNC(db_delete), -1);
|
509
|
+
rb_define_method(c_db, "put", RUBY_METHOD_FUNC(db_put), -1);
|
510
|
+
rb_define_method(c_db, "exists?", RUBY_METHOD_FUNC(db_exists), 1);
|
511
|
+
rb_define_method(c_db, "close", RUBY_METHOD_FUNC(db_close), 0);
|
512
|
+
rb_define_method(c_db, "size", RUBY_METHOD_FUNC(db_size), 0);
|
513
|
+
rb_define_method(c_db, "batch", RUBY_METHOD_FUNC(db_batch), -1);
|
514
|
+
|
515
|
+
c_iter = rb_define_class_under(m_leveldb, "Iterator", rb_cObject);
|
516
|
+
rb_define_singleton_method(c_iter, "make", RUBY_METHOD_FUNC(iter_make), 2);
|
517
|
+
rb_define_method(c_iter, "initialize", RUBY_METHOD_FUNC(iter_init), 2);
|
518
|
+
rb_define_method(c_iter, "each", RUBY_METHOD_FUNC(iter_each), 0);
|
519
|
+
rb_define_method(c_iter, "next", RUBY_METHOD_FUNC(iter_next), 0);
|
520
|
+
rb_define_method(c_iter, "scan", RUBY_METHOD_FUNC(iter_scan), 0);
|
521
|
+
rb_define_method(c_iter, "peek", RUBY_METHOD_FUNC(iter_peek), 0);
|
522
|
+
rb_define_method(c_iter, "invalid_reason", RUBY_METHOD_FUNC(iter_invalid_reason), 0);
|
523
|
+
|
524
|
+
c_batch = rb_define_class_under(m_leveldb, "WriteBatch", rb_cObject);
|
525
|
+
rb_define_singleton_method(c_batch, "make", RUBY_METHOD_FUNC(batch_make), 0);
|
526
|
+
rb_define_method(c_batch, "put", RUBY_METHOD_FUNC(batch_put), 2);
|
527
|
+
rb_define_method(c_batch, "delete", RUBY_METHOD_FUNC(batch_delete), 1);
|
184
528
|
|
185
529
|
c_error = rb_define_class_under(m_leveldb, "Error", rb_eStandardError);
|
186
530
|
}
|