ferret 0.1.3 → 0.1.4

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 (57) hide show
  1. data/Rakefile +1 -1
  2. data/TODO +3 -0
  3. data/ext/dummy.exe +0 -0
  4. data/lib/ferret.rb +1 -1
  5. data/lib/ferret/analysis/token.rb +6 -0
  6. data/lib/ferret/analysis/tokenizers.rb +5 -5
  7. data/lib/ferret/document/document.rb +10 -13
  8. data/lib/ferret/index/compound_file_io.rb +12 -9
  9. data/lib/ferret/index/field_infos.rb +0 -6
  10. data/lib/ferret/index/index.rb +220 -102
  11. data/lib/ferret/index/index_reader.rb +22 -2
  12. data/lib/ferret/index/index_writer.rb +55 -14
  13. data/lib/ferret/index/multi_reader.rb +279 -279
  14. data/lib/ferret/index/segment_infos.rb +3 -3
  15. data/lib/ferret/index/segment_merger.rb +7 -6
  16. data/lib/ferret/index/segment_reader.rb +23 -7
  17. data/lib/ferret/index/segment_term_enum.rb +6 -7
  18. data/lib/ferret/index/term_buffer.rb +3 -5
  19. data/lib/ferret/index/term_doc_enum.rb +7 -2
  20. data/lib/ferret/index/term_infos_io.rb +15 -8
  21. data/lib/ferret/query_parser/query_parser.tab.rb +49 -45
  22. data/lib/ferret/search/boolean_query.rb +3 -4
  23. data/lib/ferret/search/boolean_scorer.rb +11 -11
  24. data/lib/ferret/search/caching_wrapper_filter.rb +1 -1
  25. data/lib/ferret/search/disjunction_sum_scorer.rb +9 -7
  26. data/lib/ferret/search/field_cache.rb +1 -2
  27. data/lib/ferret/search/field_sorted_hit_queue.rb +1 -1
  28. data/lib/ferret/search/fuzzy_term_enum.rb +64 -58
  29. data/lib/ferret/search/index_searcher.rb +16 -9
  30. data/lib/ferret/search/prefix_query.rb +7 -0
  31. data/lib/ferret/search/query_filter.rb +1 -1
  32. data/lib/ferret/search/term_scorer.rb +5 -1
  33. data/lib/ferret/search/top_docs.rb +12 -0
  34. data/lib/ferret/store/buffered_index_io.rb +5 -6
  35. data/lib/ferret/store/fs_store.rb +47 -33
  36. data/lib/ferret/store/ram_store.rb +2 -2
  37. data/lib/ferret/utils.rb +1 -0
  38. data/lib/ferret/utils/bit_vector.rb +20 -2
  39. data/lib/ferret/utils/thread_local.rb +28 -0
  40. data/lib/ferret/utils/weak_key_hash.rb +11 -2
  41. data/test/benchmark/tb_rw_vint.rb +1 -1
  42. data/test/functional/thread_safety_index_test.rb +81 -0
  43. data/test/functional/thread_safety_test.rb +137 -0
  44. data/test/test_all.rb +3 -7
  45. data/test/test_helper.rb +2 -1
  46. data/test/unit/index/tc_compound_file_io.rb +2 -2
  47. data/test/unit/index/tc_index.rb +128 -6
  48. data/test/unit/index/tc_index_reader.rb +1 -1
  49. data/test/unit/index/tc_segment_infos.rb +1 -1
  50. data/test/unit/index/th_doc.rb +1 -1
  51. data/test/unit/search/tc_index_searcher.rb +6 -0
  52. data/test/unit/store/tc_fs_store.rb +3 -3
  53. data/test/unit/utils/tc_bit_vector.rb +8 -0
  54. data/test/unit/utils/tc_thread.rb +61 -0
  55. data/test/unit/utils/tc_weak_key_hash.rb +2 -2
  56. data/test/utils/number_to_spoken.rb +132 -0
  57. metadata +7 -2
