Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
FieldCacheImpl.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using System.Collections.Generic;
20 using System.IO;
21 using System.Linq;
22 using Lucene.Net.Support;
23 using NumericField = Lucene.Net.Documents.NumericField;
24 using IndexReader = Lucene.Net.Index.IndexReader;
25 using Term = Lucene.Net.Index.Term;
26 using TermDocs = Lucene.Net.Index.TermDocs;
27 using TermEnum = Lucene.Net.Index.TermEnum;
28 using FieldCacheSanityChecker = Lucene.Net.Util.FieldCacheSanityChecker;
29 using Single = Lucene.Net.Support.Single;
30 using StringHelper = Lucene.Net.Util.StringHelper;
31 
32 namespace Lucene.Net.Search
33 {
34 
35  /// <summary> Expert: The default cache implementation, storing all values in memory.
36  /// A WeakDictionary is used for storage.
37  ///
38  /// <p/>Created: May 19, 2004 4:40:36 PM
39  ///
40  /// </summary>
41  /// <since> lucene 1.4
42  /// </since>
44  {
45  private IDictionary<Type, Cache> caches;
46 
47  internal FieldCacheImpl()
48  {
49  Init();
50  }
51  private void Init()
52  {
53  lock (this)
54  {
55  caches = new HashMap<Type, Cache>(7);
56  caches[typeof(sbyte)] = new ByteCache(this);
57  caches[typeof(short)] = new ShortCache(this);
58  caches[typeof(int)] = new IntCache(this);
59  caches[typeof(float)] = new FloatCache(this);
60  caches[typeof(long)] = new LongCache(this);
61  caches[typeof(double)] = new DoubleCache(this);
62  caches[typeof(string)] = new StringCache(this);
63  caches[typeof(StringIndex)] = new StringIndexCache(this);
64  }
65  }
66 
67  // lucene.net: java version 3.0.3 with patch in rev. 912330 applied:
68  // uschindler 21/02/2010 12:16:42 LUCENE-2273: Fixed bug in FieldCacheImpl.getCacheEntries() that used
69  // WeakHashMap incorrectly and lead to ConcurrentModificationException
70  public virtual void PurgeAllCaches()
71  {
72  lock (this)
73  {
74  Init();
75  }
76  }
77 
78  // lucene.net: java version 3.0.3 with patch in rev. 912330 applied:
79  // uschindler 21/02/2010 12:16:42 LUCENE-2273: Fixed bug in FieldCacheImpl.getCacheEntries() that used
80  // WeakHashMap incorrectly and lead to ConcurrentModificationException
81  public void Purge(IndexReader r)
82  {
83  lock (this)
84  {
85  foreach (Cache c in caches.Values)
86  {
87  c.Purge(r);
88  }
89  }
90  }
91 
92  // lucene.net: java version 3.0.3 with patch in rev. 912330 applied:
93  // uschindler 21/02/2010 12:16:42 LUCENE-2273: Fixed bug in FieldCacheImpl.getCacheEntries() that used
94  // WeakHashMap incorrectly and lead to ConcurrentModificationException
95  public virtual CacheEntry[] GetCacheEntries()
96  {
97  lock (this)
98  {
99  IList<CacheEntry> result = new List<CacheEntry>(17);
100  foreach (var cacheEntry in caches)
101  {
102  var cache = cacheEntry.Value;
103  var cacheType = cacheEntry.Key;
104  lock (cache.readerCache)
105  {
106  foreach (var readerCacheEntry in cache.readerCache)
107  {
108  var readerKey = readerCacheEntry.Key;
109  var innerCache = readerCacheEntry.Value;
110  foreach (var mapEntry in innerCache)
111  {
112  Entry entry = mapEntry.Key;
113  result.Add(new CacheEntryImpl(readerKey, entry.field, cacheType, entry.custom, mapEntry.Value));
114  }
115  }
116  }
117  }
118  return result.ToArray();
119  }
120  }
121 
122  private sealed class CacheEntryImpl : CacheEntry
123  {
124  private System.Object readerKey;
125  private System.String fieldName;
126  private System.Type cacheType;
127  private System.Object custom;
128  private System.Object value;
129  internal CacheEntryImpl(System.Object readerKey, System.String fieldName, System.Type cacheType, System.Object custom, System.Object value)
130  {
131  this.readerKey = readerKey;
132  this.fieldName = fieldName;
133  this.cacheType = cacheType;
134  this.custom = custom;
135  this.value = value;
136 
137  // :HACK: for testing.
138  // if (null != locale || SortField.CUSTOM != sortFieldType) {
139  // throw new RuntimeException("Locale/sortFieldType: " + this);
140  // }
141  }
142 
143  public override object ReaderKey
144  {
145  get { return readerKey; }
146  }
147 
148  public override string FieldName
149  {
150  get { return fieldName; }
151  }
152 
153  public override Type CacheType
154  {
155  get { return cacheType; }
156  }
157 
158  public override object Custom
159  {
160  get { return custom; }
161  }
162 
163  public override object Value
164  {
165  get { return value; }
166  }
167  }
168 
169  /// <summary> Hack: When thrown from a Parser (NUMERIC_UTILS_* ones), this stops
170  /// processing terms and returns the current FieldCache
171  /// array.
172  /// </summary>
173  [Serializable]
174  internal sealed class StopFillCacheException:System.SystemException
175  {
176  }
177 
178  /// <summary>Expert: Internal cache. </summary>
179  internal abstract class Cache
180  {
181  internal Cache()
182  {
183  this.wrapper = null;
184  }
185 
186  internal Cache(FieldCache wrapper)
187  {
188  this.wrapper = wrapper;
189  }
190 
191  internal FieldCache wrapper;
192 
193  internal IDictionary<object, IDictionary<Entry, object>> readerCache = new WeakDictionary<object, IDictionary<Entry, object>>();
194 
195  protected internal abstract System.Object CreateValue(IndexReader reader, Entry key);
196 
197  /* Remove this reader from the cache, if present. */
198  public void Purge(IndexReader r)
199  {
200  object readerKey = r.FieldCacheKey;
201  lock (readerCache)
202  {
203  readerCache.Remove(readerKey);
204  }
205  }
206 
207  public virtual System.Object Get(IndexReader reader, Entry key)
208  {
209  IDictionary<Entry, object> innerCache;
210  System.Object value;
211  System.Object readerKey = reader.FieldCacheKey;
212  lock (readerCache)
213  {
214  innerCache = readerCache[readerKey];
215  if (innerCache == null)
216  {
217  innerCache = new HashMap<Entry, object>();
218  readerCache[readerKey] = innerCache;
219  value = null;
220  }
221  else
222  {
223  value = innerCache[key];
224  }
225  if (value == null)
226  {
227  value = new CreationPlaceholder();
228  innerCache[key] = value;
229  }
230  }
231  if (value is CreationPlaceholder)
232  {
233  lock (value)
234  {
235  CreationPlaceholder progress = (CreationPlaceholder) value;
236  if (progress.value_Renamed == null)
237  {
238  progress.value_Renamed = CreateValue(reader, key);
239  lock (readerCache)
240  {
241  innerCache[key] = progress.value_Renamed;
242  }
243 
244  // Only check if key.custom (the parser) is
245  // non-null; else, we check twice for a single
246  // call to FieldCache.getXXX
247  if (key.custom != null && wrapper != null)
248  {
249  System.IO.StreamWriter infoStream = wrapper.InfoStream;
250  if (infoStream != null)
251  {
252  PrintNewInsanity(infoStream, progress.value_Renamed);
253  }
254  }
255  }
256  return progress.value_Renamed;
257  }
258  }
259  return value;
260  }
261 
262  private void PrintNewInsanity(System.IO.StreamWriter infoStream, System.Object value_Renamed)
263  {
264  FieldCacheSanityChecker.Insanity[] insanities = FieldCacheSanityChecker.CheckSanity(wrapper);
265  for (int i = 0; i < insanities.Length; i++)
266  {
267  FieldCacheSanityChecker.Insanity insanity = insanities[i];
268  CacheEntry[] entries = insanity.GetCacheEntries();
269  for (int j = 0; j < entries.Length; j++)
270  {
271  if (entries[j].Value == value_Renamed)
272  {
273  // OK this insanity involves our entry
274  infoStream.WriteLine("WARNING: new FieldCache insanity created\nDetails: " + insanity.ToString());
275  infoStream.WriteLine("\nStack:\n");
276  infoStream.WriteLine(new System.Exception());
277  break;
278  }
279  }
280  }
281  }
282  }
283 
284  /// <summary>Expert: Every composite-key in the internal cache is of this type. </summary>
285  protected internal class Entry
286  {
287  internal System.String field; // which Fieldable
288  internal System.Object custom; // which custom comparator or parser
289 
290  /// <summary>Creates one of these objects for a custom comparator/parser. </summary>
291  internal Entry(System.String field, System.Object custom)
292  {
293  this.field = StringHelper.Intern(field);
294  this.custom = custom;
295  }
296 
297  /// <summary>Two of these are equal iff they reference the same field and type. </summary>
298  public override bool Equals(System.Object o)
299  {
300  if (o is Entry)
301  {
302  Entry other = (Entry) o;
303  if (other.field == field)
304  {
305  if (other.custom == null)
306  {
307  if (custom == null)
308  return true;
309  }
310  else if (other.custom.Equals(custom))
311  {
312  return true;
313  }
314  }
315  }
316  return false;
317  }
318 
319  /// <summary>Composes a hashcode based on the field and type. </summary>
320  public override int GetHashCode()
321  {
322  return field.GetHashCode() ^ (custom == null?0:custom.GetHashCode());
323  }
324  }
325 
326  // inherit javadocs
327  public virtual sbyte[] GetBytes(IndexReader reader, System.String field)
328  {
329  return GetBytes(reader, field, null);
330  }
331 
332  // inherit javadocs
333  public virtual sbyte[] GetBytes(IndexReader reader, System.String field, ByteParser parser)
334  {
335  return (sbyte[]) caches[typeof(sbyte)].Get(reader, new Entry(field, parser));
336  }
337 
338  internal sealed class ByteCache:Cache
339  {
340  internal ByteCache(FieldCache wrapper):base(wrapper)
341  {
342  }
343  protected internal override System.Object CreateValue(IndexReader reader, Entry entryKey)
344  {
345  Entry entry = entryKey;
346  System.String field = entry.field;
347  ByteParser parser = (ByteParser) entry.custom;
348  if (parser == null)
349  {
350  return wrapper.GetBytes(reader, field, Lucene.Net.Search.FieldCache_Fields.DEFAULT_BYTE_PARSER);
351  }
352  sbyte[] retArray = new sbyte[reader.MaxDoc];
353  TermDocs termDocs = reader.TermDocs();
354  TermEnum termEnum = reader.Terms(new Term(field));
355  try
356  {
357  do
358  {
359  Term term = termEnum.Term;
360  if (term == null || (System.Object) term.Field != (System.Object) field)
361  break;
362  sbyte termval = parser.ParseByte(term.Text);
363  termDocs.Seek(termEnum);
364  while (termDocs.Next())
365  {
366  retArray[termDocs.Doc] = termval;
367  }
368  }
369  while (termEnum.Next());
370  }
371  catch (StopFillCacheException)
372  {
373  }
374  finally
375  {
376  termDocs.Close();
377  termEnum.Close();
378  }
379  return retArray;
380  }
381  }
382 
383 
384  // inherit javadocs
385  public virtual short[] GetShorts(IndexReader reader, System.String field)
386  {
387  return GetShorts(reader, field, null);
388  }
389 
390  // inherit javadocs
391  public virtual short[] GetShorts(IndexReader reader, System.String field, ShortParser parser)
392  {
393  return (short[]) caches[typeof(short)].Get(reader, new Entry(field, parser));
394  }
395 
396  internal sealed class ShortCache:Cache
397  {
398  internal ShortCache(FieldCache wrapper):base(wrapper)
399  {
400  }
401 
402  protected internal override System.Object CreateValue(IndexReader reader, Entry entryKey)
403  {
404  Entry entry = entryKey;
405  System.String field = entry.field;
406  ShortParser parser = (ShortParser) entry.custom;
407  if (parser == null)
408  {
409  return wrapper.GetShorts(reader, field, Lucene.Net.Search.FieldCache_Fields.DEFAULT_SHORT_PARSER);
410  }
411  short[] retArray = new short[reader.MaxDoc];
412  TermDocs termDocs = reader.TermDocs();
413  TermEnum termEnum = reader.Terms(new Term(field));
414  try
415  {
416  do
417  {
418  Term term = termEnum.Term;
419  if (term == null || (System.Object) term.Field != (System.Object) field)
420  break;
421  short termval = parser.ParseShort(term.Text);
422  termDocs.Seek(termEnum);
423  while (termDocs.Next())
424  {
425  retArray[termDocs.Doc] = termval;
426  }
427  }
428  while (termEnum.Next());
429  }
430  catch (StopFillCacheException)
431  {
432  }
433  finally
434  {
435  termDocs.Close();
436  termEnum.Close();
437  }
438  return retArray;
439  }
440  }
441 
442 
443  // inherit javadocs
444  public virtual int[] GetInts(IndexReader reader, System.String field)
445  {
446  return GetInts(reader, field, null);
447  }
448 
449  // inherit javadocs
450  public virtual int[] GetInts(IndexReader reader, System.String field, IntParser parser)
451  {
452  return (int[]) caches[typeof(int)].Get(reader, new Entry(field, parser));
453  }
454 
455  internal sealed class IntCache:Cache
456  {
457  internal IntCache(FieldCache wrapper):base(wrapper)
458  {
459  }
460 
461  protected internal override System.Object CreateValue(IndexReader reader, Entry entryKey)
462  {
463  Entry entry = entryKey;
464  System.String field = entry.field;
465  IntParser parser = (IntParser) entry.custom;
466  if (parser == null)
467  {
468  try
469  {
470  return wrapper.GetInts(reader, field, Lucene.Net.Search.FieldCache_Fields.DEFAULT_INT_PARSER);
471  }
472  catch (System.FormatException)
473  {
474  return wrapper.GetInts(reader, field, Lucene.Net.Search.FieldCache_Fields.NUMERIC_UTILS_INT_PARSER);
475  }
476  }
477  int[] retArray = null;
478  TermDocs termDocs = reader.TermDocs();
479  TermEnum termEnum = reader.Terms(new Term(field));
480  try
481  {
482  do
483  {
484  Term term = termEnum.Term;
485  if (term == null || (System.Object) term.Field != (System.Object) field)
486  break;
487  int termval = parser.ParseInt(term.Text);
488  if (retArray == null)
489  // late init
490  retArray = new int[reader.MaxDoc];
491  termDocs.Seek(termEnum);
492  while (termDocs.Next())
493  {
494  retArray[termDocs.Doc] = termval;
495  }
496  }
497  while (termEnum.Next());
498  }
499  catch (StopFillCacheException)
500  {
501  }
502  finally
503  {
504  termDocs.Close();
505  termEnum.Close();
506  }
507  if (retArray == null)
508  // no values
509  retArray = new int[reader.MaxDoc];
510  return retArray;
511  }
512  }
513 
514 
515 
516  // inherit javadocs
517  public virtual float[] GetFloats(IndexReader reader, System.String field)
518  {
519  return GetFloats(reader, field, null);
520  }
521 
522  // inherit javadocs
523  public virtual float[] GetFloats(IndexReader reader, System.String field, FloatParser parser)
524  {
525 
526  return (float[]) caches[typeof(float)].Get(reader, new Entry(field, parser));
527  }
528 
529  internal sealed class FloatCache:Cache
530  {
531  internal FloatCache(FieldCache wrapper):base(wrapper)
532  {
533  }
534 
535  protected internal override System.Object CreateValue(IndexReader reader, Entry entryKey)
536  {
537  Entry entry = entryKey;
538  System.String field = entry.field;
539  FloatParser parser = (FloatParser) entry.custom;
540  if (parser == null)
541  {
542  try
543  {
544  return wrapper.GetFloats(reader, field, Lucene.Net.Search.FieldCache_Fields.DEFAULT_FLOAT_PARSER);
545  }
546  catch (System.FormatException)
547  {
548  return wrapper.GetFloats(reader, field, Lucene.Net.Search.FieldCache_Fields.NUMERIC_UTILS_FLOAT_PARSER);
549  }
550  }
551  float[] retArray = null;
552  TermDocs termDocs = reader.TermDocs();
553  TermEnum termEnum = reader.Terms(new Term(field));
554  try
555  {
556  do
557  {
558  Term term = termEnum.Term;
559  if (term == null || (System.Object) term.Field != (System.Object) field)
560  break;
561  float termval = parser.ParseFloat(term.Text);
562  if (retArray == null)
563  // late init
564  retArray = new float[reader.MaxDoc];
565  termDocs.Seek(termEnum);
566  while (termDocs.Next())
567  {
568  retArray[termDocs.Doc] = termval;
569  }
570  }
571  while (termEnum.Next());
572  }
573  catch (StopFillCacheException)
574  {
575  }
576  finally
577  {
578  termDocs.Close();
579  termEnum.Close();
580  }
581  if (retArray == null)
582  // no values
583  retArray = new float[reader.MaxDoc];
584  return retArray;
585  }
586  }
587 
588 
589 
590  public virtual long[] GetLongs(IndexReader reader, System.String field)
591  {
592  return GetLongs(reader, field, null);
593  }
594 
595  // inherit javadocs
596  public virtual long[] GetLongs(IndexReader reader, System.String field, Lucene.Net.Search.LongParser parser)
597  {
598  return (long[]) caches[typeof(long)].Get(reader, new Entry(field, parser));
599  }
600 
601  internal sealed class LongCache:Cache
602  {
603  internal LongCache(FieldCache wrapper):base(wrapper)
604  {
605  }
606 
607  protected internal override System.Object CreateValue(IndexReader reader, Entry entryKey)
608  {
609  Entry entry = entryKey;
610  System.String field = entry.field;
611  Lucene.Net.Search.LongParser parser = (Lucene.Net.Search.LongParser) entry.custom;
612  if (parser == null)
613  {
614  try
615  {
616  return wrapper.GetLongs(reader, field, Lucene.Net.Search.FieldCache_Fields.DEFAULT_LONG_PARSER);
617  }
618  catch (System.FormatException)
619  {
620  return wrapper.GetLongs(reader, field, Lucene.Net.Search.FieldCache_Fields.NUMERIC_UTILS_LONG_PARSER);
621  }
622  }
623  long[] retArray = null;
624  TermDocs termDocs = reader.TermDocs();
625  TermEnum termEnum = reader.Terms(new Term(field));
626  try
627  {
628  do
629  {
630  Term term = termEnum.Term;
631  if (term == null || (System.Object) term.Field != (System.Object) field)
632  break;
633  long termval = parser.ParseLong(term.Text);
634  if (retArray == null)
635  // late init
636  retArray = new long[reader.MaxDoc];
637  termDocs.Seek(termEnum);
638  while (termDocs.Next())
639  {
640  retArray[termDocs.Doc] = termval;
641  }
642  }
643  while (termEnum.Next());
644  }
645  catch (StopFillCacheException)
646  {
647  }
648  finally
649  {
650  termDocs.Close();
651  termEnum.Close();
652  }
653  if (retArray == null)
654  // no values
655  retArray = new long[reader.MaxDoc];
656  return retArray;
657  }
658  }
659 
660 
661  // inherit javadocs
662  public virtual double[] GetDoubles(IndexReader reader, System.String field)
663  {
664  return GetDoubles(reader, field, null);
665  }
666 
667  // inherit javadocs
668  public virtual double[] GetDoubles(IndexReader reader, System.String field, Lucene.Net.Search.DoubleParser parser)
669  {
670  return (double[]) caches[typeof(double)].Get(reader, new Entry(field, parser));
671  }
672 
673  internal sealed class DoubleCache:Cache
674  {
675  internal DoubleCache(FieldCache wrapper):base(wrapper)
676  {
677  }
678 
679  protected internal override System.Object CreateValue(IndexReader reader, Entry entryKey)
680  {
681  Entry entry = entryKey;
682  System.String field = entry.field;
683  Lucene.Net.Search.DoubleParser parser = (Lucene.Net.Search.DoubleParser) entry.custom;
684  if (parser == null)
685  {
686  try
687  {
688  return wrapper.GetDoubles(reader, field, Lucene.Net.Search.FieldCache_Fields.DEFAULT_DOUBLE_PARSER);
689  }
690  catch (System.FormatException)
691  {
692  return wrapper.GetDoubles(reader, field, Lucene.Net.Search.FieldCache_Fields.NUMERIC_UTILS_DOUBLE_PARSER);
693  }
694  }
695  double[] retArray = null;
696  TermDocs termDocs = reader.TermDocs();
697  TermEnum termEnum = reader.Terms(new Term(field));
698  try
699  {
700  do
701  {
702  Term term = termEnum.Term;
703  if (term == null || (System.Object) term.Field != (System.Object) field)
704  break;
705  double termval = parser.ParseDouble(term.Text);
706  if (retArray == null)
707  // late init
708  retArray = new double[reader.MaxDoc];
709  termDocs.Seek(termEnum);
710  while (termDocs.Next())
711  {
712  retArray[termDocs.Doc] = termval;
713  }
714  }
715  while (termEnum.Next());
716  }
717  catch (StopFillCacheException)
718  {
719  }
720  finally
721  {
722  termDocs.Close();
723  termEnum.Close();
724  }
725  if (retArray == null)
726  // no values
727  retArray = new double[reader.MaxDoc];
728  return retArray;
729  }
730  }
731 
732 
733  // inherit javadocs
734  public virtual System.String[] GetStrings(IndexReader reader, System.String field)
735  {
736  return (System.String[]) caches[typeof(string)].Get(reader, new Entry(field, (Parser) null));
737  }
738 
739  internal sealed class StringCache:Cache
740  {
741  internal StringCache(FieldCache wrapper):base(wrapper)
742  {
743  }
744 
745  protected internal override System.Object CreateValue(IndexReader reader, Entry entryKey)
746  {
747  System.String field = StringHelper.Intern(entryKey.field);
748  System.String[] retArray = new System.String[reader.MaxDoc];
749  TermDocs termDocs = reader.TermDocs();
750  TermEnum termEnum = reader.Terms(new Term(field));
751  try
752  {
753  do
754  {
755  Term term = termEnum.Term;
756  if (term == null || (System.Object) term.Field != (System.Object) field)
757  break;
758  System.String termval = term.Text;
759  termDocs.Seek(termEnum);
760  while (termDocs.Next())
761  {
762  retArray[termDocs.Doc] = termval;
763  }
764  }
765  while (termEnum.Next());
766  }
767  finally
768  {
769  termDocs.Close();
770  termEnum.Close();
771  }
772  return retArray;
773  }
774  }
775 
776 
777  // inherit javadocs
778  public virtual StringIndex GetStringIndex(IndexReader reader, System.String field)
779  {
780  return (StringIndex) caches[typeof(StringIndex)].Get(reader, new Entry(field, (Parser) null));
781  }
782 
783  internal sealed class StringIndexCache:Cache
784  {
785  internal StringIndexCache(FieldCache wrapper):base(wrapper)
786  {
787  }
788 
789  protected internal override System.Object CreateValue(IndexReader reader, Entry entryKey)
790  {
791  System.String field = StringHelper.Intern(entryKey.field);
792  int[] retArray = new int[reader.MaxDoc];
793  System.String[] mterms = new System.String[reader.MaxDoc + 1];
794  TermDocs termDocs = reader.TermDocs();
795  TermEnum termEnum = reader.Terms(new Term(field));
796  int t = 0; // current term number
797 
798  // an entry for documents that have no terms in this field
799  // should a document with no terms be at top or bottom?
800  // this puts them at the top - if it is changed, FieldDocSortedHitQueue
801  // needs to change as well.
802  mterms[t++] = null;
803 
804  try
805  {
806  do
807  {
808  Term term = termEnum.Term;
809  if (term == null || term.Field != field || t >= mterms.Length) break;
810 
811  // store term text
812  mterms[t] = term.Text;
813 
814  termDocs.Seek(termEnum);
815  while (termDocs.Next())
816  {
817  retArray[termDocs.Doc] = t;
818  }
819 
820  t++;
821  }
822  while (termEnum.Next());
823  }
824  finally
825  {
826  termDocs.Close();
827  termEnum.Close();
828  }
829 
830  if (t == 0)
831  {
832  // if there are no terms, make the term array
833  // have a single null entry
834  mterms = new System.String[1];
835  }
836  else if (t < mterms.Length)
837  {
838  // if there are less terms than documents,
839  // trim off the dead array space
840  System.String[] terms = new System.String[t];
841  Array.Copy(mterms, 0, terms, 0, t);
842  mterms = terms;
843  }
844 
845  StringIndex value_Renamed = new StringIndex(retArray, mterms);
846  return value_Renamed;
847  }
848  }
849 
850  private volatile System.IO.StreamWriter infoStream;
851 
852  public virtual StreamWriter InfoStream
853  {
854  get { return infoStream; }
855  set { infoStream = value; }
856  }
857  }
858 }