ferret 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/ext/Makefile +2 -2
  2. data/ext/ferret.c +27 -2
  3. data/ext/ferret.h +59 -16
  4. data/ext/ferret_ext.so +0 -0
  5. data/ext/index_io.c +72 -77
  6. data/ext/priority_queue.c +150 -145
  7. data/ext/ram_directory.c +47 -42
  8. data/ext/segment_merge_queue.c +4 -8
  9. data/ext/segment_term_enum.c +324 -0
  10. data/ext/similarity.c +59 -0
  11. data/ext/string_helper.c +2 -2
  12. data/ext/tags +150 -46
  13. data/ext/term.c +107 -152
  14. data/ext/term_buffer.c +105 -174
  15. data/ext/term_infos_reader.c +54 -0
  16. data/ext/terminfo.c +160 -0
  17. data/ext/token.c +93 -0
  18. data/lib/ferret.rb +1 -1
  19. data/lib/ferret/analysis/analyzers.rb +18 -0
  20. data/lib/ferret/analysis/standard_tokenizer.rb +19 -14
  21. data/lib/ferret/analysis/token.rb +8 -1
  22. data/lib/ferret/analysis/tokenizers.rb +10 -5
  23. data/lib/ferret/document/field.rb +33 -11
  24. data/lib/ferret/index/document_writer.rb +3 -2
  25. data/lib/ferret/index/field_infos.rb +38 -12
  26. data/lib/ferret/index/fields_io.rb +10 -4
  27. data/lib/ferret/index/index.rb +20 -4
  28. data/lib/ferret/index/index_reader.rb +19 -4
  29. data/lib/ferret/index/index_writer.rb +1 -1
  30. data/lib/ferret/index/multi_reader.rb +21 -7
  31. data/lib/ferret/index/segment_merge_info.rb +24 -22
  32. data/lib/ferret/index/segment_merge_queue.rb +2 -2
  33. data/lib/ferret/index/segment_merger.rb +28 -11
  34. data/lib/ferret/index/segment_reader.rb +19 -4
  35. data/lib/ferret/index/segment_term_enum.rb +3 -11
  36. data/lib/ferret/index/term_buffer.rb +13 -16
  37. data/lib/ferret/index/term_doc_enum.rb +8 -5
  38. data/lib/ferret/index/term_enum.rb +2 -2
  39. data/lib/ferret/index/term_info.rb +1 -5
  40. data/lib/ferret/index/term_infos_io.rb +2 -0
  41. data/lib/ferret/query_parser/query_parser.tab.rb +7 -7
  42. data/lib/ferret/search/phrase_scorer.rb +0 -1
  43. data/lib/ferret/search/similarity.rb +2 -2
  44. data/lib/ferret/search/term_scorer.rb +2 -2
  45. data/lib/ferret/store/directory.rb +2 -0
  46. data/lib/ferret/store/fs_store.rb +16 -3
  47. data/lib/ferret/store/ram_store.rb +2 -2
  48. data/test/unit/document/tc_field.rb +9 -0
  49. data/test/unit/index/tc_field_infos.rb +29 -21
  50. data/test/unit/index/tc_index.rb +44 -7
  51. data/test/unit/index/tc_term_buffer.rb +3 -3
  52. data/test/unit/index/tc_term_info.rb +1 -1
  53. data/test/unit/query_parser/tc_query_parser.rb +1 -1
  54. data/test/unit/search/tc_index_searcher.rb +3 -0
  55. data/test/unit/store/tc_fs_store.rb +47 -16
  56. data/test/unit/store/tc_ram_store.rb +1 -1
  57. metadata +8 -3
@@ -69,7 +69,6 @@ module Ferret::Search
69
69
  end
70
70
 
71
71
  def score()
72
- #puts("scoring #{@first.doc}")
73
72
  raw = similarity().tf(@freq) * @value # raw score
74
73
  return raw * Similarity.decode_norm(@norms[@first.doc]) # normalize
75
74
  end
@@ -39,13 +39,13 @@ module Ferret::Search
39
39
  end
40
40
  mantissa = b & 0x07 # 0x07 = 7 = 0b00000111
41
41
  exponent = (b >> 3) & 0x1F # 0x1f = 31 = 0b00011111