@@ -251,10 +251,9 @@ module Ferret::Search
251
251
  return Query.merge_boolean_queries(queries)
252
252
  end
253
253
 
254
- def clone()
255
- clone = super
256
- clone.clauses = @clauses.clone
257
- return clone
254
+ def initialize_copy(o)
255
+ super
256
+ @clauses = o.clauses.clone
258
257
  end
259
258
 
260
259
  # Prints a user-readable version of this query.
@@ -87,11 +87,11 @@ module Ferret::Search
87
87
  def next?
88
88
  return @scorer.next?
89
89
  end
90
- def skip_to(doc_nr)
91
- return @scorer.skip_to(doc_nr)
90
+ def skip_to(doc_num)
91
+ return @scorer.skip_to(doc_num)
92
92
  end
93
- def explain(doc_nr)
94
- return @scorer.explain(doc_nr)
93
+ def explain(doc_num)
94
+ return @scorer.explain(doc_num)
95
95
  end
96
96
  end
97
97
 
@@ -116,13 +116,13 @@ module Ferret::Search
116
116
  def initialize(parent_scorer, similarity)
117
117
  super(similarity)
118
118
  @parent_scorer = parent_scorer
119
- @required_nr_matchers = parent_scorer.required_scorers.size
119
+ @required_num_matchers = parent_scorer.required_scorers.size
120
120
  @last_scored_doc = -1
121
121
  end
122
122
  def score
123
123
  if (@parent_scorer.doc() > @last_scored_doc)
124
124
  @last_scored_doc = @parent_scorer.doc()
125
- @parent_scorer.coordinator.nr_matchers += @required_nr_matchers
125
+ @parent_scorer.coordinator.nr_matchers += @required_num_matchers
126
126
  end
127
127
 
128
128
  return super
@@ -132,7 +132,7 @@ module Ferret::Search
132
132
  def counting_conjunction_sum_scorer(required_scorers)
133
133
  # each scorer from the list counted as a single matcher
134
134
 
135
- required_nr_matchers = required_scorers.size
135
+ required_num_matchers = required_scorers.size
136
136
  ccs = CountingConjunctionScorer.new(self, Similarity.default)
137
137
  @required_scorers.each do |scorer|
138
138
  ccs << scorer
@@ -239,13 +239,13 @@ module Ferret::Search
239
239
  # returns:: true if more matching documents may remain.
240
240
  def each_hit_up_to(max = MAX_DOCS) # :yields: doc, score
241
241
  # nil pointer exception when next? was not called before:
242
- doc_nr = @counting_sum_scorer.doc()
243
- while (doc_nr < max)
244
- yield(doc_nr, score())
242
+ doc_num = @counting_sum_scorer.doc()
243
+ while (doc_num < max)
244
+ yield(doc_num, score())
245
245
  if not @counting_sum_scorer.next?
246
246
  return false
247
247
  end
248
- doc_nr = @counting_sum_scorer.doc()
248
+ doc_num = @counting_sum_scorer.doc()
249
249
  end
250
250
  return true
251
251
  end
@@ -14,7 +14,7 @@ module Ferret::Search
14
14
 
15
15
  def bits(reader)
16
16
  if (@cache == nil)
17
- @cache = Ferret::Utils::WeakKeyHash.new.extend(MonitorMixin)
17
+ @cache = Ferret::Utils::WeakKeyHash.new
18
18
  end
19
19
 
20
20
  @cache.synchronize() do # check cache
@@ -8,13 +8,15 @@ module Ferret::Search
8
8
  # Construct a +DisjunctionScorer+.
9
9
  # sub_scorers:: A collection of at least two subscorers.
10
10
  #
