ferret 0.10.6 → 0.10.7

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 (51) hide show
  1. data/ext/analysis.c +136 -107
  2. data/ext/analysis.h +4 -0
  3. data/ext/bitvector.c +2 -2
  4. data/ext/bitvector.h +1 -1
  5. data/ext/compound_io.c +4 -4
  6. data/ext/defines.h +0 -2
  7. data/ext/filter.c +3 -3
  8. data/ext/fs_store.c +4 -4
  9. data/ext/hash.c +29 -18
  10. data/ext/hash.h +34 -16
  11. data/ext/hashset.c +6 -3
  12. data/ext/hashset.h +1 -1
  13. data/ext/index.c +22 -20
  14. data/ext/q_boolean.c +3 -3
  15. data/ext/q_const_score.c +1 -1
  16. data/ext/q_fuzzy.c +1 -1
  17. data/ext/q_match_all.c +1 -1
  18. data/ext/q_multi_term.c +2 -2
  19. data/ext/q_parser.c +21 -6
  20. data/ext/q_phrase.c +2 -2
  21. data/ext/q_prefix.c +1 -1
  22. data/ext/q_range.c +3 -3
  23. data/ext/q_span.c +8 -8
  24. data/ext/q_term.c +1 -1
  25. data/ext/q_wildcard.c +1 -1
  26. data/ext/r_analysis.c +10 -4
  27. data/ext/r_index.c +89 -12
  28. data/ext/r_qparser.c +67 -4
  29. data/ext/r_search.c +11 -1
  30. data/ext/r_store.c +51 -35
  31. data/ext/ram_store.c +18 -18
  32. data/ext/search.c +1 -1
  33. data/ext/search.h +25 -23
  34. data/ext/similarity.c +1 -1
  35. data/ext/sort.c +1 -1
  36. data/ext/store.c +22 -3
  37. data/ext/store.h +8 -2
  38. data/lib/ferret/index.rb +14 -4
  39. data/lib/ferret_version.rb +1 -1
  40. data/test/test_helper.rb +3 -0
  41. data/test/unit/analysis/tc_analyzer.rb +5 -5
  42. data/test/unit/analysis/tc_token_stream.rb +3 -3
  43. data/test/unit/index/tc_index_writer.rb +1 -1
  44. data/test/unit/query_parser/tc_query_parser.rb +7 -5
  45. data/test/unit/search/tc_filter.rb +1 -1
  46. data/test/unit/search/tc_fuzzy_query.rb +1 -1
  47. data/test/unit/search/tc_index_searcher.rb +1 -1
  48. data/test/unit/search/tc_multi_searcher.rb +1 -1
  49. data/test/unit/search/tc_search_and_sort.rb +1 -1
  50. data/test/unit/search/tc_spans.rb +1 -1
  51. metadata +4 -3
data/ext/r_search.c CHANGED
@@ -2234,7 +2234,7 @@ typedef struct CWrappedFilter
2234
2234
  } CWrappedFilter;
2235
2235
  #define CWF(filt) ((CWrappedFilter *)(filt))
2236
2236
 
2237
- static ulong
2237
+ static unsigned long
2238
2238
  cwfilt_hash(Filter *filt)