42
- return [0,0,(mantissa << 5),(exponent+48)].pack("cccc").unpack("f")[0]
42
+ return [0,0,(mantissa << 5),(exponent+48)].pack("cccc").unpack("e")[0]
43
43
  end
44
44
 
45
45
  def Similarity.float_to_byte(f)
46
46
  if (f <= 0.0) then return 0 end
47
47
 
48
- bits = [f].pack("f").unpack("cccc")
48
+ bits = [f].pack("e").unpack("cccc")
49
49
  mantissa = (bits[2] & 0xEf) >> 5
50
50
  exponent = (bits[3] - 48)
51
51
 
@@ -17,8 +17,8 @@ module Ferret::Search
17
17
  super(similarity)
18
18
 
19
19
  @doc = 0
20
- @docs = Array.new(32, 0) # buffered doc numbers
21
- @freqs = Array.new(32, 0) # buffered term freqs
20
+ @docs = Array.new(SCORE_CACHE_SIZE, 0) # buffered doc numbers
21
+ @freqs = Array.new(SCORE_CACHE_SIZE, 0) # buffered term freqs
22
22
  @pointer = @pointer_max = 0;
23
23
  @score_cache = Array.new(SCORE_CACHE_SIZE)
24
24
 
@@ -14,6 +14,8 @@ module Ferret::Store
14
14
  # called _open_input_ If there is a risk of simultaneous modifications of
15
15
  # the files then locks should be used. See Lock to find out how.
16
16
  class Directory
17
+ LOCK_PREFIX = "ferret-"
18
+
17
19
  # returns an array of strings, one for each file in the directory
18
20
  def each # :yeilds: file_name
19
21
  raise NotImplementedError
@@ -192,6 +192,7 @@ module Ferret::Store
192
192
  if (@ref_count <= 0) then
193
193
  @@Directories.synchronize do
194
194
  @@Directories.delete(@dir.path)
195
+ close_internal
195
196
  end
196
197
  end
197
198
  end
@@ -206,6 +207,12 @@ module Ferret::Store
206
207
  # pass the name of the file that we are going to lock
207
208
  def initialize(lock_file)
208
209
  @lock_file = lock_file
210
+ #@clean = FSLock.make_finalizer(lock_file)
211
+ @clean = lambda { File.delete(lock_file) rescue nil}
212
+ end
213
+
214
+ def FSLock.make_finalizer(lock_file)
215
+ lambda { File.delete(lock_file) rescue nil}
209
216
  end
210
217
 
211
218
  # obtain the lock on the data source
@@ -216,6 +223,7 @@ module Ferret::Store
216
223
  # create a file if none exists. If one already exists
217
224
  # then someone beat us to the lock so return false
218
225
  File.open(@lock_file, File::WRONLY|File::EXCL|File::CREAT) {|f|}
226
+ ObjectSpace.define_finalizer(self, @clean)
219
227
  return true
220
228
  rescue SystemCallError
221
229
  # lock was not obtained so sleep for timeout then try again.
@@ -223,7 +231,7 @@ module Ferret::Store
223
231
  end
224
232
  end
225
233
  # lock could not be obtained so raise an exception
226
- raise "could not obtain lock: " + @lock_file.to_s
234
+ raise "could not obtain lock: #{@lock_file}"
227
235
  end
228
236
 
229
237
  # Release the lock on the data source. Returns true if successful.
@@ -231,6 +239,7 @@ module Ferret::Store
231
239
  return if FSDirectory.locks_disabled?
232
240
  begin
233
241
  File.delete(@lock_file)
242
+ ObjectSpace.undefine_finalizer(self)
234
243
  rescue SystemCallError
235
244
  # maybe we tried to release a lock that wasn't locked. This
236
245
  # isn't critical so just return false
@@ -246,7 +255,8 @@ module Ferret::Store
246
255
  end
247
256
  end
248
257
 
249
- # A file system output stream extending OutputStream to read from the file system
258
+ # A file system output stream extending OutputStream to read from the file
259
+ # system
250
260
  class FSIndexOutput < BufferedIndexOutput
251
261
  def initialize(path)
252
262
  super()
@@ -330,7 +340,7 @@ module Ferret::Store
330
340
 
331
341
  # returns the lock prefix for this directory
332
342
  def lock_prefix
333
- 'ferret-' + Digest::MD5.hexdigest(@dir.path)
343
+ LOCK_PREFIX + Digest::MD5.hexdigest(@dir.path)
334
344
  end
