rod 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/{README → README.rdoc} +33 -2
- data/Rakefile +7 -2
- data/changelog.txt +13 -0
- data/contributors.txt +2 -0
- data/features/append.feature +221 -0
- data/features/assoc_indexing.feature +66 -0
- data/features/basic.feature +199 -0
- data/features/collection.feature +171 -0
- data/features/flat_indexing.feature +140 -0
- data/features/fred.feature +49 -0
- data/features/inheritence.feature +211 -0
- data/features/muliple_db.feature +113 -0
- data/features/relationships.feature +195 -0
- data/features/segmented_indexing.feature +172 -0
- data/features/steps/model.rb +386 -0
- data/features/steps/rod.rb +71 -0
- data/features/steps/test_helper.rb +5 -0
- data/lib/rod/abstract_database.rb +17 -5
- data/lib/rod/constants.rb +1 -1
- data/lib/rod/database.rb +95 -74
- data/lib/rod/join_element.rb +6 -2
- data/lib/rod/model.rb +37 -9
- data/rod.gemspec +15 -12
- data/tests/check_strings.rb +10 -0
- data/tests/class_compatibility_create.rb +14 -0
- data/tests/class_compatibility_verify.rb +18 -0
- data/tests/eff1_test.rb +60 -0
- data/tests/eff2_test.rb +61 -0
- data/tests/full_runs.rb +68 -0
- data/tests/generate_classes_create.rb +25 -0
- data/tests/generate_classes_model.rb +23 -0
- data/tests/generate_classes_rewrite.rb +7 -0
- data/tests/generate_classes_verify.rb +46 -0
- data/tests/load_struct.rb +24 -0
- data/tests/migration_create.rb +25 -0
- data/tests/migration_migrate.rb +22 -0
- data/tests/migration_model1.rb +23 -0
- data/tests/migration_model2.rb +27 -0
- data/tests/migration_verify.rb +56 -0
- data/tests/mock_tests.rb +128 -0
- data/tests/read_on_create.rb +45 -0
- data/tests/save_struct.rb +49 -0
- data/tests/structures.rb +52 -0
- data/tests/unit/database.rb +60 -0
- data/tests/unit/model.rb +36 -0
- data/tests/unit/model_tests.rb +116 -0
- data/tests/validate_read_on_create.rb +12 -0
- data/utils/convert_index.rb +31 -0
- metadata +77 -28
@@ -52,7 +52,7 @@ module Rod
|
|
52
52
|
if File.exist?(@path)
|
53
53
|
remove_file("#{@path}database.yml")
|
54
54
|
else
|
55
|
-
|
55
|
+
FileUtils.mkdir_p(@path)
|
56
56
|
end
|
57
57
|
self.classes.each do |klass|
|
58
58
|
klass.send(:build_structure)
|
@@ -68,6 +68,7 @@ module Rod
|
|
68
68
|
next if special_class?(klass)
|
69
69
|
remove_files_but(klass.inline_library)
|
70
70
|
end
|
71
|
+
remove_files(self.inline_library)
|
71
72
|
generate_c_code(@path, classes)
|
72
73
|
remove_files_but(self.inline_library)
|
73
74
|
@metadata = {}
|
@@ -104,6 +105,7 @@ module Rod
|
|
104
105
|
elsif options[:migrate]
|
105
106
|
create_legacy_classes
|
106
107
|
FileUtils.cp(@path + DATABASE_FILE, @path + DATABASE_FILE + LEGACY_DATA_SUFFIX)
|
108
|
+
remove_files(self.inline_library)
|
107
109
|
end
|
108
110
|
self.classes.each do |klass|
|
109
111
|
klass.send(:build_structure)
|
@@ -266,16 +268,26 @@ module Rod
|
|
266
268
|
end
|
267
269
|
|
268
270
|
# Returns the string of given +length+ starting at given +offset+.
|
269
|
-
|
271
|
+
# Options:
|
272
|
+
# * +:skip_encoding+ - if set to +true+, the string is left as ASCII-8BIT
|
273
|
+
def read_string(length, offset,options={})
|
270
274
|
# TODO the encoding should be stored in the DB
|
271
275
|
# or configured globally
|
272
|
-
_read_string(length, offset, @handler)
|
276
|
+
value = _read_string(length, offset, @handler)
|
277
|
+
if options[:skip_encoding]
|
278
|
+
value.force_encoding("ascii-8bit")
|
279
|
+
else
|
280
|
+
value.force_encoding("utf-8")
|
281
|
+
end
|
273
282
|
end
|
274
283
|
|
275
284
|
# Stores the string in the DB encoding it to utf-8.
|
276
|
-
|
285
|
+
# Options:
|
286
|
+
# * +:skip_encoding+ - if set to +true+, the string is not encoded
|
287
|
+
def set_string(value,options={})
|
277
288
|
raise DatabaseError.new("Readonly database.") if readonly_data?
|
278
|
-
|
289
|
+
value = value.encode("utf-8") unless options[:skip_encoding]
|
290
|
+
_set_string(value,@handler)
|
279
291
|
end
|
280
292
|
|
281
293
|
# Returns the number of objects for given +klass+.
|
data/lib/rod/constants.rb
CHANGED
data/lib/rod/database.rb
CHANGED
@@ -57,19 +57,19 @@ module Rod
|
|
57
57
|
# exist.
|
58
58
|
def open_class_file(klass)
|
59
59
|
str =<<-END
|
60
|
-
|
61
|
-
|if(model_p->#{klass.struct_name}_lib_file == -1){
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
| // create the file unless it exists
|
61
|
+
| if(model_p->#{klass.struct_name}_lib_file == -1){
|
62
|
+
| char * path = malloc(sizeof(char) * (strlen(model_p->path) +
|
63
|
+
| #{klass.path_for_data("").size} + 1));
|
64
|
+
| strcpy(path,model_p->path);
|
65
|
+
| strcat(path,"#{klass.path_for_data("")}");
|
66
|
+
| model_p->#{klass.struct_name}_lib_file =
|
67
|
+
| open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
68
|
+
| if(model_p->#{klass.struct_name}_lib_file == -1) {
|
69
|
+
| rb_raise(rodException(),"Could not open file for class #{klass} on path %s writing.",path);
|
70
|
+
| }
|
71
|
+
| free(path);
|
70
72
|
| }
|
71
|
-
| free(path);
|
72
|
-
|}
|
73
73
|
END
|
74
74
|
str.margin
|
75
75
|
end
|
@@ -109,34 +109,36 @@ module Rod
|
|
109
109
|
|
|
110
110
|
| // increase the pages count by 1
|
111
111
|
| model_p->#{klass.struct_name}_page_count += ALLOCATED_PAGES;
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
| model_p->#{klass.struct_name}
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
112
|
+
| {
|
113
|
+
| // open the file for writing
|
114
|
+
| char* #{klass.struct_name}_empty_data;
|
115
|
+
| FILE * #{klass.struct_name}_file =
|
116
|
+
| fdopen(model_p->#{klass.struct_name}_lib_file,"w+");
|
117
|
+
| if(#{klass.struct_name}_file == NULL){
|
118
|
+
| rb_raise(rodException(),"Could not open file for #{klass.struct_name}.");
|
119
|
+
| }
|
120
|
+
| // seek to the end
|
121
|
+
| if(fseek(#{klass.struct_name}_file,0,SEEK_END) == -1){
|
122
|
+
| rb_raise(rodException(),"Could not seek to end file for #{klass.struct_name}.");
|
123
|
+
| }
|
124
|
+
| // write empty data at the end
|
125
|
+
| #{klass.struct_name}_empty_data = calloc(page_size() * ALLOCATED_PAGES,1);
|
126
|
+
| if(write(model_p->#{klass.struct_name}_lib_file,#{klass.struct_name}_empty_data,
|
127
|
+
| page_size() * ALLOCATED_PAGES) == -1){
|
128
|
+
| rb_raise(rodException(),"Could not write to file for #{klass.struct_name}.");
|
129
|
+
| }
|
130
|
+
| // seek to the beginning
|
131
|
+
| if(fseek(#{klass.struct_name}_file,0,SEEK_SET) == -1){
|
132
|
+
| rb_raise(rodException(),"Could not seek to start file for #{klass.struct_name}.");
|
133
|
+
| }
|
134
|
+
| // mmap the extended file
|
135
|
+
| model_p->#{klass.struct_name}_table = mmap(NULL,
|
136
|
+
| model_p->#{klass.struct_name}_page_count * page_size(),
|
137
|
+
| PROT_WRITE | PROT_READ, MAP_SHARED, model_p->#{klass.struct_name}_lib_file,0);
|
138
|
+
| if(model_p->#{klass.struct_name}_table == MAP_FAILED){
|
139
|
+
| perror(NULL);
|
140
|
+
| rb_raise(rodException(),"Could not mmap segment for #{klass.struct_name}.");
|
141
|
+
| }
|
140
142
|
| }
|
141
143
|
|#{update_pointer(klass) unless special_class?(klass)}
|
142
144
|
END
|
@@ -153,6 +155,19 @@ module Rod
|
|
153
155
|
# Implementations of abstract methods
|
154
156
|
#########################################################################
|
155
157
|
|
158
|
+
# Ruby inline generated shared library name.
|
159
|
+
def inline_library
|
160
|
+
unless defined?(@inline_library)
|
161
|
+
self.class.inline(:C) do |builder|
|
162
|
+
builder.c_singleton("void __unused_method_#{rand(1000)}(){}")
|
163
|
+
|
164
|
+
self.instance_variable_set("@inline_library",builder.so_name)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
@inline_library
|
168
|
+
end
|
169
|
+
|
170
|
+
|
156
171
|
# Generates the code C responsible for management of the database.
|
157
172
|
def generate_c_code(path, classes)
|
158
173
|
if !@code_generated || @@rod_development_mode
|
@@ -177,14 +192,7 @@ module Rod
|
|
177
192
|
END
|
178
193
|
builder.prefix(str.margin)
|
179
194
|
|
180
|
-
|
181
|
-
|VALUE rodException(){
|
182
|
-
| VALUE klass = rb_const_get(rb_cObject, rb_intern("Rod"));
|
183
|
-
| klass = rb_const_get(klass, rb_intern("DatabaseError"));
|
184
|
-
| return klass;
|
185
|
-
|}
|
186
|
-
END
|
187
|
-
builder.prefix(str.margin)
|
195
|
+
builder.prefix(self.class.rod_exception)
|
188
196
|
|
189
197
|
|
190
198
|
#########################################
|
@@ -215,7 +223,7 @@ module Rod
|
|
215
223
|
|VALUE _join_element_index(unsigned long element_offset, unsigned long element_index, VALUE handler){
|
216
224
|
| #{model_struct} * model_p;
|
217
225
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
218
|
-
| return
|
226
|
+
| return ULONG2NUM((model_p->_join_element_table + element_offset + element_index)->offset);
|
219
227
|
|}
|
220
228
|
END
|
221
229
|
builder.c(str.margin)
|
@@ -225,7 +233,7 @@ module Rod
|
|
225
233
|
| unsigned long element_index, VALUE handler){
|
226
234
|
| #{model_struct} * model_p;
|
227
235
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
228
|
-
| return
|
236
|
+
| return ULONG2NUM((model_p->_polymorphic_join_element_table +
|
229
237
|
| element_offset + element_index)->offset);
|
230
238
|
|}
|
231
239
|
END
|
@@ -236,7 +244,7 @@ module Rod
|
|
236
244
|
| unsigned long element_index, VALUE handler){
|
237
245
|
| #{model_struct} * model_p;
|
238
246
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
239
|
-
| return
|
247
|
+
| return ULONG2NUM((model_p->_polymorphic_join_element_table +
|
240
248
|
| element_offset + element_index)->class);
|
241
249
|
|}
|
242
250
|
END
|
@@ -247,12 +255,11 @@ module Rod
|
|
247
255
|
| unsigned long element_index, unsigned long offset,
|
248
256
|
| VALUE handler){
|
249
257
|
| #{model_struct} * model_p;
|
250
|
-
| Data_Get_Struct(handler,#{model_struct},model_p);
|
251
258
|
| _join_element * element_p;
|
259
|
+
| Data_Get_Struct(handler,#{model_struct},model_p);
|
252
260
|
| element_p = model_p->_join_element_table + element_offset + element_index;
|
253
261
|
| if(element_p->index != element_index){
|
254
|
-
|
|
255
|
-
| rb_raise(eClass, "Join element indices are inconsistent: %lu %lu!",
|
262
|
+
| rb_raise(rodException(), "Join element indices are inconsistent: %lu %lu!",
|
256
263
|
| element_index, element_p->index);
|
257
264
|
| }
|
258
265
|
| element_p->offset = offset;
|
@@ -265,12 +272,11 @@ module Rod
|
|
265
272
|
| unsigned long element_index, unsigned long offset, unsigned long class_id,
|
266
273
|
| VALUE handler){
|
267
274
|
| #{model_struct} * model_p;
|
268
|
-
| Data_Get_Struct(handler,#{model_struct},model_p);
|
269
275
|
| _polymorphic_join_element * element_p;
|
276
|
+
| Data_Get_Struct(handler,#{model_struct},model_p);
|
270
277
|
| element_p = model_p->_polymorphic_join_element_table + element_offset + element_index;
|
271
278
|
| if(element_p->index != element_index){
|
272
|
-
|
|
273
|
-
| rb_raise(eClass, "Polymorphic join element indices are inconsistent: %lu %lu!",
|
279
|
+
| rb_raise(rodException(), "Polymorphic join element indices are inconsistent: %lu %lu!",
|
274
280
|
| element_index, element_p->index);
|
275
281
|
| }
|
276
282
|
| element_p->offset = offset;
|
@@ -284,8 +290,9 @@ module Rod
|
|
284
290
|
| _join_element * element;
|
285
291
|
| unsigned long index;
|
286
292
|
| #{model_struct} * model_p;
|
293
|
+
| unsigned long result;
|
287
294
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
288
|
-
|
|
295
|
+
| result = model_p->_join_element_count;
|
289
296
|
| for(index = 0; index < size; index++){
|
290
297
|
| if((model_p->_join_element_count + 1) * sizeof(_join_element) >=
|
291
298
|
| page_size() * model_p->_join_element_page_count){
|
@@ -306,8 +313,9 @@ module Rod
|
|
306
313
|
| _polymorphic_join_element * element;
|
307
314
|
| unsigned long index;
|
308
315
|
| #{model_struct} * model_p;
|
316
|
+
| unsigned long result;
|
309
317
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
310
|
-
|
|
318
|
+
| result = model_p->_polymorphic_join_element_count;
|
311
319
|
| for(index = 0; index < size; index++){
|
312
320
|
| if((model_p->_polymorphic_join_element_count + 1) *
|
313
321
|
| sizeof(_polymorphic_join_element) >=
|
@@ -332,8 +340,9 @@ module Rod
|
|
332
340
|
str =<<-END
|
333
341
|
|VALUE _read_string(unsigned long length, unsigned long offset, VALUE handler){
|
334
342
|
| #{model_struct} * model_p;
|
343
|
+
| char * str;
|
335
344
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
336
|
-
|
|
345
|
+
| str = model_p->#{StringElement.struct_name}_table + offset;
|
337
346
|
| return rb_str_new(str, length);
|
338
347
|
|}
|
339
348
|
END
|
@@ -344,10 +353,9 @@ module Rod
|
|
344
353
|
|// The return value is a pair: length and offset.
|
345
354
|
|VALUE _set_string(VALUE ruby_value, VALUE handler){
|
346
355
|
| #{model_struct} * model_p;
|
347
|
-
| Data_Get_Struct(handler,#{model_struct},model_p);
|
348
356
|
| unsigned long length = RSTRING_LEN(ruby_value);
|
349
357
|
| char * value = RSTRING_PTR(ruby_value);
|
350
|
-
| unsigned long string_offset, page_offset, current_page;
|
358
|
+
| unsigned long string_offset, page_offset, current_page, sum;
|
351
359
|
| char * dest;
|
352
360
|
| // table:
|
353
361
|
| // - address of the first page
|
@@ -356,12 +364,17 @@ module Rod
|
|
356
364
|
| // count:
|
357
365
|
| // - total number of bytes
|
358
366
|
| long length_left = length;
|
367
|
+
| // see the routine description above.
|
368
|
+
| VALUE result;
|
369
|
+
| // get the structure
|
370
|
+
| Data_Get_Struct(handler,#{model_struct},model_p);
|
359
371
|
| // first free byte in current page
|
360
372
|
| string_offset = model_p->#{StringElement.struct_name}_count % page_size();
|
361
373
|
| page_offset = model_p->#{StringElement.struct_name}_count / page_size();
|
362
374
|
| current_page = page_offset;
|
363
375
|
| while(length_left > 0){
|
364
|
-
|
|
376
|
+
| sum = ((unsigned long)length_left) + string_offset;
|
377
|
+
| if(sum >= page_size()){
|
365
378
|
| \n#{mmap_class(StringElement)}
|
366
379
|
| }
|
367
380
|
| dest = model_p->#{StringElement.struct_name}_table +
|
@@ -378,9 +391,9 @@ module Rod
|
|
378
391
|
|
|
379
392
|
| model_p->#{StringElement.struct_name}_count += length;
|
380
393
|
|
|
381
|
-
|
|
382
|
-
| rb_ary_push(result,
|
383
|
-
| rb_ary_push(result,
|
394
|
+
| result = rb_ary_new();
|
395
|
+
| rb_ary_push(result, ULONG2NUM(length));
|
396
|
+
| rb_ary_push(result, ULONG2NUM(string_offset + page_offset * page_size()));
|
384
397
|
| return result;
|
385
398
|
|}
|
386
399
|
END
|
@@ -410,12 +423,13 @@ module Rod
|
|
410
423
|
|void _store_#{klass.struct_name}(VALUE object, VALUE handler){
|
411
424
|
|
|
412
425
|
| #{model_struct} * model_p;
|
426
|
+
| #{klass.struct_name} * struct_p;
|
413
427
|
| Data_Get_Struct(handler,#{model_struct},model_p);
|
414
428
|
| if((model_p->#{klass.struct_name}_count+1) * sizeof(#{klass.struct_name}) >=
|
415
429
|
| model_p->#{klass.struct_name}_page_count * page_size()){
|
416
430
|
| \n#{mmap_class(klass)}
|
417
431
|
| }
|
418
|
-
|
|
432
|
+
| struct_p = model_p->#{klass.struct_name}_table +
|
419
433
|
| model_p->#{klass.struct_name}_count;
|
420
434
|
| //printf("struct assigned\\n");
|
421
435
|
| model_p->#{klass.struct_name}_count++;
|
@@ -423,7 +437,7 @@ module Rod
|
|
423
437
|
| //the number is incresed by 1, because 0 indicates that the
|
424
438
|
| //(referenced) object is nil
|
425
439
|
| struct_p->rod_id = model_p->#{klass.struct_name}_count;
|
426
|
-
| rb_iv_set(object, \"@rod_id\",
|
440
|
+
| rb_iv_set(object, \"@rod_id\",ULONG2NUM(struct_p->rod_id));
|
427
441
|
|}
|
428
442
|
END
|
429
443
|
builder.c(str.margin)
|
@@ -435,6 +449,7 @@ module Rod
|
|
435
449
|
str = <<-END
|
436
450
|
|VALUE _init_handler(char * dir_path){
|
437
451
|
| #{model_struct} * model_p;
|
452
|
+
| VALUE cClass;
|
438
453
|
| model_p = ALLOC(#{model_struct});
|
439
454
|
|
|
440
455
|
| #{init_structs(classes)}
|
@@ -444,7 +459,7 @@ module Rod
|
|
444
459
|
| strcpy(model_p->path,dir_path);
|
445
460
|
|
|
446
461
|
| //create the wrapping object
|
447
|
-
|
|
462
|
+
| cClass = rb_define_class("#{model_struct_name(path).camelcase(true)}",
|
448
463
|
| rb_cObject);
|
449
464
|
| return Data_Wrap_Struct(cClass, 0, free, model_p);
|
450
465
|
|}
|
@@ -569,11 +584,6 @@ module Rod
|
|
569
584
|
# This has to be at the very end of builder definition!
|
570
585
|
self.instance_variable_set("@inline_library",builder.so_name)
|
571
586
|
|
572
|
-
# Ruby inline generated shared library.
|
573
|
-
def self.inline_library
|
574
|
-
@inline_library
|
575
|
-
end
|
576
|
-
|
577
587
|
end
|
578
588
|
@code_generated = true
|
579
589
|
end
|
@@ -602,5 +612,16 @@ module Rod
|
|
602
612
|
END
|
603
613
|
builder.c(str.margin)
|
604
614
|
end
|
615
|
+
|
616
|
+
def self.rod_exception
|
617
|
+
str =<<-END
|
618
|
+
|VALUE rodException(){
|
619
|
+
| VALUE klass = rb_const_get(rb_cObject, rb_intern("Rod"));
|
620
|
+
| klass = rb_const_get(klass, rb_intern("DatabaseError"));
|
621
|
+
| return klass;
|
622
|
+
|}
|
623
|
+
END
|
624
|
+
str.margin
|
625
|
+
end
|
605
626
|
end
|
606
627
|
end
|
data/lib/rod/join_element.rb
CHANGED
@@ -13,7 +13,9 @@ module Rod
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.layout
|
16
|
-
' printf(" offset: %lu, index: %lu\n",
|
16
|
+
' printf(" offset: %lu, index: %lu\n",' +
|
17
|
+
'(unsigned long)sizeof(unsigned long), ' +
|
18
|
+
'(unsigned long)sizeof(unsigned long));' + "\n"
|
17
19
|
end
|
18
20
|
|
19
21
|
def self.struct_name
|
@@ -39,7 +41,9 @@ module Rod
|
|
39
41
|
|
40
42
|
def self.layout
|
41
43
|
' printf(" offset: %lu, index: %lu, class: %lu\n",' +
|
42
|
-
'
|
44
|
+
'(unsigned long)sizeof(unsigned long), ' +
|
45
|
+
'(unsigned long)sizeof(unsigned long), ' +
|
46
|
+
'(unsigned long)sizeof(unsigned long));' + "\n"
|
43
47
|
end
|
44
48
|
end
|
45
49
|
end
|
data/lib/rod/model.rb
CHANGED
@@ -52,14 +52,19 @@ module Rod
|
|
52
52
|
self.class == other.class && self.rod_id == other.rod_id
|
53
53
|
end
|
54
54
|
|
55
|
-
# Default implementation of
|
56
|
-
def
|
55
|
+
# Default implementation of +inspect+.
|
56
|
+
def inspect
|
57
57
|
fields = self.class.fields.map{|n,o| "#{n}:#{self.send(n)}"}.join(",")
|
58
58
|
singular = self.class.singular_associations.map{|n,o| "#{n}:#{self.send(n).class}"}.join(",")
|
59
59
|
plural = self.class.plural_associations.map{|n,o| "#{n}:#{self.send(n).size}"}.join(",")
|
60
60
|
"#{self.class}:<#{fields}><#{singular}><#{plural}>"
|
61
61
|
end
|
62
62
|
|
63
|
+
# Default implementation of +to_s+.
|
64
|
+
def to_s
|
65
|
+
self.inspect
|
66
|
+
end
|
67
|
+
|
63
68
|
# Returns the number of objects of this class stored in the
|
64
69
|
# database.
|
65
70
|
def self.count
|
@@ -228,7 +233,11 @@ module Rod
|
|
228
233
|
else
|
229
234
|
raise RodException.new("Unrecognised field type '#{self.class.fields[name][:type]}'!")
|
230
235
|
end
|
231
|
-
|
236
|
+
options = {}
|
237
|
+
if self.class.fields[name][:type] == :object
|
238
|
+
options[:skip_encoding] = true
|
239
|
+
end
|
240
|
+
length, offset = database.set_string(value,options)
|
232
241
|
send("_#{name}_length=",@rod_id,length)
|
233
242
|
send("_#{name}_offset=",@rod_id,offset)
|
234
243
|
else
|
@@ -726,20 +735,23 @@ module Rod
|
|
726
735
|
result = <<-END
|
727
736
|
| \n#{self.fields.map do |field,options|
|
728
737
|
unless string_field?(options[:type])
|
729
|
-
"| printf(\" size of '#{field}': %lu\\n\",
|
738
|
+
"| printf(\" size of '#{field}': %lu\\n\"," +
|
739
|
+
"(unsigned long)sizeof(#{TYPE_MAPPING[options[:type]]}));"
|
730
740
|
else
|
731
741
|
<<-SUBEND
|
732
742
|
| printf(" string '#{field}' length: %lu offset: %lu page: %lu\\n",
|
733
|
-
| sizeof(unsigned long),
|
743
|
+
| (unsigned long)sizeof(unsigned long), (unsigned long)sizeof(unsigned long),
|
744
|
+
| (unsigned long)sizeof(unsigned long));
|
734
745
|
SUBEND
|
735
746
|
end
|
736
747
|
end.join("\n") }
|
737
748
|
| \n#{singular_associations.map do |name, options|
|
738
|
-
" printf(\" singular assoc '#{name}': %lu\\n\",
|
749
|
+
" printf(\" singular assoc '#{name}': %lu\\n\","+
|
750
|
+
"(unsigned long)sizeof(unsigned long));"
|
739
751
|
end.join("\n| ")}
|
740
752
|
| \n#{plural_associations.map do |name, options|
|
741
753
|
"| printf(\" plural assoc '#{name}' offset: %lu, count %lu\\n\",\n"+
|
742
|
-
"| sizeof(unsigned long),sizeof(unsigned long));"
|
754
|
+
"| (unsigned long)sizeof(unsigned long),(unsigned long)sizeof(unsigned long));"
|
743
755
|
end.join("\n| \n")}
|
744
756
|
END
|
745
757
|
result.margin
|
@@ -749,6 +761,9 @@ module Rod
|
|
749
761
|
def self.field_reader(name,result_type,builder)
|
750
762
|
str =<<-END
|
751
763
|
|#{result_type} _#{name}(unsigned long object_rod_id){
|
764
|
+
| if(object_rod_id == 0){
|
765
|
+
| rb_raise(rodException(), "Invalid object rod_id (0)");
|
766
|
+
| }
|
752
767
|
| VALUE klass = rb_funcall(self,rb_intern("class"),0);
|
753
768
|
| #{struct_name} * pointer = (#{struct_name} *)
|
754
769
|
| NUM2ULONG(rb_funcall(klass,rb_intern("rod_pointer"),0));
|
@@ -762,6 +777,9 @@ module Rod
|
|
762
777
|
def self.field_writer(name,arg_type,builder)
|
763
778
|
str =<<-END
|
764
779
|
|void _#{name}_equals(unsigned long object_rod_id,#{arg_type} value){
|
780
|
+
| if(object_rod_id == 0){
|
781
|
+
| rb_raise(rodException(), "Invalid object rod_id (0)");
|
782
|
+
| }
|
765
783
|
| VALUE klass = rb_funcall(self,rb_intern("class"),0);
|
766
784
|
| #{struct_name} * pointer = (#{struct_name} *)
|
767
785
|
| NUM2ULONG(rb_funcall(klass,rb_intern("rod_pointer"),0));
|
@@ -786,6 +804,7 @@ module Rod
|
|
786
804
|
|
787
805
|
inline(:C) do |builder|
|
788
806
|
builder.prefix(typedef_struct)
|
807
|
+
builder.prefix(Database.rod_exception)
|
789
808
|
if Database.development_mode
|
790
809
|
# This method is created to force rebuild of the C code, since
|
791
810
|
# it is rebuild on the basis of methods' signatures change.
|
@@ -883,7 +902,11 @@ module Rod
|
|
883
902
|
return (options[:type] == :object ? nil : "")
|
884
903
|
end
|
885
904
|
offset = send("_#{field}_offset", @rod_id)
|
886
|
-
|
905
|
+
read_options = {}
|
906
|
+
if options[:type] == :object
|
907
|
+
read_options[:skip_encoding] = true
|
908
|
+
end
|
909
|
+
value = database.read_string(length, offset, options)
|
887
910
|
if options[:type] == :object
|
888
911
|
value = Marshal.load(value)
|
889
912
|
end
|
@@ -917,6 +940,7 @@ module Rod
|
|
917
940
|
define_method(name) do
|
918
941
|
value = instance_variable_get("@#{name}")
|
919
942
|
if value.nil?
|
943
|
+
return nil if @rod_id == 0
|
920
944
|
rod_id = send("_#{name}",@rod_id)
|
921
945
|
# the indices are shifted by 1, to leave 0 for nil
|
922
946
|
if rod_id == 0
|
@@ -973,7 +997,11 @@ module Rod
|
|
973
997
|
if (instance_variable_get("@#{name}") != nil)
|
974
998
|
return instance_variable_get("@#{name}").count
|
975
999
|
else
|
976
|
-
|
1000
|
+
if @rod_id == 0
|
1001
|
+
return 0
|
1002
|
+
else
|
1003
|
+
return send("_#{name}_count",@rod_id)
|
1004
|
+
end
|
977
1005
|
end
|
978
1006
|
end
|
979
1007
|
|