@@ -92,12 +92,14 @@ public class AnalyzingInfixSuggester : Lookup, IDisposable
9292 private readonly Directory dir ;
9393 internal readonly int minPrefixChars ;
9494 private readonly bool commitOnBuild ;
95+ private readonly bool closeIndexWriterOnBuild ; // LUCENENET specific - Support for LUCENE-7564.
9596 // LUCENENET specific - index writer config factory for extending classes
9697 private readonly IAnalyzingInfixSuggesterIndexWriterConfigFactory indexWriterConfigFactory ;
9798
9899 /// <summary>
99100 /// Used for ongoing NRT additions/updates. </summary>
100- private IndexWriter writer ;
101+ // LUCENENET specific - changed from private to protected internal for LUCENE-7564 test support.
102+ protected internal IndexWriter writer ;
101103
102104 /// <summary>
103105 /// <see cref="IndexSearcher"/> used for lookups. </summary>
@@ -109,6 +111,12 @@ public class AnalyzingInfixSuggester : Lookup, IDisposable
109111 /// </summary>
110112 public const int DEFAULT_MIN_PREFIX_CHARS = 4 ;
111113
114+ /// <summary>
115+ /// Default option to close the <see cref="IndexWriter"/> once the index has been built.
116+ /// </summary>
117+ // LUCENENET specific - Support for LUCENE-7564.
118+ protected const bool DEFAULT_CLOSE_INDEXWRITER_ON_BUILD = true ;
119+
112120 /// <summary>
113121 /// How we sort the postings and search results. </summary>
114122 private static readonly Sort SORT = new Sort ( new SortField ( "weight" , SortFieldType . INT64 , true ) ) ;
@@ -138,8 +146,9 @@ public AnalyzingInfixSuggester(LuceneVersion matchVersion, Directory dir, Analyz
138146 /// Prefixes shorter than this are indexed as character
139147 /// ngrams (increasing index size but making lookups
140148 /// faster). </param>
141- // LUCENENET specific - LUCENE-5889, a 4.11.0 feature. calls new constructor with extra param.
142- // LUCENENET UPGRADE TODO: Remove method at version 4.11.0. Was retained for perfect 4.8 compatibility
149+ // LUCENENET specific - backported from LUCENE-5889 (4.11.0), LUCENE-7564 (6.4.0), LUCENE-7670 (6.4.1).
150+ // Calls new constructor with default values for commitOnBuild and closeIndexWriterOnBuild.
151+ // Retained for backwards compatibility.
143152 public AnalyzingInfixSuggester ( LuceneVersion matchVersion , Directory dir , Analyzer indexAnalyzer ,
144153 Analyzer queryAnalyzer , int minPrefixChars )
145154 : this ( matchVersion , dir , indexAnalyzer , queryAnalyzer , minPrefixChars , commitOnBuild : false )
@@ -165,7 +174,33 @@ public AnalyzingInfixSuggester(LuceneVersion matchVersion, Directory dir, Analyz
165174 // LUCENENET specific - LUCENE-5889, a 4.11.0 feature. (Code moved from other constructor to here.)
166175 public AnalyzingInfixSuggester ( LuceneVersion matchVersion , Directory dir , Analyzer indexAnalyzer ,
167176 Analyzer queryAnalyzer , int minPrefixChars , bool commitOnBuild )
168- : this ( new AnalyzingInfixSuggesterIndexWriterConfigFactory ( SORT ) , matchVersion , dir , indexAnalyzer , queryAnalyzer , minPrefixChars , commitOnBuild )
177+ : this ( matchVersion , dir , indexAnalyzer , queryAnalyzer , minPrefixChars , commitOnBuild , DEFAULT_CLOSE_INDEXWRITER_ON_BUILD )
178+ {
179+ }
180+
181+ /// <summary>
182+ /// Create a new instance, loading from a previously built
183+ /// <see cref="AnalyzingInfixSuggester"/> directory, if it exists. This directory must be
184+ /// private to the infix suggester (i.e., not an external
185+ /// Lucene index). Note that <see cref="Dispose()"/>
186+ /// will also dispose the provided directory.
187+ /// </summary>
188+ /// <param name="minPrefixChars"> Minimum number of leading characters
189+ /// before <see cref="PrefixQuery"/> is used (default 4).
190+ /// Prefixes shorter than this are indexed as character
191+ /// ngrams (increasing index size but making lookups
192+ /// faster). </param>
193+ /// <param name="commitOnBuild"> Call commit after the index has finished building. This
194+ /// would persist the suggester index to disk and future instances of this suggester can
195+ /// use this pre-built dictionary. </param>
196+ /// <param name="closeIndexWriterOnBuild"> If <c>true</c>, the <see cref="IndexWriter"/> will be closed
197+ /// after the index has finished building. </param>
198+ // LUCENENET specific - closeIndexWriterOnBuild backported from LUCENE-7564.
199+ // Note: Java's equivalent constructor also has allTermsRequired and highlight parameters, which
200+ // are not present here because those are method-level parameters in this version of Lucene.NET.
201+ public AnalyzingInfixSuggester ( LuceneVersion matchVersion , Directory dir , Analyzer indexAnalyzer ,
202+ Analyzer queryAnalyzer , int minPrefixChars , bool commitOnBuild , bool closeIndexWriterOnBuild )
203+ : this ( new AnalyzingInfixSuggesterIndexWriterConfigFactory ( SORT ) , matchVersion , dir , indexAnalyzer , queryAnalyzer , minPrefixChars , commitOnBuild , closeIndexWriterOnBuild )
169204 {
170205 }
171206
@@ -186,14 +221,41 @@ public AnalyzingInfixSuggester(LuceneVersion matchVersion, Directory dir, Analyz
186221 /// use this pre-built dictionary. </param>
187222 /// <param name="indexWriterConfigFactory"> Factory for creating the <see cref="IndexWriterConfig"/>. </param>
188223 // LUCENENET specific - added indexWriterConfigFactory parameter to allow for customizing the index writer config.
224+ // Retained for backwards compatibility.
189225 public AnalyzingInfixSuggester ( IAnalyzingInfixSuggesterIndexWriterConfigFactory indexWriterConfigFactory , LuceneVersion matchVersion ,
190226 Directory dir , Analyzer indexAnalyzer , Analyzer queryAnalyzer , int minPrefixChars , bool commitOnBuild )
227+ : this ( indexWriterConfigFactory , matchVersion , dir , indexAnalyzer , queryAnalyzer , minPrefixChars , commitOnBuild , DEFAULT_CLOSE_INDEXWRITER_ON_BUILD )
228+ {
229+ }
230+
231+ /// <summary>
232+ /// Create a new instance, loading from a previously built
233+ /// <see cref="AnalyzingInfixSuggester"/> directory, if it exists. This directory must be
234+ /// private to the infix suggester (i.e., not an external
235+ /// Lucene index). Note that <see cref="Dispose()"/>
236+ /// will also dispose the provided directory.
237+ /// </summary>
238+ /// <param name="minPrefixChars"> Minimum number of leading characters
239+ /// before <see cref="PrefixQuery"/> is used (default 4).
240+ /// Prefixes shorter than this are indexed as character
241+ /// ngrams (increasing index size but making lookups
242+ /// faster). </param>
243+ /// <param name="commitOnBuild"> Call commit after the index has finished building. This
244+ /// would persist the suggester index to disk and future instances of this suggester can
245+ /// use this pre-built dictionary. </param>
246+ /// <param name="closeIndexWriterOnBuild"> If <c>true</c>, the <see cref="IndexWriter"/> will be closed
247+ /// after the index has finished building. </param>
248+ /// <param name="indexWriterConfigFactory"> Factory for creating the <see cref="IndexWriterConfig"/>. </param>
249+ // LUCENENET specific - added indexWriterConfigFactory and closeIndexWriterOnBuild parameters.
250+ public AnalyzingInfixSuggester ( IAnalyzingInfixSuggesterIndexWriterConfigFactory indexWriterConfigFactory , LuceneVersion matchVersion ,
251+ Directory dir , Analyzer indexAnalyzer , Analyzer queryAnalyzer , int minPrefixChars , bool commitOnBuild , bool closeIndexWriterOnBuild )
191252 {
192253 if ( minPrefixChars < 0 )
193254 {
194255 throw new ArgumentOutOfRangeException ( nameof ( minPrefixChars ) , "minPrefixChars must be >= 0; got: " + minPrefixChars ) ; // LUCENENET specific - changed from IllegalArgumentException to ArgumentOutOfRangeException (.NET convention)
195256 }
196257
258+ // LUCENENET specific - moved IndexWriterConfig to AnalyzingInfixSuggesterIndexWriterConfigFactory
197259 if ( indexWriterConfigFactory is null ) throw new ArgumentNullException ( nameof ( indexWriterConfigFactory ) ) ;
198260
199261 this . m_queryAnalyzer = queryAnalyzer ;
@@ -202,14 +264,19 @@ public AnalyzingInfixSuggester(IAnalyzingInfixSuggesterIndexWriterConfigFactory
202264 this . dir = dir ;
203265 this . minPrefixChars = minPrefixChars ;
204266 this . commitOnBuild = commitOnBuild ;
267+ this . closeIndexWriterOnBuild = closeIndexWriterOnBuild ;
205268 this . indexWriterConfigFactory = indexWriterConfigFactory ;
206269
207270 if ( DirectoryReader . IndexExists ( dir ) )
208271 {
209272 // Already built; open it:
210- var config = indexWriterConfigFactory . Get ( matchVersion , GetGramAnalyzer ( ) , OpenMode . APPEND ) ;
211- writer = new IndexWriter ( dir , config ) ;
212- m_searcherMgr = new SearcherManager ( writer , true , null ) ;
273+
274+ // LUCENENET specific - backported fix from Lucene 6.4.1 to fix #1242. previously was:
275+ // var config = indexWriterConfigFactory.Get(matchVersion, GetGramAnalyzer(), OpenMode.APPEND);
276+ // writer = new IndexWriter(dir, config);
277+ // m_searcherMgr = new SearcherManager(writer, true, null);
278+
279+ m_searcherMgr = new SearcherManager ( dir , null ) ;
213280 }
214281 }
215282
@@ -268,7 +335,7 @@ public override void Build(IInputEnumerator enumerator)
268335 }
269336
270337 //System.out.println("initial indexing time: " + ((System.nanoTime()-t0)/1000000) + " msec");
271- if ( commitOnBuild ) // LUCENENET specific -Support for LUCENE - 5889.
338+ if ( commitOnBuild || closeIndexWriterOnBuild ) // LUCENENET specific - Support for LUCENE- 5889, LUCENE-7564 .
272339 {
273340 Commit ( ) ;
274341 }
@@ -279,24 +346,40 @@ public override void Build(IInputEnumerator enumerator)
279346 {
280347 if ( success )
281348 {
349+ if ( closeIndexWriterOnBuild ) // LUCENENET specific - Support for LUCENE-7564.
350+ {
351+ writer . Dispose ( ) ;
352+ writer = null ;
353+ }
282354 IOUtils . Dispose ( r ) ;
283355 }
284356 else
285357 {
286- IOUtils . DisposeWhileHandlingException ( writer , r ) ;
287- writer = null ;
358+ if ( writer != null )
359+ {
360+ writer . Rollback ( ) ;
361+ writer = null ;
362+ }
363+ IOUtils . DisposeWhileHandlingException ( r ) ;
288364 }
289365 }
290366 }
291367
292- // LUCENENET specific -Support for LUCENE-5889.
368+ // LUCENENET specific - Support for LUCENE-5889, LUCENE-7564 .
293369 public void Commit ( )
294370 {
295371 if ( writer is null )
296372 {
297- throw IllegalStateException . Create ( "Cannot commit on an closed writer. Add documents first" ) ;
373+ if ( m_searcherMgr is null || closeIndexWriterOnBuild == false )
374+ {
375+ throw IllegalStateException . Create ( "Cannot commit on an closed writer. Add documents first" ) ;
376+ }
377+ // else no-op: writer was committed and closed after the index was built, so commit is unnecessary
378+ }
379+ else
380+ {
381+ writer . Commit ( ) ;
298382 }
299- writer . Commit ( ) ;
300383 }
301384
302385 private Analyzer GetGramAnalyzer ( )
@@ -335,7 +418,7 @@ protected override TokenStreamComponents WrapComponents(string fieldName, TokenS
335418 }
336419 }
337420
338- //LUCENENET specific -Support for LUCENE - 5889.
421+ // LUCENENET specific - Support for LUCENE- 5889, LUCENE-7564 .
339422 private void EnsureOpen ( )
340423 {
341424 if ( writer != null )
@@ -346,13 +429,21 @@ private void EnsureOpen()
346429 {
347430 if ( writer is null )
348431 {
349- if ( m_searcherMgr != null )
432+ if ( DirectoryReader . IndexExists ( dir ) )
433+ {
434+ // Already built; open it:
435+ writer = new IndexWriter ( dir , indexWriterConfigFactory . Get ( matchVersion , GetGramAnalyzer ( ) , OpenMode . APPEND ) ) ;
436+ }
437+ else
350438 {
351- m_searcherMgr . Dispose ( ) ;
352- m_searcherMgr = null ;
439+ writer = new IndexWriter ( dir , indexWriterConfigFactory . Get ( matchVersion , GetGramAnalyzer ( ) , OpenMode . CREATE ) ) ;
353440 }
354- writer = new IndexWriter ( dir , indexWriterConfigFactory . Get ( matchVersion , GetGramAnalyzer ( ) , OpenMode . CREATE ) ) ;
441+ SearcherManager oldSearcherMgr = m_searcherMgr ;
355442 m_searcherMgr = new SearcherManager ( writer , true , null ) ;
443+ if ( oldSearcherMgr != null )
444+ {
445+ oldSearcherMgr . Dispose ( ) ;
446+ }
356447 }
357448 }
358449 finally
@@ -370,21 +461,22 @@ private void EnsureOpen()
370461 /// </summary>
371462 public virtual void Add ( BytesRef text , IEnumerable < BytesRef > contexts , long weight , BytesRef payload )
372463 {
373- EnsureOpen ( ) ; //LUCENENET specific -Support for LUCENE - 5889.
464+ EnsureOpen ( ) ; // LUCENENET specific - Support for LUCENE- 5889.
374465 writer . AddDocument ( BuildDocument ( text , contexts , weight , payload ) ) ;
375466 }
376467
377468 /// <summary>
378469 /// Updates a previous suggestion, matching the exact same
379470 /// text as before. Use this to change the weight or
380- /// payload of an already added suggstion . If you know
471+ /// payload of an already added suggestion . If you know
381472 /// this text is not already present you can use <see cref="Add"/>
382473 /// instead. After adding or updating a batch of
383474 /// new suggestions, you must call <see cref="Refresh()"/> in the
384475 /// end in order to see the suggestions in <see cref="DoLookup(string, IEnumerable{BytesRef}, int, bool, bool, CancellationToken)"/>
385476 /// </summary>
386477 public virtual void Update ( BytesRef text , IEnumerable < BytesRef > contexts , long weight , BytesRef payload )
387478 {
479+ EnsureOpen ( ) ; // LUCENENET specific - Support for LUCENE-5889.
388480 writer . UpdateDocument ( new Term ( EXACT_TEXT_FIELD_NAME , text . Utf8ToString ( ) ) , BuildDocument ( text , contexts , weight , payload ) ) ;
389481 }
390482
@@ -424,11 +516,16 @@ private Document BuildDocument(BytesRef text, IEnumerable<BytesRef> contexts, lo
424516 /// </summary>
425517 public virtual void Refresh ( )
426518 {
427- if ( m_searcherMgr is null ) // LUCENENET specific -Support for LUCENE-5889.
519+ if ( m_searcherMgr is null ) // LUCENENET specific - Support for LUCENE-5889.
428520 {
429521 throw IllegalStateException . Create ( "suggester was not built" ) ;
430522 }
431- m_searcherMgr . MaybeRefreshBlocking ( ) ;
523+ if ( writer != null ) // LUCENENET specific - Support for LUCENE-7564.
524+ {
525+ m_searcherMgr . MaybeRefreshBlocking ( ) ;
526+ }
527+ // else no-op: writer was committed and closed after the index was built
528+ // and before searcherMgr was constructed, so refresh is unnecessary
432529 }
433530
434531 /// <summary>
@@ -851,9 +948,12 @@ protected virtual void Dispose(bool disposing) // LUCENENET specific - implement
851948 if ( writer != null )
852949 {
853950 writer . Dispose ( ) ;
854- dir . Dispose ( ) ;
855951 writer = null ;
856952 }
953+ if ( dir != null ) // LUCENENET specific - Support for LUCENE-7564. Close dir even when writer is null.
954+ {
955+ dir . Dispose ( ) ;
956+ }
857957 }
858958 }
859959
0 commit comments