335
345
 
336
346
  # Unfortunately, on Windows, Dir does not refresh when rewind is called
@@ -347,6 +357,9 @@ module Ferret::Store
347
357
  @lock_dir = tmp
348
358
  end
349
359
 
360
+ # This method is only used by the c extension to free the directory
361
+ def close_internal
362
+ end
350
363
  #end private
351
364
  end
352
365
  end
@@ -25,7 +25,7 @@ module Ferret::Store
25
25
  # returns an array of strings, one for each file in the directory
26
26
  def each()
27
27
  @files.each do |path, file|
28
- next if file =~ Regexp.new('^rubylock-')
28
+ next if file =~ /#{LOCK_PREFIX}/
29
29
  yield file
30
30
  end
31
31
  end
@@ -89,7 +89,7 @@ module Ferret::Store
89
89
 
90
90
  # Construct a Lock.
91
91
  def make_lock(name)
92
- RAMLock.new("rubylock-" + name, self)
92
+ RAMLock.new(LOCK_PREFIX + name, self)
93
93
  end
94
94
 
95
95
 
@@ -15,6 +15,7 @@ class FieldTest < Test::Unit::TestCase
15
15
  assert_equal("TOKENIZED", Field::Index::TOKENIZED.to_s)
16
16
  assert_equal("UNTOKENIZED", Field::Index::UNTOKENIZED.to_s)
17
17
  assert_equal("NO", Field::Index::NO.to_s)
18
+ assert_equal("NO_NORMS", Field::Index::NO_NORMS.to_s)
18
19
  end
19
20
 
20
21
  def test_term_vector()
@@ -36,6 +37,7 @@ class FieldTest < Test::Unit::TestCase
36
37
  assert_equal(false, f.store_term_vector?)
37
38
  assert_equal(false, f.store_offsets?)
38
39
  assert_equal(false, f.store_positions?)
40
+ assert_equal(false, f.omit_norms?)
39
41
  assert_equal(false, f.binary?)
40
42
  assert_equal("stored/compressed,indexed,tokenized,<name:value>", f.to_s)
41
43
  end
@@ -53,7 +55,13 @@ class FieldTest < Test::Unit::TestCase
53
55
  f.index = Field::Index::NO
54
56
  assert_equal(false, f.indexed?)
55
57
  assert_equal(false, f.tokenized?)
58
+ assert_equal(false, f.omit_norms?)
56
59
  assert_equal("stored/compressed,<name:value>", f.to_s)
60
+ f.index = Field::Index::NO_NORMS
61
+ assert_equal(true, f.indexed?)
62
+ assert_equal(false, f.tokenized?)
63
+ assert_equal(true, f.omit_norms?)
64
+ assert_equal("stored/compressed,indexed,omit_norms,<name:value>", f.to_s)
57
65
  end
58
66
 
59
67
  def test_set_term_vector()
@@ -79,6 +87,7 @@ class FieldTest < Test::Unit::TestCase
79
87
  assert_equal(false, f.store_term_vector?)
80
88
  assert_equal(false, f.store_offsets?)
81
89
  assert_equal(false, f.store_positions?)
90
+ assert_equal(false, f.omit_norms?)
82
91
  assert_equal(true, f.binary?)
83
92
  assert_equal("stored/uncompressed,binary,<name:#{bin}>", f.to_s)
84
93
  end
@@ -4,13 +4,14 @@ class FieldInfosTest < Test::Unit::TestCase
4
4
  include Ferret::Index
5
5
 
6
6
  def test_field_info()
7
- fi = FieldInfo.new("name", true, 1, true, true, true)
7
+ fi = FieldInfo.new("name", true, 1, true, true, true, true)
8
8
  assert_equal(fi.name, "name")
9
9
  assert_equal(fi.number, 1)
10
10
  assert(fi.indexed?)
11
11
  assert(fi.store_term_vector?)
12
12
  assert(fi.store_offsets?)
13
13
  assert(fi.store_positions?)
14
+ assert(fi.omit_norms?)
14
15
 
15
16
  fi.name = "hello"
16
17
  fi.indexed = false
@@ -18,6 +19,7 @@ class FieldInfosTest < Test::Unit::TestCase
18
19
  fi.store_term_vector = false
