rod 0.7.1 → 0.7.2
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/.travis.yml +1 -1
- data/README.rdoc +38 -10
- data/Rakefile +20 -9
- data/changelog.txt +25 -0
- data/contributors.txt +1 -0
- data/data/backward/0.7.0/_join_element.dat +0 -0
- data/data/backward/0.7.0/_polymorphic_join_element.dat +0 -0
- data/data/backward/0.7.0/char.dat +0 -0
- data/data/backward/0.7.0/database.yml +58 -0
- data/data/backward/0.7.0/rod_test__automobile.dat +0 -0
- data/data/backward/0.7.0/rod_test__caveman.dat +0 -0
- data/data/backward/0.7.0/rod_test__dog.dat +0 -0
- data/data/backward/0.7.0/rod_test__test_model.dat +0 -0
- data/data/portability/_join_element.dat +0 -0
- data/data/portability/_polymorphic_join_element.dat +0 -0
- data/data/portability/char.dat +0 -0
- data/data/portability/database.yml +49 -0
- data/data/portability/rod_test__automobile.dat +0 -0
- data/data/portability/rod_test__caveman.dat +0 -0
- data/data/portability/rod_test__dog.dat +0 -0
- data/data/portability/rod_test__test_model.dat +0 -0
- data/features/backward.feature +33 -0
- data/features/basic.feature +3 -0
- data/features/collection_proxy.feature +95 -0
- data/features/flat_indexing.feature +44 -2
- data/features/hash_indexing.feature +63 -9
- data/features/portability.feature +72 -0
- data/features/segmented_indexing.feature +45 -2
- data/features/steps/collection_proxy.rb +1 -1
- data/features/steps/model.rb +48 -5
- data/features/steps/rod.rb +15 -16
- data/lib/rod.rb +11 -1
- data/lib/rod/abstract_database.rb +52 -42
- data/lib/rod/berkeley/collection_proxy.rb +96 -0
- data/lib/rod/berkeley/database.rb +337 -0
- data/lib/rod/berkeley/environment.rb +209 -0
- data/lib/rod/berkeley/sequence.rb +222 -0
- data/lib/rod/berkeley/transaction.rb +233 -0
- data/lib/rod/collection_proxy.rb +76 -1
- data/lib/rod/constants.rb +3 -2
- data/lib/rod/database.rb +127 -14
- data/lib/rod/index/base.rb +12 -3
- data/lib/rod/index/hash_index.rb +295 -70
- data/lib/rod/index/segmented_index.rb +3 -0
- data/lib/rod/model.rb +154 -531
- data/lib/rod/property/base.rb +190 -0
- data/lib/rod/property/field.rb +258 -0
- data/lib/rod/property/plural_association.rb +145 -0
- data/lib/rod/property/singular_association.rb +139 -0
- data/rod.gemspec +6 -4
- data/spec/berkeley/database.rb +83 -0
- data/spec/berkeley/environment.rb +58 -0
- data/spec/berkeley/sequence.rb +101 -0
- data/spec/berkeley/transaction.rb +92 -0
- data/spec/collection_proxy.rb +38 -0
- data/spec/database.rb +36 -0
- data/spec/model.rb +26 -0
- data/spec/property/base.rb +73 -0
- data/spec/property/field.rb +244 -0
- data/spec/property/plural_association.rb +67 -0
- data/spec/property/singular_association.rb +65 -0
- data/tests/class_compatibility_create.rb +2 -2
- data/tests/eff1_test.rb +1 -1
- data/tests/eff2_test.rb +1 -1
- data/tests/full_runs.rb +1 -1
- data/tests/generate_classes_create.rb +14 -14
- data/tests/migration_create.rb +47 -47
- data/tests/migration_verify.rb +1 -1
- data/tests/missing_class_create.rb +6 -6
- data/tests/properties_order_create.rb +4 -4
- data/tests/read_on_create.rb +33 -34
- data/tests/save_struct.rb +40 -39
- data/tests/unit/database.rb +1 -1
- data/tests/unit/model_tests.rb +73 -65
- metadata +71 -15
- data/tests/unit/model.rb +0 -36
data/lib/rod/index/hash_index.rb
CHANGED
@@ -10,50 +10,36 @@ module Rod
|
|
10
10
|
class Handle
|
11
11
|
end
|
12
12
|
|
13
|
+
# The class given index is associated with.
|
14
|
+
attr_reader :klass
|
15
|
+
|
13
16
|
# Initializes the index with +path+ and +class+.
|
14
17
|
# Options are not (yet) used.
|
15
18
|
def initialize(path,klass,options={})
|
16
19
|
@path = path + ".db"
|
17
20
|
@klass = klass
|
18
|
-
open(@path,:create => true)
|
19
21
|
end
|
20
22
|
|
21
23
|
# Stores the index on disk.
|
22
24
|
def save
|
23
|
-
raise RodException.new("The index #{self} is not opened!") unless opened?
|
24
|
-
if @index.empty?
|
25
|
-
close
|
26
|
-
return
|
27
|
-
end
|
28
|
-
@index.keys.each do |key|
|
29
|
-
collection = self[key]
|
30
|
-
key = key.encode("utf-8") if key.is_a?(String)
|
31
|
-
key = Marshal.dump(key)
|
32
|
-
collection.save
|
33
|
-
_put(key,collection.offset,collection.size)
|
34
|
-
end
|
35
25
|
close
|
36
26
|
end
|
37
27
|
|
38
28
|
# Clears the contents of the index.
|
39
29
|
def destroy
|
40
30
|
close if opened?
|
41
|
-
|
31
|
+
remove_file(@path)
|
42
32
|
end
|
43
33
|
|
44
|
-
#
|
34
|
+
# Iterates over the keys and corresponding
|
35
|
+
# values present in the index.
|
45
36
|
def each
|
46
37
|
if block_given?
|
47
|
-
@
|
48
|
-
yield key,value
|
49
|
-
end
|
50
|
-
open(@path) unless opened?
|
38
|
+
open(@path, :create => true) unless opened?
|
51
39
|
_each_key do |key|
|
52
40
|
next if key.empty?
|
53
41
|
key = Marshal.load(key)
|
54
|
-
|
55
|
-
yield key,self[key]
|
56
|
-
end
|
42
|
+
yield key,self[key]
|
57
43
|
end
|
58
44
|
else
|
59
45
|
enum_for(:each)
|
@@ -63,12 +49,45 @@ module Rod
|
|
63
49
|
# Copies the index from the given +index+.
|
64
50
|
# The index have to cleared before being copied.
|
65
51
|
def copy(index)
|
66
|
-
|
67
|
-
open(@path,:truncate => true)
|
52
|
+
self.destroy
|
68
53
|
super(index)
|
69
54
|
end
|
70
55
|
|
56
|
+
# Delets given +value+ for the given +key+.
|
57
|
+
# If the +value+ is nil, then the key is removed
|
58
|
+
# with all the values.
|
59
|
+
def delete(key,value=nil)
|
60
|
+
_delete(key,value)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Registers given +rod_id+ for the given +key+.
|
64
|
+
def put(key,rod_id)
|
65
|
+
_put(key,rod_id)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Iterates over all values for a given +key+. Raises
|
69
|
+
# KeyMissing if the key is not present.
|
70
|
+
def each_for(key)
|
71
|
+
_get(key) do |value|
|
72
|
+
yield value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns the first value for a given +key+ or
|
77
|
+
# raises keyMissing exception if it is not present.
|
78
|
+
def get_first(key)
|
79
|
+
_get_first(key)
|
80
|
+
end
|
81
|
+
|
82
|
+
|
71
83
|
protected
|
84
|
+
# Returns an empty BDB based collection proxy.
|
85
|
+
def empty_collection_proxy(key)
|
86
|
+
key = key.encode("utf-8") if key.is_a?(String)
|
87
|
+
key = Marshal.dump(key)
|
88
|
+
Rod::Berkeley::CollectionProxy.new(self,key)
|
89
|
+
end
|
90
|
+
|
72
91
|
# Opens the index - initializes the index C structures
|
73
92
|
# and the cache.
|
74
93
|
# Options:
|
@@ -78,7 +97,6 @@ module Rod
|
|
78
97
|
raise RodException.new("The index #{@path} is already opened!") if opened?
|
79
98
|
_open(path,options)
|
80
99
|
@opened = true
|
81
|
-
@index = {} if @index.nil?
|
82
100
|
end
|
83
101
|
|
84
102
|
# Closes the disk - frees the C structure and clears the cache.
|
@@ -86,7 +104,6 @@ module Rod
|
|
86
104
|
return unless opened?
|
87
105
|
_close()
|
88
106
|
@opened = false
|
89
|
-
@index.clear
|
90
107
|
end
|
91
108
|
|
92
109
|
# Checks if the index is opened.
|
@@ -96,20 +113,14 @@ module Rod
|
|
96
113
|
|
97
114
|
# Returns a value of the index for a given +key+.
|
98
115
|
def get(key)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
key = key.encode("utf-8") if key.is_a?(String)
|
103
|
-
value = _get(Marshal.dump(key))
|
104
|
-
rescue Rod::KeyMissing => ex
|
105
|
-
value = nil
|
106
|
-
end
|
107
|
-
@index[key] = value
|
116
|
+
# TODO # 208
|
117
|
+
open(@path,:create => true) unless opened?
|
118
|
+
empty_collection_proxy(key)
|
108
119
|
end
|
109
120
|
|
110
|
-
# Sets the +
|
111
|
-
def set(key,
|
112
|
-
|
121
|
+
# Sets the +proxy+ for the +key+ in the internal cache.
|
122
|
+
def set(key,proxy)
|
123
|
+
# do nothing - the value is set in proxy#<< method
|
113
124
|
end
|
114
125
|
|
115
126
|
# C definition of the RodException.
|
@@ -164,14 +175,139 @@ module Rod
|
|
164
175
|
str.margin
|
165
176
|
end
|
166
177
|
|
178
|
+
# The cursor free method.
|
179
|
+
def self.cursor_free
|
180
|
+
str =<<-END
|
181
|
+
|void cursor_free(DBC *cursor){
|
182
|
+
| int return_value;
|
183
|
+
| if(cursor != NULL){
|
184
|
+
| return_value = cursor->close(cursor);
|
185
|
+
| if(return_value != 0){
|
186
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
187
|
+
| }
|
188
|
+
| }
|
189
|
+
|}
|
190
|
+
END
|
191
|
+
str.margin
|
192
|
+
end
|
193
|
+
|
194
|
+
# The cursor closing method.
|
195
|
+
def self.close_cursor
|
196
|
+
str =<<-END
|
197
|
+
|VALUE close_cursor(VALUE cursor_object){
|
198
|
+
| DBC *cursor;
|
199
|
+
| int return_value;
|
200
|
+
|
|
201
|
+
| Data_Get_Struct(cursor_object,DBC,cursor);
|
202
|
+
| if(cursor != NULL){
|
203
|
+
| return_value = cursor->close(cursor);
|
204
|
+
| DATA_PTR(cursor_object) = NULL;
|
205
|
+
| if(return_value != 0){
|
206
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
207
|
+
| }
|
208
|
+
| }
|
209
|
+
| return Qnil;
|
210
|
+
|}
|
211
|
+
END
|
212
|
+
str.margin
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.iterate_over_values
|
216
|
+
str =<<-END
|
217
|
+
|VALUE iterate_over_values(VALUE arguments){
|
218
|
+
| DBT db_key, db_value;
|
219
|
+
| DBC *cursor;
|
220
|
+
| unsigned long rod_id, index;
|
221
|
+
| VALUE key, result, cursor_object;
|
222
|
+
| int return_value;
|
223
|
+
|
|
224
|
+
| index = 0;
|
225
|
+
| key = rb_ary_shift(arguments);
|
226
|
+
| cursor_object = rb_ary_shift(arguments);
|
227
|
+
| Data_Get_Struct(cursor_object,DBC,cursor);
|
228
|
+
|
|
229
|
+
| memset(&db_value, 0, sizeof(DBT));
|
230
|
+
| db_value.data = &rod_id;
|
231
|
+
| db_value.ulen = sizeof(unsigned long);
|
232
|
+
| db_value.flags = DB_DBT_USERMEM;
|
233
|
+
|
|
234
|
+
| memset(&db_key, 0, sizeof(DBT));
|
235
|
+
| db_key.data = RSTRING_PTR(key);
|
236
|
+
| db_key.size = RSTRING_LEN(key);
|
237
|
+
|
|
238
|
+
| return_value = cursor->get(cursor, &db_key, &db_value, DB_SET);
|
239
|
+
| if(return_value == DB_NOTFOUND){
|
240
|
+
| rb_raise(keyMissingException(),"%s",db_strerror(return_value));
|
241
|
+
| } else if(return_value != 0){
|
242
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
243
|
+
| }
|
244
|
+
| while(return_value != DB_NOTFOUND){
|
245
|
+
| index++;
|
246
|
+
|#ifdef __BYTE_ORDER
|
247
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
248
|
+
| rod_id = bswap_64(rod_id);
|
249
|
+
|# endif
|
250
|
+
|#endif
|
251
|
+
| rb_yield(ULONG2NUM(rod_id));
|
252
|
+
| return_value = cursor->get(cursor, &db_key, &db_value, DB_NEXT_DUP);
|
253
|
+
| if(return_value != 0 && return_value != DB_NOTFOUND){
|
254
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
255
|
+
| }
|
256
|
+
| }
|
257
|
+
| return Qnil;
|
258
|
+
|}
|
259
|
+
END
|
260
|
+
str.margin
|
261
|
+
end
|
262
|
+
|
263
|
+
def self.iterate_over_keys
|
264
|
+
str =<<-END
|
265
|
+
|VALUE iterate_over_keys(VALUE cursor_object){
|
266
|
+
| DBT db_key, db_value;
|
267
|
+
| DBC *cursor;
|
268
|
+
| int return_value;
|
269
|
+
| rod_entry_struct *entry;
|
270
|
+
| VALUE key;
|
271
|
+
|
|
272
|
+
| Data_Get_Struct(cursor_object,DBC,cursor);
|
273
|
+
| memset(&db_key, 0, sizeof(DBT));
|
274
|
+
| memset(&db_value, 0, sizeof(DBT));
|
275
|
+
| db_key.flags = DB_DBT_MALLOC;
|
276
|
+
| while((return_value = cursor->get(cursor, &db_key, &db_value, DB_NEXT_NODUP)) == 0){
|
277
|
+
| key = rb_str_new((char *)db_key.data,db_key.size);
|
278
|
+
| free(db_key.data);
|
279
|
+
| rb_yield(key);
|
280
|
+
| }
|
281
|
+
| if(return_value != DB_NOTFOUND){
|
282
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
283
|
+
| }
|
284
|
+
| return Qnil;
|
285
|
+
|}
|
286
|
+
END
|
287
|
+
str.margin
|
288
|
+
end
|
289
|
+
|
290
|
+
# You can set arbitrary ROD hash index link flags via
|
291
|
+
# ROD_BDB_LINK_FLAGS env. variable.
|
292
|
+
def self.rod_link_flags
|
293
|
+
ENV['ROD_BDB_LINK_FLAGS'] || '-ldb'
|
294
|
+
end
|
295
|
+
|
167
296
|
self.inline(:C) do |builder|
|
168
297
|
builder.include '<db.h>'
|
169
298
|
builder.include '<stdio.h>'
|
170
|
-
builder.
|
299
|
+
builder.include '<byteswap.h>'
|
300
|
+
builder.include '<endian.h>'
|
301
|
+
builder.include '<stdint.h>'
|
302
|
+
builder.add_link_flags self.rod_link_flags
|
171
303
|
builder.prefix(self.entry_struct)
|
172
304
|
builder.prefix(self.rod_exception)
|
173
305
|
builder.prefix(self.key_missing_exception)
|
174
306
|
builder.prefix(self.convert_key)
|
307
|
+
builder.prefix(self.cursor_free)
|
308
|
+
builder.prefix(self.close_cursor)
|
309
|
+
builder.prefix(self.iterate_over_values)
|
310
|
+
builder.prefix(self.iterate_over_keys)
|
175
311
|
|
176
312
|
|
177
313
|
str =<<-END
|
@@ -182,11 +318,17 @@ module Rod
|
|
182
318
|
| VALUE handleClass;
|
183
319
|
| VALUE handle;
|
184
320
|
| VALUE mod;
|
321
|
+
|
|
185
322
|
| db_pointer = ALLOC(DB);
|
186
323
|
| return_value = db_create(&db_pointer,NULL,0);
|
187
324
|
| if(return_value != 0){
|
188
325
|
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
189
326
|
| }
|
327
|
+
| return_value = db_pointer->set_flags(db_pointer,DB_DUPSORT);
|
328
|
+
| if(return_value != 0){
|
329
|
+
| db_pointer->close(db_pointer,0);
|
330
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
331
|
+
| }
|
190
332
|
|
|
191
333
|
| flags = 0;
|
192
334
|
| if(rb_hash_aref(options,ID2SYM(rb_intern("create"))) == Qtrue){
|
@@ -196,9 +338,11 @@ module Rod
|
|
196
338
|
| flags |= DB_TRUNCATE;
|
197
339
|
| }
|
198
340
|
|
|
341
|
+
| db_pointer->set_cachesize(db_pointer,0,5 * 1024 * 1024,0);
|
199
342
|
| return_value = db_pointer->open(db_pointer,NULL,path,
|
200
343
|
| NULL,DB_HASH,flags,0);
|
201
344
|
| if(return_value != 0){
|
345
|
+
| db_pointer->close(db_pointer,0);
|
202
346
|
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
203
347
|
| }
|
204
348
|
| mod = rb_const_get(rb_cObject, rb_intern("Rod"));
|
@@ -216,6 +360,7 @@ module Rod
|
|
216
360
|
|void _close(){
|
217
361
|
| VALUE handle;
|
218
362
|
| DB *db_pointer;
|
363
|
+
|
|
219
364
|
| handle = rb_iv_get(self,"@handle");
|
220
365
|
| Data_Get_Struct(handle,DB,db_pointer);
|
221
366
|
| if(db_pointer != NULL){
|
@@ -229,44 +374,63 @@ module Rod
|
|
229
374
|
builder.c(str.margin)
|
230
375
|
|
231
376
|
str =<<-END
|
232
|
-
|
377
|
+
|// Iterate over all keys in the database.
|
378
|
+
|// The value returned is the index itself.
|
379
|
+
|VALUE _each_key(){
|
233
380
|
| VALUE handle;
|
234
381
|
| DB *db_pointer;
|
235
382
|
| DBC *cursor;
|
236
|
-
|
|
237
|
-
| int return_value;
|
238
|
-
| rod_entry_struct *entry;
|
239
|
-
| VALUE key;
|
383
|
+
| VALUE key, cursor_object;
|
240
384
|
|
|
241
385
|
| handle = rb_iv_get(self,"@handle");
|
242
386
|
| Data_Get_Struct(handle,DB,db_pointer);
|
243
387
|
| if(db_pointer != NULL){
|
244
388
|
| db_pointer->cursor(db_pointer,NULL,&cursor,0);
|
245
|
-
|
|
246
|
-
|
|
247
|
-
| db_key.flags = DB_DBT_MALLOC;
|
248
|
-
| while((return_value = cursor->get(cursor, &db_key, &db_value, DB_NEXT)) == 0){
|
249
|
-
| key = rb_str_new((char *)db_key.data,db_key.size);
|
250
|
-
| free(db_key.data);
|
251
|
-
| rb_yield(key);
|
252
|
-
| }
|
253
|
-
| if(return_value != DB_NOTFOUND){
|
254
|
-
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
255
|
-
| }
|
256
|
-
| cursor->close(cursor);
|
389
|
+
| cursor_object = Data_Wrap_Struct(rb_cObject,NULL,cursor_free,cursor);
|
390
|
+
| rb_ensure(iterate_over_keys,cursor_object,close_cursor,cursor_object);
|
257
391
|
| } else {
|
258
392
|
| rb_raise(rodException(),"DB handle is NULL\\n");
|
259
393
|
| }
|
394
|
+
| return self;
|
260
395
|
|}
|
261
396
|
END
|
262
397
|
builder.c(str.margin)
|
263
398
|
|
264
399
|
str =<<-END
|
400
|
+
|// Iterate over values for a given key.
|
401
|
+
|// A KeyMissing exception is raised if the key is missing.
|
402
|
+
|// The value returned is the index itself.
|
265
403
|
|VALUE _get(VALUE key){
|
266
404
|
| VALUE handle;
|
267
405
|
| DB *db_pointer;
|
406
|
+
| DBC *cursor;
|
407
|
+
| VALUE cursor_object, iterate_arguments;
|
408
|
+
|
|
409
|
+
| handle = rb_iv_get(self,"@handle");
|
410
|
+
| Data_Get_Struct(handle,DB,db_pointer);
|
411
|
+
| if(db_pointer != NULL){
|
412
|
+
| db_pointer->cursor(db_pointer,NULL,&cursor,0);
|
413
|
+
| cursor_object = Data_Wrap_Struct(rb_cObject,NULL,cursor_free,cursor);
|
414
|
+
| iterate_arguments = rb_ary_new();
|
415
|
+
| rb_ary_push(iterate_arguments,key);
|
416
|
+
| rb_ary_push(iterate_arguments,cursor_object);
|
417
|
+
| rb_ensure(iterate_over_values,iterate_arguments,close_cursor,cursor_object);
|
418
|
+
| } else {
|
419
|
+
| rb_raise(rodException(),"DB handle is NULL\\n");
|
420
|
+
| }
|
421
|
+
| return self;
|
422
|
+
|}
|
423
|
+
END
|
424
|
+
builder.c(str.margin)
|
425
|
+
|
426
|
+
str =<<-END
|
427
|
+
|// Returns the first value for a given +key+ or raises
|
428
|
+
|// KeyMissing if the key is not present.
|
429
|
+
|VALUE _get_first(VALUE key){
|
430
|
+
| VALUE handle;
|
431
|
+
| DB *db_pointer;
|
268
432
|
| DBT db_key, db_value;
|
269
|
-
|
|
433
|
+
| unsigned long rod_id;
|
270
434
|
| VALUE result;
|
271
435
|
| int return_value;
|
272
436
|
|
|
@@ -274,8 +438,8 @@ module Rod
|
|
274
438
|
| Data_Get_Struct(handle,DB,db_pointer);
|
275
439
|
| if(db_pointer != NULL){
|
276
440
|
| memset(&db_value, 0, sizeof(DBT));
|
277
|
-
| db_value.data = &
|
278
|
-
| db_value.ulen = sizeof(
|
441
|
+
| db_value.data = &rod_id;
|
442
|
+
| db_value.ulen = sizeof(unsigned long);
|
279
443
|
| db_value.flags = DB_DBT_USERMEM;
|
280
444
|
|
|
281
445
|
| memset(&db_key, 0, sizeof(DBT));
|
@@ -287,26 +451,28 @@ module Rod
|
|
287
451
|
| rb_raise(keyMissingException(),"%s",db_strerror(return_value));
|
288
452
|
| } else if(return_value != 0){
|
289
453
|
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
290
|
-
| } else {
|
291
|
-
| result = rb_ary_new();
|
292
|
-
| rb_ary_push(result,ULONG2NUM(entry.offset));
|
293
|
-
| rb_ary_push(result,ULONG2NUM(entry.size));
|
294
|
-
| return result;
|
295
454
|
| }
|
455
|
+
|#ifdef __BYTE_ORDER
|
456
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
457
|
+
| rod_id = bswap_64(rod_id);
|
458
|
+
|# endif
|
459
|
+
|#endif
|
460
|
+
| return ULONG2NUM(rod_id);
|
296
461
|
| } else {
|
297
462
|
| rb_raise(rodException(),"DB handle is NULL\\n");
|
298
463
|
| }
|
464
|
+
| // This should never be reached.
|
465
|
+
| rb_raise(rodException(),"Invalid _get_first implementation!\\n");
|
299
466
|
| return Qnil;
|
300
467
|
|}
|
301
468
|
END
|
302
469
|
builder.c(str.margin)
|
303
470
|
|
304
471
|
str =<<-END
|
305
|
-
|void _put(VALUE key,unsigned long
|
472
|
+
|void _put(VALUE key,unsigned long rod_id){
|
306
473
|
| VALUE handle;
|
307
474
|
| DB *db_pointer;
|
308
475
|
| DBT db_key, db_value;
|
309
|
-
| rod_entry_struct entry;
|
310
476
|
| int return_value;
|
311
477
|
|
|
312
478
|
| handle = rb_iv_get(self,"@handle");
|
@@ -315,10 +481,13 @@ module Rod
|
|
315
481
|
| db_key.data = RSTRING_PTR(key);
|
316
482
|
| db_key.size = RSTRING_LEN(key);
|
317
483
|
| memset(&db_value, 0, sizeof(DBT));
|
318
|
-
|
319
|
-
|
320
|
-
|
|
321
|
-
|
484
|
+
|#ifdef __BYTE_ORDER
|
485
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
486
|
+
| rod_id = bswap_64(rod_id);
|
487
|
+
|# endif
|
488
|
+
|#endif
|
489
|
+
| db_value.data = &rod_id;
|
490
|
+
| db_value.size = sizeof(unsigned long);
|
322
491
|
| if(db_pointer != NULL){
|
323
492
|
| return_value = db_pointer->put(db_pointer, NULL, &db_key, &db_value, 0);
|
324
493
|
| if(return_value != 0){
|
@@ -330,6 +499,62 @@ module Rod
|
|
330
499
|
|}
|
331
500
|
END
|
332
501
|
builder.c(str.margin)
|
502
|
+
|
503
|
+
str =<<-END
|
504
|
+
|void _delete(VALUE key,VALUE value){
|
505
|
+
| VALUE handle;
|
506
|
+
| DB *db_pointer;
|
507
|
+
| DBT db_key, db_value;
|
508
|
+
| DBC *cursor;
|
509
|
+
| int return_value;
|
510
|
+
| unsigned long rod_id = 0;
|
511
|
+
|
|
512
|
+
| handle = rb_iv_get(self,"@handle");
|
513
|
+
| Data_Get_Struct(handle,DB,db_pointer);
|
514
|
+
| memset(&db_key, 0, sizeof(DBT));
|
515
|
+
| db_key.data = RSTRING_PTR(key);
|
516
|
+
| db_key.size = RSTRING_LEN(key);
|
517
|
+
| memset(&db_value, 0, sizeof(DBT));
|
518
|
+
|
|
519
|
+
| if(db_pointer != NULL){
|
520
|
+
| if(value == Qnil){
|
521
|
+
| return_value = db_pointer->del(db_pointer, NULL, &db_key, 0);
|
522
|
+
| if(return_value == DB_NOTFOUND){
|
523
|
+
| rb_raise(keyMissingException(),"%s",db_strerror(return_value));
|
524
|
+
| } else if(return_value != 0){
|
525
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
526
|
+
| }
|
527
|
+
| } else {
|
528
|
+
| rod_id = NUM2ULONG(value);
|
529
|
+
|#ifdef __BYTE_ORDER
|
530
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
531
|
+
| rod_id = bswap_64(rod_id);
|
532
|
+
|# endif
|
533
|
+
|#endif
|
534
|
+
| memset(&db_value, 0, sizeof(DBT));
|
535
|
+
| db_value.data = &rod_id;
|
536
|
+
| db_value.size = sizeof(unsigned long);
|
537
|
+
| db_pointer->cursor(db_pointer,NULL,&cursor,0);
|
538
|
+
| return_value = cursor->get(cursor,&db_key,&db_value,DB_GET_BOTH);
|
539
|
+
| if(return_value == DB_NOTFOUND){
|
540
|
+
| cursor->close(cursor);
|
541
|
+
| rb_raise(keyMissingException(),"%s",db_strerror(return_value));
|
542
|
+
| } else if(return_value != 0){
|
543
|
+
| cursor->close(cursor);
|
544
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
545
|
+
| }
|
546
|
+
| return_value = cursor->del(cursor,0);
|
547
|
+
| cursor->close(cursor);
|
548
|
+
| if(return_value != 0){
|
549
|
+
| rb_raise(rodException(),"%s",db_strerror(return_value));
|
550
|
+
| }
|
551
|
+
| }
|
552
|
+
| } else {
|
553
|
+
| rb_raise(rodException(),"DB handle is NULL\\n");
|
554
|
+
| }
|
555
|
+
|}
|
556
|
+
END
|
557
|
+
builder.c(str.margin)
|
333
558
|
end
|
334
559
|
end
|
335
560
|
end
|