2 * Copyright 2004 The Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 using Document
= Lucene
.Net
.Documents
.Document
;
18 using Field
= Lucene
.Net
.Documents
.Field
;
19 using Similarity
= Lucene
.Net
.Search
.Similarity
;
20 using Directory
= Lucene
.Net
.Store
.Directory
;
21 using FSDirectory
= Lucene
.Net
.Store
.FSDirectory
;
22 using IndexInput
= Lucene
.Net
.Store
.IndexInput
;
23 using Lock
= Lucene
.Net
.Store
.Lock
;
24 namespace Lucene
.Net
.Index
27 /// <summary>IndexReader is an abstract class, providing an interface for accessing an
28 /// index. Search of an index is done entirely through this abstract interface,
29 /// so that any subclass which implements it is searchable.
30 /// <p> Concrete subclasses of IndexReader are usually constructed with a call to
31 /// one of the static <code>open()</code> methods, e.g. {@link #Open(String)}.
32 /// <p> For efficiency, in this API documents are often referred to via
33 /// <i>document numbers</i>, non-negative integers which each name a unique
34 /// document in the index. These document numbers are ephemeral--they may change
35 /// as documents are added to and deleted from an index. Clients should thus not
36 /// rely on a given document having the same number between sessions.
38 /// <author> Doug Cutting
40 /// <version> $Id: IndexReader.cs,v 1.3 2005/10/06 19:29:55 dsd Exp $
42 public abstract class IndexReader
44 private class AnonymousClassWith
: Lock
.With
46 private void InitBlock(Lucene
.Net
.Store
.Directory directory
, bool closeDirectory
)
48 this.directory
= directory
;
49 this.closeDirectory
= closeDirectory
;
51 private Lucene
.Net
.Store
.Directory directory
;
52 private bool closeDirectory
;
53 internal AnonymousClassWith(Lucene
.Net
.Store
.Directory directory
, bool closeDirectory
, Lucene
.Net
.Store
.Lock Param1
, long Param2
) : base(Param1
, Param2
)
55 InitBlock(directory
, closeDirectory
);
57 public override System
.Object
DoBody()
59 SegmentInfos infos
= new SegmentInfos();
60 infos
.Read(directory
);
64 return SegmentReader
.Get(infos
, infos
.Info(0), closeDirectory
);
66 IndexReader
[] readers
= new IndexReader
[infos
.Count
];
67 for (int i
= 0; i
< infos
.Count
; i
++)
68 readers
[i
] = SegmentReader
.Get(infos
.Info(i
));
69 return new MultiReader(directory
, infos
, closeDirectory
, readers
);
72 private class AnonymousClassWith1
: Lock
.With
74 private void InitBlock(IndexReader enclosingInstance
)
76 this.enclosingInstance
= enclosingInstance
;
78 private IndexReader enclosingInstance
;
79 public IndexReader Enclosing_Instance
83 return enclosingInstance
;
87 internal AnonymousClassWith1(IndexReader enclosingInstance
, Lucene
.Net
.Store
.Lock Param1
, long Param2
) : base(Param1
, Param2
)
89 InitBlock(enclosingInstance
);
91 public override System
.Object
DoBody()
93 Enclosing_Instance
.DoCommit();
94 Enclosing_Instance
.segmentInfos
.Write(Enclosing_Instance
.directory
);
99 public sealed class FieldOption
101 private System
.String option
;
102 internal FieldOption()
105 internal FieldOption(System
.String option
)
107 this.option
= option
;
109 public override System
.String
ToString()
114 public static readonly FieldOption ALL
= new FieldOption("ALL");
115 // all indexed fields
116 public static readonly FieldOption INDEXED
= new FieldOption("INDEXED");
117 // all fields which are not indexed
118 public static readonly FieldOption UNINDEXED
= new FieldOption("UNINDEXED");
119 // all fields which are indexed with termvectors enables
120 public static readonly FieldOption INDEXED_WITH_TERMVECTOR
= new FieldOption("INDEXED_WITH_TERMVECTOR");
121 // all fields which are indexed but don't have termvectors enabled
122 public static readonly FieldOption INDEXED_NO_TERMVECTOR
= new FieldOption("INDEXED_NO_TERMVECTOR");
123 // all fields where termvectors are enabled. Please note that only standard termvector fields are returned
124 public static readonly FieldOption TERMVECTOR
= new FieldOption("TERMVECTOR");
125 // all field with termvectors wiht positions enabled
126 public static readonly FieldOption TERMVECTOR_WITH_POSITION
= new FieldOption("TERMVECTOR_WITH_POSITION");
127 // all fields where termvectors with offset position are set
128 public static readonly FieldOption TERMVECTOR_WITH_OFFSET
= new FieldOption("TERMVECTOR_WITH_OFFSET");
129 // all fields where termvectors with offset and position values set
130 public static readonly FieldOption TERMVECTOR_WITH_POSITION_OFFSET
= new FieldOption("TERMVECTOR_WITH_POSITION_OFFSET");
133 /// <summary> Constructor used if IndexReader is not owner of its directory.
134 /// This is used for IndexReaders that are used within other IndexReaders that take care or locking directories.
137 /// <param name="directory">Directory where IndexReader files reside.
139 protected internal IndexReader(Directory directory
)
141 this.directory
= directory
;
144 /// <summary> Constructor used if IndexReader is owner of its directory.
145 /// If IndexReader is owner of its directory, it locks its directory in case of write operations.
148 /// <param name="directory">Directory where IndexReader files reside.
150 /// <param name="segmentInfos">Used for write-l
152 /// <param name="">closeDirectory
154 internal IndexReader(Directory directory
, SegmentInfos segmentInfos
, bool closeDirectory
)
156 Init(directory
, segmentInfos
, closeDirectory
, true);
159 internal virtual void Init(Directory directory
, SegmentInfos segmentInfos
, bool closeDirectory
, bool directoryOwner
)
161 this.directory
= directory
;
162 this.segmentInfos
= segmentInfos
;
163 this.directoryOwner
= directoryOwner
;
164 this.closeDirectory
= closeDirectory
;
167 private Directory directory
;
168 private bool directoryOwner
;
169 private bool closeDirectory
;
171 private SegmentInfos segmentInfos
;
172 private Lock writeLock
;
174 private bool hasChanges
;
177 /// <summary>Returns an IndexReader reading the index in an FSDirectory in the named
180 public static IndexReader
Open(System
.String path
)
182 return Open(FSDirectory
.GetDirectory(path
, false), true);
185 /// <summary>Returns an IndexReader reading the index in an FSDirectory in the named
188 public static IndexReader
Open(System
.IO
.FileInfo path
)
190 return Open(FSDirectory
.GetDirectory(path
, false), true);
193 /// <summary>Returns an IndexReader reading the index in the given Directory. </summary>
194 public static IndexReader
Open(Directory directory
)
196 return Open(directory
, false);
199 private static IndexReader
Open(Directory directory
, bool closeDirectory
)
203 // in- & inter-process sync
204 return (IndexReader
) new AnonymousClassWith(directory
, closeDirectory
, directory
.MakeLock(IndexWriter
.COMMIT_LOCK_NAME
), IndexWriter
.COMMIT_LOCK_TIMEOUT
).Run();
208 /// <summary>Returns the directory this index resides in. </summary>
209 public virtual Directory
Directory()
214 /// <summary> Returns the time the index in the named directory was last modified.
216 /// <p>Synchronization of IndexReader and IndexWriter instances is
217 /// no longer done via time stamps of the segments file since the time resolution
218 /// depends on the hardware platform. Instead, a version number is maintained
219 /// within the segments file, which is incremented everytime when the index is
223 /// <deprecated> Replaced by {@link #GetCurrentVersion(String)}
226 public static long LastModified(System
.String directory
)
228 return LastModified(new System
.IO
.FileInfo(directory
));
231 /// <summary> Returns the time the index in the named directory was last modified.
233 /// <p>Synchronization of IndexReader and IndexWriter instances is
234 /// no longer done via time stamps of the segments file since the time resolution
235 /// depends on the hardware platform. Instead, a version number is maintained
236 /// within the segments file, which is incremented everytime when the index is
240 /// <deprecated> Replaced by {@link #GetCurrentVersion(File)}
243 public static long LastModified(System
.IO
.FileInfo directory
)
245 return FSDirectory
.FileModified(directory
, "segments");
248 /// <summary> Returns the time the index in the named directory was last modified.
250 /// <p>Synchronization of IndexReader and IndexWriter instances is
251 /// no longer done via time stamps of the segments file since the time resolution
252 /// depends on the hardware platform. Instead, a version number is maintained
253 /// within the segments file, which is incremented everytime when the index is
257 /// <deprecated> Replaced by {@link #GetCurrentVersion(Directory)}
260 public static long LastModified(Directory directory
)
262 return directory
.FileModified("segments");
265 /// <summary> Reads version number from segments files. The version number counts the
266 /// number of changes of the index.
269 /// <param name="directory">where the index resides.
271 /// <returns> version number.
273 /// <throws> IOException if segments file cannot be read </throws>
274 public static long GetCurrentVersion(System
.String directory
)
276 return GetCurrentVersion(new System
.IO
.FileInfo(directory
));
279 /// <summary> Reads version number from segments files. The version number counts the
280 /// number of changes of the index.
283 /// <param name="directory">where the index resides.
285 /// <returns> version number.
287 /// <throws> IOException if segments file cannot be read </throws>
288 public static long GetCurrentVersion(System
.IO
.FileInfo directory
)
290 Directory dir
= FSDirectory
.GetDirectory(directory
, false);
291 long version
= GetCurrentVersion(dir
);
296 /// <summary> Reads version number from segments files. The version number counts the
297 /// number of changes of the index.
300 /// <param name="directory">where the index resides.
302 /// <returns> version number.
304 /// <throws> IOException if segments file cannot be read. </throws>
305 public static long GetCurrentVersion(Directory directory
)
307 return SegmentInfos
.ReadCurrentVersion(directory
);
310 /// <summary> Return an array of term frequency vectors for the specified document.
311 /// The array contains a vector for each vectorized field in the document.
312 /// Each vector contains terms and frequencies for all terms in a given vectorized field.
313 /// If no such fields existed, the method returns null. The term vectors that are
314 /// returned my either be of type TermFreqVector or of type TermPositionsVector if
315 /// positions or offsets have been stored.
318 /// <param name="docNumber">document for which term frequency vectors are returned
320 /// <returns> array of term frequency vectors. May be null if no term vectors have been
321 /// stored for the specified document.
323 /// <throws> IOException if index cannot be accessed </throws>
324 /// <seealso cref="Lucene.Net.document.Field.TermVector">
326 abstract public TermFreqVector
[] GetTermFreqVectors(int docNumber
);
329 /// <summary> Return a term frequency vector for the specified document and field. The
330 /// returned vector contains terms and frequencies for the terms in
331 /// the specified field of this document, if the field had the storeTermVector
332 /// flag set. If termvectors had been stored with positions or offsets, a
333 /// TermPositionsVector is returned.
336 /// <param name="docNumber">document for which the term frequency vector is returned
338 /// <param name="field">field for which the term frequency vector is returned.
340 /// <returns> term frequency vector May be null if field does not exist in the specified
341 /// document or term vector was not stored.
343 /// <throws> IOException if index cannot be accessed </throws>
344 /// <seealso cref="Lucene.Net.document.Field.TermVector">
346 abstract public TermFreqVector
GetTermFreqVector(int docNumber
, System
.String field
);
348 /// <summary> Returns <code>true</code> if an index exists at the specified directory.
349 /// If the directory does not exist or if there is no index in it.
350 /// <code>false</code> is returned.
352 /// <param name="directory">the directory to check for an index
354 /// <returns> <code>true</code> if an index exists; <code>false</code> otherwise
356 public static bool IndexExists(System
.String directory
)
359 if (System
.IO
.File
.Exists((new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
, "segments"))).FullName
))
362 tmpBool
= System
.IO
.Directory
.Exists((new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
, "segments"))).FullName
);
366 /// <summary> Returns <code>true</code> if an index exists at the specified directory.
367 /// If the directory does not exist or if there is no index in it.
369 /// <param name="directory">the directory to check for an index
371 /// <returns> <code>true</code> if an index exists; <code>false</code> otherwise
373 public static bool IndexExists(System
.IO
.FileInfo directory
)
376 if (System
.IO
.File
.Exists((new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, "segments"))).FullName
))
379 tmpBool
= System
.IO
.Directory
.Exists((new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, "segments"))).FullName
);
383 /// <summary> Returns <code>true</code> if an index exists at the specified directory.
384 /// If the directory does not exist or if there is no index in it.
386 /// <param name="directory">the directory to check for an index
388 /// <returns> <code>true</code> if an index exists; <code>false</code> otherwise
390 /// <throws> IOException if there is a problem with accessing the index </throws>
391 public static bool IndexExists(Directory directory
)
393 return directory
.FileExists("segments");
396 /// <summary>Returns the number of documents in this index. </summary>
397 public abstract int NumDocs();
399 /// <summary>Returns one greater than the largest possible document number.
400 /// This may be used to, e.g., determine how big to allocate an array which
401 /// will have an element for every document number in an index.
403 public abstract int MaxDoc();
405 /// <summary>Returns the stored fields of the <code>n</code><sup>th</sup>
406 /// <code>Document</code> in this index.
408 public abstract Document
Document(int n
);
410 /// <summary>Returns true if document <i>n</i> has been deleted </summary>
411 public abstract bool IsDeleted(int n
);
413 /// <summary>Returns true if any documents have been deleted </summary>
414 public abstract bool HasDeletions();
416 /// <summary>Returns the byte-encoded normalization factor for the named Field of
417 /// every document. This is used by the search code to score documents.
420 /// <seealso cref="Field#SetBoost(float)">
422 public abstract byte[] Norms(System
.String field
);
424 /// <summary>Reads the byte-encoded normalization factor for the named Field of every
425 /// document. This is used by the search code to score documents.
428 /// <seealso cref="Field#SetBoost(float)">
430 public abstract void Norms(System
.String field
, byte[] bytes
, int offset
);
432 /// <summary>Expert: Resets the normalization factor for the named Field of the named
433 /// document. The norm represents the product of the Field's {@link
434 /// Field#SetBoost(float) boost} and its {@link Similarity#LengthNorm(String,
435 /// int) length normalization}. Thus, to preserve the length normalization
436 /// values when resetting this, one should base the new value upon the old.
439 /// <seealso cref="#Norms(String)">
441 /// <seealso cref="Similarity#DecodeNorm(byte)">
443 public void SetNorm(int doc
, System
.String field
, byte value_Renamed
)
449 DoSetNorm(doc
, field
, value_Renamed
);
454 /// <summary>Implements setNorm in subclass.</summary>
455 protected internal abstract void DoSetNorm(int doc
, System
.String field
, byte value_Renamed
);
457 /// <summary>Expert: Resets the normalization factor for the named Field of the named
461 /// <seealso cref="#Norms(String)">
463 /// <seealso cref="Similarity#DecodeNorm(byte)">
465 public virtual void SetNorm(int doc
, System
.String field
, float value_Renamed
)
467 SetNorm(doc
, field
, Similarity
.EncodeNorm(value_Renamed
));
471 /// <summary>Returns an enumeration of all the terms in the index.
472 /// The enumeration is ordered by Term.compareTo(). Each term
473 /// is greater than all that precede it in the enumeration.
475 public abstract TermEnum
Terms();
477 /// <summary>Returns an enumeration of all terms after a given term.
478 /// The enumeration is ordered by Term.compareTo(). Each term
479 /// is greater than all that precede it in the enumeration.
481 public abstract TermEnum
Terms(Term t
);
483 /// <summary>Returns the number of documents containing the term <code>t</code>. </summary>
484 public abstract int DocFreq(Term t
);
486 /// <summary>Returns an enumeration of all the documents which contain
487 /// <code>term</code>. For each document, the document number, the frequency of
488 /// the term in that document is also provided, for use in search scoring.
489 /// Thus, this method implements the mapping:
491 /// Term => <docNum, freq><sup>*</sup>
493 /// <p>The enumeration is ordered by document number. Each document number
494 /// is greater than all that precede it in the enumeration.
496 public virtual TermDocs
TermDocs(Term term
)
498 TermDocs termDocs
= TermDocs();
503 /// <summary>Returns an unpositioned {@link TermDocs} enumerator. </summary>
504 public abstract TermDocs
TermDocs();
506 /// <summary>Returns an enumeration of all the documents which contain
507 /// <code>term</code>. For each document, in addition to the document number
508 /// and frequency of the term in that document, a list of all of the ordinal
509 /// positions of the term in the document is available. Thus, this method
510 /// implements the mapping:
512 /// Term => <docNum, freq,
513 /// <pos<sub>1</sub>, pos<sub>2</sub>, ...
514 /// pos<sub>freq-1</sub>>
517 /// <p> This positional information faciliates phrase and proximity searching.
518 /// <p>The enumeration is ordered by document number. Each document number is
519 /// greater than all that precede it in the enumeration.
521 public virtual TermPositions
TermPositions(Term term
)
523 TermPositions termPositions
= TermPositions();
524 termPositions
.Seek(term
);
525 return termPositions
;
528 /// <summary>Returns an unpositioned {@link TermPositions} enumerator. </summary>
529 public abstract TermPositions
TermPositions();
531 /// <summary> Tries to acquire the WriteLock on this directory.
532 /// this method is only valid if this IndexReader is directory owner.
535 /// <throws> IOException If WriteLock cannot be acquired. </throws>
536 private void AquireWriteLock()
539 throw new System
.IO
.IOException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations");
541 if (this.writeLock
== null)
543 Lock writeLock
= directory
.MakeLock(IndexWriter
.WRITE_LOCK_NAME
);
544 if (!writeLock
.Obtain(IndexWriter
.WRITE_LOCK_TIMEOUT
))
547 throw new System
.IO
.IOException("Index locked for write: " + writeLock
);
549 this.writeLock
= writeLock
;
551 // we have to check whether index has changed since this reader was opened.
552 // if so, this reader is no longer valid for deletion
553 if (SegmentInfos
.ReadCurrentVersion(directory
) > segmentInfos
.GetVersion())
556 this.writeLock
.Release();
557 this.writeLock
= null;
558 throw new System
.IO
.IOException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations");
563 /// <summary>Deletes the document numbered <code>docNum</code>. Once a document is
564 /// deleted it will not appear in TermDocs or TermPostitions enumerations.
565 /// Attempts to read its Field with the {@link #document}
566 /// method will result in an error. The presence of this document may still be
567 /// reflected in the {@link #docFreq} statistic, though
568 /// this will be corrected eventually as the index is further modified.
570 public void Delete(int docNum
)
581 /// <summary>Implements deletion of the document numbered <code>docNum</code>.
582 /// Applications should call {@link #Delete(int)} or {@link #Delete(Term)}.
584 protected internal abstract void DoDelete(int docNum
);
586 /// <summary>Deletes all documents containing <code>term</code>.
587 /// This is useful if one uses a document Field to hold a unique ID string for
588 /// the document. Then to delete such a document, one merely constructs a
589 /// term with the appropriate Field and the unique ID string as its text and
590 /// passes it to this method. Returns the number of documents deleted.
591 /// See {@link #Delete(int)} for information about when this deletion will
592 /// become effective.
594 public int Delete(Term term
)
596 TermDocs docs
= TermDocs(term
);
615 /// <summary>Undeletes all documents currently marked as deleted in this index.</summary>
616 public void UndeleteAll()
627 /// <summary>Implements actual undeleteAll() in subclass. </summary>
628 protected internal abstract void DoUndeleteAll();
630 /// <summary> Commit changes resulting from delete, undeleteAll, or setNorm operations
633 /// <throws> IOException </throws>
634 protected internal void Commit()
644 // in- & inter-process sync
645 new AnonymousClassWith1(this, directory
.MakeLock(IndexWriter
.COMMIT_LOCK_NAME
), IndexWriter
.COMMIT_LOCK_TIMEOUT
).Run();
647 if (writeLock
!= null)
649 writeLock
.Release(); // release write lock
660 /// <summary>Implements commit. </summary>
661 protected internal abstract void DoCommit();
663 /// <summary> Closes files associated with this index.
664 /// Also saves any new deletions to disk.
665 /// No other methods should be called after this has been called.
675 System
.GC
.SuppressFinalize(this);
679 /// <summary>Implements close. </summary>
680 protected internal abstract void DoClose();
682 /// <summary>Release the write lock, if needed. </summary>
685 if (writeLock
!= null)
687 writeLock
.Release(); // release write lock
692 /// <summary> Returns a list of all unique field names that exist in the index pointed
693 /// to by this IndexReader.
695 /// <returns> Collection of Strings indicating the names of the fields
697 /// <throws> IOException if there is a problem with accessing the index </throws>
700 /// <deprecated> Replaced by {@link #GetFieldNames(IndexReader.FieldOption)}
702 public abstract System
.Collections
.ICollection
GetFieldNames();
704 /// <summary> Returns a list of all unique Field names that exist in the index pointed
705 /// to by this IndexReader. The boolean argument specifies whether the fields
706 /// returned are indexed or not.
708 /// <param name="indexed"><code>true</code> if only indexed fields should be returned;
709 /// <code>false</code> if only unindexed fields should be returned.
711 /// <returns> Collection of Strings indicating the names of the fields
713 /// <throws> IOException if there is a problem with accessing the index </throws>
716 /// <deprecated> Replaced by {@link #GetFieldNames(IndexReader.FieldOption)}
718 public abstract System
.Collections
.ICollection
GetFieldNames(bool indexed
);
720 /// <summary> </summary>
721 /// <param name="storedTermVector">if true, returns only Indexed fields that have term vector info,
722 /// else only indexed fields without term vector info
724 /// <returns> Collection of Strings indicating the names of the fields
727 /// <deprecated> Replaced by {@link #GetFieldNames(IndexReader.FieldOption)}
729 public virtual System
.Collections
.ICollection
GetIndexedFieldNames(bool storedTermVector
)
731 if (storedTermVector
)
733 System
.Collections
.Hashtable fieldSet
= new System
.Collections
.Hashtable();
734 foreach (object item
in GetIndexedFieldNames(Field
.TermVector
.YES
))
736 if (fieldSet
.ContainsKey(item
) == false)
738 fieldSet
.Add(item
, item
);
741 foreach (object item
in GetIndexedFieldNames(Field
.TermVector
.WITH_POSITIONS
))
743 if (fieldSet
.ContainsKey(item
) == false)
745 fieldSet
.Add(item
, item
);
748 foreach (object item
in GetIndexedFieldNames(Field
.TermVector
.WITH_OFFSETS
))
750 if (fieldSet
.ContainsKey(item
) == false)
752 fieldSet
.Add(item
, item
);
755 foreach (object item
in GetIndexedFieldNames(Field
.TermVector
.WITH_POSITIONS_OFFSETS
))
757 if (fieldSet
.ContainsKey(item
) == false)
759 fieldSet
.Add(item
, item
);
765 return GetIndexedFieldNames(Field
.TermVector
.NO
);
768 /// <summary> Get a list of unique field names that exist in this index, are indexed, and have
769 /// the specified term vector information.
772 /// <param name="tvSpec">specifies which term vector information should be available for the fields
774 /// <returns> Collection of Strings indicating the names of the fields
777 /// <deprecated> Replaced by {@link #GetFieldNames(IndexReader.FieldOption)}
779 public abstract System
.Collections
.ICollection
GetIndexedFieldNames(Field
.TermVector tvSpec
);
781 /// <summary> Get a list of unique field names that exist in this index and have the specified
782 /// field option information.
784 /// <param name="fldOption">specifies which field option should be available for the returned fields
786 /// <returns> Collection of Strings indicating the names of the fields.
788 /// <seealso cref="IndexReader.FieldOption">
790 public abstract System
.Collections
.ICollection
GetFieldNames(FieldOption fldOption
);
792 /// <summary> Returns <code>true</code> iff the index in the named directory is
793 /// currently locked.
795 /// <param name="directory">the directory to check for a lock
797 /// <throws> IOException if there is a problem with accessing the index </throws>
798 public static bool IsLocked(Directory directory
)
800 return directory
.MakeLock(IndexWriter
.WRITE_LOCK_NAME
).IsLocked() || directory
.MakeLock(IndexWriter
.COMMIT_LOCK_NAME
).IsLocked();
803 /// <summary> Returns <code>true</code> iff the index in the named directory is
804 /// currently locked.
806 /// <param name="directory">the directory to check for a lock
808 /// <throws> IOException if there is a problem with accessing the index </throws>
809 public static bool IsLocked(System
.String directory
)
811 Directory dir
= FSDirectory
.GetDirectory(directory
, false);
812 bool result
= IsLocked(dir
);
817 /// <summary> Forcibly unlocks the index in the named directory.
819 /// Caution: this should only be used by failure recovery code,
820 /// when it is known that no other process nor thread is in fact
821 /// currently accessing this index.
823 public static void Unlock(Directory directory
)
825 directory
.MakeLock(IndexWriter
.WRITE_LOCK_NAME
).Release();
826 directory
.MakeLock(IndexWriter
.COMMIT_LOCK_NAME
).Release();
829 /// <summary> Prints the filename and size of each file within a given compound file.
830 /// Add the -extract flag to extract files to the current working directory.
831 /// In order to make the extracted version of the index work, you have to copy
832 /// the segments file from the compound index into the directory where the extracted files are stored.
834 /// <param name="">args
837 public static void Main(System
.String
[] args
)
839 System
.String dirname
= null, filename
= null;
840 bool extract
= false;
842 for (int i
= 0; i
< args
.Length
; ++i
)
844 if (args
[i
].Equals("-extract"))
848 else if (dirname
== null)
852 else if (filename
== null)
858 if (dirname
== null || filename
== null)
860 System
.Console
.Out
.WriteLine("Usage: Lucene.Net.index.IndexReader [-extract] <directory> <cfsfile>");
864 Directory dir
= null;
865 CompoundFileReader cfr
= null;
869 dir
= FSDirectory
.GetDirectory(dirname
, false);
871 cfr
= new CompoundFileReader(dir
, filename
);
873 System
.String
[] files
= cfr
.List();
874 System
.Array
.Sort(files
); // sort the array of filename so that the output is more readable
876 for (int i
= 0; i
< files
.Length
; ++i
)
878 long len
= cfr
.FileLength(files
[i
]);
882 System
.Console
.Out
.WriteLine("extract " + files
[i
] + " with " + len
+ " bytes to local directory...");
883 IndexInput ii
= cfr
.OpenInput(files
[i
]);
885 System
.IO
.FileStream f
= new System
.IO
.FileStream(files
[i
], System
.IO
.FileMode
.Create
);
887 // read and write with a small buffer, which is more effectiv than reading byte by byte
888 byte[] buffer
= new byte[1024];
889 int chunk
= buffer
.Length
;
892 int bufLen
= (int) System
.Math
.Min(chunk
, len
);
893 ii
.ReadBytes(buffer
, 0, bufLen
);
895 byte[] byteArray
= new byte[buffer
.Length
];
896 for (int index
=0; index
< buffer
.Length
; index
++)
897 byteArray
[index
] = (byte) buffer
[index
];
899 f
.Write(byteArray
, 0, bufLen
);
908 System
.Console
.Out
.WriteLine(files
[i
] + ": " + len
+ " bytes");
911 catch (System
.IO
.IOException ioe
)
913 System
.Console
.Error
.WriteLine(ioe
.StackTrace
);
924 catch (System
.IO
.IOException ioe
)
926 System
.Console
.Error
.WriteLine(ioe
.StackTrace
);