ferret 0.9.1 → 0.9.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.
Files changed (105) hide show
  1. data/README +6 -5
  2. data/Rakefile +34 -13
  3. data/TODO +1 -0
  4. data/TUTORIAL +1 -1
  5. data/ext/analysis.c +87 -70
  6. data/ext/analysis.h +18 -6
  7. data/ext/array.c +1 -2
  8. data/ext/array.h +1 -1
  9. data/ext/bitvector.c +10 -6
  10. data/ext/bitvector.h +2 -2
  11. data/ext/compound_io.c +30 -27
  12. data/ext/document.c +15 -15
  13. data/ext/document.h +5 -5
  14. data/ext/except.c +2 -0
  15. data/ext/except.h +25 -23
  16. data/ext/extconf.rb +1 -0
  17. data/ext/ferret.c +10 -8
  18. data/ext/ferret.h +9 -8
  19. data/ext/field.c +29 -25
  20. data/ext/filter.c +52 -14
  21. data/ext/frtio.h +13 -0
  22. data/ext/fs_store.c +115 -170
  23. data/ext/global.c +9 -8
  24. data/ext/global.h +17 -13
  25. data/ext/hash.c +13 -19
  26. data/ext/hash.h +11 -11
  27. data/ext/hashset.c +5 -7
  28. data/ext/hashset.h +9 -8
  29. data/ext/helper.c +1 -1
  30. data/ext/helper.h +2 -1
  31. data/ext/inc/except.h +25 -23
  32. data/ext/inc/lang.h +11 -1
  33. data/ext/ind.c +33 -21
  34. data/ext/index.h +44 -39
  35. data/ext/index_io.c +61 -57
  36. data/ext/index_rw.c +418 -361
  37. data/ext/lang.c +10 -0
  38. data/ext/lang.h +11 -1
  39. data/ext/nix_io.c +135 -0
  40. data/ext/priorityqueue.c +16 -16
  41. data/ext/priorityqueue.h +9 -6
  42. data/ext/q_boolean.c +128 -76
  43. data/ext/q_const_score.c +20 -20
  44. data/ext/q_filtered_query.c +20 -20
  45. data/ext/q_fuzzy.c +37 -23
  46. data/ext/q_match_all.c +15 -19
  47. data/ext/q_multi_phrase.c +87 -46
  48. data/ext/q_parser.c +247 -119
  49. data/ext/q_phrase.c +86 -52
  50. data/ext/q_prefix.c +25 -14
  51. data/ext/q_range.c +59 -14
  52. data/ext/q_span.c +263 -172
  53. data/ext/q_term.c +62 -51
  54. data/ext/q_wildcard.c +24 -13
  55. data/ext/r_analysis.c +328 -80
  56. data/ext/r_doc.c +11 -6
  57. data/ext/r_index_io.c +40 -32
  58. data/ext/r_qparser.c +15 -14
  59. data/ext/r_search.c +270 -152
  60. data/ext/r_store.c +32 -17
  61. data/ext/ram_store.c +38 -22
  62. data/ext/search.c +617 -87
  63. data/ext/search.h +227 -163
  64. data/ext/similarity.c +54 -45
  65. data/ext/similarity.h +3 -3
  66. data/ext/sort.c +132 -53
  67. data/ext/store.c +21 -2
  68. data/ext/store.h +14 -14
  69. data/ext/tags +4322 -232
  70. data/ext/term.c +140 -109
  71. data/ext/termdocs.c +74 -60
  72. data/ext/vector.c +181 -152
  73. data/ext/w32_io.c +150 -0
  74. data/lib/ferret.rb +1 -1
  75. data/lib/ferret/analysis/standard_tokenizer.rb +4 -3
  76. data/lib/ferret/document/field.rb +1 -1
  77. data/lib/ferret/index/field_infos.rb +1 -1
  78. data/lib/ferret/index/term.rb +1 -1
  79. data/lib/ferret/query_parser/query_parser.tab.rb +8 -24
  80. data/lib/ferret/search.rb +1 -0
  81. data/lib/ferret/search/boolean_query.rb +0 -4
  82. data/lib/ferret/search/index_searcher.rb +21 -8
  83. data/lib/ferret/search/multi_phrase_query.rb +7 -0
  84. data/lib/ferret/search/multi_searcher.rb +261 -0
  85. data/lib/ferret/search/phrase_query.rb +1 -1
  86. data/lib/ferret/search/query.rb +34 -5
  87. data/lib/ferret/search/sort.rb +7 -3
  88. data/lib/ferret/search/sort_field.rb +8 -4
  89. data/lib/ferret/store/fs_store.rb +13 -6
  90. data/lib/ferret/store/index_io.rb +0 -14
  91. data/lib/ferret/store/ram_store.rb +3 -2
  92. data/lib/rferret.rb +1 -1
  93. data/test/unit/analysis/ctc_analyzer.rb +131 -0
  94. data/test/unit/analysis/ctc_tokenstream.rb +98 -9
  95. data/test/unit/index/tc_index.rb +40 -1
  96. data/test/unit/index/tc_term.rb +7 -0
  97. data/test/unit/index/th_doc.rb +8 -0
  98. data/test/unit/query_parser/tc_query_parser.rb +6 -4
  99. data/test/unit/search/rtc_sort_field.rb +6 -6
  100. data/test/unit/search/tc_index_searcher.rb +8 -0
  101. data/test/unit/search/tc_multi_searcher.rb +275 -0
  102. data/test/unit/search/tc_multi_searcher2.rb +126 -0
  103. data/test/unit/search/tc_search_and_sort.rb +66 -0
  104. metadata +31 -26
  105. data/test/unit/query_parser/rtc_query_parser.rb +0 -138
data/ext/r_doc.c CHANGED
@@ -32,14 +32,18 @@ frt_field_alloc(VALUE klass)
32
32
  return self;
33
33
  }
34
34
 
35
- #define GET_DF DocField *df; Data_Get_Struct(self, DocField, df)
35
+ #define GET_DF DocField *df = (DocField *)DATA_PTR(self)
36
+
36
37
  static VALUE
37
38
  frt_field_init(int argc, VALUE *argv, VALUE self)
38
39
  {
39
40
  GET_DF;
40
41
  VALUE rname, rdata, rstored, rindexed, rstore_tv, rbinary, rboost;
42
+ char *name;
43
+ char *data;
41
44
  float boost = 1.0;
42
45
  int stored = 0, indexed = 0, store_tv = 0;
46
+ int len;
43
47
  bool binary = false;
44
48
  switch (rb_scan_args(argc, argv, "25", &rname, &rdata, &rstored,
45
49
  &rindexed, &rstore_tv, &rbinary, &rboost)) {
@@ -53,9 +57,9 @@ frt_field_init(int argc, VALUE *argv, VALUE self)
53
57
  rdata = rb_obj_as_string(rdata);
54
58
  break;
55
59
  }
56
- char *name = RSTRING(rname)->ptr;
57
- int len = RSTRING(rdata)->len;
58
- char *data = ALLOC_N(char, len + 1);
60
+ name = RSTRING(rname)->ptr;
61
+ len = RSTRING(rdata)->len;
62
+ data = ALLOC_N(char, len + 1);
59
63
  MEMCPY(data, RSTRING(rdata)->ptr, char, len);
60
64
  data[len] = 0;
61
65
  df_set(df, name, data, stored, indexed, store_tv);
@@ -268,8 +272,8 @@ static VALUE
268
272
  frt_doc_alloc(VALUE klass)
269
273
  {
270
274
  Document *doc = doc_create();
271
- doc->free_data = NULL;
272
275
  VALUE self = Data_Wrap_Struct(klass, &frt_doc_mark, &frt_doc_free, doc);
276
+ doc->free_data = NULL;
273
277
  object_add(doc, self);
274
278
  return self;
275
279
  }
@@ -300,7 +304,8 @@ frt_get_doc(Document *doc)
300
304
  return self;
301
305
  }
302
306
 
303
- #define GET_DOC Document *doc; Data_Get_Struct(self, Document, doc)
307
+ #define GET_DOC Document *doc = (Document *)DATA_PTR(self)
308
+
304
309
  static VALUE
305
310
  frt_doc_init(VALUE self)