11
- # minimum_nr_matchers:: The positive minimum number of subscorers that should
12
- # match to match this query.
13
- # <br>When +@minimum_nr_matchers+ is bigger than
14
- # the number of +sub_scorers+,
15
- # no matches will be produced.
16
- # <br>When @minimum_nr_matchers equals the number of sub_scorers,
17
- # it more efficient to use +ConjunctionScorer+.
11
+ # minimum_nr_matchers:: The positive minimum number of subscorers that
12
+ # should match to match this query.
13
+ #
14
+ # When +@minimum_nr_matchers+ is bigger than the number
15
+ # of +sub_scorers+,no matches will be produced.
16
+ #
17
+ # When @minimum_nr_matchers equals the number of
18
+ # sub_scorers, it more efficient to use
19
+ # +ConjunctionScorer+.
18
20
  def initialize(sub_scorers, minimum_nr_matchers = 1)
19
21
  super(nil)
20
22
 
@@ -1,5 +1,4 @@
1
1
  module Ferret::Search
2
- require 'monitor'
3
2
 
4
3
  # Expert: The default cache implementation, storing all values in memory.
5
4
  # A WeakKeyHash is used for storage.
@@ -36,7 +35,7 @@ module Ferret::Search
36
35
  FLOAT_PARSER = lambda {|i| i.to_f}
37
36
 
38
37
  # The internal cache. Maps Entry to array of interpreted term values.
39
- @@cache = Ferret::Utils::WeakKeyHash.new.extend(MonitorMixin)
38
+ @@cache = Ferret::Utils::WeakKeyHash.new
40
39
 
41
40
  # See if an object is in the cache.
42
41
  def FieldCache.lookup(reader, field, sort_type)
@@ -83,7 +83,7 @@ module Ferret::Search
83
83
 
84
84
  # Internal cache of comparators. Similar to FieldCache, only
85
85
  # caches comparators instead of term values.
86
- @@comparators = Ferret::Utils::WeakKeyHash.new.extend(MonitorMixin)
86
+ @@comparators = Ferret::Utils::WeakKeyHash.new
87
87
 
88
88
  # Returns a comparator if it is in the cache.
89
89
  def lookup(reader, field, sort_type, comproc)
@@ -1,3 +1,5 @@
1
+ require 'monitor'
2
+
1
3
  module Ferret::Search
2
4
  # Subclass of FilteredTermEnum for enumerating all terms that are similiar
3
5
  # to the specified filter term.
@@ -5,6 +7,8 @@ module Ferret::Search
5
7
  # Term enumerations are always ordered by Term.compareTo(). Each term in
6
8
  # the enumeration is greater than all that precede it.
7
9
  class FuzzyTermEnum < FilteredTermEnum
10
+ include MonitorMixin
11
+
8
12
  include Ferret::Index
9
13
  attr_reader :end_enum
10
14
 
@@ -144,73 +148,75 @@ module Ferret::Search
144
148
  # than the required threshold and 1.0 indicates that the text and
145
149
  # target are identical
146
150
  def similarity(target)
147
- m = target.length
148
- n = @text.length
151
+ synchronize do
152
+ m = target.length
153
+ n = @text.length
154
+
155
+ if (n == 0)
156
+ # we don't have anything to compare. That means if we just add the
157
+ # letters for m we get the new word
158
+ return (@prefix_length == 0) ? 0.0 : 1.0 - (m.to_f / @prefix_length)
159
+ end
160
+ if (m == 0)
161
+ return (@prefix_length == 0) ? 0.0 : 1.0 - (n.to_f / @prefix_length)
162
+ end
149
163
 
150
- if (n == 0)
151
- # we don't have anything to compare. That means if we just add the
152
- # letters for m we get the new word
153
- return (@prefix_length == 0) ? 0.0 : 1.0 - (m.to_f / @prefix_length)
154
- end
155
- if (m == 0)
156
- return (@prefix_length == 0) ? 0.0 : 1.0 - (n.to_f / @prefix_length)
157
- end
164
+ max_distance = max_distance(m)
158
165
 