19
20
  fi.store_offset = false
20
21
  fi.store_position = false
22
+ fi.omit_norms = false
21
23
 
22
24
  assert_equal(fi.name, "hello")
23
25
  assert_equal(fi.number, 2)
@@ -25,49 +27,53 @@ class FieldInfosTest < Test::Unit::TestCase
25
27
  assert(!fi.store_term_vector?)
26
28
  assert(!fi.store_offsets?)
27
29
  assert(!fi.store_positions?)
30
+ assert(!fi.omit_norms?)
28
31
 
29
- fi.set!(true, true, true, true)
32
+ fi.set!(true, true, true, true, true)
30
33
  assert(fi.indexed?)
31
34
  assert(fi.store_term_vector?)
32
35
  assert(fi.store_offsets?)
33
36
  assert(fi.store_positions?)
37
+ assert(fi.omit_norms?)
34
38
 
35
39
  fi = FieldInfo.new("name", true, 1, true)
36
40
  assert(!fi.store_offsets?)
37
41
  assert(!fi.store_positions?)
42
+ assert(!fi.omit_norms?)
38
43
  end
39
44
 
40
- def fi_test_attr(fi, name, number, indexed, store_tv, store_pos, store_off)
45
+ def fi_test_attr(fi, name, number, indexed, store_tv, store_pos, store_off, omit_norms)
41
46
  assert_equal(name, fi.name)
42
47
  assert_equal(number, fi.number)
43
48
  assert_equal(indexed, fi.indexed?)
44
49
  assert_equal(store_tv, fi.store_term_vector?)
45
50
  assert_equal(store_pos, fi.store_positions?)
46
51
  assert_equal(store_off, fi.store_offsets?)
52
+ assert_equal(omit_norms, fi.omit_norms?)
47
53
  end
48
54
 
49
55
  def test_fis_add()
50
56
  fis = FieldInfos.new()
51
57
  fi = fis.add("field1", false)
52
- fi_test_attr(fi, "field1", 0, false, false, false, false)
58
+ fi_test_attr(fi, "field1", 0, false, false, false, false, false)
53
59
  assert_equal(1, fis.size)
54
60
 
55
61
  fi = fis.add("field1", true, true)
56
- fi_test_attr(fi, "field1", 0, true, true, false, false)
62
+ fi_test_attr(fi, "field1", 0, true, true, false, false, false)
57
63
  assert_equal(1, fis.size)
58
64
 
59
65
  fi = fis.add("field2", false)
60
- fi_test_attr(fi, "field2", 1, false, false, false, false)
66
+ fi_test_attr(fi, "field2", 1, false, false, false, false, false)
61
67
  assert_equal(2, fis.size)
62
68
 
63
- fi = fis.add("field1", true, true, true, true)
69
+ fi = fis.add("field1", true, true, true, true, true)
64
70
  assert_equal(fi, fis[fi.number])
65
71
  assert_equal(fi, fis["field1"])
66
72
  assert_equal(0, fis.field_number("field1"))
67
73
  assert_equal(1, fis.field_number("field2"))
68
74
  assert_equal(FieldInfos::NOT_A_FIELD, fis.field_number("field3"))
69
75
  assert_equal(nil, fis["field3"])
70
- fi_test_attr(fi, "field1", 0, true, true, true, true)
76
+ fi_test_attr(fi, "field1", 0, true, true, true, true, false)
71
77
  assert_equal(2, fis.size)
72
78
  end
73
79
 
@@ -90,7 +96,7 @@ class FieldInfosTest < Test::Unit::TestCase
90
96
  assert(! fis.has_vectors?)
91
97
  fis.add("random_field")
92
98
  assert(! fis.has_vectors?)
93
- fis.add("store_term_vector_field", true, true, false, false)
99
+ fis.add("store_term_vector_field", true, true, false, false, false)
94
100
  assert(fis.has_vectors?)
95
101
  end
96
102
 
@@ -98,22 +104,24 @@ class FieldInfosTest < Test::Unit::TestCase
98
104
  def test_fis_rw()
99
105
  fis = FieldInfos.new()
100
106
  dir = Ferret::Store::RAMDirectory.new()