306
311
  {
data/ext/r_index_io.c CHANGED
@@ -21,6 +21,7 @@ VALUE rterm_index_interval_key;
21
21
 
22
22
  extern void frt_set_term(VALUE rterm, Term *t);
23
23
  extern VALUE frt_get_rterm(char *field, char *text);
24
+ extern Analyzer *frt_get_cwrapped_analyzer(VALUE ranalyzer);
24
25
 
25
26
  /****************************************************************************
26
27
  *
@@ -35,7 +36,7 @@ frt_te_free(void *p)
35
36
  te->close(te);
36
37
  }
37
38
 
38
- #define GET_TE TermEnum *te; Data_Get_Struct(self, TermEnum, te)
39
+ #define GET_TE TermEnum *te = (TermEnum *)DATA_PTR(self)
39
40
  static VALUE
40
41
  frt_te_next(VALUE self)
41
42
  {
@@ -100,8 +101,8 @@ frt_tvoi_init(VALUE self, VALUE rstart, VALUE rend)
100
101
  return self;
101
102
  }
102
103
 
103
- #define GET_TVOI TVOffsetInfo *tvoi;\
104
- Data_Get_Struct(self, TVOffsetInfo, tvoi)
104
+ #define GET_TVOI TVOffsetInfo *tvoi = (TVOffsetInfo *)DATA_PTR(self)
105
+
105
106
  static VALUE
106
107
  frt_tvoi_set_start(VALUE self, VALUE rstart)
107
108
  {
@@ -135,9 +136,9 @@ frt_tvoi_get_end(VALUE self)
135
136
  static VALUE
136
137
  frt_tvoi_eql(VALUE self, VALUE rother)
137
138
  {
138
- if (TYPE(rother) != T_DATA) return Qfalse;
139
- TVOffsetInfo *other;
140
139
  GET_TVOI;
140
+ TVOffsetInfo *other;
141
+ if (TYPE(rother) != T_DATA) return Qfalse;
141
142
  Data_Get_Struct(rother, TVOffsetInfo, other);
142
143
 
143
144
  return ((tvoi->start == other->start) && (tvoi->end == other->end))
@@ -234,7 +235,8 @@ frt_get_tv(TermVector *tv)
234
235
  return self;
235
236
  }
236
237
 
237
- #define GET_TV TermVector *tv; Data_Get_Struct(self, TermVector, tv);
238
+ #define GET_TV TermVector *tv = (TermVector *)DATA_PTR(self)
239
+
238
240
  static VALUE
239
241
  frt_tv_get_field(VALUE self)
240
242
  {
@@ -271,9 +273,10 @@ frt_tv_get_positions(VALUE self)
271
273
  {
272
274
  int i, j, freq;
273
275
  GET_TV;
276
+ VALUE rpositions, rpositionss;
277
+
274
278
  if (!tv->positions) return Qnil;
275
- VALUE rpositions;
276
- VALUE rpositionss = rb_ary_new2(tv->tcnt);
279
+ rpositionss = rb_ary_new2(tv->tcnt);
277
280
  for (i = 0; i < tv->tcnt; i++) {
278
281
  freq = tv->freqs[i];
279
282
  rpositions = rb_ary_new2(freq);
@@ -290,9 +293,10 @@ frt_tv_get_offsets(VALUE self)
290
293
  {
291
294
  int i, j, freq;
292
295
  GET_TV;
296
+ VALUE roffsetss, roffsets, roffset;
293
297
  if (!tv->offsets) return Qnil;
294
- VALUE roffsets, roffset;
295
- VALUE roffsetss = rb_ary_new2(tv->tcnt);
298
+ roffsetss = rb_ary_new2(tv->tcnt);
299
+
296
300
  for (i = 0; i < tv->tcnt; i++) {
297
301
  freq = tv->freqs[i];
298
302
  roffsets = rb_ary_new2(freq);
@@ -324,7 +328,8 @@ frt_get_tde(TermDocEnum *tde)
324
328
  return Data_Wrap_Struct(cTermDocEnum, NULL, &frt_tde_free, tde);
325
329
  }
326
330
 
327
- #define GET_TDE TermDocEnum *tde; Data_Get_Struct(self, TermDocEnum, tde)
331
+ #define GET_TDE TermDocEnum *tde = (TermDocEnum *)DATA_PTR(self)
332
+
328
333
  static VALUE
329
334
  frt_tde_close(VALUE self)
330
335
  {
@@ -375,12 +380,12 @@ frt_tde_next_position(VALUE self)
375
380
  static VALUE
376
381
  frt_tde_read(VALUE self, VALUE rdocs, VALUE rfreqs)
377
382
  {
378
- int i;
383
+ int i, req_num, cnt;
379
384
  GET_TDE;
380
385
  Check_Type(rdocs, T_ARRAY);
381
386
  Check_Type(rfreqs, T_ARRAY);
382
- int req_num = MIN(RARRAY(rdocs)->len, RARRAY(rfreqs)->len);
383
- int cnt = tde->read(tde, (int *)RARRAY(rdocs)->ptr,
387
+ req_num = MIN(RARRAY(rdocs)->len, RARRAY(rfreqs)->len);
388
+ cnt = tde->read(tde, (int *)RARRAY(rdocs)->ptr,
384
389
  (int *)RARRAY(rfreqs)->ptr, req_num);
385
390
  for (i = 0; i < cnt; i++) {
386
391
  RARRAY(rdocs)->ptr[i] = INT2FIX(RARRAY(rdocs)->ptr[i]);
@@ -425,8 +430,6 @@ static VALUE
425
430
  frt_iw_init(int argc, VALUE *argv, VALUE self)
426
431
  {
427
432
  VALUE rdir, roptions, rval;
428
- bool close_dir = false;
429
- bool close_analyzer = true;
430
433
  bool create = false;
431
434
  bool use_compound_file = true;
432
435
  Store *store;
@@ -436,20 +439,21 @@ frt_iw_init(int argc, VALUE *argv, VALUE self)
436
439
  if (argc > 0) {
437
440
  if (TYPE(rdir) == T_DATA) {
438
441
  store = DATA_PTR(rdir);
442
+ ref(store);
439
443
  } else {
440
- rdir = rb_obj_as_string(rdir);
444
+ StringValue(rdir);
441
445
  store = open_fs_store(RSTRING(rdir)->ptr);
442
- close_dir = true;
443
446
  }
444
447
  } else {
445
448
  store = open_ram_store();
446
- close_dir = true;
447
449
  }
448
450
  if (argc == 2) {
449
451
  Check_Type(roptions, T_HASH);
452
+ /* Let ruby's GC handle the closing of the store
450
453
  if (!close_dir) {
451
454
  close_dir = RTEST(rb_hash_aref(roptions, rclose_dir_key));
452
455
  }
456
+ */
453
457
  /* use_compound_file defaults to true */
454
458
  use_compound_file =
455
459
  (rb_hash_aref(roptions, ruse_compound_file_key) == Qfalse) ? false : true;
@@ -458,8 +462,7 @@ frt_iw_init(int argc, VALUE *argv, VALUE self)
458
462
  if (rval == Qnil) {
459
463
  analyzer = mb_standard_analyzer_create(true);
460
464
  } else {
461
- Data_Get_Struct(rval, Analyzer, analyzer);
462
- close_analyzer = false;
465
+ analyzer = frt_get_cwrapped_analyzer(rval);
463
466
  }
464
467
  create = RTEST(rb_hash_aref(roptions, rcreate_key));
465
468
  if (!create && RTEST(rb_hash_aref(roptions, rcreate_if_missing_key))) {
@@ -468,7 +471,8 @@ frt_iw_init(int argc, VALUE *argv, VALUE self)
468
471
  }
469
472
  }
470
473
  }
471
- iw = iw_open(store, analyzer, create, close_dir, close_analyzer);
474
+ iw = iw_open(store, analyzer, create);
475
+ store_deref(store);
472
476
  iw->use_compound_file = use_compound_file;
473
477
 
474
478
  SET_INT_ATTR(merge_factor);
@@ -481,7 +485,8 @@ frt_iw_init(int argc, VALUE *argv, VALUE self)
481
485
  return self;
482
486
  }
483
487
 
484
- #define GET_IW IndexWriter *iw; Data_Get_Struct(self, IndexWriter, iw)
488
+ #define GET_IW IndexWriter *iw = (IndexWriter *)DATA_PTR(self)
489
+
485
490
  static VALUE
486
491
  frt_iw_close(VALUE self)
