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
IndexReader.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 Lucene.Net.Documents;
21 using Document = Lucene.Net.Documents.Document;
22 using FieldSelector = Lucene.Net.Documents.FieldSelector;
23 using Lucene.Net.Store;
24 using Similarity = Lucene.Net.Search.Similarity;
25 
26 namespace Lucene.Net.Index
27 {
28 
29  /// <summary>IndexReader is an abstract class, providing an interface for accessing an
30  /// index. Search of an index is done entirely through this abstract interface,
31  /// so that any subclass which implements it is searchable.
32  /// <p/> Concrete subclasses of IndexReader are usually constructed with a call to
33  /// one of the static <c>open()</c> methods, e.g. <see cref="Open(Lucene.Net.Store.Directory, bool)" />
34  ///.
35  /// <p/> For efficiency, in this API documents are often referred to via
36  /// <i>document numbers</i>, non-negative integers which each name a unique
37  /// document in the index. These document numbers are ephemeral--they may change
38  /// as documents are added to and deleted from an index. Clients should thus not
39  /// rely on a given document having the same number between sessions.
40  /// <p/> An IndexReader can be opened on a directory for which an IndexWriter is
41  /// opened already, but it cannot be used to delete documents from the index then.
42  /// <p/>
43  /// <b>NOTE</b>: for backwards API compatibility, several methods are not listed
44  /// as abstract, but have no useful implementations in this base class and
45  /// instead always throw UnsupportedOperationException. Subclasses are
46  /// strongly encouraged to override these methods, but in many cases may not
47  /// need to.
48  /// <p/>
49  /// <p/>
50  /// <b>NOTE</b>: as of 2.4, it's possible to open a read-only
51  /// IndexReader using the static open methods that accepts the
52  /// boolean readOnly parameter. Such a reader has better
53  /// better concurrency as it's not necessary to synchronize on the
54  /// isDeleted method. You must explicitly specify false
55  /// if you want to make changes with the resulting IndexReader.
56  /// <p/>
57  /// <a name="thread-safety"></a><p/><b>NOTE</b>: <see cref="IndexReader" />
58  /// instances are completely thread
59  /// safe, meaning multiple threads can call any of its methods,
60  /// concurrently. If your application requires external
61  /// synchronization, you should <b>not</b> synchronize on the
62  /// <c>IndexReader</c> instance; use your own
63  /// (non-Lucene) objects instead.
64  /// </summary>
65  public abstract class IndexReader : System.ICloneable, System.IDisposable
66  {
67  private class AnonymousClassFindSegmentsFile : SegmentInfos.FindSegmentsFile
68  {
69  private void InitBlock(Lucene.Net.Store.Directory directory2)
70  {
71  this.directory2 = directory2;
72  }
73  private Lucene.Net.Store.Directory directory2;
74  internal AnonymousClassFindSegmentsFile(Lucene.Net.Store.Directory directory2, Lucene.Net.Store.Directory Param1):base(Param1)
75  {
76  InitBlock(directory2);
77  }
78  public override System.Object DoBody(System.String segmentFileName)
79  {
80  return (long) directory2.FileModified(segmentFileName);
81  }
82  }
83 
84  /// <summary> Constants describing field properties, for example used for
85  /// <see cref="IndexReader.GetFieldNames(FieldOption)" />.
86  /// </summary>
87  public sealed class FieldOption
88  {
89  private readonly System.String option;
90  internal FieldOption()
91  {
92  }
93  internal FieldOption(System.String option)
94  {
95  this.option = option;
96  }
97  public override System.String ToString()
98  {
99  return this.option;
100  }
101  /// <summary>All fields </summary>
102  public static readonly FieldOption ALL = new FieldOption("ALL");
103  /// <summary>All indexed fields </summary>
104  public static readonly FieldOption INDEXED = new FieldOption("INDEXED");
105  /// <summary>All fields that store payloads </summary>
106  public static readonly FieldOption STORES_PAYLOADS = new FieldOption("STORES_PAYLOADS");
107  /// <summary>All fields that omit tf </summary>
108  public static readonly FieldOption OMIT_TERM_FREQ_AND_POSITIONS = new FieldOption("OMIT_TERM_FREQ_AND_POSITIONS");
109  /// <summary>All fields which are not indexed </summary>
110  public static readonly FieldOption UNINDEXED = new FieldOption("UNINDEXED");
111  /// <summary>All fields which are indexed with termvectors enabled </summary>
112  public static readonly FieldOption INDEXED_WITH_TERMVECTOR = new FieldOption("INDEXED_WITH_TERMVECTOR");
113  /// <summary>All fields which are indexed but don't have termvectors enabled </summary>
114  public static readonly FieldOption INDEXED_NO_TERMVECTOR = new FieldOption("INDEXED_NO_TERMVECTOR");
115  /// <summary>All fields with termvectors enabled. Please note that only standard termvector fields are returned </summary>
116  public static readonly FieldOption TERMVECTOR = new FieldOption("TERMVECTOR");
117  /// <summary>All fields with termvectors with position values enabled </summary>
118  public static readonly FieldOption TERMVECTOR_WITH_POSITION = new FieldOption("TERMVECTOR_WITH_POSITION");
119  /// <summary>All fields with termvectors with offset values enabled </summary>
120  public static readonly FieldOption TERMVECTOR_WITH_OFFSET = new FieldOption("TERMVECTOR_WITH_OFFSET");
121  /// <summary>All fields with termvectors with offset values and position values enabled </summary>
122  public static readonly FieldOption TERMVECTOR_WITH_POSITION_OFFSET = new FieldOption("TERMVECTOR_WITH_POSITION_OFFSET");
123  }
124 
125  private bool closed;
126  protected internal bool hasChanges;
127 
128  private int refCount;
129 
130  protected internal static int DEFAULT_TERMS_INDEX_DIVISOR = 1;
131 
132  /// <summary>Expert: returns the current refCount for this reader </summary>
133  public virtual int RefCount
134  {
135  get
136  {
137  lock (this)
138  {
139  return refCount;
140  }
141  }
142  }
143 
144  /// <summary> Expert: increments the refCount of this IndexReader
145  /// instance. RefCounts are used to determine when a
146  /// reader can be closed safely, i.e. as soon as there are
147  /// no more references. Be sure to always call a
148  /// corresponding <see cref="DecRef" />, in a finally clause;
149  /// otherwise the reader may never be closed. Note that
150  /// <see cref="Close" /> simply calls decRef(), which means that
151  /// the IndexReader will not really be closed until <see cref="DecRef" />
152  /// has been called for all outstanding
153  /// references.
154  ///
155  /// </summary>
156  /// <seealso cref="DecRef">
157  /// </seealso>
158  public virtual void IncRef()
159  {
160  lock (this)
161  {
162  System.Diagnostics.Debug.Assert(refCount > 0);
163  EnsureOpen();
164  refCount++;
165  }
166  }
167 
168  /// <summary> Expert: decreases the refCount of this IndexReader
169  /// instance. If the refCount drops to 0, then pending
170  /// changes (if any) are committed to the index and this
171  /// reader is closed.
172  ///
173  /// </summary>
174  /// <throws> IOException in case an IOException occurs in commit() or doClose() </throws>
175  /// <summary>
176  /// </summary>
177  /// <seealso cref="IncRef">
178  /// </seealso>
179  public virtual void DecRef()
180  {
181  lock (this)
182  {
183  System.Diagnostics.Debug.Assert(refCount > 0);
184  EnsureOpen();
185  if (refCount == 1)
186  {
187  Commit();
188  DoClose();
189  }
190  refCount--;
191  }
192  }
193 
194  protected internal IndexReader()
195  {
196  refCount = 1;
197  }
198 
199  /// <throws> AlreadyClosedException if this IndexReader is closed </throws>
200  protected internal void EnsureOpen()
201  {
202  if (refCount <= 0)
203  {
204  throw new AlreadyClosedException("this IndexReader is closed");
205  }
206  }
207 
208  /// <summary>Returns an IndexReader reading the index in the given
209  /// Directory. You should pass readOnly=true, since it
210  /// gives much better concurrent performance, unless you
211  /// intend to do write operations (delete documents or
212  /// change norms) with the reader.
213  /// </summary>
214  /// <param name="directory">the index directory</param>
215  /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader</param>
216  /// <exception cref="CorruptIndexException">CorruptIndexException if the index is corrupt</exception>
217  /// <exception cref="System.IO.IOException">IOException if there is a low-level IO error</exception>
218  public static IndexReader Open(Directory directory, bool readOnly)
219  {
220  return Open(directory, null, null, readOnly, DEFAULT_TERMS_INDEX_DIVISOR);
221  }
222 
223  /// <summary>Expert: returns an IndexReader reading the index in the given
224  /// <see cref="IndexCommit" />. You should pass readOnly=true, since it
225  /// gives much better concurrent performance, unless you
226  /// intend to do write operations (delete documents or
227  /// change norms) with the reader.
228  /// </summary>
229  /// <param name="commit">the commit point to open
230  /// </param>
231  /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
232  /// </param>
233  /// <throws> CorruptIndexException if the index is corrupt </throws>
234  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
235  public static IndexReader Open(IndexCommit commit, bool readOnly)
236  {
237  return Open(commit.Directory, null, commit, readOnly, DEFAULT_TERMS_INDEX_DIVISOR);
238  }
239 
240  /// <summary>Expert: returns an IndexReader reading the index in
241  /// the given Directory, with a custom <see cref="IndexDeletionPolicy" />
242  ///. You should pass readOnly=true,
243  /// since it gives much better concurrent performance,
244  /// unless you intend to do write operations (delete
245  /// documents or change norms) with the reader.
246  /// </summary>
247  /// <param name="directory">the index directory
248  /// </param>
249  /// <param name="deletionPolicy">a custom deletion policy (only used
250  /// if you use this reader to perform deletes or to set
251  /// norms); see <see cref="IndexWriter" /> for details.
252  /// </param>
253  /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
254  /// </param>
255  /// <throws> CorruptIndexException if the index is corrupt </throws>
256  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
257  public static IndexReader Open(Directory directory, IndexDeletionPolicy deletionPolicy, bool readOnly)
258  {
259  return Open(directory, deletionPolicy, null, readOnly, DEFAULT_TERMS_INDEX_DIVISOR);
260  }
261 
262  /// <summary>Expert: returns an IndexReader reading the index in
263  /// the given Directory, with a custom <see cref="IndexDeletionPolicy" />
264  ///. You should pass readOnly=true,
265  /// since it gives much better concurrent performance,
266  /// unless you intend to do write operations (delete
267  /// documents or change norms) with the reader.
268  /// </summary>
269  /// <param name="directory">the index directory
270  /// </param>
271  /// <param name="deletionPolicy">a custom deletion policy (only used
272  /// if you use this reader to perform deletes or to set
273  /// norms); see <see cref="IndexWriter" /> for details.
274  /// </param>
275  /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
276  /// </param>
277  /// <param name="termInfosIndexDivisor">Subsamples which indexed
278  /// terms are loaded into RAM. This has the same effect as <see>
279  /// <cref>IndexWriter.SetTermIndexInterval</cref>
280  /// </see> except that setting
281  /// must be done at indexing time while this setting can be
282  /// set per reader. When set to N, then one in every
283  /// N*termIndexInterval terms in the index is loaded into
284  /// memory. By setting this to a value > 1 you can reduce
285  /// memory usage, at the expense of higher latency when
286  /// loading a TermInfo. The default value is 1. Set this
287  /// to -1 to skip loading the terms index entirely.
288  /// </param>
289  /// <throws> CorruptIndexException if the index is corrupt </throws>
290  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
291  public static IndexReader Open(Directory directory, IndexDeletionPolicy deletionPolicy, bool readOnly, int termInfosIndexDivisor)
292  {
293  return Open(directory, deletionPolicy, null, readOnly, termInfosIndexDivisor);
294  }
295 
296  /// <summary>Expert: returns an IndexReader reading the index in
297  /// the given Directory, using a specific commit and with
298  /// a custom <see cref="IndexDeletionPolicy" />. You should pass
299  /// readOnly=true, since it gives much better concurrent
300  /// performance, unless you intend to do write operations
301  /// (delete documents or change norms) with the reader.
302  /// </summary>
303  /// <param name="commit">the specific <see cref="IndexCommit" /> to open;
304  /// see <see cref="IndexReader.ListCommits" /> to list all commits
305  /// in a directory
306  /// </param>
307  /// <param name="deletionPolicy">a custom deletion policy (only used
308  /// if you use this reader to perform deletes or to set
309  /// norms); see <see cref="IndexWriter" /> for details.
310  /// </param>
311  /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
312  /// </param>
313  /// <throws> CorruptIndexException if the index is corrupt </throws>
314  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
315  public static IndexReader Open(IndexCommit commit, IndexDeletionPolicy deletionPolicy, bool readOnly)
316  {
317  return Open(commit.Directory, deletionPolicy, commit, readOnly, DEFAULT_TERMS_INDEX_DIVISOR);
318  }
319 
320  /// <summary>Expert: returns an IndexReader reading the index in
321  /// the given Directory, using a specific commit and with
322  /// a custom <see cref="IndexDeletionPolicy" />. You should pass
323  /// readOnly=true, since it gives much better concurrent
324  /// performance, unless you intend to do write operations
325  /// (delete documents or change norms) with the reader.
326  /// </summary>
327  /// <param name="commit">the specific <see cref="IndexCommit" /> to open;
328  /// see <see cref="IndexReader.ListCommits" /> to list all commits
329  /// in a directory
330  /// </param>
331  /// <param name="deletionPolicy">a custom deletion policy (only used
332  /// if you use this reader to perform deletes or to set
333  /// norms); see <see cref="IndexWriter" /> for details.
334  /// </param>
335  /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
336  /// </param>
337  /// <param name="termInfosIndexDivisor">Subsambles which indexed
338  /// terms are loaded into RAM. This has the same effect as <see>
339  /// <cref>IndexWriter.SetTermIndexInterval</cref>
340  /// </see> except that setting
341  /// must be done at indexing time while this setting can be
342  /// set per reader. When set to N, then one in every
343  /// N*termIndexInterval terms in the index is loaded into
344  /// memory. By setting this to a value > 1 you can reduce
345  /// memory usage, at the expense of higher latency when
346  /// loading a TermInfo. The default value is 1. Set this
347  /// to -1 to skip loading the terms index entirely.
348  /// </param>
349  /// <throws> CorruptIndexException if the index is corrupt </throws>
350  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
351  public static IndexReader Open(IndexCommit commit, IndexDeletionPolicy deletionPolicy, bool readOnly, int termInfosIndexDivisor)
352  {
353  return Open(commit.Directory, deletionPolicy, commit, readOnly, termInfosIndexDivisor);
354  }
355 
356  private static IndexReader Open(Directory directory, IndexDeletionPolicy deletionPolicy, IndexCommit commit, bool readOnly, int termInfosIndexDivisor)
357  {
358  return DirectoryReader.Open(directory, deletionPolicy, commit, readOnly, termInfosIndexDivisor);
359  }
360 
361  /// <summary> Refreshes an IndexReader if the index has changed since this instance
362  /// was (re)opened.
363  /// <p/>
364  /// Opening an IndexReader is an expensive operation. This method can be used
365  /// to refresh an existing IndexReader to reduce these costs. This method
366  /// tries to only load segments that have changed or were created after the
367  /// IndexReader was (re)opened.
368  /// <p/>
369  /// If the index has not changed since this instance was (re)opened, then this
370  /// call is a NOOP and returns this instance. Otherwise, a new instance is
371  /// returned. The old instance is <b>not</b> closed and remains usable.<br/>
372  /// <p/>
373  /// If the reader is reopened, even though they share
374  /// resources internally, it's safe to make changes
375  /// (deletions, norms) with the new reader. All shared
376  /// mutable state obeys "copy on write" semantics to ensure
377  /// the changes are not seen by other readers.
378  /// <p/>
379  /// You can determine whether a reader was actually reopened by comparing the
380  /// old instance with the instance returned by this method:
381  /// <code>
382  /// IndexReader reader = ...
383  /// ...
384  /// IndexReader newReader = r.reopen();
385  /// if (newReader != reader) {
386  /// ... // reader was reopened
387  /// reader.close();
388  /// }
389  /// reader = newReader;
390  /// ...
391  /// </code>
392  ///
393  /// Be sure to synchronize that code so that other threads,
394  /// if present, can never use reader after it has been
395  /// closed and before it's switched to newReader.
396  ///
397  /// <p/><b>NOTE</b>: If this reader is a near real-time
398  /// reader (obtained from <see cref="IndexWriter.GetReader()" />,
399  /// reopen() will simply call writer.getReader() again for
400  /// you, though this may change in the future.
401  ///
402  /// </summary>
403  /// <throws> CorruptIndexException if the index is corrupt </throws>
404  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
405  public virtual IndexReader Reopen()
406  {
407  lock (this)
408  {
409  throw new NotSupportedException("This reader does not support reopen().");
410  }
411  }
412 
413 
414  /// <summary>Just like <see cref="Reopen()" />, except you can change the
415  /// readOnly of the original reader. If the index is
416  /// unchanged but readOnly is different then a new reader
417  /// will be returned.
418  /// </summary>
419  public virtual IndexReader Reopen(bool openReadOnly)
420  {
421  lock (this)
422  {
423  throw new NotSupportedException("This reader does not support reopen().");
424  }
425  }
426 
427  /// <summary>Expert: reopen this reader on a specific commit point.
428  /// This always returns a readOnly reader. If the
429  /// specified commit point matches what this reader is
430  /// already on, and this reader is already readOnly, then
431  /// this same instance is returned; if it is not already
432  /// readOnly, a readOnly clone is returned.
433  /// </summary>
434  public virtual IndexReader Reopen(IndexCommit commit)
435  {
436  lock (this)
437  {
438  throw new NotSupportedException("This reader does not support reopen(IndexCommit).");
439  }
440  }
441 
442  /// <summary> Efficiently clones the IndexReader (sharing most
443  /// internal state).
444  /// <p/>
445  /// On cloning a reader with pending changes (deletions,
446  /// norms), the original reader transfers its write lock to
447  /// the cloned reader. This means only the cloned reader
448  /// may make further changes to the index, and commit the
449  /// changes to the index on close, but the old reader still
450  /// reflects all changes made up until it was cloned.
451  /// <p/>
452  /// Like <see cref="Reopen()" />, it's safe to make changes to
453  /// either the original or the cloned reader: all shared
454  /// mutable state obeys "copy on write" semantics to ensure
455  /// the changes are not seen by other readers.
456  /// <p/>
457  /// </summary>
458  /// <throws> CorruptIndexException if the index is corrupt </throws>
459  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
460  public virtual System.Object Clone()
461  {
462  throw new System.NotSupportedException("This reader does not implement clone()");
463  }
464 
465  /// <summary> Clones the IndexReader and optionally changes readOnly. A readOnly
466  /// reader cannot open a writeable reader.
467  /// </summary>
468  /// <throws> CorruptIndexException if the index is corrupt </throws>
469  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
470  public virtual IndexReader Clone(bool openReadOnly)
471  {
472  lock (this)
473  {
474  throw new System.NotSupportedException("This reader does not implement clone()");
475  }
476  }
477 
478  /// <summary> Returns the directory associated with this index. The Default
479  /// implementation returns the directory specified by subclasses when
480  /// delegating to the IndexReader(Directory) constructor, or throws an
481  /// UnsupportedOperationException if one was not specified.
482  /// </summary>
483  /// <throws> UnsupportedOperationException if no directory </throws>
484  public virtual Directory Directory()
485  {
486  EnsureOpen();
487  throw new NotSupportedException("This reader does not support this method.");
488  }
489 
490  /// <summary> Returns the time the index in the named directory was last modified.
491  /// Do not use this to check whether the reader is still up-to-date, use
492  /// <see cref="IsCurrent()" /> instead.
493  /// </summary>
494  /// <throws> CorruptIndexException if the index is corrupt </throws>
495  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
496  public static long LastModified(Directory directory2)
497  {
498  return (long) ((System.Int64) new AnonymousClassFindSegmentsFile(directory2, directory2).Run());
499  }
500 
501  /// <summary> Reads version number from segments files. The version number is
502  /// initialized with a timestamp and then increased by one for each change of
503  /// the index.
504  ///
505  /// </summary>
506  /// <param name="directory">where the index resides.
507  /// </param>
508  /// <returns> version number.
509  /// </returns>
510  /// <throws> CorruptIndexException if the index is corrupt </throws>
511  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
512  public static long GetCurrentVersion(Directory directory)
513  {
514  return SegmentInfos.ReadCurrentVersion(directory);
515  }
516 
517  /// <summary> Reads commitUserData, previously passed to
518  /// <see cref="IndexWriter.Commit(System.Collections.Generic.IDictionary{string, string})" />,
519  /// from current index segments file. This will return null if
520  /// <see cref="IndexWriter.Commit(System.Collections.Generic.IDictionary{string, string})" />
521  /// has never been called for this index.
522  /// </summary>
523  /// <param name="directory">where the index resides.
524  /// </param>
525  /// <returns> commit userData.
526  /// </returns>
527  /// <throws> CorruptIndexException if the index is corrupt </throws>
528  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
529  /// <summary>
530  /// </summary>
531  /// <seealso cref="GetCommitUserData(Store.Directory)">
532  /// </seealso>
533  public static System.Collections.Generic.IDictionary<string, string> GetCommitUserData(Directory directory)
534  {
535  return SegmentInfos.ReadCurrentUserData(directory);
536  }
537 
538  /// <summary> Version number when this IndexReader was opened. Not implemented in the
539  /// IndexReader base class.
540  ///
541  /// <p/>
542  /// If this reader is based on a Directory (ie, was created by calling
543  /// <see cref="Open(Lucene.Net.Store.Directory, bool)" />, or <see cref="Reopen()" />
544  /// on a reader based on a Directory), then
545  /// this method returns the version recorded in the commit that the reader
546  /// opened. This version is advanced every time <see cref="IndexWriter.Commit()" /> is
547  /// called.
548  /// <p/>
549  ///
550  /// <p/>
551  /// If instead this reader is a near real-time reader (ie, obtained by a call
552  /// to <see cref="IndexWriter.GetReader()" />, or by calling <see cref="Reopen()" /> on a near
553  /// real-time reader), then this method returns the version of the last
554  /// commit done by the writer. Note that even as further changes are made
555  /// with the writer, the version will not changed until a commit is
556  /// completed. Thus, you should not rely on this method to determine when a
557  /// near real-time reader should be opened. Use <see cref="IsCurrent" /> instead.
558  /// <p/>
559  ///
560  /// </summary>
561  /// <throws> UnsupportedOperationException </throws>
562  /// <summary> unless overridden in subclass
563  /// </summary>
564  public virtual long Version
565  {
566  get { throw new System.NotSupportedException("This reader does not support this method."); }
567  }
568 
569  /// <summary> Retrieve the String userData optionally passed to
570  /// <see cref="IndexWriter.Commit(System.Collections.Generic.IDictionary{string, string})" />.
571  /// This will return null if
572  /// <see cref="IndexWriter.Commit(System.Collections.Generic.IDictionary{string, string})" />
573  /// has never been called for this index.
574  /// </summary>
575  /// <seealso cref="GetCommitUserData(Store.Directory)">
576  /// </seealso>
577  public virtual IDictionary<string, string> CommitUserData
578  {
579  get { throw new System.NotSupportedException("This reader does not support this method."); }
580  }
581 
582  /// <summary> Check whether any new changes have occurred to the index since this
583  /// reader was opened.
584  ///
585  /// <p/>
586  /// If this reader is based on a Directory (ie, was created by calling
587  /// <see>
588  /// <cref>Open(Store.Directory)</cref>
589  /// </see> , or <see cref="Reopen()" /> on a reader based on a Directory), then
590  /// this method checks if any further commits (see <see cref="IndexWriter.Commit()" />
591  /// have occurred in that directory).
592  /// <p/>
593  ///
594  /// <p/>
595  /// If instead this reader is a near real-time reader (ie, obtained by a call
596  /// to <see cref="IndexWriter.GetReader()" />, or by calling <see cref="Reopen()" /> on a near
597  /// real-time reader), then this method checks if either a new commmit has
598  /// occurred, or any new uncommitted changes have taken place via the writer.
599  /// Note that even if the writer has only performed merging, this method will
600  /// still return false.
601  /// <p/>
602  ///
603  /// <p/>
604  /// In any event, if this returns false, you should call <see cref="Reopen()" /> to
605  /// get a new reader that sees the changes.
606  /// <p/>
607  ///
608  /// </summary>
609  /// <throws> CorruptIndexException if the index is corrupt </throws>
610  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
611  /// <throws> UnsupportedOperationException unless overridden in subclass </throws>
612  public virtual bool IsCurrent()
613  {
614  throw new NotSupportedException("This reader does not support this method.");
615  }
616 
617  /// <summary> Checks is the index is optimized (if it has a single segment and
618  /// no deletions). Not implemented in the IndexReader base class.
619  /// </summary>
620  /// <returns> &amp;lt;c&amp;gt;true&amp;lt;/c&amp;gt; if the index is optimized; &amp;lt;c&amp;gt;false&amp;lt;/c&amp;gt; otherwise </returns>
621  /// <throws> UnsupportedOperationException unless overridden in subclass </throws>
622  public virtual bool IsOptimized()
623  {
624  throw new NotSupportedException("This reader does not support this method.");
625  }
626 
627  /// <summary> Return an array of term frequency vectors for the specified document.
628  /// The array contains a vector for each vectorized field in the document.
629  /// Each vector contains terms and frequencies for all terms in a given vectorized field.
630  /// If no such fields existed, the method returns null. The term vectors that are
631  /// returned may either be of type <see cref="ITermFreqVector" />
632  /// or of type <see cref="TermPositionVector" /> if
633  /// positions or offsets have been stored.
634  ///
635  /// </summary>
636  /// <param name="docNumber">document for which term frequency vectors are returned
637  /// </param>
638  /// <returns> array of term frequency vectors. May be null if no term vectors have been
639  /// stored for the specified document.
640  /// </returns>
641  /// <throws> IOException if index cannot be accessed </throws>
642  /// <seealso cref="Lucene.Net.Documents.Field.TermVector">
643  /// </seealso>
644  abstract public ITermFreqVector[] GetTermFreqVectors(int docNumber);
645 
646 
647  /// <summary> Return a term frequency vector for the specified document and field. The
648  /// returned vector contains terms and frequencies for the terms in
649  /// the specified field of this document, if the field had the storeTermVector
650  /// flag set. If termvectors had been stored with positions or offsets, a
651  /// <see cref="TermPositionVector" /> is returned.
652  ///
653  /// </summary>
654  /// <param name="docNumber">document for which the term frequency vector is returned
655  /// </param>
656  /// <param name="field">field for which the term frequency vector is returned.
657  /// </param>
658  /// <returns> term frequency vector May be null if field does not exist in the specified
659  /// document or term vector was not stored.
660  /// </returns>
661  /// <throws> IOException if index cannot be accessed </throws>
662  /// <seealso cref="Lucene.Net.Documents.Field.TermVector">
663  /// </seealso>
664  abstract public ITermFreqVector GetTermFreqVector(int docNumber, String field);
665 
666  /// <summary> Load the Term Vector into a user-defined data structure instead of relying on the parallel arrays of
667  /// the <see cref="ITermFreqVector" />.
668  /// </summary>
669  /// <param name="docNumber">The number of the document to load the vector for
670  /// </param>
671  /// <param name="field">The name of the field to load
672  /// </param>
673  /// <param name="mapper">The <see cref="TermVectorMapper" /> to process the vector. Must not be null
674  /// </param>
675  /// <throws> IOException if term vectors cannot be accessed or if they do not exist on the field and doc. specified. </throws>
676  /// <summary>
677  /// </summary>
678  abstract public void GetTermFreqVector(int docNumber, String field, TermVectorMapper mapper);
679 
680  /// <summary> Map all the term vectors for all fields in a Document</summary>
681  /// <param name="docNumber">The number of the document to load the vector for
682  /// </param>
683  /// <param name="mapper">The <see cref="TermVectorMapper" /> to process the vector. Must not be null
684  /// </param>
685  /// <throws> IOException if term vectors cannot be accessed or if they do not exist on the field and doc. specified. </throws>
686  abstract public void GetTermFreqVector(int docNumber, TermVectorMapper mapper);
687 
688  /// <summary> Returns <c>true</c> if an index exists at the specified directory.
689  /// If the directory does not exist or if there is no index in it.
690  /// </summary>
691  /// <param name="directory">the directory to check for an index
692  /// </param>
693  /// <returns> <c>true</c> if an index exists; <c>false</c> otherwise
694  /// </returns>
695  /// <throws> IOException if there is a problem with accessing the index </throws>
696  public static bool IndexExists(Directory directory)
697  {
698  return SegmentInfos.GetCurrentSegmentGeneration(directory) != - 1;
699  }
700 
701  /// <summary>Returns the number of documents in this index. </summary>
702  [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
703  public abstract int NumDocs();
704 
705  /// <summary>Returns one greater than the largest possible document number.
706  /// This may be used to, e.g., determine how big to allocate an array which
707  /// will have an element for every document number in an index.
708  /// </summary>
709  public abstract int MaxDoc { get; }
710 
711  /// <summary>Returns the number of deleted documents. </summary>
712  public virtual int NumDeletedDocs
713  {
714  get { return MaxDoc - NumDocs(); }
715  }
716 
717  /// <summary> Returns the stored fields of the <c>n</c><sup>th</sup>
718  /// <c>Document</c> in this index.
719  /// <p/>
720  /// <b>NOTE:</b> for performance reasons, this method does not check if the
721  /// requested document is deleted, and therefore asking for a deleted document
722  /// may yield unspecified results. Usually this is not required, however you
723  /// can call <see cref="IsDeleted(int)" /> with the requested document ID to verify
724  /// the document is not deleted.
725  ///
726  /// </summary>
727  /// <throws> CorruptIndexException if the index is corrupt </throws>
728  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
729  public virtual Document Document(int n)
730  {
731  EnsureOpen();
732  return Document(n, null);
733  }
734 
735  /// <summary> Returns the stored fields of the <c>n</c><sup>th</sup>
736  /// <c>Document</c> in this index.
737  /// <p/>
738  /// <b>NOTE:</b> for performance reasons, this method does not check if the
739  /// requested document is deleted, and therefore asking for a deleted document
740  /// may yield unspecified results. Usually this is not required, however you
741  /// can call <see cref="IsDeleted(int)" /> with the requested document ID to verify
742  /// the document is not deleted.
743  ///
744  /// </summary>
745  /// <throws> CorruptIndexException if the index is corrupt </throws>
746  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
747  public Document this[int doc]
748  {
749  get { return Document(doc); }
750  }
751 
752  /// <summary> Get the <see cref="Lucene.Net.Documents.Document" /> at the <c>n</c>
753  /// <sup>th</sup> position. The <see cref="FieldSelector" /> may be used to determine
754  /// what <see cref="Lucene.Net.Documents.Field" />s to load and how they should
755  /// be loaded. <b>NOTE:</b> If this Reader (more specifically, the underlying
756  /// <c>FieldsReader</c>) is closed before the lazy
757  /// <see cref="Lucene.Net.Documents.Field" /> is loaded an exception may be
758  /// thrown. If you want the value of a lazy
759  /// <see cref="Lucene.Net.Documents.Field" /> to be available after closing you
760  /// must explicitly load it or fetch the Document again with a new loader.
761  /// <p/>
762  /// <b>NOTE:</b> for performance reasons, this method does not check if the
763  /// requested document is deleted, and therefore asking for a deleted document
764  /// may yield unspecified results. Usually this is not required, however you
765  /// can call <see cref="IsDeleted(int)" /> with the requested document ID to verify
766  /// the document is not deleted.
767  ///
768  /// </summary>
769  /// <param name="n">Get the document at the <c>n</c><sup>th</sup> position
770  /// </param>
771  /// <param name="fieldSelector">The <see cref="FieldSelector" /> to use to determine what
772  /// Fields should be loaded on the Document. May be null, in which case
773  /// all Fields will be loaded.
774  /// </param>
775  /// <returns> The stored fields of the
776  /// <see cref="Lucene.Net.Documents.Document" /> at the nth position
777  /// </returns>
778  /// <throws> CorruptIndexException if the index is corrupt </throws>
779  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
780  /// <seealso cref="IFieldable">
781  /// </seealso>
782  /// <seealso cref="Lucene.Net.Documents.FieldSelector">
783  /// </seealso>
784  /// <seealso cref="Lucene.Net.Documents.SetBasedFieldSelector">
785  /// </seealso>
786  /// <seealso cref="Lucene.Net.Documents.LoadFirstFieldSelector">
787  /// </seealso>
788  // TODO (1.5): When we convert to JDK 1.5 make this Set<String>
789  public abstract Document Document(int n, FieldSelector fieldSelector);
790 
791  /// <summary>Returns true if document <i>n</i> has been deleted </summary>
792  public abstract bool IsDeleted(int n);
793 
794  /// <summary>Returns true if any documents have been deleted </summary>
795  public abstract bool HasDeletions { get; }
796 
797  /// <summary>Returns true if there are norms stored for this field. </summary>
798  public virtual bool HasNorms(System.String field)
799  {
800  // backward compatible implementation.
801  // SegmentReader has an efficient implementation.
802  EnsureOpen();
803  return Norms(field) != null;
804  }
805 
806  /// <summary>
807  /// Returns the byte-encoded normalization factor for the named field of
808  /// every document. This is used by the search code to score documents.
809  /// </summary>
810  /// <seealso cref="Lucene.Net.Documents.AbstractField.Boost" />
811  public abstract byte[] Norms(System.String field);
812 
813  /// <summary>
814  /// Reads the byte-encoded normalization factor for the named field of every
815  /// document. This is used by the search code to score documents.
816  /// </summary>
817  /// <seealso cref="Lucene.Net.Documents.AbstractField.Boost" />
818  public abstract void Norms(System.String field, byte[] bytes, int offset);
819 
820  /// <summary>Expert: Resets the normalization factor for the named field of the named
821  /// document. The norm represents the product of the field's <see cref="IFieldable.Boost">boost</see>
822  /// and its <see cref="Similarity.LengthNorm(String,int)">length normalization</see>. Thus, to preserve the length normalization
823  /// values when resetting this, one should base the new value upon the old.
824  ///
825  /// <b>NOTE:</b> If this field does not store norms, then
826  /// this method call will silently do nothing.
827  /// </summary>
828  /// <seealso cref="Norms(String)" />
829  /// <seealso cref="Similarity.DecodeNorm(byte)" />
830  /// <exception cref="StaleReaderException">
831  /// If the index has changed since this reader was opened
832  /// </exception>
833  /// <exception cref="CorruptIndexException">
834  /// If the index is corrupt
835  /// </exception>
836  /// <exception cref="LockObtainFailedException">
837  /// If another writer has this index open (<c>write.lock</c> could not be obtained)
838  /// </exception>
839  /// <exception cref="System.IO.IOException">
840  /// If there is a low-level IO error
841  /// </exception>
842  public virtual void SetNorm(int doc, String field, byte value)
843  {
844  lock (this)
845  {
846  EnsureOpen();
847  AcquireWriteLock();
848  hasChanges = true;
849  DoSetNorm(doc, field, value);
850  }
851  }
852 
853  /// <summary>Implements setNorm in subclass.</summary>
854  protected internal abstract void DoSetNorm(int doc, System.String field, byte value_Renamed);
855 
856  /// <summary>
857  /// Expert: Resets the normalization factor for the named field of the named document.
858  /// </summary>
859  /// <seealso cref="Norms(String)" />
860  /// <seealso cref="Similarity.DecodeNorm(byte)" />
861  /// <exception cref="StaleReaderException">
862  /// If the index has changed since this reader was opened
863  /// </exception>
864  /// <exception cref="CorruptIndexException">
865  /// If the index is corrupt
866  /// </exception>
867  /// <exception cref="LockObtainFailedException">
868  /// If another writer has this index open (<c>write.lock</c> could not be obtained)
869  /// </exception>
870  /// <exception cref="System.IO.IOException">
871  /// If there is a low-level IO error
872  /// </exception>
873  public virtual void SetNorm(int doc, System.String field, float value)
874  {
875  EnsureOpen();
876  SetNorm(doc, field, Similarity.EncodeNorm(value));
877  }
878 
879  /// <summary>Returns an enumeration of all the terms in the index. The
880  /// enumeration is ordered by Term.compareTo(). Each term is greater
881  /// than all that precede it in the enumeration. Note that after
882  /// calling terms(), <see cref="TermEnum.Next()" /> must be called
883  /// on the resulting enumeration before calling other methods such as
884  /// <see cref="TermEnum.Term" />.
885  /// </summary>
886  /// <exception cref="System.IO.IOException">
887  /// If there is a low-level IO error
888  /// </exception>
889  public abstract TermEnum Terms();
890 
891  /// <summary>Returns an enumeration of all terms starting at a given term. If
892  /// the given term does not exist, the enumeration is positioned at the
893  /// first term greater than the supplied term. The enumeration is
894  /// ordered by Term.compareTo(). Each term is greater than all that
895  /// precede it in the enumeration.
896  /// </summary>
897  /// <exception cref="System.IO.IOException">
898  /// If there is a low-level IO error
899  /// </exception>
900  public abstract TermEnum Terms(Term t);
901 
902  /// <summary>Returns the number of documents containing the term <c>t</c>.</summary>
903  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
904  public abstract int DocFreq(Term t);
905 
906  /// <summary>Returns an enumeration of all the documents which contain
907  /// <c>term</c>. For each document, the document number, the frequency of
908  /// the term in that document is also provided, for use in
909  /// search scoring. If term is null, then all non-deleted
910  /// docs are returned with freq=1.
911  /// Thus, this method implements the mapping:
912  /// <p/><list>
913  /// Term &#160;&#160; =&gt; &#160;&#160; &lt;docNum, freq&gt;<sup>*</sup>
914  /// </list>
915  /// <p/>The enumeration is ordered by document number. Each document number
916  /// is greater than all that precede it in the enumeration.
917  /// </summary>
918  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
919  public virtual TermDocs TermDocs(Term term)
920  {
921  EnsureOpen();
922  TermDocs termDocs = TermDocs();
923  termDocs.Seek(term);
924  return termDocs;
925  }
926 
927  /// <summary>Returns an unpositioned <see cref="Lucene.Net.Index.TermDocs" /> enumerator.</summary>
928  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
929  public abstract TermDocs TermDocs();
930 
931  /// <summary>Returns an enumeration of all the documents which contain
932  /// <c>term</c>. For each document, in addition to the document number
933  /// and frequency of the term in that document, a list of all of the ordinal
934  /// positions of the term in the document is available. Thus, this method
935  /// implements the mapping:
936  ///
937  /// <p/><list>
938  /// Term &#160;&#160; =&gt; &#160;&#160; &lt;docNum, freq,
939  /// &lt;pos<sub>1</sub>, pos<sub>2</sub>, ...
940  /// pos<sub>freq-1</sub>&gt;
941  /// &gt;<sup>*</sup>
942  /// </list>
943  /// <p/> This positional information facilitates phrase and proximity searching.
944  /// <p/>The enumeration is ordered by document number. Each document number is
945  /// greater than all that precede it in the enumeration.
946  /// </summary>
947  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
948  public virtual TermPositions TermPositions(Term term)
949  {
950  EnsureOpen();
951  TermPositions termPositions = TermPositions();
952  termPositions.Seek(term);
953  return termPositions;
954  }
955 
956  /// <summary>Returns an unpositioned <see cref="Lucene.Net.Index.TermPositions" /> enumerator.</summary>
957  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
958  public abstract TermPositions TermPositions();
959 
960 
961 
962  /// <summary>
963  /// Deletes the document numbered <c>docNum</c>. Once a document is
964  /// deleted it will not appear in TermDocs or TermPostitions enumerations.
965  /// Attempts to read its field with the <see cref="Document(int)" />
966  /// method will result in an error. The presence of this document may still be
967  /// reflected in the <see cref="DocFreq" /> statistic, though
968  /// this will be corrected eventually as the index is further modified.
969  /// </summary>
970  /// <exception cref="StaleReaderException">
971  /// If the index has changed since this reader was opened
972  /// </exception>
973  /// <exception cref="CorruptIndexException">If the index is corrupt</exception>
974  /// <exception cref="LockObtainFailedException">
975  /// If another writer has this index open (<c>write.lock</c> could not be obtained)
976  /// </exception>
977  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
978  public virtual void DeleteDocument(int docNum)
979  {
980  lock (this)
981  {
982  EnsureOpen();
983  AcquireWriteLock();
984  hasChanges = true;
985  DoDelete(docNum);
986  }
987  }
988 
989 
990  /// <summary>Implements deletion of the document numbered <c>docNum</c>.
991  /// Applications should call <see cref="DeleteDocument(int)" /> or <see cref="DeleteDocuments(Term)" />.
992  /// </summary>
993  protected internal abstract void DoDelete(int docNum);
994 
995 
996  /// <summary>
997  /// Deletes all documents that have a given <c>term</c> indexed.
998  /// This is useful if one uses a document field to hold a unique ID string for
999  /// the document. Then to delete such a document, one merely constructs a
1000  /// term with the appropriate field and the unique ID string as its text and
1001  /// passes it to this method.
1002  /// See <see cref="DeleteDocument(int)" /> for information about when this deletion will
1003  /// become effective.
1004  /// </summary>
1005  /// <returns>The number of documents deleted</returns>
1006  /// <exception cref="StaleReaderException">
1007  /// If the index has changed since this reader was opened
1008  /// </exception>
1009  /// <exception cref="CorruptIndexException">If the index is corrupt</exception>
1010  /// <exception cref="LockObtainFailedException">
1011  /// If another writer has this index open (<c>write.lock</c> could not be obtained)
1012  /// </exception>
1013  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
1014  public virtual int DeleteDocuments(Term term)
1015  {
1016  EnsureOpen();
1017  TermDocs docs = TermDocs(term);
1018  if (docs == null)
1019  return 0;
1020  int n = 0;
1021  try
1022  {
1023  while (docs.Next())
1024  {
1025  DeleteDocument(docs.Doc);
1026  n++;
1027  }
1028  }
1029  finally
1030  {
1031  docs.Close();
1032  }
1033  return n;
1034  }
1035 
1036  /// <summary>Undeletes all documents currently marked as deleted in this index.
1037  ///
1038  /// </summary>
1039  /// <exception cref="StaleReaderException">
1040  /// If the index has changed since this reader was opened
1041  /// </exception>
1042  /// <exception cref="CorruptIndexException">If the index is corrupt</exception>
1043  /// <exception cref="LockObtainFailedException">
1044  /// If another writer has this index open (<c>write.lock</c> could not be obtained)
1045  /// </exception>
1046  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
1047  public virtual void UndeleteAll()
1048  {
1049  lock (this)
1050  {
1051  EnsureOpen();
1052  AcquireWriteLock();
1053  hasChanges = true;
1054  DoUndeleteAll();
1055  }
1056  }
1057 
1058  /// <summary>Implements actual undeleteAll() in subclass. </summary>
1059  protected internal abstract void DoUndeleteAll();
1060 
1061  /// <summary>
1062  /// Does nothing by default. Subclasses that require a write lock for
1063  /// index modifications must implement this method.
1064  /// </summary>
1065  protected internal virtual void AcquireWriteLock()
1066  {
1067  lock (this)
1068  {
1069  /* NOOP */
1070  }
1071  }
1072 
1073  /// <summary> </summary>
1074  /// <exception cref="System.IO.IOException" />
1075  public void Flush()
1076  {
1077  lock (this)
1078  {
1079  EnsureOpen();
1080  Commit();
1081  }
1082  }
1083 
1084  /// <param name="commitUserData">Opaque Map (String -> String)
1085  /// that's recorded into the segments file in the index,
1086  /// and retrievable by <see cref="IndexReader.GetCommitUserData" />
1087  /// </param>
1088  /// <exception cref="System.IO.IOException" />
1089  public void Flush(IDictionary<string, string> commitUserData)
1090  {
1091  lock (this)
1092  {
1093  EnsureOpen();
1094  Commit(commitUserData);
1095  }
1096  }
1097 
1098  /// <summary> Commit changes resulting from delete, undeleteAll, or
1099  /// setNorm operations
1100  ///
1101  /// If an exception is hit, then either no changes or all
1102  /// changes will have been committed to the index
1103  /// (transactional semantics).
1104  /// </summary>
1105  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
1106  public /*protected internal*/ void Commit()
1107  {
1108  lock (this)
1109  {
1110  Commit(null);
1111  }
1112  }
1113 
1114  /// <summary> Commit changes resulting from delete, undeleteAll, or
1115  /// setNorm operations
1116  ///
1117  /// If an exception is hit, then either no changes or all
1118  /// changes will have been committed to the index
1119  /// (transactional semantics).
1120  /// </summary>
1121  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
1122  public void Commit(IDictionary<string, string> commitUserData)
1123  {
1124  lock (this)
1125  {
1126  if (hasChanges)
1127  {
1128  DoCommit(commitUserData);
1129  }
1130  hasChanges = false;
1131  }
1132  }
1133 
1134  /// <summary>Implements commit.</summary>
1135  protected internal abstract void DoCommit(IDictionary<string, string> commitUserData);
1136 
1137  [Obsolete("Use Dispose() instead")]
1138  public void Close()
1139  {
1140  Dispose();
1141  }
1142 
1143  /// <summary> Closes files associated with this index.
1144  /// Also saves any new deletions to disk.
1145  /// No other methods should be called after this has been called.
1146  /// </summary>
1147  /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
1148  public void Dispose()
1149  {
1150  Dispose(true);
1151  }
1152 
1153  protected virtual void Dispose(bool disposing)
1154  {
1155  if (disposing)
1156  {
1157  lock (this)
1158  {
1159  if (!closed)
1160  {
1161  DecRef();
1162  closed = true;
1163  }
1164  }
1165  }
1166  }
1167 
1168  /// <summary>Implements close. </summary>
1169  protected internal abstract void DoClose();
1170 
1171 
1172  /// <summary> Get a list of unique field names that exist in this index and have the specified
1173  /// field option information.
1174  /// </summary>
1175  /// <param name="fldOption">specifies which field option should be available for the returned fields
1176  /// </param>
1177  /// <returns> Collection of Strings indicating the names of the fields.
1178  /// </returns>
1179  /// <seealso cref="IndexReader.FieldOption">
1180  /// </seealso>
1181  public abstract ICollection<string> GetFieldNames(FieldOption fldOption);
1182 
1183  /// <summary> Expert: return the IndexCommit that this reader has
1184  /// opened. This method is only implemented by those
1185  /// readers that correspond to a Directory with its own
1186  /// segments_N file.
1187  ///
1188  /// <p/><b>WARNING</b>: this API is new and experimental and
1189  /// may suddenly change.<p/>
1190  /// </summary>
1191  public virtual IndexCommit IndexCommit
1192  {
1193  get { throw new NotSupportedException("This reader does not support this method."); }
1194  }
1195 
1196  /// <summary> Prints the filename and size of each file within a given compound file.
1197  /// Add the -extract flag to extract files to the current working directory.
1198  /// In order to make the extracted version of the index work, you have to copy
1199  /// the segments file from the compound index into the directory where the extracted files are stored.
1200  /// </summary>
1201  /// <param name="args">Usage: Lucene.Net.Index.IndexReader [-extract] &lt;cfsfile&gt;
1202  /// </param>
1203  [STAThread]
1204  public static void Main(String[] args)
1205  {
1206  System.String filename = null;
1207  bool extract = false;
1208 
1209  foreach (string t in args)
1210  {
1211  if (t.Equals("-extract"))
1212  {
1213  extract = true;
1214  }
1215  else if (filename == null)
1216  {
1217  filename = t;
1218  }
1219  }
1220 
1221  if (filename == null)
1222  {
1223  System.Console.Out.WriteLine("Usage: Lucene.Net.Index.IndexReader [-extract] <cfsfile>");
1224  return ;
1225  }
1226 
1227  Directory dir = null;
1228  CompoundFileReader cfr = null;
1229 
1230  try
1231  {
1232  var file = new System.IO.FileInfo(filename);
1233  System.String dirname = new System.IO.FileInfo(file.FullName).DirectoryName;
1234  filename = file.Name;
1235  dir = FSDirectory.Open(new System.IO.DirectoryInfo(dirname));
1236  cfr = new CompoundFileReader(dir, filename);
1237 
1238  System.String[] files = cfr.ListAll();
1239  System.Array.Sort(files); // sort the array of filename so that the output is more readable
1240 
1241  foreach (string t in files)
1242  {
1243  long len = cfr.FileLength(t);
1244 
1245  if (extract)
1246  {
1247  System.Console.Out.WriteLine("extract " + t + " with " + len + " bytes to local directory...");
1248  IndexInput ii = cfr.OpenInput(t);
1249 
1250  var f = new System.IO.FileStream(t, System.IO.FileMode.Create);
1251 
1252  // read and write with a small buffer, which is more effectiv than reading byte by byte
1253  var buffer = new byte[1024];
1254  int chunk = buffer.Length;
1255  while (len > 0)
1256  {
1257  var bufLen = (int) System.Math.Min(chunk, len);
1258  ii.ReadBytes(buffer, 0, bufLen);
1259  f.Write(buffer, 0, bufLen);
1260  len -= bufLen;
1261  }
1262 
1263  f.Close();
1264  ii.Close();
1265  }
1266  else
1267  System.Console.Out.WriteLine(t + ": " + len + " bytes");
1268  }
1269  }
1270  catch (System.IO.IOException ioe)
1271  {
1272  System.Console.Error.WriteLine(ioe.StackTrace);
1273  }
1274  finally
1275  {
1276  try
1277  {
1278  if (dir != null)
1279  dir.Close();
1280  if (cfr != null)
1281  cfr.Close();
1282  }
1283  catch (System.IO.IOException ioe)
1284  {
1285  System.Console.Error.WriteLine(ioe.StackTrace);
1286  }
1287  }
1288  }
1289 
1290  /// <summary>Returns all commit points that exist in the Directory.
1291  /// Normally, because the default is <see cref="KeepOnlyLastCommitDeletionPolicy" />
1292  ///, there would be only
1293  /// one commit point. But if you're using a custom <see cref="IndexDeletionPolicy" />
1294  /// then there could be many commits.
1295  /// Once you have a given commit, you can open a reader on
1296  /// it by calling <see cref="IndexReader.Open(IndexCommit,bool)" />
1297  /// There must be at least one commit in
1298  /// the Directory, else this method throws <see cref="System.IO.IOException" />.
1299  /// Note that if a commit is in
1300  /// progress while this method is running, that commit
1301  /// may or may not be returned array.
1302  /// </summary>
1303  public static System.Collections.Generic.ICollection<IndexCommit> ListCommits(Directory dir)
1304  {
1305  return DirectoryReader.ListCommits(dir);
1306  }
1307 
1308  /// <summary>Expert: returns the sequential sub readers that this
1309  /// reader is logically composed of. For example,
1310  /// IndexSearcher uses this API to drive searching by one
1311  /// sub reader at a time. If this reader is not composed
1312  /// of sequential child readers, it should return null.
1313  /// If this method returns an empty array, that means this
1314  /// reader is a null reader (for example a MultiReader
1315  /// that has no sub readers).
1316  /// <p/>
1317  /// NOTE: You should not try using sub-readers returned by
1318  /// this method to make any changes (setNorm, deleteDocument,
1319  /// etc.). While this might succeed for one composite reader
1320  /// (like MultiReader), it will most likely lead to index
1321  /// corruption for other readers (like DirectoryReader obtained
1322  /// through <see cref="IndexReader.Open(Lucene.Net.Store.Directory,bool)" />. Use the parent reader directly.
1323  /// </summary>
1324  public virtual IndexReader[] GetSequentialSubReaders()
1325  {
1326  return null;
1327  }
1328 
1329  /// <summary>Expert</summary>
1330  public virtual object FieldCacheKey
1331  {
1332  get { return this; }
1333  }
1334 
1335  /* Expert. Warning: this returns null if the reader has
1336  * no deletions
1337  */
1338 
1339  public virtual object DeletesCacheKey
1340  {
1341  get { return this; }
1342  }
1343 
1344  /// <summary>Returns the number of unique terms (across all fields)
1345  /// in this reader.
1346  ///
1347  /// This method returns long, even though internally
1348  /// Lucene cannot handle more than 2^31 unique terms, for
1349  /// a possible future when this limitation is removed.
1350  ///
1351  /// </summary>
1352  /// <throws> UnsupportedOperationException if this count </throws>
1353  /// <summary> cannot be easily determined (eg Multi*Readers).
1354  /// Instead, you should call <see cref="GetSequentialSubReaders" />
1355  /// and ask each sub reader for
1356  /// its unique term count.
1357  /// </summary>
1358  public virtual long UniqueTermCount
1359  {
1360  get { throw new System.NotSupportedException("this reader does not implement getUniqueTermCount()"); }
1361  }
1362 
1363  /// <summary>
1364  /// For IndexReader implementations that use
1365  /// TermInfosReader to read terms, this returns the
1366  /// current indexDivisor as specified when the reader was
1367  /// opened.
1368  /// </summary>
1369  public virtual int TermInfosIndexDivisor
1370  {
1371  get { throw new NotSupportedException("This reader does not support this method."); }
1372  }
1373  }
1374 }