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/collection_proxy.rb
CHANGED
@@ -43,16 +43,91 @@ module Rod
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
# Returns the size of intersection with the other collection proxy.
|
47
|
+
# XXX this method assumes that the elements are sorted according to rod_id,
|
48
|
+
# the collection is not polymorphic and no elements were added nor deleted.
|
49
|
+
def intersection_size(other)
|
50
|
+
@database.fast_intersection_size(self.offset,self.size,other.offset,other.size)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Computes a union with the +other+ collection proxy.
|
54
|
+
def |(other)
|
55
|
+
# So far this optimization works only for monomorphic
|
56
|
+
# collection proxies without added elements.
|
57
|
+
if @klass && @added.empty?
|
58
|
+
my_ids = self.size.times.map do |index|
|
59
|
+
id_for(index)
|
60
|
+
end.sort
|
61
|
+
other_ids = other.size.times.map do |index|
|
62
|
+
other.id_for(index)
|
63
|
+
end.sort
|
64
|
+
ids = []
|
65
|
+
last_id = nil
|
66
|
+
while(!my_ids.empty?) do
|
67
|
+
id = my_ids.shift
|
68
|
+
other_ids.shift if other_ids.first == id
|
69
|
+
ids << id unless last_id == id
|
70
|
+
last_id = id
|
71
|
+
end
|
72
|
+
while(!other_ids.empty?) do
|
73
|
+
id = other_ids.shift
|
74
|
+
ids << id unless last_id == id
|
75
|
+
last_id = id
|
76
|
+
end
|
77
|
+
result = CollectionProxy.new(0,@database,0,@klass)
|
78
|
+
ids.each{|id| result << [id,@klass]}
|
79
|
+
else
|
80
|
+
result = self.to_a | other.to_a
|
81
|
+
end
|
82
|
+
result
|
83
|
+
end
|
84
|
+
|
85
|
+
# Computes an intersection with the +other+ collection proxy.
|
86
|
+
def &(other)
|
87
|
+
# So far this optimization works only for monomorphic
|
88
|
+
# collection proxies without added elements.
|
89
|
+
if @klass && @added.empty?
|
90
|
+
my_ids = self.size.times.map do |index|
|
91
|
+
id_for(index)
|
92
|
+
end.sort
|
93
|
+
other_ids = other.size.times.map do |index|
|
94
|
+
other.id_for(index)
|
95
|
+
end.sort
|
96
|
+
ids = []
|
97
|
+
last_id = nil
|
98
|
+
while(!my_ids.empty?) do
|
99
|
+
if my_ids.first == other_ids.first
|
100
|
+
id = my_ids.shift
|
101
|
+
other_ids.shift
|
102
|
+
ids << id unless last_id == id
|
103
|
+
last_id = id
|
104
|
+
elsif my_ids.first < other_ids.first
|
105
|
+
my_ids.shift
|
106
|
+
else
|
107
|
+
other_ids.shift
|
108
|
+
end
|
109
|
+
end
|
110
|
+
result = CollectionProxy.new(0,@database,0,@klass)
|
111
|
+
ids.each{|id| result << [id,@klass]}
|
112
|
+
else
|
113
|
+
result = self.to_a & other.to_a
|
114
|
+
end
|
115
|
+
result
|
116
|
+
end
|
117
|
+
|
46
118
|
# Appends element to the end of the collection.
|
47
119
|
def <<(element)
|
48
120
|
if element.nil?
|
49
121
|
pair = [0,NilClass]
|
50
|
-
|
122
|
+
elsif element.is_a?(Model)
|
51
123
|
if element.new?
|
52
124
|
pair = [element,element.class]
|
53
125
|
else
|
54
126
|
pair = [element.rod_id,element.class]
|
55
127
|
end
|
128
|
+
else
|
129
|
+
# Assume we have an array with direct values of rod_id and class.
|
130
|
+
pair = element
|
56
131
|
end
|
57
132
|
index = @size
|
58
133
|
@map[index] = @added.size
|
data/lib/rod/constants.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Rod
|
2
|
-
VERSION = "0.7.
|
2
|
+
VERSION = "0.7.2"
|
3
3
|
|
4
4
|
# The name of file containing the data base.
|
5
5
|
DATABASE_FILE = "database.yml"
|
@@ -12,7 +12,8 @@ module Rod
|
|
12
12
|
:integer => 'long',
|
13
13
|
:float => 'double',
|
14
14
|
:ulong => 'unsigned long',
|
15
|
-
:object => 'char *'
|
15
|
+
:object => 'char *',
|
16
|
+
:json => 'char *'
|
16
17
|
}
|
17
18
|
|
18
19
|
RUBY_TO_C_MAPPING = {
|
data/lib/rod/database.rb
CHANGED
@@ -49,7 +49,7 @@ module Rod
|
|
49
49
|
| strcpy(path,model_p->path);
|
50
50
|
| strcat(path,"#{klass.path_for_data("")}");
|
51
51
|
| model_p->#{klass.struct_name}_lib_file =
|
52
|
-
| open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
52
|
+
| open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
53
53
|
| if(model_p->#{klass.struct_name}_lib_file == -1) {
|
54
54
|
| rb_raise(rodException(),"Could not open file for class #{klass} on path %s writing.",path);
|
55
55
|
| }
|
@@ -92,11 +92,10 @@ module Rod
|
|
92
92
|
|
|
93
93
|
| // exted the file
|
94
94
|
|
|
95
|
-
| // increase the pages count by
|
95
|
+
| // increase the pages count by numer of pages allocated at-once
|
96
96
|
| model_p->#{klass.struct_name}_page_count += ALLOCATED_PAGES;
|
97
97
|
| {
|
98
98
|
| // open the file for writing
|
99
|
-
| char* #{klass.struct_name}_empty_data;
|
100
99
|
| FILE * #{klass.struct_name}_file =
|
101
100
|
| fdopen(model_p->#{klass.struct_name}_lib_file,"w+");
|
102
101
|
| if(#{klass.struct_name}_file == NULL){
|
@@ -107,11 +106,11 @@ module Rod
|
|
107
106
|
| rb_raise(rodException(),"Could not seek to end file for #{klass.struct_name}.");
|
108
107
|
| }
|
109
108
|
| // write empty data at the end
|
110
|
-
|
|
111
|
-
| if(write(model_p->#{klass.struct_name}_lib_file,#{klass.struct_name}_empty_data,
|
109
|
+
| if(write(model_p->#{klass.struct_name}_lib_file,model_p->empty_data,
|
112
110
|
| page_size() * ALLOCATED_PAGES) == -1){
|
113
111
|
| rb_raise(rodException(),"Could not write to file for #{klass.struct_name}.");
|
114
112
|
| }
|
113
|
+
|
|
115
114
|
| // seek to the beginning
|
116
115
|
| if(fseek(#{klass.struct_name}_file,0,SEEK_SET) == -1){
|
117
116
|
| rb_raise(rodException(),"Could not seek to start file for #{klass.struct_name}.");
|
@@ -167,6 +166,10 @@ module Rod
|
|
167
166
|
builder.include '<unistd.h>'
|
168
167
|
builder.include '<errno.h>'
|
169
168
|
builder.include '<sys/mman.h>'
|
169
|
+
builder.include '<sys/stat.h>'
|
170
|
+
builder.include '<byteswap.h>'
|
171
|
+
builder.include '<endian.h>'
|
172
|
+
builder.include '<stdint.h>'
|
170
173
|
classes.each do |klass|
|
171
174
|
builder.prefix(klass.typedef_struct)
|
172
175
|
end
|
@@ -198,19 +201,51 @@ module Rod
|
|
198
201
|
end.join("\n|\n")}
|
199
202
|
| // the path to the DB
|
200
203
|
| char * path;
|
204
|
+
| // chunk written to extend file
|
205
|
+
| char * empty_data;
|
201
206
|
|
|
202
207
|
|} #{model_struct};
|
203
208
|
END
|
204
209
|
builder.prefix(str.margin)
|
205
210
|
|
211
|
+
str =<<-END
|
212
|
+
|// Deallocates the model struct.
|
213
|
+
|void model_struct_free(#{model_struct} * model_p){
|
214
|
+
| if(model_p != NULL){
|
215
|
+
| if(model_p->path != NULL){
|
216
|
+
| // TODO causes segfault
|
217
|
+
| //printf("GC %lu %lu\\n",(unsigned long)model_p,
|
218
|
+
| // (unsigned long)model_p->path);
|
219
|
+
| //free(model_p->path);
|
220
|
+
| model_p->path = NULL;
|
221
|
+
| }
|
222
|
+
| if(model_p->empty_data != NULL){
|
223
|
+
| //free(model_p->empty_data);
|
224
|
+
| model_p->empty_data = NULL;
|
225
|
+
| }
|
226
|
+
| }
|
227
|
+
| free(model_p);
|
228
|
+
|}
|
229
|
+
END
|
230
|
+
builder.prefix(str.margin)
|
231
|
+
|
232
|
+
|
206
233
|
#########################################
|
207
234
|
# Join indices
|
208
235
|
#########################################
|
209
236
|
str =<<-END
|
210
237
|
|VALUE _join_element_index(unsigned long element_offset, unsigned long element_index, VALUE handler){
|
211
238
|
| #{model_struct} * model_p;
|
239
|
+
| unsigned long result;
|
240
|
+
|
|
212
241
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
213
|
-
|
|
242
|
+
| result = (model_p->_join_element_table + element_offset + element_index)->offset;
|
243
|
+
|#ifdef __BYTE_ORDER
|
244
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
245
|
+
| result = bswap_64(result);
|
246
|
+
|# endif
|
247
|
+
|#endif
|
248
|
+
| return ULONG2NUM(result);
|
214
249
|
|}
|
215
250
|
END
|
216
251
|
builder.c(str.margin)
|
@@ -219,9 +254,17 @@ module Rod
|
|
219
254
|
|VALUE _polymorphic_join_element_index(unsigned long element_offset,
|
220
255
|
| unsigned long element_index, VALUE handler){
|
221
256
|
| #{model_struct} * model_p;
|
257
|
+
| unsigned long result;
|
258
|
+
|
|
222
259
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
223
|
-
|
|
224
|
-
| element_offset + element_index)->offset
|
260
|
+
| result = (model_p->_polymorphic_join_element_table +
|
261
|
+
| element_offset + element_index)->offset;
|
262
|
+
|#ifdef __BYTE_ORDER
|
263
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
264
|
+
| result = bswap_64(result);
|
265
|
+
|# endif
|
266
|
+
|#endif
|
267
|
+
| return ULONG2NUM(result);
|
225
268
|
|}
|
226
269
|
END
|
227
270
|
builder.c(str.margin)
|
@@ -230,9 +273,17 @@ module Rod
|
|
230
273
|
|VALUE _polymorphic_join_element_class(unsigned long element_offset,
|
231
274
|
| unsigned long element_index, VALUE handler){
|
232
275
|
| #{model_struct} * model_p;
|
276
|
+
| unsigned long result;
|
277
|
+
|
|
233
278
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
234
|
-
|
|
235
|
-
| element_offset + element_index)->class
|
279
|
+
| result = (model_p->_polymorphic_join_element_table +
|
280
|
+
| element_offset + element_index)->class;
|
281
|
+
|#ifdef __BYTE_ORDER
|
282
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
283
|
+
| result = bswap_64(result);
|
284
|
+
|# endif
|
285
|
+
|#endif
|
286
|
+
| return ULONG2NUM(result);
|
236
287
|
|}
|
237
288
|
END
|
238
289
|
builder.c(str.margin)
|
@@ -243,12 +294,18 @@ module Rod
|
|
243
294
|
| VALUE handler){
|
244
295
|
| #{model_struct} * model_p;
|
245
296
|
| _join_element * element_p;
|
297
|
+
|
|
246
298
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
247
299
|
| element_p = model_p->_join_element_table + element_offset + element_index;
|
248
300
|
| if(element_p->index != element_index){
|
249
301
|
| rb_raise(rodException(), "Join element indices are inconsistent: %lu %lu!",
|
250
302
|
| element_index, element_p->index);
|
251
303
|
| }
|
304
|
+
|#ifdef __BYTE_ORDER
|
305
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
306
|
+
| offset = bswap_64(offset);
|
307
|
+
|# endif
|
308
|
+
|#endif
|
252
309
|
| element_p->offset = offset;
|
253
310
|
|}
|
254
311
|
END
|
@@ -260,12 +317,19 @@ module Rod
|
|
260
317
|
| VALUE handler){
|
261
318
|
| #{model_struct} * model_p;
|
262
319
|
| _polymorphic_join_element * element_p;
|
320
|
+
|
|
263
321
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
264
322
|
| element_p = model_p->_polymorphic_join_element_table + element_offset + element_index;
|
265
323
|
| if(element_p->index != element_index){
|
266
324
|
| rb_raise(rodException(), "Polymorphic join element indices are inconsistent: %lu %lu!",
|
267
325
|
| element_index, element_p->index);
|
268
326
|
| }
|
327
|
+
|#ifdef __BYTE_ORDER
|
328
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
329
|
+
| offset = bswap_64(offset);
|
330
|
+
| class_id = bswap_64(class_id);
|
331
|
+
|# endif
|
332
|
+
|#endif
|
269
333
|
| element_p->offset = offset;
|
270
334
|
| element_p->class = class_id;
|
271
335
|
|}
|
@@ -278,6 +342,7 @@ module Rod
|
|
278
342
|
| unsigned long index;
|
279
343
|
| #{model_struct} * model_p;
|
280
344
|
| unsigned long result;
|
345
|
+
|
|
281
346
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
282
347
|
| result = model_p->_join_element_count;
|
283
348
|
| for(index = 0; index < size; index++){
|
@@ -301,6 +366,7 @@ module Rod
|
|
301
366
|
| unsigned long index;
|
302
367
|
| #{model_struct} * model_p;
|
303
368
|
| unsigned long result;
|
369
|
+
|
|
304
370
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
305
371
|
| result = model_p->_polymorphic_join_element_count;
|
306
372
|
| for(index = 0; index < size; index++){
|
@@ -321,6 +387,40 @@ module Rod
|
|
321
387
|
END
|
322
388
|
builder.c(str.margin)
|
323
389
|
|
390
|
+
str =<<-END
|
391
|
+
|VALUE _fast_intersection_size(unsigned long first_offset,
|
392
|
+
| unsigned long first_length, unsigned long second_offset,
|
393
|
+
| unsigned long second_length, VALUE handler){
|
394
|
+
| unsigned long i,j,count,v1,v2;
|
395
|
+
| #{model_struct} * model_p;
|
396
|
+
|
|
397
|
+
| i = 0; j = 0; count = 0;
|
398
|
+
| Data_Get_Struct(handler,#{model_struct},model_p);
|
399
|
+
|
|
400
|
+
| while(i < first_length && j < second_length){
|
401
|
+
| v1 = (model_p->_join_element_table + first_offset + i)->offset;
|
402
|
+
| v2 = (model_p->_join_element_table + second_offset + j)->offset;
|
403
|
+
|#ifdef __BYTE_ORDER
|
404
|
+
|# if __BYTE_ORDER == __BIG_ENDIAN
|
405
|
+
| v1 = bswap_64(v1);
|
406
|
+
| v2 = bswap_64(v2);
|
407
|
+
|# endif
|
408
|
+
|#endif
|
409
|
+
| if(v1 < v2){
|
410
|
+
| i++;
|
411
|
+
| } else {
|
412
|
+
| if(v1 > v2){
|
413
|
+
| j++;
|
414
|
+
| } else {
|
415
|
+
| i++; j++; count++;
|
416
|
+
| }
|
417
|
+
| }
|
418
|
+
| }
|
419
|
+
| return ULONG2NUM(count);
|
420
|
+
|}
|
421
|
+
END
|
422
|
+
builder.c(str.margin)
|
423
|
+
|
324
424
|
#########################################
|
325
425
|
# Strings
|
326
426
|
#########################################
|
@@ -328,6 +428,7 @@ module Rod
|
|
328
428
|
|VALUE _read_string(unsigned long length, unsigned long offset, VALUE handler){
|
329
429
|
| #{model_struct} * model_p;
|
330
430
|
| char * str;
|
431
|
+
|
|
331
432
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
332
433
|
| str = model_p->#{StringElement.struct_name}_table + offset;
|
333
434
|
| return rb_str_new(str, length);
|
@@ -353,6 +454,7 @@ module Rod
|
|
353
454
|
| long length_left = length;
|
354
455
|
| // see the routine description above.
|
355
456
|
| VALUE result;
|
457
|
+
|
|
356
458
|
| // get the structure
|
357
459
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
358
460
|
| // first free byte in current page
|
@@ -407,9 +509,9 @@ module Rod
|
|
407
509
|
str =<<-END
|
408
510
|
|// Store the object in the database.
|
409
511
|
|void _store_#{klass.struct_name}(VALUE object, VALUE handler){
|
410
|
-
|
|
411
512
|
| #{model_struct} * model_p;
|
412
513
|
| #{klass.struct_name} * struct_p;
|
514
|
+
|
|
413
515
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
414
516
|
| if((model_p->#{klass.struct_name}_count+1) * sizeof(#{klass.struct_name}) >=
|
415
517
|
| model_p->#{klass.struct_name}_page_count * page_size()){
|
@@ -436,17 +538,22 @@ module Rod
|
|
436
538
|
|VALUE _init_handler(char * dir_path){
|
437
539
|
| #{model_struct} * model_p;
|
438
540
|
| VALUE cClass;
|
439
|
-
| model_p = ALLOC(#{model_struct});
|
440
541
|
|
|
542
|
+
| model_p = ALLOC(#{model_struct});
|
441
543
|
| #{init_structs(classes)}
|
442
544
|
|
|
443
545
|
| // set dir path
|
444
546
|
| model_p->path = malloc(sizeof(char)*(strlen(dir_path)+1));
|
445
547
|
| strcpy(model_p->path,dir_path);
|
446
548
|
|
|
549
|
+
| // initialize empty data written when extending file
|
550
|
+
| model_p->empty_data = calloc(page_size() * ALLOCATED_PAGES,1);
|
551
|
+
|
|
447
552
|
| //create the wrapping object
|
448
553
|
| cClass = rb_define_class("#{model_struct_name(path).camelcase(true)}",
|
449
554
|
| rb_cObject);
|
555
|
+
| // TODO #225
|
556
|
+
| //return Data_Wrap_Struct(cClass, 0, model_struct_free, model_p);
|
450
557
|
| return Data_Wrap_Struct(cClass, 0, free, model_p);
|
451
558
|
|}
|
452
559
|
END
|
@@ -472,6 +579,7 @@ module Rod
|
|
472
579
|
str =<<-END
|
473
580
|
|void _open(VALUE handler){
|
474
581
|
| #{model_struct} * model_p;
|
582
|
+
|
|
475
583
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
476
584
|
|
|
477
585
|
| \n#{classes.map do |klass|
|
@@ -502,6 +610,7 @@ module Rod
|
|
502
610
|
|// if +classes+ are Qnil, the DB was open in readonly mode.
|
503
611
|
|void _close(VALUE handler){
|
504
612
|
| #{model_struct} * model_p;
|
613
|
+
|
|
505
614
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
506
615
|
|
|
507
616
|
| \n#{classes.map do |klass|
|
@@ -528,13 +637,13 @@ module Rod
|
|
528
637
|
str = <<-END
|
529
638
|
|void _print_layout(VALUE handler){
|
530
639
|
| #{model_struct} * model_p;
|
640
|
+
|
|
531
641
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
532
642
|
| printf("============= Data layout START =============\\n");
|
533
643
|
| \n#{classes.map do |klass|
|
534
644
|
str =<<-SUBEND
|
535
645
|
| printf("-- #{klass} --\\n");
|
536
646
|
| printf("Size of #{klass.struct_name} %lu\\n",(unsigned long)sizeof(#{klass.struct_name}));
|
537
|
-
| \n#{klass.layout}
|
538
647
|
| printf("Page count: %lu, count %lu, pointer: %lx\\n",
|
539
648
|
| model_p->#{klass.struct_name}_page_count,
|
540
649
|
| model_p->#{klass.struct_name}_count,
|
@@ -580,6 +689,7 @@ module Rod
|
|
580
689
|
str =<<-END
|
581
690
|
|#{result_type} _#{name}(VALUE handler){
|
582
691
|
| #{model_struct} * model_p;
|
692
|
+
|
|
583
693
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
584
694
|
| return model_p->#{name};
|
585
695
|
|}
|
@@ -592,6 +702,7 @@ module Rod
|
|
592
702
|
str =<<-END
|
593
703
|
|void _#{name}_equals(VALUE handler,#{arg_type} value){
|
594
704
|
| #{model_struct} * model_p;
|
705
|
+
|
|
595
706
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
596
707
|
| model_p->#{name} = value;
|
597
708
|
|}
|
@@ -602,7 +713,9 @@ module Rod
|
|
602
713
|
def self.rod_exception
|
603
714
|
str =<<-END
|
604
715
|
|VALUE rodException(){
|
605
|
-
| VALUE klass
|
716
|
+
| VALUE klass;
|
717
|
+
|
|
718
|
+
| klass = rb_const_get(rb_cObject, rb_intern("Rod"));
|
606
719
|
| klass = rb_const_get(klass, rb_intern("DatabaseError"));
|
607
720
|
| return klass;
|
608
721
|
|}
|
data/lib/rod/index/base.rb
CHANGED
@@ -42,9 +42,9 @@ module Rod
|
|
42
42
|
proxy = get(key)
|
43
43
|
end
|
44
44
|
if proxy.nil?
|
45
|
-
proxy =
|
45
|
+
proxy = empty_collection_proxy(key)
|
46
46
|
else
|
47
|
-
|
47
|
+
if Array === proxy
|
48
48
|
offset, count = proxy
|
49
49
|
proxy = CollectionProxy.new(count,@klass.database,offset,@klass)
|
50
50
|
end
|
@@ -61,6 +61,7 @@ module Rod
|
|
61
61
|
# Copies the values from +index+ to this index.
|
62
62
|
def copy(index)
|
63
63
|
index.each.with_index do |key_value,position|
|
64
|
+
# TODO #206 this doesn't work for hash
|
64
65
|
self.set(key_value[0],key_value[1])
|
65
66
|
# TODO #182 implement size for index
|
66
67
|
# report_progress(position,index.size) if $ROD_DEBUG
|
@@ -85,6 +86,14 @@ module Rod
|
|
85
86
|
"#{self.class}@#{@path}"
|
86
87
|
end
|
87
88
|
|
89
|
+
protected
|
90
|
+
|
91
|
+
# Returns an empty collection proxy. Might be changed
|
92
|
+
# in subclasses to provie index-specific collection proxies.
|
93
|
+
def empty_collection_proxy(key)
|
94
|
+
CollectionProxy.new(0,@klass.database,0,@klass)
|
95
|
+
end
|
96
|
+
|
88
97
|
class << self
|
89
98
|
# Creats the proper instance of Index or one of its sublcasses.
|
90
99
|
# The +path+ is the path were the index is stored, while +index+ is the previous index instance.
|
@@ -105,7 +114,7 @@ module Rod
|
|
105
114
|
warn("Index type 'true' is deprecated. It will be removed in ROD 0.8.0")
|
106
115
|
FlatIndex.new(path,klass,options)
|
107
116
|
else
|
108
|
-
raise RodException.new("Invalid index type #{type}")
|
117
|
+
raise RodException.new("Invalid index type '#{type}'")
|
109
118
|
end
|
110
119
|
end
|
111
120
|
end
|