2239
2239
  {
2240
2240
  return NUM2ULONG(rb_funcall(CWF(filt)->rfilter, id_hash, 0));
@@ -2676,6 +2676,10 @@ frt_ms_init(int argc, VALUE *argv, VALUE self)
2676
2676
  *
2677
2677
  ****************************************************************************/
2678
2678
 
2679
+ /* rdochack
2680
+ cTopDocs = rb_define_class_under(mSearch, "TopDocs", rb_cObject);
2681
+ */
2682
+
2679
2683
  /*
2680
2684
  * Document-class: Ferret::Search::Hit
2681
2685
  *
@@ -2691,6 +2695,9 @@ static void
2691
2695
  Init_Hit(void)
2692
2696
  {
2693
2697
  const char *hit_class = "Hit";
2698
+ /* rdochack
2699
+ cHit = rb_define_class_under(mSearch, "Hit", rb_cObject);
2700
+ */
2694
2701
  cHit = rb_struct_define(hit_class, "doc", "score", NULL);
2695
2702
  rb_set_class_path(cHit, mSearch, hit_class);
2696
2703
  rb_const_set(mSearch, rb_intern(hit_class), cHit);
@@ -2720,6 +2727,9 @@ static void
2720
2727
  Init_TopDocs(void)
2721
2728
  {
2722
2729
  const char *td_class = "TopDocs";
2730
+ /* rdochack
2731
+ cTopDocs = rb_define_class_under(mSearch, "TopDocs", rb_cObject);
2732
+ */
2723
2733
  cTopDocs = rb_struct_define(td_class,
2724
2734
  "total_hits",
2725
2735
  "hits",
data/ext/r_store.c CHANGED
@@ -1,6 +1,7 @@
1
1
  #include "ferret.h"
2
2
  #include "store.h"
3
3
 
4
+ static ID id_ref_cnt;
4
5
  VALUE cLock;
5
6
  VALUE cLockError;
6
7
  VALUE cDirectory;
@@ -13,16 +14,26 @@ VALUE cFSDirectory;
13
14
  *
14
15
  ****************************************************************************/
15
16
 
17
+ void
18
+ frt_unwrap_locks(Store *store)
19
+ {
20
+ int i;
21
+ for (i = 0; i < store->locks->size; i++) {
22
+ void *lock = store->locks->elems[i];
23
+ VALUE rlock = object_get(lock);
24
+ object_del(lock);
25
+ if (rlock != Qnil) {
26
+ Frt_Unwrap_Struct(rlock);
27
+ }
28
+ }
29
+ }
30
+
16
31
  void
17
32
  frt_lock_free(void *p)
18
33
  {
19
34
  Lock *lock = (Lock *)p;
20
- if (object_get(lock->store) != Qnil) {
21
- lock->store->close_lock(lock);
22
- } else {
23
- free(lock->name);
24
- free(lock);
25
- }
35
+ object_del(p);
36
+ close_lock(lock);
26
37
  }
27
38
 
28
39
  void
@@ -141,11 +152,11 @@ frt_lock_release(VALUE self)
141
152
  void
142
153
  frt_dir_free(Store *store)
143
154
  {
155
+ frt_unwrap_locks(store);
144
156
  object_del(store);
145
157
  store_deref(store);
146
158
  }
147
159
 
148
- #define GET_STORE(store, self) Data_Get_Struct(self, Store, store)
149
160
  /*
150
161
  * call-seq:
151
162
  * dir.close() -> nil
@@ -157,13 +168,15 @@ frt_dir_free(Store *store)
157
168
  static VALUE
158
169
  frt_dir_close(VALUE self)
159
170
  {
160
- /*
161
- * No need to do anything here. Leave it to the garbage collector
162
- GET_STORE;
163
- Frt_Unwrap_Struct(self);
164
- object_del(store);
165
- store_deref(store);
166
- */
171
+ Store *store = DATA_PTR(self);
172
+ int ref_cnt = FIX2INT(rb_ivar_get(self, id_ref_cnt)) - 1;
173
+ rb_ivar_set(self, id_ref_cnt, INT2FIX(ref_cnt));
174
+ if (ref_cnt < 0) {
175
+ Frt_Unwrap_Struct(self);
176
+ object_del(store);
177
+ frt_unwrap_locks(store);
178
+ store_deref(store);
179
+ }
167
180
  return Qnil;
168
181
  }
169
182
 
@@ -176,8 +189,7 @@ frt_dir_close(VALUE self)
176
189
  static VALUE
177
190
  frt_dir_exists(VALUE self, VALUE rfname)
178
191
  {
179
- Store *store;
180
- GET_STORE(store, self);
192
+ Store *store = DATA_PTR(self);
181
193
  StringValue(rfname);
182
194
  return store->exists(store, RSTRING(rfname)->ptr) ? Qtrue : Qfalse;
183
195
  }
@@ -191,8 +203,7 @@ frt_dir_exists(VALUE self, VALUE rfname)
191
203
  static VALUE
192
204
  frt_dir_touch(VALUE self, VALUE rfname)
193
205
  {
194
- Store *store;
195
- GET_STORE(store, self);
206
+ Store *store = DATA_PTR(self);
196
207
  StringValue(rfname);
197
208
  store->touch(store, RSTRING(rfname)->ptr);
198
209
  return Qnil;
@@ -207,8 +218,7 @@ frt_dir_touch(VALUE self, VALUE rfname)
207
218
  static VALUE
208
219
  frt_dir_delete(VALUE self, VALUE rfname)
209
220
  {
210
- Store *store;
211
- GET_STORE(store, self);
221
+ Store *store = DATA_PTR(self);
212
222
  StringValue(rfname);
213
223
  return (store->remove(store, RSTRING(rfname)->ptr) == 0) ? Qtrue : Qfalse;
214
224
  }
@@ -222,8 +232,7 @@ frt_dir_delete(VALUE self, VALUE rfname)
222
232
  static VALUE
223
233
  frt_dir_file_count(VALUE self)
224
234
  {
225
- Store *store;
226
- GET_STORE(store, self);
235
+ Store *store = DATA_PTR(self);
227
236
  return INT2FIX(store->count(store));
228
237
  }
229
238
 
@@ -236,8 +245,7 @@ frt_dir_file_count(VALUE self)
236
245
  static VALUE
237
246
  frt_dir_refresh(VALUE self)
238
247
  {
239
- Store *store;
240
- GET_STORE(store, self);
248
+ Store *store = DATA_PTR(self);
241
249
  store->clear_all(store);
242
250
  return self;
243
251
  }
@@ -252,8 +260,7 @@ frt_dir_refresh(VALUE self)
252
260
  static VALUE
253
261
  frt_dir_rename(VALUE self, VALUE rfrom, VALUE rto)
254
262
  {
255
- Store *store;
256
- GET_STORE(store, self);
263
+ Store *store = DATA_PTR(self);
257
264
  StringValue(rfrom);
258
265
  StringValue(rto);
259
266
  store->rename(store, RSTRING(rfrom)->ptr, RSTRING(rto)->ptr);
@@ -272,11 +279,14 @@ frt_dir_rename(VALUE self, VALUE rfrom, VALUE rto)
272
279
  static VALUE
273
280
  frt_dir_make_lock(VALUE self, VALUE rlock_name)
274
281
  {
275
- Store *store;
276
- GET_STORE(store, self);
282
+ VALUE rlock;
283
+ Lock *lock;
284
+ Store *store = DATA_PTR(self);
277
285
  StringValue(rlock_name);
278
- return Data_Wrap_Struct(cLock, &frt_lock_mark, &frt_lock_free,
279
- store->open_lock(store, RSTRING(rlock_name)->ptr));
286
+ lock = open_lock(store, RSTRING(rlock_name)->ptr);
287
+ rlock = Data_Wrap_Struct(cLock, &frt_lock_mark, &frt_lock_free, lock);
288
+ object_add(lock, rlock);
289
+ return rlock;
280
290
  }
281
291
 
282
292
  /****************************************************************************
@@ -311,8 +321,9 @@ frt_ramdir_init(int argc, VALUE *argv, VALUE self)
311
321
  }
312
322
  default: store = open_ram_store();
313
323
  }
314
- Frt_Wrap_Struct(self, NULL, frt_dir_free, store);
324
+ Frt_Wrap_Struct(self, NULL, &frt_dir_free, store);
315
325
  object_add(store, self);
326
+ rb_ivar_set(self, id_ref_cnt, INT2FIX(0));
316
327
  return self;
317
328
  }
318
329
 
@@ -350,16 +361,20 @@ frt_fsdir_new(int argc, VALUE *argv, VALUE klass)
350
361
  frt_create_dir(rpath);
351
362
  }
352
363
  if (!rb_funcall(rb_cFile, id_is_directory, 1, rpath)) {
353
- rb_raise(rb_eIOError, "There is no directory: %s. Use create = true to "
354
- "create one.", RSTRING(rpath)->ptr);
364
+ rb_raise(rb_eIOError, "No directory <%s> found. Use :create => true"
365
+ " to create one.", RSTRING(rpath)->ptr);
355
366
  }
356
367
  store = open_fs_store(RSTRING(rpath)->ptr);
357
368
  if (create) store->clear_all(store);
358
369
  if ((self = object_get(store)) == Qnil) {
359
370
  self = Data_Wrap_Struct(klass, NULL, &frt_dir_free, store);
360
371
  object_add(store, self);
361
- } else {
362
- store_deref(store);
372
+ rb_ivar_set(self, id_ref_cnt, INT2FIX(0));
373
+ }
374
+ else {
375
+ int ref_cnt = FIX2INT(rb_ivar_get(self, id_ref_cnt)) + 1;
376
+ rb_ivar_set(self, id_ref_cnt, INT2FIX(ref_cnt));
377
+ DEREF(store);
363
378
  }
364
379
  return self;
365
380
  }
@@ -489,6 +504,7 @@ extern VALUE mFerret = rb_define_module("Ferret");
489
504
  void
490
505
  Init_Store(void)
491
506
  {
507
+ id_ref_cnt = rb_intern("@id_ref_cnt");
492
508
  mStore = rb_define_module_under(mFerret, "Store");
493
509
  Init_Directory();
494
510
  Init_Lock();
data/ext/ram_store.c CHANGED
@@ -389,7 +389,7 @@ static void ram_lock_release(Lock *lock)
389
389
  ram_remove(lock->store, lock->name);
390
390
  }
391
391
 
392
- static Lock *ram_open_lock(Store *store, char *lockname)
392
+ static Lock *ram_open_lock_i(Store *store, char *lockname)
393
393
  {
394
394
  Lock *lock = ALLOC(Lock);
395
395
  char lname[100];
@@ -402,7 +402,7 @@ static Lock *ram_open_lock(Store *store, char *lockname)
402
402
  return lock;
403
403
  }
404
404
 
405
- static void ram_close_lock(Lock *lock)
405
+ static void ram_close_lock_i(Lock *lock)
406
406
  {
407
407
  free(lock->name);
408
408
  free(lock);
@@ -413,22 +413,22 @@ Store *open_ram_store()
413
413
  {
414
414
  Store *new_store = store_new();
415
415
 
416
- new_store->dir.ht = h_new_str(NULL, rf_close);
417
- new_store->touch = &ram_touch;
418
- new_store->exists = &ram_exists;
419
- new_store->remove = &ram_remove;
420
- new_store->rename = &ram_rename;
421
- new_store->count = &ram_count;
422
- new_store->clear = &ram_clear;
423
- new_store->clear_all = &ram_clear_all;
424
- new_store->clear_locks = &ram_clear_locks;
425
- new_store->length = &ram_length;
426
- new_store->each = &ram_each;
427
- new_store->new_output = &ram_new_output;
428
- new_store->open_input = &ram_open_input;
429
- new_store->open_lock = &ram_open_lock;
430
- new_store->close_lock = &ram_close_lock;
431
- new_store->close_i = &ram_close_i;
416
+ new_store->dir.ht = h_new_str(NULL, rf_close);
417
+ new_store->touch = &ram_touch;
418
+ new_store->exists = &ram_exists;
419
+ new_store->remove = &ram_remove;
420
+ new_store->rename = &ram_rename;
421
+ new_store->count = &ram_count;
422
+ new_store->clear = &ram_clear;
423
+ new_store->clear_all = &ram_clear_all;
424
+ new_store->clear_locks = &ram_clear_locks;
425
+ new_store->length = &ram_length;
426
+ new_store->each = &ram_each;
427
+ new_store->new_output = &ram_new_output;
428
+ new_store->open_input = &ram_open_input;
429
+ new_store->open_lock_i = &ram_open_lock_i;
430
+ new_store->close_lock_i = &ram_close_lock_i;
431
+ new_store->close_i = &ram_close_i;
432
432
  return new_store;
433
433
  }
434
434
 
data/ext/search.c CHANGED
@@ -413,7 +413,7 @@ Query *q_combine(Query **queries, int q_cnt)
413
413
  return ret_q;
414
414
  }
415
415
 
416
- ulong q_hash(Query *self)
416
+ unsigned long q_hash(Query *self)
417
417
  {
418
418
  return (self->hash(self) << 5) | self->type;
419
419
  }
data/ext/search.h CHANGED
@@ -99,14 +99,14 @@ extern char *td_to_s(TopDocs *td);
99
99
 
100
100
  typedef struct Filter
101
101
  {
102
- char *name;
103
- HashTable *cache;
104
- BitVector *(*get_bv_i)(struct Filter *self, IndexReader *ir);
105
- char *(*to_s)(struct Filter *self);
106
- ulong (*hash)(struct Filter *self);
107
- int (*eq)(struct Filter *self, struct Filter *o);
108
- void (*destroy_i)(struct Filter *self);
109
- int ref_cnt;
102
+ char *name;
103
+ HashTable *cache;
104
+ BitVector *(*get_bv_i)(struct Filter *self, IndexReader *ir);
105
+ char *(*to_s)(struct Filter *self);
106
+ unsigned long (*hash)(struct Filter *self);
107
+ int (*eq)(struct Filter *self, struct Filter *o);
108
+ void (*destroy_i)(struct Filter *self);
109
+ int ref_cnt;
110
110
  } Filter;
111
111
 
112
112
  #define filt_new(type) filt_create(sizeof(type), #type)
@@ -114,7 +114,7 @@ extern Filter *filt_create(size_t size, const char *name);
114
114
  extern BitVector *filt_get_bv(Filter *filt, IndexReader *ir);
115
115
  extern void filt_destroy_i(Filter *filt);
116
116
  extern void filt_deref(Filter *filt);
117
- extern ulong filt_hash(Filter *filt);
117
+ extern unsigned long filt_hash(Filter *filt);
118
118
  extern int filt_eq(Filter *filt, Filter *o);
119
119
 
120
120
  /***************************************************************************
@@ -196,18 +196,18 @@ enum QUERY_TYPE
196
196
 
197
197
  struct Query
198
198
  {
199
- int ref_cnt;
200
- float boost;
201
- Weight *weight;
202
- Query *(*rewrite)(Query *self, IndexReader *ir);
203
- void (*extract_terms)(Query *self, HashSet *terms);
204
- Similarity *(*get_similarity)(Query *self, Searcher *searcher);
205
- char *(*to_s)(Query *self, const char *field);
206
- ulong (*hash)(Query *self);
207
- int (*eq)(Query *self, Query *o);
208
- void (*destroy_i)(Query *self);
209
- Weight *(*create_weight_i)(Query *self, Searcher *searcher);
210
- MatchVector *(*get_matchv_i)(Query *self, MatchVector *mv, TermVector *tv);
199
+ int ref_cnt;
200
+ float boost;
201
+ Weight *weight;
202
+ Query *(*rewrite)(Query *self, IndexReader *ir);
203
+ void (*extract_terms)(Query *self, HashSet *terms);
204
+ Similarity *(*get_similarity)(Query *self, Searcher *searcher);
205
+ char *(*to_s)(Query *self, const char *field);
206
+ unsigned long (*hash)(Query *self);
207
+ int (*eq)(Query *self, Query *o);
208
+ void (*destroy_i)(Query *self);
209
+ Weight *(*create_weight_i)(Query *self, Searcher *searcher);
210
+ MatchVector *(*get_matchv_i)(Query *self, MatchVector *mv, TermVector *tv);
211
211
  enum QUERY_TYPE type;
212
212
  };
213
213
 
@@ -220,7 +220,7 @@ extern void q_deref(Query *self);
220
220
  extern const char *q_get_query_name(enum QUERY_TYPE type);
221
221
  extern Weight *q_weight(Query *self, Searcher *searcher);
222
222
  extern Query *q_combine(Query **queries, int q_cnt);
223
- extern ulong q_hash(Query *self);
223
+ extern unsigned long q_hash(Query *self);
224
224
  extern int q_eq(Query *self, Query *o);
225
225
  extern Query *q_create(size_t size);
226
226
  #define q_new(type) q_create(sizeof(type))
@@ -825,9 +825,11 @@ typedef struct QParser
825
825
  HashSet *fields_buf;
826
826
  HashSet *def_fields;
827
827
  HashSet *all_fields;
828
+ HashSet *tokenized_fields;
828
829
  Analyzer *analyzer;
829
830
  HashTable *ts_cache;
830
831
  Query *result;
832
+ TokenStream *non_tokenizer;
831
833
  bool or_default : 1;
832
834
  bool wild_lower : 1;
833
835
  bool clean_str : 1;
@@ -837,7 +839,7 @@ typedef struct QParser
837
839
  } QParser;
838
840
 
839
841
  extern QParser *qp_new(HashSet *all_fields, HashSet *def_fields,
840
- Analyzer *analyzer);
842
+ HashSet *tokenized_fields, Analyzer *analyzer);
841
843
  extern void qp_destroy(QParser *self);
842
844
  extern Query *qp_parse(QParser *self, char *qstr);
843
845
  extern char *qp_clean_str(char *str);
data/ext/similarity.c CHANGED
@@ -33,7 +33,7 @@ int term_eq(const void *t1, const void *t2)
33
33
  (strcmp(((Term *)t1)->field, ((Term *)t2)->field) == 0);
34
34
  }
35
35
 
36
- ulong term_hash(const void *t)
36
+ unsigned long term_hash(const void *t)
37
37
  {
38
38
  return str_hash(((Term *)t)->text) * str_hash(((Term *)t)->field);
39
39
  }
data/ext/sort.c CHANGED
@@ -8,7 +8,7 @@
8
8
  *
9
9
  ***************************************************************************/
10
10
 
11
- ulong sort_field_hash(const void *p)
11
+ unsigned long sort_field_hash(const void *p)
12
12
  {
13
13
  SortField *self = (SortField *)p;
14
14
  return str_hash(self->field) ^ (self->type*37);
data/ext/store.c CHANGED
@@ -22,19 +22,19 @@ void with_lock(Lock *lock, void (*func)(void *arg), void *arg)
22
22
  void with_lock_name(Store *store, char *lock_name,
23
23
  void (*func)(void *arg), void *arg)
24
24
  {
25
- Lock *lock = store->open_lock(store, lock_name);
25
+ Lock *lock = store->open_lock_i(store, lock_name);
26
26
  if (!lock->obtain(lock)) {
27
27
  RAISE(LOCK_ERROR, "couldn't obtain lock \"%s\"", lock->name);
28
28
  }
29
29
  func(arg);
30
30
  lock->release(lock);
31
- store->close_lock(lock);
31
+ store->close_lock_i(lock);
32
32
  }
33
33
 
34
34
  void store_deref(Store *store)
35
35
  {
36
36
  mutex_lock(&store->mutex_i);
37
- if (--store->ref_cnt == 0) {
37
+ if (--store->ref_cnt <= 0) {
38
38
  store->close_i(store);
39
39
  }
40
40
  else {
@@ -42,6 +42,23 @@ void store_deref(Store *store)
42
42
  }
43
43
  }
44
44
 
45
+ Lock *open_lock(Store *store, char *lockname)
46
+ {
47
+ Lock *lock = store->open_lock_i(store, lockname);
48
+ hs_add(store->locks, lock);
49
+ return lock;
50
+ }
51
+
52
+ void close_lock(Lock *lock)
53
+ {
54
+ hs_del(lock->store->locks, lock);
55
+ }
56
+
57
+ void close_lock_i(Lock *lock)
58
+ {
59
+ lock->store->close_lock_i(lock);
60
+ }
61
+
45
62
  /**
46
63
  * Create a store struct initializing the mutex.
47
64
  */
@@ -51,6 +68,7 @@ Store *store_new()
51
68
  store->ref_cnt = 1;
52
69
  mutex_init(&store->mutex_i, NULL);
53
70
  mutex_init(&store->mutex, NULL);
71
+ store->locks = hs_new(ptr_hash, ptr_eq, (free_ft)&close_lock_i);
54
72
  return store;
55
73
  }
56
74
 
@@ -63,6 +81,7 @@ void store_destroy(Store *store)
63
81
  {
64
82
  mutex_destroy(&store->mutex_i);
65
83
  mutex_destroy(&store->mutex);
84
+ hs_destroy(store->locks);
66
85
  free(store);
67
86
  }
68
87