159
- max_distance = max_distance(m)
160
-
161
- if (max_distance < (m-n).abs)
162
- #just adding the characters of m to n or vice-versa results in
163
- #too many edits
164
- #for example "pre" length is 3 and "prefixes" length is 8. We can see that
165
- #given this optimal circumstance, the edit distance cannot be less than 5.
166
- #which is 8-3 or more precisesly Math.abs(3-8).
167
- #if our maximum edit distance is 4, then we can discard this word
168
- #without looking at it.
169
- return 0.0
170
- end
166
+ if (max_distance < (m-n).abs)
167
+ #just adding the characters of m to n or vice-versa results in
168
+ #too many edits
169
+ #for example "pre" length is 3 and "prefixes" length is 8. We can see that
170
+ #given this optimal circumstance, the edit distance cannot be less than 5.
171
+ #which is 8-3 or more precisesly Math.abs(3-8).
172
+ #if our maximum edit distance is 4, then we can discard this word
173
+ #without looking at it.
174
+ return 0.0
175
+ end
171
176
 
172
- #let's make sure we have enough room in our array to do the distance calculations.
173
- if (@d[0].length <= m)
174
- grow_distance_array(m)
175
- end
177
+ #let's make sure we have enough room in our array to do the distance calculations.
178
+ if (@d[0].length <= m)
179
+ grow_distance_array(m)
180
+ end
176
181
 
177
- # init matrix d
178
- (n+1).times {|i| @d[i][0] = i}
179
- (m+1).times {|j| @d[0][j] = j}
180
-
181
- # start computing edit distance
182
- 1.upto(n) do |i|
183
- best_possible_edit_distance = m
184
- s_i = @text[i-1]
185
- 1.upto(m) do |j|
186
- if (s_i != target[j-1])
187
- @d[i][j] = min(@d[i-1][j], @d[i][j-1], @d[i-1][j-1])+1
188
- else
189
- @d[i][j] = min(@d[i-1][j]+1, @d[i][j-1]+1, @d[i-1][j-1])
182
+ # init matrix d
183
+ (n+1).times {|i| @d[i][0] = i}
184
+ (m+1).times {|j| @d[0][j] = j}
185
+
186
+ # start computing edit distance
187
+ 1.upto(n) do |i|
188
+ best_possible_edit_distance = m
189
+ s_i = @text[i-1]
190
+ 1.upto(m) do |j|
191
+ if (s_i != target[j-1])
192
+ @d[i][j] = min(@d[i-1][j], @d[i][j-1], @d[i-1][j-1])+1
193
+ else
194
+ @d[i][j] = min(@d[i-1][j]+1, @d[i][j-1]+1, @d[i-1][j-1])
195
+ end
196
+ if @d[i][j] < best_possible_edit_distance
197
+ best_possible_edit_distance = @d[i][j]
198
+ end
190
199
  end
191
- if @d[i][j] < best_possible_edit_distance
192
- best_possible_edit_distance = @d[i][j]
200
+
201
+ # After calculating row i, the best possible edit distance can be
202
+ # found by found by finding the smallest value in a given column.
203
+ # If the best_possible_edit_distance is greater than the max distance,
204
+ # abort.
205
+ if (i > max_distance and best_possible_edit_distance > max_distance)
206
+ # equal is okay, but not greater
207
+ # the closest the target can be to the text is just too far away.
208
+ # this target is leaving the party early.
209
+ return 0.0
193
210
  end
194
211
  end
195
212
 
196
- # After calculating row i, the best possible edit distance can be
197
- # found by found by finding the smallest value in a given column.
198
- # If the best_possible_edit_distance is greater than the max distance,
199
- # abort.
200
- if (i > max_distance and best_possible_edit_distance > max_distance)
201
- # equal is okay, but not greater
202
- # the closest the target can be to the text is just too far away.
203
- # this target is leaving the party early.
204
- return 0.0
205
- end
213
+ # this will return less than 0.0 when the edit distance is
214
+ # greater than the number of characters in the shorter word.
215
+ # but this was the formula that was previously used in FuzzyTermEnum,
216
+ # so it has not been changed (even though minimum_similarity must be
217
+ # greater than 0.0)
218
+ return 1.0 - (@d[n][m].to_f / (@prefix_length + (n < m ? n : m)))
206
219
  end
