This is an automated email from the ASF dual-hosted git repository. nightowl888 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/lucenenet.git
commit 6ccde70c0883140928a5660f67bc7039d4b34593 Author: Shad Storhaug <[email protected]> AuthorDate: Tue Mar 16 21:56:22 2021 +0700 Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter: Restored locks to the state of Lucene 4.8.0. --- .../Taxonomy/Directory/DirectoryTaxonomyWriter.cs | 236 ++++++++++----------- 1 file changed, 116 insertions(+), 120 deletions(-) diff --git a/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyWriter.cs b/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyWriter.cs index c45a3f5..cba71c9 100644 --- a/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyWriter.cs +++ b/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyWriter.cs @@ -370,11 +370,11 @@ namespace Lucene.Net.Facet.Taxonomy.Directory /// </summary> protected virtual void Dispose(bool disposing) { - if (disposing && !isClosed) + lock (syncLock) { - lock (syncLock) + if (disposing && !isClosed) { - CommitLocked(); + Commit(); DoClose(); } } @@ -391,16 +391,19 @@ namespace Lucene.Net.Facet.Taxonomy.Directory /// Closes the <see cref="Index.IndexReader"/> as well as the /// <see cref="ITaxonomyWriterCache"/> instances that were used. /// </summary> - private void CloseResources() // LUCENENET: Made private, since this has the same purpose as Dispose(bool). Removed redundant lock. + private void CloseResources() // LUCENENET: Made private, since this has the same purpose as Dispose(bool). { - if (initializedReaderManager) + lock (syncLock) { - readerManager.Dispose(); - readerManager = null; - initializedReaderManager = false; + if (initializedReaderManager) + { + readerManager.Dispose(); + readerManager = null; + initializedReaderManager = false; + } + cache?.Dispose(); + parentStream.Dispose(); // LUCENENET specific } - cache?.Dispose(); - parentStream.Dispose(); // LUCENENET specific } /// <summary> @@ -591,7 +594,7 @@ namespace Lucene.Net.Facet.Taxonomy.Directory shouldRefreshReaderManager = true; // also add to the parent array - taxoArrays = GetTaxoArraysLocked().Add(id, parent); + taxoArrays = GetTaxoArrays().Add(id, parent); // NOTE: this line must be executed last, or else the cache gets updated // before the parents array (LUCENE-4596) @@ -666,22 +669,22 @@ namespace Lucene.Net.Facet.Taxonomy.Directory } } - // LUCENENET: Removed the lock here because all callers already have a - // lock before getting in here and all callers to AddCategoryDocument also - // have a lock before calling it. private void RefreshReaderManager() { - // this method is synchronized since it cannot happen concurrently with - // addCategoryDocument -- when this method returns, we must know that the - // reader manager's state is current. also, it sets shouldRefresh to false, - // and this cannot overlap with addCatDoc too. - // NOTE: since this method is sync'ed, it can call maybeRefresh, instead of - // maybeRefreshBlocking. If ever this is changed, make sure to change the - // call too. - if (shouldRefreshReaderManager && initializedReaderManager) + lock (syncLock) { - readerManager.MaybeRefresh(); - shouldRefreshReaderManager = false; + // this method is synchronized since it cannot happen concurrently with + // addCategoryDocument -- when this method returns, we must know that the + // reader manager's state is current. also, it sets shouldRefresh to false, + // and this cannot overlap with addCatDoc too. + // NOTE: since this method is sync'ed, it can call maybeRefresh, instead of + // maybeRefreshBlocking. If ever this is changed, make sure to change the + // call too. + if (shouldRefreshReaderManager && initializedReaderManager) + { + readerManager.MaybeRefresh(); + shouldRefreshReaderManager = false; + } } } @@ -689,21 +692,16 @@ namespace Lucene.Net.Facet.Taxonomy.Directory { lock (syncLock) { - CommitLocked(); - } - } - - private void CommitLocked() // LUCENENET: Added to avoid lock recursion - { - EnsureOpen(); - // LUCENE-4972: if we always call setCommitData, we create empty commits - if (!indexWriter.CommitData.TryGetValue(INDEX_EPOCH, out string epochStr) - || epochStr == null - || Convert.ToInt64(epochStr, 16) != indexEpoch) - { - indexWriter.SetCommitData(CombinedCommitData(indexWriter.CommitData)); + EnsureOpen(); + // LUCENE-4972: if we always call setCommitData, we create empty commits + if (!indexWriter.CommitData.TryGetValue(INDEX_EPOCH, out string epochStr) + || epochStr == null + || Convert.ToInt64(epochStr, 16) != indexEpoch) + { + indexWriter.SetCommitData(CombinedCommitData(indexWriter.CommitData)); + } + indexWriter.Commit(); } - indexWriter.Commit(); } /// <summary> @@ -784,114 +782,112 @@ namespace Lucene.Net.Facet.Taxonomy.Directory // we need to guarantee that if several threads call this concurrently, only // one executes it, and after it returns, the cache is updated and is either // complete or not. - private void PerhapsFillCache() // LUCENENET: Ensure the caller has a lock + private void PerhapsFillCache() { - if (cacheMisses < cacheMissesUntilFill) + lock (syncLock) { - return; - } + if (cacheMisses < cacheMissesUntilFill) + { + return; + } - if (!shouldFillCache) - { - // we already filled the cache once, there's no need to re-fill it - return; - } - shouldFillCache = false; + if (!shouldFillCache) + { + // we already filled the cache once, there's no need to re-fill it + return; + } + shouldFillCache = false; - InitReaderManager(); + InitReaderManager(); - bool aborted = false; - DirectoryReader reader = readerManager.Acquire(); - try - { - TermsEnum termsEnum = null; - DocsEnum docsEnum = null; - foreach (AtomicReaderContext ctx in reader.Leaves) + bool aborted = false; + DirectoryReader reader = readerManager.Acquire(); + try { - Terms terms = ctx.AtomicReader.GetTerms(Consts.FULL); - if (terms != null) // cannot really happen, but be on the safe side + TermsEnum termsEnum = null; + DocsEnum docsEnum = null; + foreach (AtomicReaderContext ctx in reader.Leaves) { - termsEnum = terms.GetEnumerator(termsEnum); - while (termsEnum.MoveNext()) + Terms terms = ctx.AtomicReader.GetTerms(Consts.FULL); + if (terms != null) // cannot really happen, but be on the safe side { - if (!cache.IsFull) - { - BytesRef t = termsEnum.Term; - // Since we guarantee uniqueness of categories, each term has exactly - // one document. Also, since we do not allow removing categories (and - // hence documents), there are no deletions in the index. Therefore, it - // is sufficient to call next(), and then doc(), exactly once with no - // 'validation' checks. - FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(t.Utf8ToString())); - docsEnum = termsEnum.Docs(null, docsEnum, DocsFlags.NONE); - bool res = cache.Put(cp, docsEnum.NextDoc() + ctx.DocBase); - if (Debugging.AssertsEnabled) Debugging.Assert(!res, "entries should not have been evicted from the cache"); - } - else + termsEnum = terms.GetEnumerator(termsEnum); + while (termsEnum.MoveNext()) { - // the cache is full and the next put() will evict entries from it, therefore abort the iteration. - aborted = true; - break; + if (!cache.IsFull) + { + BytesRef t = termsEnum.Term; + // Since we guarantee uniqueness of categories, each term has exactly + // one document. Also, since we do not allow removing categories (and + // hence documents), there are no deletions in the index. Therefore, it + // is sufficient to call next(), and then doc(), exactly once with no + // 'validation' checks. + FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(t.Utf8ToString())); + docsEnum = termsEnum.Docs(null, docsEnum, DocsFlags.NONE); + bool res = cache.Put(cp, docsEnum.NextDoc() + ctx.DocBase); + if (Debugging.AssertsEnabled) Debugging.Assert(!res, "entries should not have been evicted from the cache"); + } + else + { + // the cache is full and the next put() will evict entries from it, therefore abort the iteration. + aborted = true; + break; + } } } - } - if (aborted) - { - break; + if (aborted) + { + break; + } } } - } - finally - { - readerManager.Release(reader); - } - - cacheIsComplete = !aborted; - if (cacheIsComplete) - { - //lock (syncLock) // LUCENENET: the caller of this method already has a lock, so we don't need to make it recursive + finally { - // everything is in the cache, so no need to keep readerManager open. - // this block is executed in a sync block so that it works well with - // initReaderManager called in parallel. - readerManager.Dispose(); - readerManager = null; - initializedReaderManager = false; + readerManager.Release(reader); } - } - } - private TaxonomyIndexArrays GetTaxoArrays() - { - var result = taxoArrays; // LUCENENET: Careful, we need to ensure a parallel thread does't wipe out our return value - if (result is null) - { - lock (syncLock) + cacheIsComplete = !aborted; + if (cacheIsComplete) { - return GetTaxoArraysLocked(); + lock (syncLock) + { + // everything is in the cache, so no need to keep readerManager open. + // this block is executed in a sync block so that it works well with + // initReaderManager called in parallel. + readerManager.Dispose(); + readerManager = null; + initializedReaderManager = false; + } } } - return result; } - private TaxonomyIndexArrays GetTaxoArraysLocked() + private TaxonomyIndexArrays GetTaxoArrays() { - var result = taxoArrays; // LUCENENET: Careful, we need to ensure a parallel thread does't wipe out our return value - if (result is null) + if (taxoArrays is null) { - InitReaderManager(); - - DirectoryReader reader = readerManager.Acquire(); - try - { - return taxoArrays = new TaxonomyIndexArrays(reader); - } - finally + lock (syncLock) { - readerManager.Release(reader); + if (taxoArrays is null) + { + InitReaderManager(); + DirectoryReader reader = readerManager.Acquire(); + try + { + // according to Java Concurrency, this might perform better on some + // JVMs, since the object initialization doesn't happen on the + // volatile member. + var tmpArrays = new TaxonomyIndexArrays(reader); + taxoArrays = tmpArrays; + } + finally + { + readerManager.Release(reader); + } + } } } - return result; + return taxoArrays; } public virtual int GetParent(int ordinal)
