ferret 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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)