207
-
208
- # this will return less than 0.0 when the edit distance is
209
- # greater than the number of characters in the shorter word.
210
- # but this was the formula that was previously used in FuzzyTermEnum,
211
- # so it has not been changed (even though minimum_similarity must be
212
- # greater than 0.0)
213
- return 1.0 - (@d[n][m].to_f / (@prefix_length + (n < m ? n : m)))
214
220
  end
215
221
 
216
222
  # Grow the second dimension of the array, so that we can calculate the
@@ -11,13 +11,20 @@ module Ferret::Search
11
11
  attr_accessor :similarity, :reader
12
12
 
13
13
  # Creates a searcher searching the index in the provided directory.
14
+ #
15
+ # You need to pass one argument which should be one of the following:
16
+ #
17
+ # * An index reader which the searcher will search
18
+ # * A directory where the searcher will open an index reader to search
19
+ # * A string which represents a path to the directory to be searched
20
+ #
14
21
  def initialize(arg)
15
22
  if arg.is_a?(IndexReader)
16
23
  @reader = arg
17
24
  elsif arg.is_a?(Ferret::Store::Directory)
18
- @reader = IndexReader.open(arg)
25
+ @reader = IndexReader.open(arg, false)
19
26
  elsif arg.is_a?(String)
20
- @dir = Ferret::Store::FSDirectory.new(arg, true)
27
+ @dir = Ferret::Store::FSDirectory.new(arg, false)
21
28
  @reader = IndexReader.open(@dir, true)
22
29
  else
23
30
  raise ArgumentError, "Unknown argument passed to initialize IndexReader"
@@ -50,10 +57,10 @@ module Ferret::Search
50
57
  end
51
58
 
52
59
  # Expert: Returns the stored fields of document +i+.
53
- # Called by HitCollector implementations.
60
+ #
54
61
  # See IndexReader#get_document
55
62
  def doc(i)
56
- return @reader.document(i)
63
+ return @reader.get_document(i)
57
64
  end
58
65
 
59
66
  # Expert: Returns one greater than the largest possible document number.
@@ -73,12 +80,12 @@ module Ferret::Search
73
80
  # pass to this method. You can also pass a hash with one or more of the
74
81
  # following; {filter, num_docs, first_doc, sort}
75
82
  #
76
- # query:: the query to run on the index
77
- # filter:: filters docs from the search result
83
+ # query:: The query to run on the index
84
+ # filter:: filters docs from the search result
78
85
  # first_doc:: The index in the results of the first doc retrieved.
79
- # Default is 0
80
- # num_docs:: The number of results returned. Default is 10
81
- # sort:: an array of SortFields describing how to sort the results.
86
+ # Default is 0
87
+ # num_docs:: The number of results returned. Default is 10
88
+ # sort:: An array of SortFields describing how to sort the results.
82
89
  def search(query, options = {})
83
90
  filter = options[:filter]
84
91
  first_doc = options[:first_doc]||0
@@ -43,5 +43,12 @@ module Ferret::Search
43
43
  return buffer
44
44
  end
45
45
 
46
+ def eql?(o)
47
+ (@prefix == o.prefix and boost() == o.boost)
48
+ end
49
+
50
+ def hash()
51
+ boost().hash ^ @prefix.hash
52
+ end
46
53
  end
47
54
  end
@@ -21,7 +21,7 @@ module Ferret::Search
21
21
  def bits(reader)
22
22
 
23
23
  if (@cache == nil)