101
- fis.add("field1", false, false, false, false)
102
- fis.add("field2", true, false, false, false)
103
- fis.add("field3", true, true, false, false)
104
- fis.add("field4", true, true, true, false)
105
- fis.add("field5", true, true, true, true)
107
+ fis.add("field1", false, false, false, false, true)
108
+ fis.add("field2", true, false, false, false, true)
109
+ fis.add("field3", true, true, false, false, true)
110
+ fis.add("field4", true, true, true, false, true)
111
+ fis.add("field5", true, true, true, true, true)
112
+ fis.add("field6", true, true, true, true, false)
106
113
  fis.write_to_dir(dir, "fis_rw.test")
107
114
  fis = nil
108
115
 
109
116
  fis = FieldInfos.new(dir, "fis_rw.test")
110
- fi_test_attr(fis[0], "field1", 0, false, false, false, false)
111
- fi_test_attr(fis[1], "field2", 1, true, false, false, false)
112
- fi_test_attr(fis[2], "field3", 2, true, true, false, false)
113
- fi_test_attr(fis[3], "field4", 3, true, true, true, false)
114
- fi_test_attr(fis[4], "field5", 4, true, true, true, true)
115
-
116
- assert_equal(5, fis.size)
117
+ fi_test_attr(fis[0], "field1", 0, false, false, false, false, true)
118
+ fi_test_attr(fis[1], "field2", 1, true, false, false, false, true)
119
+ fi_test_attr(fis[2], "field3", 2, true, true, false, false, true)
120
+ fi_test_attr(fis[3], "field4", 3, true, true, true, false, true)
121
+ fi_test_attr(fis[4], "field5", 4, true, true, true, true, true)
122
+ fi_test_attr(fis[5], "field6", 5, true, true, true, true, false)
123
+
124
+ assert_equal(6, fis.size)
117
125
  end
118
126
 
119
127
  end
@@ -8,7 +8,6 @@ class IndexTest < Test::Unit::TestCase
8
8
  include Ferret::Document
9
9
 
10
10
  def setup()
11
- @qp = Ferret::QueryParser.new()
12
11
  end
13
12
 
14
13
  def tear_down()
@@ -81,7 +80,7 @@ class IndexTest < Test::Unit::TestCase
81
80
  {"def_field" => "one two"},
82
81
  {"def_field" => "two", :field2 => "three", "field3" => "four"},
83
82
  {"def_field" => "one multi2"},
84
- {"def_field" => "two", :field2 => "three multi2", "field3" => "five multi"}
83
+ {"def_field" => "two", :field2 => "this three multi2", "field3" => "five multi"}
85
84
  ]
86
85
  data.each {|doc| index << doc }
87
86
  q = "one AND two"
@@ -110,6 +109,7 @@ class IndexTest < Test::Unit::TestCase
110
109
  doc["field2"] = "dave"
111
110
  index << doc
112
111
  check_results(index, q, [6, 7])
112
+ check_results(index, "*:this", [])
113
113
  assert_equal(8, index.size)
114
114
  assert_equal("dave", index[7]["field2"])
115
115
  index.optimize
@@ -129,28 +129,39 @@ class IndexTest < Test::Unit::TestCase
129
129
  def test_ram_index
130
130
  index = Index.new(:default_field => "def_field")
131
131
  do_test_index_with_array(index)
132
+ index.close
133
+
132
134
  index = Index.new(:default_field => "def_field")
133
135
  do_test_index_with_hash(index)
136
+ index.close
137
+
134
138
  index = Index.new(:default_field => "def_field")
135
139
  do_test_index_with_doc_array(index)
140
+ index.close
136
141
  end
137
142
 
138
143
  def test_fs_index
139
144
  fs_path = File.expand_path(File.join(File.dirname(__FILE__), '../../temp/fsdir'))
140
- `rm -rf #{File.join(fs_path, "*")}`
145
+ Dir[File.join(fs_path, "*")].each {|path| begin File.delete(path) rescue nil end}
141
146
  assert_raise(Errno::ENOENT) {Index.new(:path => fs_path, :create_if_missing => false, :default_field => "def_field")}
142
147
  index = Index.new(:path => fs_path, :default_field => "def_field")
143
148
  do_test_index_with_array(index)
