rod 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|