24
- @cache = Ferret::Utils::WeakKeyHash.new.extend(MonitorMixin)
24
+ @cache = Ferret::Utils::WeakKeyHash.new
25
25
  end
26
26
 
27
27
  @cache.synchronize() do # check cache
@@ -25,6 +25,8 @@ module Ferret::Search
25
25
  @weight = weight
26
26
  @term_docs = td
27
27
  @norms = norms
28
+ #XXX
29
+ @norms_size = @norms.size
28
30
  @weight_value = weight.value
29
31
 
30
32
  SCORE_CACHE_SIZE.times do |i|
@@ -85,8 +87,10 @@ module Ferret::Search
85
87
 
86
88
 
87
89
  # Advances to the next document matching the query.
88
- # <br>The iterator over the matching documents is buffered using
90
+ #
91
+ # The iterator over the matching documents is buffered using
89
92
  # TermDocEnum#read(int[],int[]).
93
+ #
90
94
  # returns:: true iff there is another document matching the query.
91
95
  def next?()
92
96
  @pointer += 1
@@ -5,6 +5,18 @@ module Ferret::Search
5
5
  # Expert: The total number of hits for the query.
6
6
  # See Hits#length()
7
7
  attr_accessor :score_docs, :total_hits, :fields
8
+ alias :size :total_hits
9
+
10
+ # iterate through each of the score docs, yielding the document number and
11
+ # the score. eg:
12
+ #
13
+ # top_docs.each do |doc, score|
14
+ # puts "Doc number #{doc} found with score of #{score}"}
15
+ # end
16
+ #
17
+ def each
18
+ score_docs.each {|sd| yield(sd.doc, sd.score) }
19
+ end
8
20
 
9
21
  # Expert: Constructs a TopDocs.
10
22
  def initialize(total_hits, score_docs, fields = SortField::FIELD_SCORE)
@@ -140,14 +140,13 @@ module Ferret::Store
140
140
  # Creates a clone of the BufferedIndexReader. Reading from a
141
141
  # BufferedIndexInput should not change the state (read position) in the
142
142
  # clone and vice-versa.
143
- def clone()
144
- bii = super
145
- bii.buffer = @buffer.clone if @buffer
146
- return bii
143
+ def initialize_copy(o)
144
+ super
145
+ @buffer = o.buffer.clone if o.buffer
147
146
  end
148
147
 
149
- attr_writer :buffer
150
- protected :buffer=
148
+ attr_reader :buffer
149
+ protected :buffer
151
150
 
152
151
  private
153
152
 
@@ -31,6 +31,30 @@ module Ferret::Store
31
31
  # The lock dir is the directory where the file locks will be stored
32
32
  LOCK_DIR = nil
33
33
 
34
+ # Create a new directory from the path.
35
+ # path:: the path to the directory.
36
+ # create:: if true, create, or erase any existing contents.
37
+ def initialize(path, create)
38
+ super()
39
+ if create then FileUtils.mkdir_p(path) end
40
+ if not File.directory?(path) then
41
+ raise "There is no directory: #{path}. Use create = true to create one"
42
+ end
43
+ @dir = Dir.new(path)
44
+ # put the lock_dir here as well if no default exists.
45
+ if LOCK_DIR then
46
+ @lock_dir = Dir.new(LOCK_DIR)
47
+ else
48
+ @lock_dir = Dir.new(path)
49
+ end
50
+ @ref_count = 0
51
+ end
52
+
53
+ class <<FSDirectory
54
+ alias :allocate :new
55
+ protected :allocate
56
+ end
57
+
34
58
  # Returns the directory instance for the named location.
35
59
  #
36
60
  # Directories are cached, so that, for a given canonical path, the same
@@ -39,12 +63,12 @@ module Ferret::Store
39
63
  #
40
64
  # path:: the path to the directory.
41
65
  # create:: if true, create, or erase any existing contents.