144
- `rm -rf #{File.join(fs_path, "*")}`
145
- index = Index.new(:path => fs_path, :create => true, :default_field => "def_field")
149
+ index.close
150
+
151
+ Dir[File.join(fs_path, "*")].each {|path| begin File.delete(path) rescue nil end}
152
+ index = Index.new(:path => fs_path, :default_field => "def_field")
146
153
  do_test_index_with_hash(index)
147
- index = Index.new(:path => fs_path, :create => true, :default_field => "def_field")
154
+ index.close
155
+
156
+ Dir[File.join(fs_path, "*")].each {|path| begin File.delete(path) rescue nil end}
157
+ index = Index.new(:path => fs_path, :default_field => "def_field")
148
158
  do_test_index_with_doc_array(index)
159
+ index.close
149
160
  end
150
161
 
151
162
  def test_fs_index_is_persistant
152
163
  fs_path = File.expand_path(File.join(File.dirname(__FILE__), '../../temp/fsdir'))
153
- `rm -rf #{File.join(fs_path, "*")}`
164
+ Dir[File.join(fs_path, "*")].each {|path| begin File.delete(path) rescue nil end}
154
165
  data = [
155
166
  {"def_field" => "one two", :id => "me"},
156
167
  {"def_field" => "one", :field2 => "three"},
@@ -165,9 +176,11 @@ class IndexTest < Test::Unit::TestCase
165
176
  data.each {|doc| index << doc }
166
177
  assert_equal(8, index.size)
167
178
  index.close
179
+
168
180
  index = Index.new(:path => fs_path, :create_if_missing => false)
169
181
  assert_equal(8, index.size)
170
182
  assert_equal("four", index[5]["field3"])
183
+ index.close
171
184
  end
172
185
 
173
186
  def test_merging_indexes
@@ -246,6 +259,7 @@ class IndexTest < Test::Unit::TestCase
246
259
  index3.close
247
260
  dir3.close
248
261
  assert_equal("golf", index[15]["f"])
262
+ index.close
249
263
  end
250
264
 
251
265
  def test_persist_index
@@ -310,6 +324,7 @@ class IndexTest < Test::Unit::TestCase
310
324
  iw.close()
311
325
  assert_equal(3, index.size)
312
326
  assert_equal("content3", index[2]["f"])
327
+ index.close
313
328
  end
314
329
 
315
330
  def test_delete
@@ -340,6 +355,7 @@ class IndexTest < Test::Unit::TestCase
340
355
  index.query_delete("cat:/cat1*")
341
356
  assert_equal(3, index.size)
342
357
  assert_equal(0, index.search("cat:/cat1*").size)
358
+ index.close
343
359
  end
344
360
 
345
361
  def test_update
@@ -390,6 +406,7 @@ class IndexTest < Test::Unit::TestCase
390
406
  assert_equal("cool", index["3"][:tag])
391
407
  assert_equal("cool", index["4"][:tag])
392
408
  assert_equal(4, index.search("tag:cool").size)
409
+ index.close
393
410
  end
394
411
 
395
412
  def test_index_key
@@ -405,6 +422,7 @@ class IndexTest < Test::Unit::TestCase
405
422
  assert_equal(2, index.size)
406
423
  assert_equal("two", index[0][:val])
407
424
  assert_equal("four", index[1][:val])
425
+ index.close
408
426
  end
409
427
 
410
428
  def test_index_multi_key
@@ -427,5 +445,24 @@ class IndexTest < Test::Unit::TestCase
427
445
  assert_equal("second floor", index[1][:location])
428
446
  assert_equal("backpack", index[3][:product])
429
447
  assert_equal("first floor", index[2][:location])
448
+ index.close
449
+ end
450
+
451
+ def test_auto_flush
452
+ fs_path = File.expand_path(File.join(File.dirname(__FILE__), '../../temp/fsdir'))
453
+ Dir[File.join(fs_path, "*")].each {|path| begin File.delete(path) rescue nil end}
454
+ data = %q(one two three four five six seven eight nine ten eleven twelve)
455
+ index1 = Index.new(:path => fs_path, :auto_flush => true)
456
+ index2 = Index.new(:path => fs_path, :auto_flush => true)
457
+ begin
458
+ data.each do |doc|
459
+ index1 << doc
460
+ index2 << doc
461
+ end
462
+ rescue Exception => e
463
+ assert(false, "This should not cause an error when auto flush has been set")
464
+ end
465
+ index1.close
466
+ index2.close
430
467
  end
431
468
  end