rod 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/.travis.yml +1 -1
  2. data/README.rdoc +38 -10
  3. data/Rakefile +20 -9
  4. data/changelog.txt +25 -0
  5. data/contributors.txt +1 -0
  6. data/data/backward/0.7.0/_join_element.dat +0 -0
  7. data/data/backward/0.7.0/_polymorphic_join_element.dat +0 -0
  8. data/data/backward/0.7.0/char.dat +0 -0
  9. data/data/backward/0.7.0/database.yml +58 -0
  10. data/data/backward/0.7.0/rod_test__automobile.dat +0 -0
  11. data/data/backward/0.7.0/rod_test__caveman.dat +0 -0
  12. data/data/backward/0.7.0/rod_test__dog.dat +0 -0
  13. data/data/backward/0.7.0/rod_test__test_model.dat +0 -0
  14. data/data/portability/_join_element.dat +0 -0
  15. data/data/portability/_polymorphic_join_element.dat +0 -0
  16. data/data/portability/char.dat +0 -0
  17. data/data/portability/database.yml +49 -0
  18. data/data/portability/rod_test__automobile.dat +0 -0
  19. data/data/portability/rod_test__caveman.dat +0 -0
  20. data/data/portability/rod_test__dog.dat +0 -0
  21. data/data/portability/rod_test__test_model.dat +0 -0
  22. data/features/backward.feature +33 -0
  23. data/features/basic.feature +3 -0
  24. data/features/collection_proxy.feature +95 -0
  25. data/features/flat_indexing.feature +44 -2
  26. data/features/hash_indexing.feature +63 -9
  27. data/features/portability.feature +72 -0
  28. data/features/segmented_indexing.feature +45 -2
  29. data/features/steps/collection_proxy.rb +1 -1
  30. data/features/steps/model.rb +48 -5
  31. data/features/steps/rod.rb +15 -16
  32. data/lib/rod.rb +11 -1
  33. data/lib/rod/abstract_database.rb +52 -42
  34. data/lib/rod/berkeley/collection_proxy.rb +96 -0
  35. data/lib/rod/berkeley/database.rb +337 -0
  36. data/lib/rod/berkeley/environment.rb +209 -0
  37. data/lib/rod/berkeley/sequence.rb +222 -0
  38. data/lib/rod/berkeley/transaction.rb +233 -0
  39. data/lib/rod/collection_proxy.rb +76 -1
  40. data/lib/rod/constants.rb +3 -2
  41. data/lib/rod/database.rb +127 -14
  42. data/lib/rod/index/base.rb +12 -3
  43. data/lib/rod/index/hash_index.rb +295 -70
  44. data/lib/rod/index/segmented_index.rb +3 -0
  45. data/lib/rod/model.rb +154 -531
  46. data/lib/rod/property/base.rb +190 -0
  47. data/lib/rod/property/field.rb +258 -0
  48. data/lib/rod/property/plural_association.rb +145 -0
  49. data/lib/rod/property/singular_association.rb +139 -0
  50. data/rod.gemspec +6 -4
  51. data/spec/berkeley/database.rb +83 -0
  52. data/spec/berkeley/environment.rb +58 -0
  53. data/spec/berkeley/sequence.rb +101 -0
  54. data/spec/berkeley/transaction.rb +92 -0
  55. data/spec/collection_proxy.rb +38 -0
  56. data/spec/database.rb +36 -0
  57. data/spec/model.rb +26 -0
  58. data/spec/property/base.rb +73 -0
  59. data/spec/property/field.rb +244 -0
  60. data/spec/property/plural_association.rb +67 -0
  61. data/spec/property/singular_association.rb +65 -0
  62. data/tests/class_compatibility_create.rb +2 -2
  63. data/tests/eff1_test.rb +1 -1
  64. data/tests/eff2_test.rb +1 -1
  65. data/tests/full_runs.rb +1 -1
  66. data/tests/generate_classes_create.rb +14 -14
  67. data/tests/migration_create.rb +47 -47
  68. data/tests/migration_verify.rb +1 -1
  69. data/tests/missing_class_create.rb +6 -6
  70. data/tests/properties_order_create.rb +4 -4
  71. data/tests/read_on_create.rb +33 -34
  72. data/tests/save_struct.rb +40 -39
  73. data/tests/unit/database.rb +1 -1
  74. data/tests/unit/model_tests.rb +73 -65
  75. metadata +71 -15
  76. data/tests/unit/model.rb +0 -36
@@ -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
- else
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
@@ -1,5 +1,5 @@
1
1
  module Rod
2
- VERSION = "0.7.1"
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 = {
@@ -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 1
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
- | #{klass.struct_name}_empty_data = calloc(page_size() * ALLOCATED_PAGES,1);
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
- | return ULONG2NUM((model_p->_join_element_table + element_offset + element_index)->offset);
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
- | return ULONG2NUM((model_p->_polymorphic_join_element_table +
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
- | return ULONG2NUM((model_p->_polymorphic_join_element_table +
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 = rb_const_get(rb_cObject, rb_intern("Rod"));
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
  |}
@@ -42,9 +42,9 @@ module Rod
42
42
  proxy = get(key)
43
43
  end
44
44
  if proxy.nil?
45
- proxy = CollectionProxy.new(0,@klass.database,0,@klass)
45
+ proxy = empty_collection_proxy(key)
46
46
  else
47
- unless proxy.is_a?(CollectionProxy)
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