487
492
  {
@@ -630,21 +635,21 @@ static VALUE
630
635
  frt_ir_init(int argc, VALUE *argv, VALUE self)
631
636
  {
632
637
  VALUE rdir, rclose_dir;
633
- bool close_dir = true;
638
+ //bool close_dir = false;
634
639
  Store *store = NULL;
635
640
  IndexReader *ir;
636
641
  switch (rb_scan_args(argc, argv, "11", &rdir, &rclose_dir)) {
637
- case 2: close_dir = RTEST(rclose_dir);
642
+ case 2: //close_dir = RTEST(rclose_dir);
638
643
  case 1:
639
644
  if (TYPE(rdir) == T_DATA) {
640
645
  store = DATA_PTR(rdir);
641
646
  } else {
642
647
  rdir = rb_obj_as_string(rdir);
643
648
  store = open_fs_store(RSTRING(rdir)->ptr);
644
- close_dir = true;
649
+ deref(store);
645
650
  }
646
651
  }
647
- ir = ir_open(store, close_dir);
652
+ ir = ir_open(store);
648
653
  Frt_Wrap_Struct(self, &frt_ir_mark, &frt_ir_free, ir);
649
654
  object_add(ir, self);
650
655
  return self;
@@ -657,7 +662,8 @@ frt_ir_open(int argc, VALUE *argv, VALUE klass)
657
662
  return frt_ir_init(argc, argv, self);
658
663
  }
659
664
 
660
- #define GET_IR IndexReader *ir; Data_Get_Struct(self, IndexReader, ir)
665
+ #define GET_IR IndexReader *ir = (IndexReader *)DATA_PTR(self)
666
+
661
667
  static VALUE
662
668
  frt_ir_set_norm(VALUE self, VALUE rdoc_num, VALUE rfield, VALUE rval)
663
669
  {
@@ -671,8 +677,9 @@ static VALUE
671
677
  frt_ir_get_norms(VALUE self, VALUE rfield)
672
678
  {
673
679
  GET_IR;
680
+ uchar *norms;
674
681
  rfield = rb_obj_as_string(rfield);
675
- uchar *norms = ir->get_norms(ir, RSTRING(rfield)->ptr);
682
+ norms = ir->get_norms(ir, RSTRING(rfield)->ptr);
676
683
  if (norms) {
677
684
  return rb_str_new((char *)norms, ir->max_doc(ir));
678
685
  } else {
@@ -684,8 +691,9 @@ static VALUE
684
691
  frt_ir_get_norms_into(VALUE self, VALUE rfield, VALUE rnorms, VALUE roffset)
685
692
  {
686
693
  GET_IR;
694
+ int offset;
687
695
  rfield = rb_obj_as_string(rfield);
688
- int offset = FIX2INT(roffset);
696
+ offset = FIX2INT(roffset);
689
697
  Check_Type(rnorms, T_STRING);
690
698
  if (RSTRING(rnorms)->len < offset + ir->max_doc(ir)) {
691
699
  rb_raise(rb_eArgError, "supplied a string of length:%d to IndexReader#get_norms_into but needed a string of length offset:%d + maxdoc:%d", RSTRING(rnorms)->len, offset, ir->max_doc(ir));
@@ -778,9 +786,9 @@ static VALUE
778
786
  frt_ir_get_term_vector(VALUE self, VALUE rdoc_num, VALUE rfield)
779
787
  {
780
788
  GET_IR;
789
+ TermVector *tv;
781
790
  rfield = rb_obj_as_string(rfield);
782
- TermVector *tv =
783
- ir->get_term_vector(ir, FIX2INT(rdoc_num), RSTRING(rfield)->ptr);
791
+ tv = ir->get_term_vector(ir, FIX2INT(rdoc_num), RSTRING(rfield)->ptr);
784
792
  return frt_get_tv(tv);
785
793
  }
786
794
 
data/ext/r_qparser.c CHANGED
@@ -10,10 +10,11 @@ VALUE rwild_lower_key;
10
10
  VALUE roccur_default_key;
11
11
  VALUE rdefault_slop_key;
12
12
  VALUE rclean_str_key;
13
- VALUE ranalyzer_key;
13
+ extern VALUE ranalyzer_key;
14
14
 
15
15
  extern VALUE frt_get_analyzer(Analyzer *a);
16
16
  extern VALUE frt_get_q(Query *q);
17
+ extern Analyzer *frt_get_cwrapped_analyzer(VALUE ranalyzer);
17
18
 
18
19
  /****************************************************************************
19
20
  *
@@ -56,7 +57,7 @@ frt_get_fields(VALUE rfields)
56
57
  fields = NULL;
57
58
  } else {
58
59
  s = str = estrdup(RSTRING(rval)->ptr);
59
- while ((p = index(s, '|'))) {
60
+ while ((p = strchr(s, '|')) != '\0') {
60
61
  *p = '\0';
61
62
  hs_add(fields, estrdup(s));
62
63
  s = p + 1;
@@ -84,7 +85,18 @@ frt_qp_init(int argc, VALUE *argv, VALUE self)
84
85
  if (argc > 0) {
85
86
  def_fields = frt_get_fields(rdef_field);
86
87
  }
87
- qp = qp_create(all_fields, def_fields, NULL);
88
+
89
+ if (argc == 2) {
90
+ if (Qnil != (rval = rb_hash_aref(roptions, ranalyzer_key))) {
91
+ analyzer = frt_get_cwrapped_analyzer(rval);
92
+ }
93
+ }
94
+
95
+ if (!analyzer) {
96
+ analyzer = mb_standard_analyzer_create(true);
97
+ }
98
+
99
+ qp = qp_create(all_fields, def_fields, analyzer);
88
100
  qp->allow_any_fields = true;
89
101
  qp->clean_str = true;
90
102
  /* handle options */
@@ -107,17 +119,7 @@ frt_qp_init(int argc, VALUE *argv, VALUE self)
107
119
  if (Qnil != (rval = rb_hash_aref(roptions, rclean_str_key))) {
108
120
  qp->clean_str = RTEST(rval);
109
121
  }
110
- if (Qnil != (rval = rb_hash_aref(roptions, ranalyzer_key))) {
111
- Data_Get_Struct(rval, Analyzer, analyzer);
112
- }
113
- }
114
- if (!analyzer) {
115
- analyzer = letter_analyzer_create(true);
116
- /* make sure the analyzer will be disposed of when the QueryParser
117
- * is garbage collected. */
118
- rval = frt_get_analyzer(analyzer);
119
122
  }
120
- qp->analyzer = analyzer;
121
123
  Frt_Wrap_Struct(self, frt_qp_mark, frt_qp_free, qp);
122
124
  object_add(qp, self);
123
125
  return self;
@@ -162,7 +164,6 @@ Init_qparser(void)
162
164
  roccur_default_key = ID2SYM(rb_intern("occur_default"));
163
165
  rdefault_slop_key = ID2SYM(rb_intern("default_slop"));
164
166
  rclean_str_key = ID2SYM(rb_intern("clean_string"));
165
- ranalyzer_key = ID2SYM(rb_intern("analyzer"));
166
167
 
167
168
  /* QueryParser */
168
169
  cQueryParser = rb_define_class_under(mFerret, "QueryParser", rb_cObject);
data/ext/r_search.c CHANGED
@@ -14,7 +14,9 @@ extern void frt_ir_mark(void *p);
14
14
  static VALUE cScoreDoc;
15
15
  static VALUE cTopDocs;
16
16
  static VALUE cExplanation;
17
+ static VALUE cSearcher;
17
18
  static VALUE cIndexSearcher;
19
+ static VALUE cMultiSearcher;
18
20
  static VALUE cSortField;
19
21
  static VALUE cSortType;
20
22
  static VALUE cSort;
@@ -85,6 +87,7 @@ extern void frt_set_term(VALUE rterm, Term *t);
85
87
  extern Term *frt_get_term(VALUE rterm);
86
88
  extern VALUE frt_get_analyzer(Analyzer *a);
87
89
  extern HashSet *frt_get_fields(VALUE rfields);
90
+ extern Analyzer *frt_get_cwrapped_analyzer(VALUE ranalyzer);
88
91
 
89
92
  /****************************************************************************
90
93
  *
@@ -147,7 +150,8 @@ frt_td_mark(void *p)
147
150
  frt_gc_mark(td->hits);
148
151
  }
149
152
 
150
- #define GET_TD TopDocs *td; Data_Get_Struct(self, TopDocs, td)
153
+ #define GET_TD TopDocs *td = (TopDocs *)DATA_PTR(self)
154
+
151
155
  static VALUE
152
156
  frt_get_td(TopDocs *td)
153
157
  {
@@ -192,7 +196,7 @@ frt_td_total_hits(VALUE self)
192
196
  static VALUE
193
197
  frt_td_fields(VALUE self)
194
198
  {
195
- GET_TD;
199
+ rb_raise(rb_eNotImpError, "not implemented in the c extension version");
196
200
  return Qnil;
197
201
  }
198
202
 
@@ -215,7 +219,8 @@ frt_td_each(VALUE self)
215
219
  *
216
220
  ****************************************************************************/
217
221
 
218
- #define GET_EXPL Explanation *expl; Data_Get_Struct(self, Explanation, expl)
222
+ #define GET_EXPL Explanation *expl = (Explanation *)DATA_PTR(self)
223
+
219
224
  static VALUE
220
225
  frt_expl_to_s(VALUE self)
221
226
  {
@@ -252,12 +257,12 @@ frt_expl_value(VALUE self)
252
257
  static void
253
258
  frt_q_free(void *p)
254
259
  {
255
- Query *q = (Query *)p;
256
260
  object_del(p);
257
- q->destroy(q);
261
+ q_deref((Query *)p);
258
262
  }
259
263
 
260
- #define GET_Q Query *q; Data_Get_Struct(self, Query, q)
264
+ #define GET_Q Query *q = (Query *)DATA_PTR(self)
265
+
261
266
 
262
267
  static VALUE
263
268
  frt_q_to_s(int argc, VALUE *argv, VALUE self)
@@ -387,15 +392,15 @@ frt_bc_mark(void *p)
387
392
  static void
388
393
  frt_bc_free(void *p)
389
394
  {
390
- BooleanClause *bc = (BooleanClause *)p;
391
- object_del(bc);
392
- free(bc);
395
+ object_del(p);
396
+ bc_deref((BooleanClause *)p);
393
397
  }
394
398
 
395
399
  static VALUE
396
400
  frt_get_bc(BooleanClause *bc)
397
401
  {
398
402
  VALUE self = Data_Wrap_Struct(cBooleanClause, &frt_bc_mark, &frt_bc_free, bc);
403
+ ref(bc);
399
404
  object_add(bc, self);
400
405
  return self;
401
406
  }
@@ -411,13 +416,14 @@ frt_bc_init(int argc, VALUE *argv, VALUE self)
411
416
  occur = FIX2INT(roccur);
412
417
  }
413
418
  Data_Get_Struct(rquery, Query, sub_q);
419
+ ref(sub_q);
414
420
  bc = bc_create(sub_q, occur);
415
421
  Frt_Wrap_Struct(self, &frt_bc_mark, &frt_bc_free, bc);
416
422
  object_add(bc, self);
417
423
  return self;
418
424
  }
419
425
 
420
- #define GET_BC BooleanClause *bc; Data_Get_Struct(self, BooleanClause, bc)
426
+ #define GET_BC BooleanClause *bc = (BooleanClause *)DATA_PTR(self)
421
427
  static VALUE
422
428
  frt_bc_get_query(VALUE self)
423
429
  {
@@ -505,10 +511,11 @@ frt_bq_init(int argc, VALUE *argv, VALUE self)
505
511
  {
506
512
  VALUE rcoord_disabled;
507
513
  bool coord_disabled = false;
514
+ Query *q;
508
515
  if (rb_scan_args(argc, argv, "01", &rcoord_disabled)) {
509
516
  coord_disabled = RTEST(rcoord_disabled);
510
517
  }
511
- Query *q = bq_create(coord_disabled);
518
+ q = bq_create(coord_disabled);
512
519
  Frt_Wrap_Struct(self, &frt_bq_mark, &frt_q_free, q);
513
520
  object_add(q, self);
514
521
 
@@ -575,10 +582,12 @@ frt_rq_new_more(VALUE klass, VALUE rfield, VALUE rlterm, VALUE rincl)
575
582
  {
576
583
  Query *q;
577
584
  VALUE self;
578
- rfield = rb_obj_as_string(rfield);
579
585
  char *lterm = NIL_P(rlterm) ? NULL : RSTRING(rb_obj_as_string(rlterm))->ptr;
580
- if (!lterm)
581
- rb_raise(rb_eArgError, "The lower term must not be nil in a more than query");
586
+ rfield = rb_obj_as_string(rfield);
587
+ if (!lterm) {
588
+ rb_raise(rb_eArgError, "The lower term must not be nil in a more "
589
+ "than query");
590
+ }
582
591
  q = rq_create_more(RSTRING(rfield)->ptr, lterm, RTEST(rincl));
583
592
  self = Data_Wrap_Struct(klass, NULL, &frt_q_free, q);
584
593
  object_add(q, self);
@@ -590,10 +599,12 @@ frt_rq_new_less(VALUE klass, VALUE rfield, VALUE ruterm, VALUE rincu)
590
599
  {
591
600
  Query *q;
592
601
  VALUE self;
593
- rfield = rb_obj_as_string(rfield);
594
602
  char *uterm = NIL_P(ruterm) ? NULL : RSTRING(rb_obj_as_string(ruterm))->ptr;
595
- if (!uterm)
596
- rb_raise(rb_eArgError, "The upper term must not be nil in a less than query");
603
+ rfield = rb_obj_as_string(rfield);
604
+ if (!uterm) {
605
+ rb_raise(rb_eArgError, "The upper term must not be nil in a less "
606
+ "than query");
607
+ }
597
608
  q = rq_create_less(RSTRING(rfield)->ptr, uterm, RTEST(rincu));
598
609
  self = Data_Wrap_Struct(klass, NULL, &frt_q_free, q);
599
610
  object_add(q, self);
@@ -734,7 +745,6 @@ frt_mphq_set_slop(VALUE self, VALUE rslop)
734
745
  return self;
735
746
  }
736
747
 
737
-
738
748
  /****************************************************************************
739
749
  *
740
750
  * PrefixQuery Methods
@@ -1054,9 +1064,10 @@ frt_spanxq_mark(void *p)
1054
1064
  static VALUE
1055
1065
  frt_spanxq_init(VALUE self, VALUE rinc, VALUE rexc)
1056
1066
  {
1067
+ Query *q;
1057
1068
  Check_Type(rinc, T_DATA);
1058
1069
  Check_Type(rexc, T_DATA);
1059
- Query *q = spanxq_create(DATA_PTR(rinc), DATA_PTR(rexc));
1070
+ q = spanxq_create(DATA_PTR(rinc), DATA_PTR(rexc));
1060
1071
  q->destroy_all = false;
1061
1072
  Frt_Wrap_Struct(self, &frt_spanxq_mark, &frt_q_free, q);
1062
1073
  object_add(q, self);
@@ -1077,7 +1088,7 @@ frt_f_free(void *p)
1077
1088
  f->destroy(f);
1078
1089
  }
1079
1090
 
1080
- #define GET_F Filter *f; Data_Get_Struct(self, Filter, f)
1091
+ #define GET_F Filter *f = (Filter *)DATA_PTR(self)
1081
1092
 
1082
1093
  static VALUE
1083
1094
  frt_f_to_s(VALUE self)
@@ -1126,11 +1137,14 @@ frt_rf_new_more(int argc, VALUE *argv, VALUE klass)
1126
1137
  Filter *f;
1127
1138
  VALUE self;
1128
1139
  VALUE rfield, rlterm, rincl;
1140
+ char *lterm;
1129
1141
  rb_scan_args(argc, argv, "21", &rfield, &rlterm, &rincl);
1130
1142
  rfield = rb_obj_as_string(rfield);
1131
- char *lterm = NIL_P(rlterm) ? NULL : RSTRING(rb_obj_as_string(rlterm))->ptr;
1132
- if (!lterm)
1133
- rb_raise(rb_eArgError, "The lower term must not be nil in a more than filter");
1143
+ lterm = NIL_P(rlterm) ? NULL : RSTRING(rb_obj_as_string(rlterm))->ptr;
1144
+ if (!lterm) {
1145
+ rb_raise(rb_eArgError, "The lower term must not be nil in a more "
1146
+ "than filter");
1147
+ }
1134
1148
  f = rfilt_create(RSTRING(rfield)->ptr, lterm, NULL, rincl != Qfalse, false);
1135
1149
  self = Data_Wrap_Struct(klass, NULL, &frt_f_free, f);
1136
1150
  object_add(f, self);
@@ -1143,11 +1157,14 @@ frt_rf_new_less(int argc, VALUE *argv, VALUE klass)
1143
1157
  Filter *f;
1144
1158
  VALUE self;
1145
1159
  VALUE rfield, ruterm, rincu;
1160
+ char *uterm;
1146
1161
  rb_scan_args(argc, argv, "21", &rfield, &ruterm, &rincu);
1147
1162
  rfield = rb_obj_as_string(rfield);
1148
- char *uterm = NIL_P(ruterm) ? NULL : RSTRING(rb_obj_as_string(ruterm))->ptr;
1149
- if (!uterm)
1150
- rb_raise(rb_eArgError, "The upper term must not be nil in a less than filter");
1163
+ uterm = NIL_P(ruterm) ? NULL : RSTRING(rb_obj_as_string(ruterm))->ptr;
1164
+ if (!uterm) {
1165
+ rb_raise(rb_eArgError, "The upper term must not be nil in a less "
1166
+ "than filter");
1167
+ }
1151
1168
  f = rfilt_create(RSTRING(rfield)->ptr, NULL, uterm, false, rincu != Qfalse);
1152
1169
  self = Data_Wrap_Struct(klass, NULL, &frt_f_free, f);
1153
1170
  object_add(f, self);
@@ -1181,9 +1198,8 @@ frt_qf_init(VALUE self, VALUE rquery)
1181
1198
  static void
1182
1199
  frt_sf_free(void *p)
1183
1200
  {
1184
- SortField *sf = (SortField *)p;
1185
- object_del(sf);
1186
- sort_field_destroy(sf);
1201
+ object_del(p);
1202
+ sort_field_destroy((SortField *)p);
1187
1203
  }
1188
1204
 
1189
1205
  static VALUE
@@ -1220,13 +1236,16 @@ frt_sf_init(int argc, VALUE *argv, VALUE self)
1220
1236
  rfield = rb_obj_as_string(rfield);
1221
1237
 
1222
1238
  sf = sort_field_create(RSTRING(rfield)->ptr, sort_type, is_reverse);
1239
+ if (sf->field == NULL && RSTRING(rfield)->ptr != NULL) {
1240
+ sf->field = estrdup(RSTRING(rfield)->ptr);
1241
+ }
1223
1242
 
1224
1243
  Frt_Wrap_Struct(self, NULL, &frt_sf_free, sf);
1225
1244
  object_add(sf, self);
1226
1245
  return self;
1227
1246
  }
1228
1247
 
1229
- #define GET_SF SortField *sf; Data_Get_Struct(self, SortField, sf)
1248
+ #define GET_SF SortField *sf = (SortField *)DATA_PTR(self)
1230
1249
  static VALUE
1231
1250
  frt_sf_is_reverse(VALUE self)
1232
1251
  {
@@ -1254,9 +1273,19 @@ frt_sf_get_comparator(VALUE self)
1254
1273
  return Qnil;
1255
1274
  }
1256
1275
 
1276
+ static VALUE
1277
+ frt_sf_to_s(VALUE self)
1278
+ {
1279
+ GET_SF;
1280
+ char *str = sort_field_to_s(sf);
1281
+ VALUE rstr = rb_str_new2(str);
1282
+ free(str);
1283
+ return rstr;
1284
+ }
1285
+
1257
1286
  /****************************************************************************
1258
1287
  *
1259
- * SortField Methods
1288
+ * Sort Methods
1260
1289
  *
1261
1290
  ****************************************************************************/
1262
1291
 
@@ -1317,7 +1346,7 @@ frt_sort_add(Sort *sort, VALUE rsf, bool reverse)
1317
1346
  sort_add_sort_field(sort, sf);
1318
1347
  }
1319
1348
 
1320
- #define GET_SORT Sort *sort; Data_Get_Struct(self, Sort, sort)
1349
+ #define GET_SORT Sort *sort = (Sort *)DATA_PTR(self)
1321
1350
  static VALUE
1322
1351
  frt_sort_init(int argc, VALUE *argv, VALUE self)
1323
1352
  {
@@ -1363,65 +1392,34 @@ frt_sort_get_fields(VALUE self)
1363
1392
  return object_get(sort->sort_fields);
1364
1393
  }
1365
1394
 
1395
+
1396
+ static VALUE
1397
+ frt_sort_to_s(VALUE self)
1398
+ {
1399
+ GET_SORT;
1400
+ char *str = sort_to_s(sort);
1401
+ VALUE rstr = rb_str_new2(str);
1402
+ free(str);
1403
+ return rstr;
1404
+ }
1366
1405
  /****************************************************************************
1367
1406
  *
1368
- * IndexSearcher Methods
1407
+ * Searcher Methods
1369
1408
  *
1370
1409
  ****************************************************************************/
1371
1410
 
1372
1411
  static void
1373
- frt_is_free(void *p)
1412
+ frt_sea_free(void *p)
1374
1413
  {
1375
1414
  Searcher *sea = (Searcher *)p;
1376
- sea->close(sea);
1415
+ object_del(sea);
1416
+ sea_close(sea);
1377
1417
  }
1378
1418
 
1379
- static void
1380
- frt_is_mark(void *p)
1381
- {
1382
- Searcher *sea = (Searcher *)p;
1383
- frt_gc_mark(sea->ir);
1384
- frt_gc_mark(sea->ir->store);
1385
- }
1386
-
1387
- #define FRT_GET_IR(rir, ir) do {\
1388
- rir = Data_Wrap_Struct(cIndexReader, &frt_ir_mark, &frt_ir_free, ir);\
1389
- object_add(ir, rir);\
1390
- } while (0)
1391
-
1392
- static VALUE
1393
- frt_is_init(VALUE self, VALUE obj)
1394
- {
1395
- Store *store = NULL;
1396
- IndexReader *ir = NULL;
1397
- Searcher *sea;
1398
- if (TYPE(obj) == T_STRING) {
1399
- store = open_fs_store(StringValueCStr(obj));
1400
- ir = ir_open(store, true);
1401
- FRT_GET_IR(obj, ir);
1402
- } else {
1403
- Check_Type(obj, T_DATA);
1404
- if (rb_obj_is_kind_of(obj, cDirectory) == Qtrue) {
1405
- Data_Get_Struct(obj, Store, store);
1406
- ir = ir_open(store, false);
1407
- FRT_GET_IR(obj, ir);
1408
- } else if (rb_obj_is_kind_of(obj, cIndexReader) == Qtrue) {
1409
- Data_Get_Struct(obj, IndexReader, ir);
1410
- } else {
1411
- rb_raise(rb_eArgError, "Unknown type for argument to IndexSearcher.new");
1412
- }
1413
- }
1414
-
1415
- sea = sea_create(ir);
1416
- sea->close_ir = false;
1417
- Frt_Wrap_Struct(self, &frt_is_mark, &frt_is_free, sea);
1418
- return self;
1419
- }
1420
-
1421
- #define GET_SEA Searcher *sea; Data_Get_Struct(self, Searcher, sea)
1419
+ #define GET_SEA Searcher *sea = (Searcher *)DATA_PTR(self)
1422
1420
 
1423
1421
  static VALUE
1424
- frt_is_close(VALUE self)
1422
+ frt_sea_close(VALUE self)
1425
1423
  {
1426
1424
  GET_SEA;
1427
1425
  Frt_Unwrap_Struct(self);
@@ -1430,14 +1428,14 @@ frt_is_close(VALUE self)
1430
1428
  }
1431
1429
 
1432
1430
  static VALUE
1433
- frt_is_get_reader(VALUE self, VALUE rterm)
1431
+ frt_sea_get_reader(VALUE self, VALUE rterm)
1434
1432
  {
1435
1433
  GET_SEA;
1436
1434
  return object_get(sea->ir);
1437
1435
  }
1438
1436
 
1439
1437
  static VALUE
1440
- frt_is_doc_freq(VALUE self, VALUE rterm)
1438
+ frt_sea_doc_freq(VALUE self, VALUE rterm)
1441
1439
  {
1442
1440
  GET_SEA;
1443
1441
  Term t;
@@ -1446,13 +1444,15 @@ frt_is_doc_freq(VALUE self, VALUE rterm)
1446
1444
  }
1447
1445
 
1448
1446
  static VALUE
1449
- frt_is_doc_freqs(VALUE self, VALUE rterms)
1447
+ frt_sea_doc_freqs(VALUE self, VALUE rterms)
1450
1448
  {
1451
1449
  int i;
1452
1450
  GET_SEA;
1453
1451
  Term t;
1452
+ VALUE freqs;
1454
1453
  Check_Type(rterms, T_ARRAY);
1455
- VALUE freqs = rb_ary_new2(RARRAY(rterms)->len);
1454
+
1455
+ freqs = rb_ary_new2(RARRAY(rterms)->len);
1456
1456
  for (i = 0; i < RARRAY(rterms)->len; i++) {
1457
1457
  frt_set_term(RARRAY(rterms)->ptr[i], &t);
1458
1458
  rb_ary_store(freqs, i, INT2FIX(sea->doc_freq(sea, &t)));
@@ -1461,21 +1461,21 @@ frt_is_doc_freqs(VALUE self, VALUE rterms)
1461
1461
  }
1462
1462
 
1463
1463
  static VALUE
1464
- frt_is_doc(VALUE self, VALUE rdoc_num)
1464
+ frt_sea_doc(VALUE self, VALUE rdoc_num)
1465
1465
  {
1466
1466
  GET_SEA;
1467
1467
  return frt_get_doc(sea->get_doc(sea, FIX2INT(rdoc_num)));
1468
1468
  }
1469
1469
 
1470
1470
  static VALUE
1471
- frt_is_max_doc(VALUE self)
1471
+ frt_sea_max_doc(VALUE self)
1472
1472
  {
1473
1473
  GET_SEA;
1474
1474
  return INT2FIX(sea->max_doc(sea));
1475
1475
  }
1476
1476
 
1477
1477
  static TopDocs *
1478
- frt_is_search_internal(Query *query, VALUE roptions, Searcher *sea)
1478
+ frt_sea_search_internal(Query *query, VALUE roptions, Searcher *sea)
1479
1479
  {
1480
1480
  VALUE rval;
1481
1481
  int first_doc = 0, num_docs = 10;
@@ -1508,68 +1508,179 @@ frt_is_search_internal(Query *query, VALUE roptions, Searcher *sea)
1508
1508
  }
1509
1509
 
1510
1510
  static VALUE
1511
- frt_is_search(int argc, VALUE *argv, VALUE self)
1511
+ frt_sea_search(int argc, VALUE *argv, VALUE self)
1512
1512
  {
1513
1513
  GET_SEA;
1514
1514
  VALUE rquery, roptions;
1515
1515
  Query *query;
1516
1516
  rb_scan_args(argc, argv, "11", &rquery, &roptions);
1517
1517
  Data_Get_Struct(rquery, Query, query);
1518
- return frt_get_td(frt_is_search_internal(query, roptions, sea));
1518
+ return frt_get_td(frt_sea_search_internal(query, roptions, sea));
1519
1519
  }
1520
1520
 
1521
1521
  static VALUE
1522
- frt_is_search_each(VALUE self, VALUE rquery, VALUE roptions)
1522
+ frt_sea_search_each(VALUE self, VALUE rquery, VALUE roptions)
1523
1523
  {
1524
1524
  return Qnil;
1525
1525
  }
1526
1526
 
1527
1527
  static VALUE
1528
- frt_is_explain(VALUE self, VALUE rquery, VALUE rdoc_num)
1528
+ frt_sea_explain(VALUE self, VALUE rquery, VALUE rdoc_num)
1529
1529
  {
1530
1530
  GET_SEA;
1531
1531
  Query *query;
1532
+ Explanation *expl;
1532
1533
  Data_Get_Struct(rquery, Query, query);
1533
- Explanation *expl = sea->explain(sea, query, FIX2INT(rdoc_num));
1534
+ expl = sea->explain(sea, query, FIX2INT(rdoc_num));
1534
1535
  return Data_Wrap_Struct(cExplanation, NULL, &expl_destoy, expl);
1535
1536
  }
1536
1537
 
1537
1538
  /****************************************************************************
1538
1539
  *
1539
- * Index Methods
1540
+ * IndexSearcher Methods
1540
1541
  *
1541
1542
  ****************************************************************************/
1542
1543
 
1543
- extern inline void ensure_searcher_open(Index *self);
1544
- extern inline void ensure_reader_open(Index *self);
1545
- extern inline void ensure_writer_open(Index *self);
1544
+ static void
1545
+ frt_is_mark(void *p)
1546
+ {
1547
+ Searcher *sea = (Searcher *)p;
1548
+ frt_gc_mark(sea->ir);
1549
+ frt_gc_mark(sea->ir->store);
1550
+ }
1551
+
1552
+ #define FRT_GET_IR(rir, ir) do {\
1553
+ rir = Data_Wrap_Struct(cIndexReader, &frt_ir_mark, &frt_ir_free, ir);\
1554
+ object_add(ir, rir);\
1555
+ } while (0)
1556
+
1557
+ static VALUE
1558
+ frt_is_init(VALUE self, VALUE obj)
1559
+ {
1560
+ Store *store = NULL;
1561
+ IndexReader *ir = NULL;
1562
+ Searcher *sea;
1563
+ if (TYPE(obj) == T_STRING) {
1564
+ store = open_fs_store(StringValueCStr(obj));
1565
+ ir = ir_open(store);
1566
+ deref(store);
1567
+ FRT_GET_IR(obj, ir);
1568
+ } else {
1569
+ Check_Type(obj, T_DATA);
1570
+ if (rb_obj_is_kind_of(obj, cDirectory) == Qtrue) {
1571
+ Data_Get_Struct(obj, Store, store);
1572
+ ir = ir_open(store);
1573
+ FRT_GET_IR(obj, ir);
1574
+ } else if (rb_obj_is_kind_of(obj, cIndexReader) == Qtrue) {
1575
+ Data_Get_Struct(obj, IndexReader, ir);
1576
+ } else {
1577
+ rb_raise(rb_eArgError, "Unknown type for argument to IndexSearcher.new");
1578
+ }
1579
+ }
1580
+
1581
+ sea = sea_create(ir);
1582
+ sea->close_ir = false;
1583
+ Frt_Wrap_Struct(self, &frt_is_mark, &frt_sea_free, sea);
1584
+ object_add(sea, self);
1585
+ return self;
1586
+ }
1587
+
1588
+ /****************************************************************************
1589
+ *
1590
+ * MultiSearcher Methods
1591
+ *
1592
+ ****************************************************************************/
1593
+
1594
+ static void
1595
+ frt_ms_free(void *p)
1596
+ {
1597
+ Searcher *sea = (Searcher *)p;
1598
+ MultiSearcher *msea = (MultiSearcher *)sea->data;
1599
+ free(msea->searchers);
1600
+ object_del(sea);
1601
+ sea_close(sea);
1602
+ }
1603
+
1604
+ static void
1605
+ frt_ms_mark(void *p)
1606
+ {
1607
+ int i;
1608
+ Searcher *sea = (Searcher *)p;
1609
+ MultiSearcher *msea = (MultiSearcher *)sea->data;
1610
+ for (i = 0; i < msea->s_cnt; i++) {
1611
+ frt_gc_mark(msea->searchers[i]);
1612
+ }
1613
+ }
1614
+
1615
+ static VALUE
1616
+ frt_ms_init(int argc, VALUE *argv, VALUE self)
1617
+ {
1618
+ int i, j;
1619
+
1620
+ VALUE rsearcher;
1621
+ Array *searchers = ary_create(argc, (free_ft)NULL);
1622
+ Searcher *s;
1623
+
1624
+ for (i = 0; i < argc; i++) {
1625
+ rsearcher = argv[i];
1626
+ switch (TYPE(rsearcher)) {
1627
+ case T_ARRAY:
1628
+ for (j = 0; j < RARRAY(rsearcher)->len; j++) {
1629
+ VALUE rs = RARRAY(rsearcher)->ptr[j];
1630
+ Data_Get_Struct(rs, Searcher, s);
1631
+ ary_append(searchers, s);
1632
+ }
1633
+ break;
1634
+ case T_DATA:
1635
+ Data_Get_Struct(rsearcher, Searcher, s);
1636
+ ary_append(searchers, s);
1637
+ break;
1638
+ default:
1639
+ rb_raise(rb_eArgError, "Can't add class %s to MultiSearcher",
1640
+ rb_obj_classname(rsearcher));
1641
+ break;
1642
+ }
1643
+ }
1644
+ s = msea_create((Searcher **)searchers->elems, searchers->size, false);
1645
+ free(searchers); /* only free the Array, not the elems array holding the searchers */
1646
+ Frt_Wrap_Struct(self, &frt_ms_mark, &frt_ms_free, s);
1647
+ object_add(s, self);
1648
+ return self;
1649
+ }
1546
1650
 
1651
+ /****************************************************************************
1652
+ *
1653
+ * Index Methods
1654
+ *
1655
+ ****************************************************************************/
1656
+
1657
+ /*
1547
1658
  static void
1548
1659
  frt_ind_free_store_i(Index *self)
1549
1660
  {
1550
1661
  VALUE rval;
1551
1662
  if (self->close_store && (Qnil != (rval = object_get(self->store)))) {
1552
- /* user passed close_dir option so unwrap it */
1663
+ // user passed close_dir option so unwrap it
1553
1664
  Frt_Unwrap_Struct(rval);
1554
1665
  object_del(self->store);
1555
1666
  }
1556
1667
  }
1668
+ */
1557
1669
 
1558
1670
  static void
1559
1671
  frt_ind_free(void *p)
1560
1672
  {
1561
- Index *self = (Index *)p;
1562
- frt_ind_free_store_i(self);
1563
- object_del(self);
1564
- index_destroy(self);
1673
+ Index *ind = (Index *)p;
1674
+ object_del(ind);
1675
+ index_destroy(ind);
1565
1676
  }
1566
1677
 
1567
1678
  static void
1568
1679
  frt_ind_mark(void *p)
1569
1680
  {
1570
- Index *self = (Index *)p;
1571
- frt_gc_mark(self->store);
1572
- frt_gc_mark(self->analyzer);
1681
+ Index *ind = (Index *)p;
1682
+ frt_gc_mark(ind->store);
1683
+ frt_gc_mark(ind->analyzer);
1573
1684
  }
1574
1685
 
1575
1686
  static VALUE
@@ -1582,14 +1693,13 @@ frt_ind_init(int argc, VALUE *argv, VALUE self)
1582
1693
  Store *store = NULL;
1583
1694
  Analyzer *analyzer = NULL;
1584
1695
  bool create = false;
1585
- bool close_store = false;
1586
1696
  HashSet *def_fields = NULL;
1587
1697
 
1588
1698
  if (Qnil != (rval = rb_hash_aref(roptions, rpath_key))) {
1589
1699
  rval = rb_obj_as_string(rval);
1590
1700
  /* TODO: create the directory if it is missing */
1591
1701
  store = open_fs_store(RSTRING(rval)->ptr);
1592
- close_store = true;
1702
+ deref(store);
1593
1703
  } else if (Qnil != (rval = rb_hash_aref(roptions, rdir_key))) {
1594
1704
  Data_Get_Struct(rval, Store, store);
1595
1705
  }
@@ -1611,19 +1721,21 @@ frt_ind_init(int argc, VALUE *argv, VALUE self)
1611
1721
  }
1612
1722
 
1613
1723
  if (Qnil != (rval = rb_hash_aref(roptions, ranalyzer_key))) {
1614
- Data_Get_Struct(rval, Analyzer, analyzer);
1724
+ analyzer = frt_get_cwrapped_analyzer(rval);
1615
1725
  }
1616
1726
  if (Qnil != (rval = rb_hash_aref(roptions, rdefault_search_field_key))) {
1617
1727
  def_fields = frt_get_fields(rval);
1618
1728
  }
1619
1729
  if (Qnil != (rval = rb_hash_aref(roptions, rclose_dir_key))) {
1620
- if (RTEST(rval) && !close_store) close_store = true;
1730
+ /* No need to do anything here. Let the GC do the work.
1731
+ * if (RTEST(rval) && !close_store) close_store = true;
1732
+ */
1621
1733
  }
1622
1734
  if (Qnil != (rval = rb_hash_aref(roptions, rdefault_field_key))) {
1623
1735
  if (!def_fields) def_fields = frt_get_fields(rval);
1624
1736
  }
1625
1737
  ind = index_create(store, analyzer, def_fields, create);
1626
- if (close_store) ind->close_store = close_store;
1738
+ if (analyzer) a_deref(analyzer);
1627
1739
 
1628
1740
  /* QueryParser options */
1629
1741
  if (Qnil != (rval = rb_hash_aref(roptions, rhandle_parse_errors_key))) {
@@ -1686,13 +1798,13 @@ frt_ind_init(int argc, VALUE *argv, VALUE self)
1686
1798
  return self;
1687
1799
  }
1688
1800
 
1689
- #define GET_IND Index *ind; Data_Get_Struct(self, Index, ind);\
1801
+ #define GET_IND Index *ind = (Index *)DATA_PTR(self);\
1690
1802
  if (!ind) rb_raise(rb_eStandardError, "Called method on closed Index object")
1691
1803
  static VALUE
1692
1804
  frt_ind_close(VALUE self)
1693
1805
  {
1694
1806
  GET_IND;
1695
- frt_ind_free_store_i(ind);
1807
+ //frt_ind_free_store_i(ind);
1696
1808
  Frt_Unwrap_Struct(self);
1697
1809
  object_del(ind);
1698
1810
  index_destroy(ind);
@@ -1778,9 +1890,9 @@ frt_ind_add_doc(int argc, VALUE *argv, VALUE self)
1778
1890
  doc = frt_rdoc_to_doc(ind, rdoc, &close_doc);
1779
1891
 
1780
1892
  if (argc == 2) {
1781
- Analyzer *analyzer;
1782
- Data_Get_Struct(ranalyzer, Analyzer, analyzer);
1893
+ Analyzer *analyzer = frt_get_cwrapped_analyzer(ranalyzer);
1783
1894
  index_add_doc_a(ind, doc, analyzer);
1895
+ a_deref(analyzer);
1784
1896
  } else {
1785
1897
  index_add_doc(ind, doc);
1786
1898
  }
@@ -1789,7 +1901,7 @@ frt_ind_add_doc(int argc, VALUE *argv, VALUE self)
1789
1901
  }
1790
1902
 
1791
1903
  static Query *
1792
- frt_get_query_i(Index *ind, VALUE rquery, bool *destroy_query)
1904
+ frt_ind_get_query_i(Index *ind, VALUE rquery)
1793
1905
  {
1794
1906
  Query *q = NULL;
1795
1907
 
@@ -1798,10 +1910,10 @@ frt_get_query_i(Index *ind, VALUE rquery, bool *destroy_query)
1798
1910
  rquery = rb_obj_as_string(rquery);
1799
1911
  case T_STRING:
1800
1912
  q = index_get_query(ind, RSTRING(rquery)->ptr);
1801
- *destroy_query = true;
1802
1913
  break;
1803
1914
  case T_DATA:
1804
1915
  Data_Get_Struct(rquery, Query, q);
1916
+ ref(q);
1805
1917
  break;
1806
1918
  default:
1807
1919
  rb_raise(rb_eArgError, "Can only handle a String or a Query.");
@@ -1816,14 +1928,13 @@ frt_ind_search(int argc, VALUE *argv, VALUE self)
1816
1928
  {
1817
1929
  Query *q;
1818
1930
  VALUE rquery, roptions, rtd;
1819
- bool destroy_query = false;
1820
1931
  GET_IND;
1821
1932
  rb_scan_args(argc, argv, "11", &rquery, &roptions);
1822
1933
  ensure_searcher_open(ind);
1823
1934
 
1824
- q = frt_get_query_i(ind, rquery, &destroy_query);
1825
- rtd = frt_get_td(frt_is_search_internal(q, roptions, ind->sea));
1826
- if (destroy_query) q->destroy(q);
1935
+ q = frt_ind_get_query_i(ind, rquery);
1936
+ rtd = frt_get_td(frt_sea_search_internal(q, roptions, ind->sea));
1937
+ q_deref(q);
1827
1938
 
1828
1939
  return rtd;
1829
1940
  }
@@ -1835,7 +1946,6 @@ frt_ind_search_each(int argc, VALUE *argv, VALUE self)
1835
1946
  Query *q;
1836
1947
  TopDocs *td;
1837
1948
  VALUE rquery, roptions, rtotal_hits;
1838
- bool destroy_query = false;
1839
1949
  GET_IND;
1840
1950
 
1841
1951
 
@@ -1845,10 +1955,10 @@ frt_ind_search_each(int argc, VALUE *argv, VALUE self)
1845
1955
 
1846
1956
  ensure_searcher_open(ind);
1847
1957
 
1848
- q = frt_get_query_i(ind, rquery, &destroy_query);
1958
+ q = frt_ind_get_query_i(ind, rquery);
1849
1959
  //printf(">>>>>%s<<<<<\n", q->to_s(q, "file_name"));
1850
- td = frt_is_search_internal(q, roptions, ind->sea);
1851
- if (destroy_query) q->destroy(q);
1960
+ td = frt_sea_search_internal(q, roptions, ind->sea);
1961
+ q_deref(q);
1852
1962
 
1853
1963
  rtotal_hits = INT2FIX(td->total_hits);
1854
1964
 
@@ -2061,7 +2171,7 @@ struct QueryUpdateArg {
2061
2171
  Index *ind;
2062
2172
  };
2063
2173
 
2064
- static void frt_ind_qupd_i(Searcher *sea, int doc_num, void *arg)
2174
+ static void frt_ind_qupd_i(Searcher *sea, int doc_num, float score, void *arg)
2065
2175
  {
2066
2176
  struct QueryUpdateArg *qua = (struct QueryUpdateArg *)arg;
2067
2177
  Document *doc = sea->ir->get_doc(sea->ir, doc_num);
@@ -2073,22 +2183,19 @@ static void frt_ind_qupd_i(Searcher *sea, int doc_num, void *arg)
2073
2183
  static VALUE
2074
2184
  frt_ind_query_update(VALUE self, VALUE rquery, VALUE rdoc)
2075
2185
  {
2076
- GET_IND;
2077
-
2078
2186
  int i;
2079
2187
  Query *q;
2080
- bool destroy_query = false;
2081
2188
  struct QueryUpdateArg qua;
2082
-
2189
+ GET_IND;
2083
2190
 
2084
2191
  ensure_searcher_open(ind);
2085
2192
  qua.rdoc = rdoc;
2086
- qua.docs = ary_create(8, &doc_destroy);
2193
+ qua.docs = ary_create(8, (free_ft)&doc_destroy);
2087
2194
  qua.ind = ind;
2088
2195
 
2089
- q = frt_get_query_i(ind, rquery, &destroy_query);
2196
+ q = frt_ind_get_query_i(ind, rquery);
2090
2197
  sea_search_each(ind->sea, q, NULL, &frt_ind_qupd_i, &qua);
2091
- if (destroy_query) q->destroy(q);
2198
+ q_deref(q);
2092
2199
 
2093
2200
  for (i = 0; i < qua.docs->size; i++) {
2094
2201
  index_add_doc(ind, qua.docs->elems[i]);
@@ -2206,37 +2313,37 @@ static VALUE
2206
2313
  frt_ind_persist(int argc, VALUE *argv, VALUE self)
2207
2314
  {
2208
2315
  VALUE rdir, rcreate;
2209
- bool create, close_store;
2316
+ bool create;
2210
2317
  Store *old_store;
2211
2318
  GET_IND;
2212
2319
 
2213
2320
  index_flush(ind);
2214
- frt_ind_free_store_i(ind);
2321
+ //frt_ind_free_store_i(ind);
2215
2322
  old_store = ind->store;
2216
- close_store = ind->close_store;
2217
2323
 
2218
2324
  rb_scan_args(argc, argv, "11", &rdir, &rcreate);
2219
2325
  create = RTEST(rcreate);
2220
2326
 
2221
2327
  if (T_DATA == TYPE(rdir)) {
2222
2328
  Data_Get_Struct(rdir, Store, ind->store);
2329
+ ref(ind->store);
2223
2330
  } else {
2224
2331
  rdir = rb_obj_as_string(rdir);
2225
2332
  ind->store = open_fs_store(RSTRING(rdir)->ptr);
2226
- ind->close_store = true;
2227
2333
  }
2228
2334
 
2229
2335
  if (!create && !ind->store->exists(ind->store, "segments")) create = true;
2230
2336
 
2231
2337
  if (create) {
2232
- ind->iw = iw_open(ind->store, NULL, create, false, false);
2338
+ ind->iw = iw_open(ind->store, ind->analyzer, create);
2339
+ ref(ind->analyzer);
2233
2340
  ind->iw->use_compound_file = ind->use_compound_file;
2234
2341
  }
2235
2342
 
2236
2343
  ensure_writer_open(ind);
2237
2344
  iw_add_indexes(ind->iw, &old_store, 1);
2238
2345
 
2239
- if (close_store) old_store->close(old_store);
2346
+ store_deref(old_store);
2240
2347
 
2241
2348
  index_auto_flush_iw(ind);
2242
2349
 
@@ -2246,11 +2353,12 @@ frt_ind_persist(int argc, VALUE *argv, VALUE self)
2246
2353
  static VALUE
2247
2354
  frt_ind_explain(VALUE self, VALUE rquery, VALUE rdoc_num)
2248
2355
  {
2356
+ Query *q;
2357
+ Explanation *expl;
2249
2358
  GET_IND;
2250
- bool destroy_query = false;
2251
- Query *q = frt_get_query_i(ind, rquery, &destroy_query);
2252
- Explanation *expl = index_explain(ind, q, FIX2INT(rdoc_num));
2253
- if (destroy_query) q->destroy(q);
2359
+ q = frt_ind_get_query_i(ind, rquery);
2360
+ expl = index_explain(ind, q, FIX2INT(rdoc_num));
2361
+ q_deref(q);
2254
2362
  return Data_Wrap_Struct(cExplanation, NULL, &expl_destoy, expl);
2255
2363
  }
2256
2364
 
@@ -2498,6 +2606,7 @@ Init_search(void)
2498
2606
  rb_define_method(cSortField, "name", frt_sf_get_name, 0);
2499
2607
  rb_define_method(cSortField, "sort_type", frt_sf_get_sort_type, 0);
2500
2608
  rb_define_method(cSortField, "comparator", frt_sf_get_comparator, 0);
2609
+ rb_define_method(cSortField, "to_s", frt_sf_to_s, 0);
2501
2610
 
2502
2611
  /* SortType */
2503
2612
  cSortType = rb_define_class_under(cSortField, "SortType", rb_cObject);
@@ -2536,27 +2645,36 @@ Init_search(void)
2536
2645
 
2537
2646
  rb_define_method(cSort, "initialize", frt_sort_init, -1);
2538
2647
  rb_define_method(cSort, "fields", frt_sort_get_fields, 0);
2648
+ rb_define_method(cSort, "to_s", frt_sort_to_s, 0);
2539
2649
 
2540
2650
  rb_define_const(cSort, "RELEVANCE",
2541
2651
  frt_sort_init(0, NULL, frt_sort_alloc(cSort)));
2542
2652
  rb_define_const(cSort, "INDEX_ORDER",
2543
2653
  frt_sort_init(1, &oSORT_FIELD_DOC, frt_sort_alloc(cSort)));
2544
2654
 
2655
+ /* Searcher */
2656
+ cSearcher = rb_define_class_under(mSearch, "Searcher", rb_cObject);
2657
+ rb_define_method(cSearcher, "close", frt_sea_close, 0);
2658
+ rb_define_method(cSearcher, "reader", frt_sea_get_reader, 0);
2659
+ rb_define_method(cSearcher, "doc_freq", frt_sea_doc_freq, 1);
2660
+ rb_define_method(cSearcher, "doc_freqs", frt_sea_doc_freqs, 1);
2661
+ rb_define_method(cSearcher, "doc", frt_sea_doc, 1);
2662
+ rb_define_method(cSearcher, "[]", frt_sea_doc, 1);
2663
+ rb_define_method(cSearcher, "max_doc", frt_sea_max_doc, 0);
2664
+ rb_define_method(cSearcher, "search", frt_sea_search, -1);
2665
+ rb_define_method(cSearcher, "search_each", frt_sea_search_each, 2);
2666
+ rb_define_method(cSearcher, "explain", frt_sea_explain, 2);
2667
+
2545
2668
  /* IndexSearcher */
2546
- cIndexSearcher = rb_define_class_under(mSearch, "IndexSearcher", rb_cObject);
2669
+ cIndexSearcher = rb_define_class_under(mSearch, "IndexSearcher", cSearcher);
2547
2670
  rb_define_alloc_func(cIndexSearcher, frt_data_alloc);
2548
-
2549
2671
  rb_define_method(cIndexSearcher, "initialize", frt_is_init, 1);
2550
- rb_define_method(cIndexSearcher, "close", frt_is_close, 0);
2551
- rb_define_method(cIndexSearcher, "reader", frt_is_get_reader, 0);
2552
- rb_define_method(cIndexSearcher, "doc_freq", frt_is_doc_freq, 1);
2553
- rb_define_method(cIndexSearcher, "doc_freqs", frt_is_doc_freqs, 1);
2554
- rb_define_method(cIndexSearcher, "doc", frt_is_doc, 1);
2555
- rb_define_method(cIndexSearcher, "[]", frt_is_doc, 1);
2556
- rb_define_method(cIndexSearcher, "max_doc", frt_is_max_doc, 0);
2557
- rb_define_method(cIndexSearcher, "search", frt_is_search, -1);
2558
- rb_define_method(cIndexSearcher, "search_each", frt_is_search_each, 2);
2559
- rb_define_method(cIndexSearcher, "explain", frt_is_explain, 2);
2672
+
2673
+ /* MultiSearcher */
2674
+ cMultiSearcher = rb_define_class_under(mSearch, "MultiSearcher", cSearcher);
2675
+ rb_define_alloc_func(cMultiSearcher, frt_data_alloc);
2676
+ rb_define_method(cMultiSearcher, "initialize", frt_ms_init, -1);
2677
+
2560
2678
 
2561
2679
  /* Index */
2562
2680
  cIndex = rb_define_class_under(mIndex, "Index", rb_cObject);