42
- def FSDirectory.get_directory(path, create=false)
66
+ def FSDirectory.new(path, create = false)
43
67
  dir = nil
44
68
  @@Directories.synchronize do
45
69
  dir = @@Directories[path]
46
70
  if not dir then
47
- dir = FSDirectory.new(path, create)
71
+ dir = FSDirectory.allocate(path, create)
48
72
  @@Directories[path] = dir
49
73
  end
50
74
  dir.refresh if create
@@ -76,6 +100,7 @@ module Ferret::Store
76
100
  def refresh
77
101
  synchronize do
78
102
  # delete all the files
103
+ refresh_dir
79
104
  each do |fname|
80
105
  File.delete(dir_path(fname))
81
106
  end
@@ -133,7 +158,9 @@ module Ferret::Store
133
158
  # If a file already exists with the new name, then it is replaced.
134
159
  # This replacement should be atomic.
135
160
  def rename(from, to)
136
- File.rename(dir_path(from), dir_path(to))
161
+ synchronize do
162
+ File.rename(dir_path(from), dir_path(to))
163
+ end
137
164
  end
138
165
 
139
166
 
@@ -160,10 +187,12 @@ module Ferret::Store
160
187
 
161
188
  # Closes the store.
162
189
  def close()
163
- @ref_count -= 1
164
- if (@ref_count <=0) then
165
- @@Directories.synchronize do
166
- @@Directories.delete(@dir.path)
190
+ synchronize do
191
+ @ref_count -= 1
192
+ if (@ref_count <= 0) then
193
+ @@Directories.synchronize do
194
+ @@Directories.delete(@dir.path)
195
+ end
167
196
  end
168
197
  end
169
198
  end
@@ -242,29 +271,32 @@ module Ferret::Store
242
271
 
243
272
  # A file system input stream extending InputStream to read from the file system
244
273
  class FSIndexInput < BufferedIndexInput
245
- attr_writer :is_clone
246
- attr_reader :length
247
- attr_reader :file
274
+ attr_accessor :is_clone
275
+ attr_reader :length, :file
248
276
 
249
277
  def initialize(path)
250
278
  @file = File.open(path, "rb")
251
279
  @file.extend(MonitorMixin)
280
+ #class <<@file
281
+ # attr_accessor :ref_count
282
+ #end
283
+ #@file.ref_count = 1
252
284
  @length = File.size(path)
253
285
  @is_clone = false
254
286
  super()
255
287
  end
256
288
 
257
289
  def close
290
+ #@file.ref_count -= 1
291
+ #@file.close if @file.ref_count == 0
258
292
  @file.close if not @is_clone
259
293
  end
260
294
 
261
295
  # We need to record if this is a clone so we know when to close the file.
262
296
  # The file should only be closed when the original FSIndexInput is closed.
263
- def clone()
264
- fsii = super
265
- fsii.is_clone = true
266
- fsii.file.seek(@file.pos)
267
- return fsii
297
+ def initialize_copy(o)
298
+ super
299
+ @is_clone = true
268
300
  end
269
301
 
270
302
  private
@@ -290,24 +322,6 @@ module Ferret::Store
290
322
  end
291
323
 
292
324
  private
293
- # Create a new directory from the path.
294
- # path:: the path to the directory.
295
- # create:: if true, create, or erase any existing contents.
296
- def initialize(path, create)
297
- super()
298
- if create then FileUtils.mkdir_p(path) end
299
- if not File.directory?(path) then
300
- raise "There is no directory: #{path}. Use create = true to create one"
301
- end
302
- @dir = Dir.new(path)
303
- # put the lock_dir here as well if no default exists.
304
- if LOCK_DIR then
305
- @lock_dir = Dir.new(LOCK_DIR)
306
- else
307
- @lock_dir = Dir.new(path)
308
- end
309
- @ref_count = 0
310
- end
311
325
 
312
326
  # Add the directory path to the file name for opening
313
327
  def dir_path(name)