IndexReader.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:36k
源码类别:

搜索引擎

开发平台:

C#

  1. /*
  2.  * Copyright 2004 The Apache Software Foundation
  3.  * 
  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
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0
  9.  * 
  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.
  15.  */
  16. using System;
  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
  25. {
  26. /// <summary>IndexReader is an abstract class, providing an interface for accessing an
  27. /// index.  Search of an index is done entirely through this abstract interface,
  28. /// so that any subclass which implements it is searchable.
  29. /// <p> Concrete subclasses of IndexReader are usually constructed with a call to
  30. /// one of the static <code>open()</code> methods, e.g. {@link #Open(String)}.
  31. /// <p> For efficiency, in this API documents are often referred to via
  32. /// <i>document numbers</i>, non-negative integers which each name a unique
  33. /// document in the index.  These document numbers are ephemeral--they may change
  34. /// as documents are added to and deleted from an index.  Clients should thus not
  35. /// rely on a given document having the same number between sessions.
  36. /// </summary>
  37. /// <summary><p> An IndexReader can be opened on a directory for which an IndexWriter is
  38. /// opened already, but it cannot be used to delete documents from the index then.
  39. /// </summary>
  40. /// <author>  Doug Cutting
  41. /// </author>
  42. /// <version>  $Id: IndexReader.java 354917 2005-12-08 00:22:00Z ehatcher $
  43. /// </version>
  44. public abstract class IndexReader
  45. {
  46. private class AnonymousClassWith : Lock.With
  47. {
  48. private void  InitBlock(Lucene.Net.Store.Directory directory, bool closeDirectory)
  49. {
  50. this.directory = directory;
  51. this.closeDirectory = closeDirectory;
  52. }
  53. private Lucene.Net.Store.Directory directory;
  54. private bool closeDirectory;
  55. internal AnonymousClassWith(Lucene.Net.Store.Directory directory, bool closeDirectory, Lucene.Net.Store.Lock Param1, long Param2):base(Param1, Param2)
  56. {
  57. InitBlock(directory, closeDirectory);
  58. }
  59. public override System.Object DoBody()
  60. {
  61. SegmentInfos infos = new SegmentInfos();
  62. infos.Read(directory);
  63. if (infos.Count == 1)
  64. {
  65. // index is optimized
  66. return SegmentReader.Get(infos, infos.Info(0), closeDirectory);
  67. }
  68. IndexReader[] readers = new IndexReader[infos.Count];
  69. for (int i = 0; i < infos.Count; i++)
  70. readers[i] = SegmentReader.Get(infos.Info(i));
  71. return new MultiReader(directory, infos, closeDirectory, readers);
  72. }
  73. }
  74. private class AnonymousClassWith1 : Lock.With
  75. {
  76. private void  InitBlock(IndexReader enclosingInstance)
  77. {
  78. this.enclosingInstance = enclosingInstance;
  79. }
  80. private IndexReader enclosingInstance;
  81. public IndexReader Enclosing_Instance
  82. {
  83. get
  84. {
  85. return enclosingInstance;
  86. }
  87. }
  88. internal AnonymousClassWith1(IndexReader enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2) : base(Param1, Param2)
  89. {
  90. InitBlock(enclosingInstance);
  91. }
  92. public override System.Object DoBody()
  93. {
  94. Enclosing_Instance.DoCommit();
  95. Enclosing_Instance.segmentInfos.Write(Enclosing_Instance.directory);
  96. return null;
  97. }
  98. }
  99. public sealed class FieldOption
  100. {
  101. private System.String option;
  102. internal FieldOption()
  103. {
  104. }
  105. internal FieldOption(System.String option)
  106. {
  107. this.option = option;
  108. }
  109. public override System.String ToString()
  110. {
  111. return this.option;
  112. }
  113. // all fields
  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");
  131. }
  132. /// <summary> Constructor used if IndexReader is not owner of its directory. 
  133. /// This is used for IndexReaders that are used within other IndexReaders that take care or locking directories.
  134. /// 
  135. /// </summary>
  136. /// <param name="directory">Directory where IndexReader files reside.
  137. /// </param>
  138. protected internal IndexReader(Directory directory)
  139. {
  140. this.directory = directory;
  141. }
  142. /// <summary> Constructor used if IndexReader is owner of its directory.
  143. /// If IndexReader is owner of its directory, it locks its directory in case of write operations.
  144. /// 
  145. /// </summary>
  146. /// <param name="directory">Directory where IndexReader files reside.
  147. /// </param>
  148. /// <param name="segmentInfos">Used for write-l
  149. /// </param>
  150. /// <param name="closeDirectory">
  151. /// </param>
  152. internal IndexReader(Directory directory, SegmentInfos segmentInfos, bool closeDirectory)
  153. {
  154. Init(directory, segmentInfos, closeDirectory, true);
  155. }
  156. internal virtual void  Init(Directory directory, SegmentInfos segmentInfos, bool closeDirectory, bool directoryOwner)
  157. {
  158. this.directory = directory;
  159. this.segmentInfos = segmentInfos;
  160. this.directoryOwner = directoryOwner;
  161. this.closeDirectory = closeDirectory;
  162. }
  163. private Directory directory;
  164. private bool directoryOwner;
  165. private bool closeDirectory;
  166. private SegmentInfos segmentInfos;
  167. private Lock writeLock;
  168. private bool stale;
  169. private bool hasChanges;
  170. /// <summary>Returns an IndexReader reading the index in an FSDirectory in the named
  171. /// path. 
  172. /// </summary>
  173. public static IndexReader Open(System.String path)
  174. {
  175. return Open(FSDirectory.GetDirectory(path, false), true);
  176. }
  177. /// <summary>Returns an IndexReader reading the index in an FSDirectory in the named
  178. /// path. 
  179. /// </summary>
  180. public static IndexReader Open(System.IO.FileInfo path)
  181. {
  182. return Open(FSDirectory.GetDirectory(path, false), true);
  183. }
  184. /// <summary>Returns an IndexReader reading the index in the given Directory. </summary>
  185. public static IndexReader Open(Directory directory)
  186. {
  187. return Open(directory, false);
  188. }
  189. private static IndexReader Open(Directory directory, bool closeDirectory)
  190. {
  191. lock (directory)
  192. {
  193. // in- & inter-process sync
  194. return (IndexReader) new AnonymousClassWith(directory, closeDirectory, directory.MakeLock(IndexWriter.COMMIT_LOCK_NAME), IndexWriter.COMMIT_LOCK_TIMEOUT).Run();
  195. }
  196. }
  197. /// <summary>Returns the directory this index resides in. </summary>
  198. public virtual Directory Directory()
  199. {
  200. return directory;
  201. }
  202. /// <summary> Returns the time the index in the named directory was last modified.
  203. /// Do not use this to check whether the reader is still up-to-date, use
  204. /// {@link #IsCurrent()} instead. 
  205. /// </summary>
  206. public static long LastModified(System.String directory)
  207. {
  208. return LastModified(new System.IO.FileInfo(directory));
  209. }
  210. /// <summary> Returns the time the index in the named directory was last modified. 
  211. /// Do not use this to check whether the reader is still up-to-date, use
  212. /// {@link #IsCurrent()} instead. 
  213. /// </summary>
  214. public static long LastModified(System.IO.FileInfo directory)
  215. {
  216. return FSDirectory.FileModified(directory, IndexFileNames.SEGMENTS);
  217. }
  218. /// <summary> Returns the time the index in the named directory was last modified. 
  219. /// Do not use this to check whether the reader is still up-to-date, use
  220. /// {@link #IsCurrent()} instead. 
  221. /// </summary>
  222. public static long LastModified(Directory directory)
  223. {
  224. return directory.FileModified(IndexFileNames.SEGMENTS);
  225. }
  226. /// <summary> Reads version number from segments files. The version number is
  227. /// initialized with a timestamp and then increased by one for each change of
  228. /// the index.
  229. /// 
  230. /// </summary>
  231. /// <param name="directory">where the index resides.
  232. /// </param>
  233. /// <returns> version number.
  234. /// </returns>
  235. /// <throws>  IOException if segments file cannot be read </throws>
  236. public static long GetCurrentVersion(System.String directory)
  237. {
  238. return GetCurrentVersion(new System.IO.FileInfo(directory));
  239. }
  240. /// <summary> Reads version number from segments files. The version number is
  241. /// initialized with a timestamp and then increased by one for each change of
  242. /// the index.
  243. /// 
  244. /// </summary>
  245. /// <param name="directory">where the index resides.
  246. /// </param>
  247. /// <returns> version number.
  248. /// </returns>
  249. /// <throws>  IOException if segments file cannot be read </throws>
  250. public static long GetCurrentVersion(System.IO.FileInfo directory)
  251. {
  252. Directory dir = FSDirectory.GetDirectory(directory, false);
  253. long version = GetCurrentVersion(dir);
  254. dir.Close();
  255. return version;
  256. }
  257. /// <summary> Reads version number from segments files. The version number is
  258. /// initialized with a timestamp and then increased by one for each change of
  259. /// the index.
  260. /// 
  261. /// </summary>
  262. /// <param name="directory">where the index resides.
  263. /// </param>
  264. /// <returns> version number.
  265. /// </returns>
  266. /// <throws>  IOException if segments file cannot be read. </throws>
  267. public static long GetCurrentVersion(Directory directory)
  268. {
  269. return SegmentInfos.ReadCurrentVersion(directory);
  270. }
  271. /// <summary> Version number when this IndexReader was opened.</summary>
  272. public virtual long GetVersion()
  273. {
  274. return segmentInfos.GetVersion();
  275. }
  276. /// <summary> Check whether this IndexReader still works on a current version of the index.
  277. /// If this is not the case you will need to re-open the IndexReader to
  278. /// make sure you see the latest changes made to the index.
  279. /// 
  280. /// </summary>
  281. /// <throws>  IOException </throws>
  282. public virtual bool IsCurrent()
  283. {
  284. if (SegmentInfos.ReadCurrentVersion(directory) != segmentInfos.GetVersion())
  285. {
  286. return false;
  287. }
  288. return true;
  289. }
  290. /// <summary>  Return an array of term frequency vectors for the specified document.
  291. /// The array contains a vector for each vectorized field in the document.
  292. /// Each vector contains terms and frequencies for all terms in a given vectorized field.
  293. /// If no such fields existed, the method returns null. The term vectors that are
  294. /// returned my either be of type TermFreqVector or of type TermPositionsVector if
  295. /// positions or offsets have been stored.
  296. /// 
  297. /// </summary>
  298. /// <param name="docNumber">document for which term frequency vectors are returned
  299. /// </param>
  300. /// <returns> array of term frequency vectors. May be null if no term vectors have been
  301. /// stored for the specified document.
  302. /// </returns>
  303. /// <throws>  IOException if index cannot be accessed </throws>
  304. /// <seealso cref="Lucene.Net.document.Field.TermVector">
  305. /// </seealso>
  306. abstract public TermFreqVector[] GetTermFreqVectors(int docNumber);
  307. /// <summary>  Return a term frequency vector for the specified document and field. The
  308. /// returned vector contains terms and frequencies for the terms in
  309. /// the specified field of this document, if the field had the storeTermVector
  310. /// flag set. If termvectors had been stored with positions or offsets, a 
  311. /// TermPositionsVector is returned.
  312. /// 
  313. /// </summary>
  314. /// <param name="docNumber">document for which the term frequency vector is returned
  315. /// </param>
  316. /// <param name="field">field for which the term frequency vector is returned.
  317. /// </param>
  318. /// <returns> term frequency vector May be null if field does not exist in the specified
  319. /// document or term vector was not stored.
  320. /// </returns>
  321. /// <throws>  IOException if index cannot be accessed </throws>
  322. /// <seealso cref="Lucene.Net.document.Field.TermVector">
  323. /// </seealso>
  324. abstract public TermFreqVector GetTermFreqVector(int docNumber, System.String field);
  325. /// <summary> Returns <code>true</code> if an index exists at the specified directory.
  326. /// If the directory does not exist or if there is no index in it.
  327. /// <code>false</code> is returned.
  328. /// </summary>
  329. /// <param name="directory">the directory to check for an index
  330. /// </param>
  331. /// <returns> <code>true</code> if an index exists; <code>false</code> otherwise
  332. /// </returns>
  333. public static bool IndexExists(System.String directory)
  334. {
  335. bool tmpBool;
  336.             if (System.IO.File.Exists((new System.IO.FileInfo(System.IO.Path.Combine(directory, IndexFileNames.SEGMENTS))).FullName))
  337. tmpBool = true;
  338. else
  339. tmpBool = System.IO.Directory.Exists((new System.IO.FileInfo(System.IO.Path.Combine(directory, IndexFileNames.SEGMENTS))).FullName);
  340. return tmpBool;
  341. }
  342. /// <summary> Returns <code>true</code> if an index exists at the specified directory.
  343. /// If the directory does not exist or if there is no index in it.
  344. /// </summary>
  345. /// <param name="directory">the directory to check for an index
  346. /// </param>
  347. /// <returns> <code>true</code> if an index exists; <code>false</code> otherwise
  348. /// </returns>
  349. public static bool IndexExists(System.IO.FileInfo directory)
  350. {
  351. bool tmpBool;
  352. if (System.IO.File.Exists((new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, IndexFileNames.SEGMENTS))).FullName))
  353. tmpBool = true;
  354. else
  355. tmpBool = System.IO.Directory.Exists((new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, IndexFileNames.SEGMENTS))).FullName);
  356. return tmpBool;
  357. }
  358. /// <summary> Returns <code>true</code> if an index exists at the specified directory.
  359. /// If the directory does not exist or if there is no index in it.
  360. /// </summary>
  361. /// <param name="directory">the directory to check for an index
  362. /// </param>
  363. /// <returns> <code>true</code> if an index exists; <code>false</code> otherwise
  364. /// </returns>
  365. /// <throws>  IOException if there is a problem with accessing the index </throws>
  366. public static bool IndexExists(Directory directory)
  367. {
  368. return directory.FileExists(IndexFileNames.SEGMENTS);
  369. }
  370. /// <summary>Returns the number of documents in this index. </summary>
  371. public abstract int NumDocs();
  372. /// <summary>Returns one greater than the largest possible document number.
  373. /// This may be used to, e.g., determine how big to allocate an array which
  374. /// will have an element for every document number in an index.
  375. /// </summary>
  376. public abstract int MaxDoc();
  377. /// <summary>Returns the stored fields of the <code>n</code><sup>th</sup>
  378. /// <code>Document</code> in this index. 
  379. /// </summary>
  380. public abstract Document Document(int n);
  381. /// <summary>Returns true if document <i>n</i> has been deleted </summary>
  382. public abstract bool IsDeleted(int n);
  383. /// <summary>Returns true if any documents have been deleted </summary>
  384. public abstract bool HasDeletions();
  385. /// <summary>Returns true if there are norms stored for this field. </summary>
  386. public virtual bool HasNorms(System.String field)
  387. {
  388. // backward compatible implementation.
  389. // SegmentReader has an efficient implementation.
  390. return Norms(field) != null;
  391. }
  392. /// <summary>Returns the byte-encoded normalization factor for the named field of
  393. /// every document.  This is used by the search code to score documents.
  394. /// 
  395. /// </summary>
  396. /// <seealso cref="Field.SetBoost(float)">
  397. /// </seealso>
  398. public abstract byte[] Norms(System.String field);
  399. /// <summary>Reads the byte-encoded normalization factor for the named field of every
  400. /// document.  This is used by the search code to score documents.
  401. /// 
  402. /// </summary>
  403. /// <seealso cref="Field.SetBoost(float)">
  404. /// </seealso>
  405. public abstract void  Norms(System.String field, byte[] bytes, int offset);
  406. /// <summary>Expert: Resets the normalization factor for the named field of the named
  407. /// document.  The norm represents the product of the field's {@link
  408. /// Field#SetBoost(float) boost} and its {@link Similarity#LengthNorm(String,
  409. /// int) length normalization}.  Thus, to preserve the length normalization
  410. /// values when resetting this, one should base the new value upon the old.
  411. /// 
  412. /// </summary>
  413. /// <seealso cref="Norms(String)">
  414. /// </seealso>
  415. /// <seealso cref="Similarity.DecodeNorm(byte)">
  416. /// </seealso>
  417. public void  SetNorm(int doc, System.String field, byte value_Renamed)
  418. {
  419. lock (this)
  420. {
  421. if (directoryOwner)
  422. AquireWriteLock();
  423. DoSetNorm(doc, field, value_Renamed);
  424. hasChanges = true;
  425. }
  426. }
  427. /// <summary>Implements setNorm in subclass.</summary>
  428. protected internal abstract void  DoSetNorm(int doc, System.String field, byte value_Renamed);
  429. /// <summary>Expert: Resets the normalization factor for the named field of the named
  430. /// document.
  431. /// 
  432. /// </summary>
  433. /// <seealso cref="Norms(String)">
  434. /// </seealso>
  435. /// <seealso cref="Similarity.DecodeNorm(byte)">
  436. /// </seealso>
  437. public virtual void  SetNorm(int doc, System.String field, float value_Renamed)
  438. {
  439. SetNorm(doc, field, Similarity.EncodeNorm(value_Renamed));
  440. }
  441. /// <summary>Returns an enumeration of all the terms in the index.
  442. /// The enumeration is ordered by Term.compareTo().  Each term
  443. /// is greater than all that precede it in the enumeration.
  444. /// </summary>
  445. public abstract TermEnum Terms();
  446. /// <summary>Returns an enumeration of all terms after a given term.
  447. /// The enumeration is ordered by Term.compareTo().  Each term
  448. /// is greater than all that precede it in the enumeration.
  449. /// </summary>
  450. public abstract TermEnum Terms(Term t);
  451. /// <summary>Returns the number of documents containing the term <code>t</code>. </summary>
  452. public abstract int DocFreq(Term t);
  453. /// <summary>Returns an enumeration of all the documents which contain
  454. /// <code>term</code>. For each document, the document number, the frequency of
  455. /// the term in that document is also provided, for use in search scoring.
  456. /// Thus, this method implements the mapping:
  457. /// <p><ul>
  458. /// Term &nbsp;&nbsp; =&gt; &nbsp;&nbsp; &lt;docNum, freq&gt;<sup>*</sup>
  459. /// </ul>
  460. /// <p>The enumeration is ordered by document number.  Each document number
  461. /// is greater than all that precede it in the enumeration.
  462. /// </summary>
  463. public virtual TermDocs TermDocs(Term term)
  464. {
  465. TermDocs termDocs = TermDocs();
  466. termDocs.Seek(term);
  467. return termDocs;
  468. }
  469. /// <summary>Returns an unpositioned {@link TermDocs} enumerator. </summary>
  470. public abstract TermDocs TermDocs();
  471. /// <summary>Returns an enumeration of all the documents which contain
  472. /// <code>term</code>.  For each document, in addition to the document number
  473. /// and frequency of the term in that document, a list of all of the ordinal
  474. /// positions of the term in the document is available.  Thus, this method
  475. /// implements the mapping:
  476. /// 
  477. /// <p><ul>
  478. /// Term &nbsp;&nbsp; =&gt; &nbsp;&nbsp; &lt;docNum, freq,
  479. /// &lt;pos<sub>1</sub>, pos<sub>2</sub>, ...
  480. /// pos<sub>freq-1</sub>&gt;
  481. /// &gt;<sup>*</sup>
  482. /// </ul>
  483. /// <p> This positional information faciliates phrase and proximity searching.
  484. /// <p>The enumeration is ordered by document number.  Each document number is
  485. /// greater than all that precede it in the enumeration.
  486. /// </summary>
  487. public virtual TermPositions TermPositions(Term term)
  488. {
  489. TermPositions termPositions = TermPositions();
  490. termPositions.Seek(term);
  491. return termPositions;
  492. }
  493. /// <summary>Returns an unpositioned {@link TermPositions} enumerator. </summary>
  494. public abstract TermPositions TermPositions();
  495. /// <summary> Tries to acquire the WriteLock on this directory.
  496. /// this method is only valid if this IndexReader is directory owner.
  497. /// 
  498. /// </summary>
  499. /// <throws>  IOException If WriteLock cannot be acquired. </throws>
  500. private void  AquireWriteLock()
  501. {
  502. if (stale)
  503. throw new System.IO.IOException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations");
  504. if (this.writeLock == null)
  505. {
  506. Lock writeLock = directory.MakeLock(IndexWriter.WRITE_LOCK_NAME);
  507. if (!writeLock.obtain(IndexWriter.WRITE_LOCK_TIMEOUT))
  508. // obtain write lock
  509. {
  510. throw new System.IO.IOException("Index locked for write: " + writeLock);
  511. }
  512. this.writeLock = writeLock;
  513. // we have to check whether index has changed since this reader was opened.
  514. // if so, this reader is no longer valid for deletion
  515. if (SegmentInfos.ReadCurrentVersion(directory) > segmentInfos.GetVersion())
  516. {
  517. stale = true;
  518. this.writeLock.Release();
  519. this.writeLock = null;
  520. throw new System.IO.IOException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations");
  521. }
  522. }
  523. }
  524. /// <summary>Deletes the document numbered <code>docNum</code>.  Once a document is
  525. /// deleted it will not appear in TermDocs or TermPostitions enumerations.
  526. /// Attempts to read its field with the {@link #document}
  527. /// method will result in an error.  The presence of this document may still be
  528. /// reflected in the {@link #docFreq} statistic, though
  529. /// this will be corrected eventually as the index is further modified.
  530. /// 
  531. /// </summary>
  532. /// <deprecated> Use {@link #DeleteDocument(int docNum)} instead.
  533. /// </deprecated>
  534. public void  Delete(int docNum)
  535. {
  536. lock (this)
  537. {
  538. DeleteDocument(docNum);
  539. }
  540. }
  541. /// <summary>Deletes the document numbered <code>docNum</code>.  Once a document is
  542. /// deleted it will not appear in TermDocs or TermPostitions enumerations.
  543. /// Attempts to read its field with the {@link #document}
  544. /// method will result in an error.  The presence of this document may still be
  545. /// reflected in the {@link #docFreq} statistic, though
  546. /// this will be corrected eventually as the index is further modified.
  547. /// </summary>
  548. //UPGRADE_NOTE: Synchronized keyword was removed from method 'DeleteDocument'. Lock expression was added. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1027'"
  549. public void  DeleteDocument(int docNum)
  550. {
  551. lock (this)
  552. {
  553. if (directoryOwner)
  554. AquireWriteLock();
  555. DoDelete(docNum);
  556. hasChanges = true;
  557. }
  558. }
  559. /// <summary>Implements deletion of the document numbered <code>docNum</code>.
  560. /// Applications should call {@link #Delete(int)} or {@link #Delete(Term)}.
  561. /// </summary>
  562. protected internal abstract void  DoDelete(int docNum);
  563. /// <summary>Deletes all documents containing <code>term</code>.
  564. /// This is useful if one uses a document field to hold a unique ID string for
  565. /// the document.  Then to delete such a document, one merely constructs a
  566. /// term with the appropriate field and the unique ID string as its text and
  567. /// passes it to this method.
  568. /// See {@link #Delete(int)} for information about when this deletion will
  569. /// become effective.
  570. /// </summary>
  571. /// <returns> the number of documents deleted
  572. /// 
  573. /// </returns>
  574. /// <deprecated> Use {@link #DeleteDocuments(Term term)} instead.
  575. /// </deprecated>
  576. public int Delete(Term term)
  577. {
  578. return DeleteDocuments(term);
  579. }
  580. /// <summary>Deletes all documents containing <code>term</code>.
  581. /// This is useful if one uses a document field to hold a unique ID string for
  582. /// the document.  Then to delete such a document, one merely constructs a
  583. /// term with the appropriate field and the unique ID string as its text and
  584. /// passes it to this method.
  585. /// See {@link #Delete(int)} for information about when this deletion will 
  586. /// become effective.
  587. /// </summary>
  588. /// <returns> the number of documents deleted
  589. /// </returns>
  590. public int DeleteDocuments(Term term)
  591. {
  592. TermDocs docs = TermDocs(term);
  593. if (docs == null)
  594. return 0;
  595. int n = 0;
  596. try
  597. {
  598. while (docs.Next())
  599. {
  600. DeleteDocument(docs.Doc());
  601. n++;
  602. }
  603. }
  604. finally
  605. {
  606. docs.Close();
  607. }
  608. return n;
  609. }
  610. /// <summary>Undeletes all documents currently marked as deleted in this index.</summary>
  611. public void  UndeleteAll()
  612. {
  613. lock (this)
  614. {
  615. if (directoryOwner)
  616. AquireWriteLock();
  617. DoUndeleteAll();
  618. hasChanges = true;
  619. }
  620. }
  621. /// <summary>Implements actual undeleteAll() in subclass. </summary>
  622. protected internal abstract void  DoUndeleteAll();
  623. /// <summary> Commit changes resulting from delete, undeleteAll, or setNorm operations
  624. /// 
  625. /// </summary>
  626. /// <throws>  IOException </throws>
  627. protected internal void  Commit()
  628. {
  629. lock (this)
  630. {
  631. if (hasChanges)
  632. {
  633. if (directoryOwner)
  634. {
  635. lock (directory)
  636. {
  637. // in- & inter-process sync
  638. new AnonymousClassWith1(this, directory.MakeLock(IndexWriter.COMMIT_LOCK_NAME), IndexWriter.COMMIT_LOCK_TIMEOUT).Run();
  639. }
  640. if (writeLock != null)
  641. {
  642. writeLock.Release(); // release write lock
  643. writeLock = null;
  644. }
  645. }
  646. else
  647. DoCommit();
  648. }
  649. hasChanges = false;
  650. }
  651. }
  652. /// <summary>Implements commit. </summary>
  653. protected internal abstract void  DoCommit();
  654. /// <summary> Closes files associated with this index.
  655. /// Also saves any new deletions to disk.
  656. /// No other methods should be called after this has been called.
  657. /// </summary>
  658. public void  Close()
  659. {
  660. lock (this)
  661. {
  662. Commit();
  663. DoClose();
  664. if (closeDirectory)
  665. directory.Close();
  666.                 System.GC.SuppressFinalize(this);
  667. }
  668. }
  669. /// <summary>Implements close. </summary>
  670. protected internal abstract void  DoClose();
  671. /// <summary>Release the write lock, if needed. </summary>
  672. ~IndexReader()
  673. {
  674. if (writeLock != null)
  675. {
  676. writeLock.Release(); // release write lock
  677. writeLock = null;
  678. }
  679. }
  680. /// <summary> Returns a list of all unique field names that exist in the index pointed
  681. /// to by this IndexReader.
  682. /// </summary>
  683. /// <returns> Collection of Strings indicating the names of the fields
  684. /// </returns>
  685. /// <throws>  IOException if there is a problem with accessing the index </throws>
  686. /// <summary> 
  687. /// </summary>
  688. /// <deprecated>  Replaced by {@link #GetFieldNames(IndexReader.FieldOption)}
  689. /// </deprecated>
  690. public abstract System.Collections.ICollection GetFieldNames();
  691. /// <summary> Returns a list of all unique field names that exist in the index pointed
  692. /// to by this IndexReader.  The boolean argument specifies whether the fields
  693. /// returned are indexed or not.
  694. /// </summary>
  695. /// <param name="indexed"><code>true</code> if only indexed fields should be returned;
  696. /// <code>false</code> if only unindexed fields should be returned.
  697. /// </param>
  698. /// <returns> Collection of Strings indicating the names of the fields
  699. /// </returns>
  700. /// <throws>  IOException if there is a problem with accessing the index </throws>
  701. /// <summary> 
  702. /// </summary>
  703. /// <deprecated>  Replaced by {@link #GetFieldNames(IndexReader.FieldOption)}
  704. /// </deprecated>
  705. public abstract System.Collections.ICollection GetFieldNames(bool indexed);
  706. /// <summary> </summary>
  707. /// <param name="storedTermVector">if true, returns only Indexed fields that have term vector info, 
  708. /// else only indexed fields without term vector info 
  709. /// </param>
  710. /// <returns> Collection of Strings indicating the names of the fields
  711. /// 
  712. /// </returns>
  713. /// <deprecated>  Replaced by {@link #GetFieldNames(IndexReader.FieldOption)}
  714. /// </deprecated>
  715. public virtual System.Collections.ICollection GetIndexedFieldNames(bool storedTermVector)
  716. {
  717. if (storedTermVector)
  718. {
  719. System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
  720.                 foreach (object item in GetIndexedFieldNames(Field.TermVector.YES))
  721.                 {
  722.                     if (fieldSet.ContainsKey(item) == false)
  723.                     {
  724.                         fieldSet.Add(item, item);
  725.                     }
  726.                 }
  727.                 foreach (object item in GetIndexedFieldNames(Field.TermVector.WITH_POSITIONS))
  728.                 {
  729.                     if (fieldSet.ContainsKey(item) == false)
  730.                     {
  731.                         fieldSet.Add(item, item);
  732.                     }
  733.                 }
  734.                 foreach (object item in GetIndexedFieldNames(Field.TermVector.WITH_OFFSETS))
  735.                 {
  736.                     if (fieldSet.ContainsKey(item) == false)
  737.                     {
  738.                         fieldSet.Add(item, item);
  739.                     }
  740.                 }
  741.                 foreach (object item in GetIndexedFieldNames(Field.TermVector.WITH_POSITIONS_OFFSETS))
  742.                 {
  743.                     if (fieldSet.ContainsKey(item) == false)
  744.                     {
  745.                         fieldSet.Add(item, item);
  746.                     }
  747.                 }
  748.                 return fieldSet;
  749. }
  750. else
  751. return GetIndexedFieldNames(Field.TermVector.NO);
  752. }
  753. /// <summary> Get a list of unique field names that exist in this index, are indexed, and have
  754. /// the specified term vector information.
  755. /// 
  756. /// </summary>
  757. /// <param name="tvSpec">specifies which term vector information should be available for the fields
  758. /// </param>
  759. /// <returns> Collection of Strings indicating the names of the fields
  760. /// 
  761. /// </returns>
  762. /// <deprecated>  Replaced by {@link #GetFieldNames(IndexReader.FieldOption)}
  763. /// </deprecated>
  764. public abstract System.Collections.ICollection GetIndexedFieldNames(Field.TermVector tvSpec);
  765. /// <summary> Get a list of unique field names that exist in this index and have the specified
  766. /// field option information.
  767. /// </summary>
  768. /// <param name="fldOption">specifies which field option should be available for the returned fields
  769. /// </param>
  770. /// <returns> Collection of Strings indicating the names of the fields.
  771. /// </returns>
  772. /// <seealso cref="IndexReader.FieldOption">
  773. /// </seealso>
  774. public abstract System.Collections.ICollection GetFieldNames(FieldOption fldOption);
  775. /// <summary> Returns <code>true</code> iff the index in the named directory is
  776. /// currently locked.
  777. /// </summary>
  778. /// <param name="directory">the directory to check for a lock
  779. /// </param>
  780. /// <throws>  IOException if there is a problem with accessing the index </throws>
  781. public static bool IsLocked(Directory directory)
  782. {
  783. return directory.MakeLock(IndexWriter.WRITE_LOCK_NAME).IsLocked() || directory.MakeLock(IndexWriter.COMMIT_LOCK_NAME).IsLocked();
  784. }
  785. /// <summary> Returns <code>true</code> iff the index in the named directory is
  786. /// currently locked.
  787. /// </summary>
  788. /// <param name="directory">the directory to check for a lock
  789. /// </param>
  790. /// <throws>  IOException if there is a problem with accessing the index </throws>
  791. public static bool IsLocked(System.String directory)
  792. {
  793. Directory dir = FSDirectory.GetDirectory(directory, false);
  794. bool result = IsLocked(dir);
  795. dir.Close();
  796. return result;
  797. }
  798. /// <summary> Forcibly unlocks the index in the named directory.
  799. /// <P>
  800. /// Caution: this should only be used by failure recovery code,
  801. /// when it is known that no other process nor thread is in fact
  802. /// currently accessing this index.
  803. /// </summary>
  804. public static void  Unlock(Directory directory)
  805. {
  806. directory.MakeLock(IndexWriter.WRITE_LOCK_NAME).Release();
  807. directory.MakeLock(IndexWriter.COMMIT_LOCK_NAME).Release();
  808. }
  809. /// <summary> Prints the filename and size of each file within a given compound file.
  810. /// Add the -extract flag to extract files to the current working directory.
  811. /// In order to make the extracted version of the index work, you have to copy
  812. /// the segments file from the compound index into the directory where the extracted files are stored.
  813. /// </summary>
  814. /// <param name="args">Usage: Lucene.Net.index.IndexReader [-extract] &lt;cfsfile&gt;
  815. /// </param>
  816. [STAThread]
  817. public static void  Main(System.String[] args)
  818. {
  819. System.String filename = null;
  820. bool extract = false;
  821. for (int i = 0; i < args.Length; ++i)
  822. {
  823. if (args[i].Equals("-extract"))
  824. {
  825. extract = true;
  826. }
  827. else if (filename == null)
  828. {
  829. filename = args[i];
  830. }
  831. }
  832. if (filename == null)
  833. {
  834. System.Console.Out.WriteLine("Usage: Lucene.Net.index.IndexReader [-extract] <cfsfile>");
  835. return ;
  836. }
  837. Directory dir = null;
  838. CompoundFileReader cfr = null;
  839. try
  840. {
  841. System.IO.FileInfo file = new System.IO.FileInfo(filename);
  842. System.String dirname = new System.IO.FileInfo(file.FullName).DirectoryName;
  843. filename = file.Name;
  844. dir = FSDirectory.GetDirectory(dirname, false);
  845. cfr = new CompoundFileReader(dir, filename);
  846. System.String[] files = cfr.List();
  847. System.Array.Sort(files); // sort the array of filename so that the output is more readable
  848. for (int i = 0; i < files.Length; ++i)
  849. {
  850. long len = cfr.FileLength(files[i]);
  851. if (extract)
  852. {
  853. System.Console.Out.WriteLine("extract " + files[i] + " with " + len + " bytes to local directory...");
  854. IndexInput ii = cfr.OpenInput(files[i]);
  855. System.IO.FileStream f = new System.IO.FileStream(files[i], System.IO.FileMode.Create);
  856. // read and write with a small buffer, which is more effectiv than reading byte by byte
  857. byte[] buffer = new byte[1024];
  858. int chunk = buffer.Length;
  859. while (len > 0)
  860. {
  861. int bufLen = (int) System.Math.Min(chunk, len);
  862. ii.ReadBytes(buffer, 0, bufLen);
  863.                             byte[] byteArray = new byte[buffer.Length];
  864.                             for (int index=0; index < buffer.Length; index++)
  865.                                 byteArray[index] = (byte) buffer[index];
  866.                             f.Write(byteArray, 0, bufLen);
  867.                             len -= bufLen;
  868. }
  869. f.Close();
  870. ii.Close();
  871. }
  872. else
  873. System.Console.Out.WriteLine(files[i] + ": " + len + " bytes");
  874. }
  875. }
  876. catch (System.IO.IOException ioe)
  877. {
  878. System.Console.Error.WriteLine(ioe.StackTrace);
  879. }
  880. finally
  881. {
  882. try
  883. {
  884. if (dir != null)
  885. dir.Close();
  886. if (cfr != null)
  887. cfr.Close();
  888. }
  889. catch (System.IO.IOException ioe)
  890. {
  891. System.Console.Error.WriteLine(ioe.StackTrace);
  892. }
  893. }
  894. }
  895. }
  896. }