Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java (working copy) @@ -33,8 +33,8 @@ import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -71,7 +71,7 @@ IndexTaxonomyReaderPair pair = new IndexTaxonomyReaderPair(); pair.indexReader = IndexReader.open(dirs[i][0]); pair.indexSearcher = new IndexSearcher(pair.indexReader); - pair.taxReader = new LuceneTaxonomyReader(dirs[i][1]); + pair.taxReader = new DirectoryTaxonomyReader(dirs[i][1]); pairs[i] = pair; } return pairs; @@ -85,7 +85,7 @@ pair.indexWriter = new IndexWriter(dirs[i][0], new IndexWriterConfig( LuceneTestCase.TEST_VERSION_CURRENT, new StandardAnalyzer( LuceneTestCase.TEST_VERSION_CURRENT))); - pair.taxWriter = new LuceneTaxonomyWriter(dirs[i][1]); + pair.taxWriter = new DirectoryTaxonomyWriter(dirs[i][1]); pair.indexWriter.commit(); pair.taxWriter.commit(); pairs[i] = pair; Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/FacetTestBase.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/FacetTestBase.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/FacetTestBase.java (working copy) @@ -41,8 +41,8 @@ import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -135,7 +135,7 @@ } RandomIndexWriter iw = new RandomIndexWriter(random, indexDir, getIndexWriterConfig(getAnalyzer())); - TaxonomyWriter taxo = new LuceneTaxonomyWriter(taxoDir, OpenMode.CREATE); + TaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); populateIndex(iw, taxo, getFacetIndexingParams(partitionSize)); @@ -146,7 +146,7 @@ iw.close(); // prepare for searching - taxoReader = new LuceneTaxonomyReader(taxoDir); + taxoReader = new DirectoryTaxonomyReader(taxoDir); indexReader = IndexReader.open(indexDir); searcher = newSearcher(indexReader); } Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/search/association/AssociationsFacetRequestTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/search/association/AssociationsFacetRequestTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/search/association/AssociationsFacetRequestTest.java (working copy) @@ -29,8 +29,8 @@ import org.apache.lucene.facet.search.results.FacetResult; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -69,7 +69,7 @@ RandomIndexWriter writer = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.KEYWORD, false))); - TaxonomyWriter taxoWriter = new LuceneTaxonomyWriter(taxoDir); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); EnhancementsDocumentBuilder builder = new EnhancementsDocumentBuilder( taxoWriter, new DefaultEnhancementsIndexingParams( @@ -106,7 +106,7 @@ @Test public void testIntSumAssociation() throws Exception { - LuceneTaxonomyReader taxo = new LuceneTaxonomyReader(taxoDir); + DirectoryTaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); // facet requests for two facets FacetSearchParams fsp = new FacetSearchParams(); @@ -132,7 +132,7 @@ @Test public void testFloatSumAssociation() throws Exception { - LuceneTaxonomyReader taxo = new LuceneTaxonomyReader(taxoDir); + DirectoryTaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); // facet requests for two facets FacetSearchParams fsp = new FacetSearchParams(); @@ -161,7 +161,7 @@ // Same category list cannot be aggregated by two different aggregators. If // you want to do that, you need to separate the categories into two // category list (you'll still have one association list). - LuceneTaxonomyReader taxo = new LuceneTaxonomyReader(taxoDir); + DirectoryTaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); // facet requests for two facets FacetSearchParams fsp = new FacetSearchParams(); Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java (working copy) @@ -32,8 +32,8 @@ import org.apache.lucene.facet.search.params.FacetSearchParams; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -57,7 +57,7 @@ private FacetSearchParams defaultParams = new FacetSearchParams(); private FacetSearchParams nonDefaultParams; private static IndexReader reader; - private static LuceneTaxonomyReader taxo; + private static DirectoryTaxonomyReader taxo; private static Directory dir; private static Directory taxoDir; @@ -78,7 +78,7 @@ newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.KEYWORD, false))); taxoDir = newDirectory(); - TaxonomyWriter taxoWriter = new LuceneTaxonomyWriter(taxoDir); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); for (int i = 0; i < 100; i++) { ArrayList paths = new ArrayList(); @@ -104,7 +104,7 @@ reader = writer.getReader(); writer.close(); - taxo = new LuceneTaxonomyReader(taxoDir); + taxo = new DirectoryTaxonomyReader(taxoDir); } @Test Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/MultiIteratorsPerCLParamsTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/MultiIteratorsPerCLParamsTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/MultiIteratorsPerCLParamsTest.java (working copy) @@ -32,8 +32,8 @@ import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; import org.apache.lucene.facet.util.ScoredDocIdsUtils; /** @@ -93,7 +93,7 @@ Directory taxoDir = newDirectory(); populateIndex(iParams, indexDir, taxoDir); - TaxonomyReader taxo = new LuceneTaxonomyReader(taxoDir); + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); IndexReader reader = IndexReader.open(indexDir); CategoryListCache clCache = null; @@ -168,7 +168,7 @@ Directory taxoDir) throws Exception { RandomIndexWriter writer = new RandomIndexWriter(random, indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.KEYWORD, false))); - TaxonomyWriter taxoWriter = new LuceneTaxonomyWriter(taxoDir); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); for (CategoryPath[] categories : perDocCategories) { writer.addDocument(new CategoryDocumentBuilder(taxoWriter, iParams) Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/FacetRequestTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/FacetRequestTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/FacetRequestTest.java (working copy) @@ -9,7 +9,7 @@ import org.apache.lucene.facet.search.FacetResultsHandler; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -58,8 +58,8 @@ // create empty indexes, so that LTR ctor won't complain about a missing index. new IndexWriter(dir1, new IndexWriterConfig(TEST_VERSION_CURRENT, null)).close(); new IndexWriter(dir2, new IndexWriterConfig(TEST_VERSION_CURRENT, null)).close(); - TaxonomyReader tr1 = new LuceneTaxonomyReader(dir1); - TaxonomyReader tr2 = new LuceneTaxonomyReader(dir2); + TaxonomyReader tr1 = new DirectoryTaxonomyReader(dir1); + TaxonomyReader tr2 = new DirectoryTaxonomyReader(dir2); FacetResultsHandler frh1 = fr.createFacetResultsHandler(tr1); FacetResultsHandler frh2 = fr.createFacetResultsHandler(tr2); assertTrue("should not return the same FacetResultHandler instance for different TaxonomyReader instances", frh1 != frh2); @@ -77,7 +77,7 @@ Directory dir = newDirectory(); // create empty indexes, so that LTR ctor won't complain about a missing index. new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, null)).close(); - TaxonomyReader tr = new LuceneTaxonomyReader(dir); + TaxonomyReader tr = new DirectoryTaxonomyReader(dir); FacetResultsHandler frh = fr.createFacetResultsHandler(tr); fr.setDepth(10); assertEquals(FacetRequest.DEFAULT_DEPTH, frh.getFacetRequest().getDepth()); Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/FacetSearchParamsTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/FacetSearchParamsTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/search/params/FacetSearchParamsTest.java (working copy) @@ -8,8 +8,8 @@ import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; import org.apache.lucene.facet.util.PartitionsUtils; /** @@ -37,8 +37,8 @@ assertEquals("unexpected default facet indexing params class", DefaultFacetIndexingParams.class.getName(), fsp.getFacetIndexingParams().getClass().getName()); assertEquals("no facet requests should be added by default", 0, fsp.getFacetRequests().size()); Directory dir = newDirectory(); - new LuceneTaxonomyWriter(dir).close(); - TaxonomyReader tr = new LuceneTaxonomyReader(dir); + new DirectoryTaxonomyWriter(dir).close(); + TaxonomyReader tr = new DirectoryTaxonomyReader(dir); assertEquals("unexpected partition offset for 0 categories", 1, PartitionsUtils.partitionOffset(fsp, 1, tr)); assertEquals("unexpected partition size for 0 categories", 1, PartitionsUtils.partitionSize(fsp,tr)); tr.close(); @@ -56,11 +56,11 @@ public void testPartitionSizeWithCategories() throws Exception { FacetSearchParams fsp = new FacetSearchParams(); Directory dir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(dir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(dir); tw.addCategory(new CategoryPath("a")); tw.commit(); tw.close(); - TaxonomyReader tr = new LuceneTaxonomyReader(dir); + TaxonomyReader tr = new DirectoryTaxonomyReader(dir); assertEquals("unexpected partition offset for 1 categories", 2, PartitionsUtils.partitionOffset(fsp, 1, tr)); assertEquals("unexpected partition size for 1 categories", 2, PartitionsUtils.partitionSize(fsp,tr)); tr.close(); Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestTotalFacetCountsCache.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestTotalFacetCountsCache.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestTotalFacetCountsCache.java (working copy) @@ -34,8 +34,8 @@ import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.SlowRAMDirectory; import org.apache.lucene.util._TestUtil; @@ -67,12 +67,12 @@ */ private static class TFCThread extends Thread { private final IndexReader r; - private final LuceneTaxonomyReader tr; + private final DirectoryTaxonomyReader tr; private final FacetIndexingParams iParams; TotalFacetCounts tfc; - public TFCThread(IndexReader r, LuceneTaxonomyReader tr, FacetIndexingParams iParams) { + public TFCThread(IndexReader r, DirectoryTaxonomyReader tr, FacetIndexingParams iParams) { this.r = r; this.tr = tr; this.iParams = iParams; @@ -156,7 +156,7 @@ // Open the slow readers IndexReader slowIndexReader = IndexReader.open(indexDir); - TaxonomyReader slowTaxoReader = new LuceneTaxonomyReader(taxoDir); + TaxonomyReader slowTaxoReader = new DirectoryTaxonomyReader(taxoDir); // Class to perform search and return results as threads class Multi extends Thread { @@ -420,7 +420,7 @@ // Write index using 'normal' directories IndexWriter w = new IndexWriter(indexDir, new IndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false))); - LuceneTaxonomyWriter tw = new LuceneTaxonomyWriter(taxoDir); + DirectoryTaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir); DefaultFacetIndexingParams iParams = new DefaultFacetIndexingParams(); // Add documents and facets for (int i = 0; i < 1000; i++) { @@ -433,7 +433,7 @@ taxoDir.setSleepMillis(1); IndexReader r = IndexReader.open(indexDir); - LuceneTaxonomyReader tr = new LuceneTaxonomyReader(taxoDir); + DirectoryTaxonomyReader tr = new DirectoryTaxonomyReader(taxoDir); // Create and start threads. Thread1 should lock the cache and calculate // the TFC array. The second thread should block until the first is Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java (working copy) @@ -35,8 +35,8 @@ import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -64,7 +64,7 @@ RandomIndexWriter iw = new RandomIndexWriter(random, dirs[0][0], newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new LuceneTaxonomyWriter(dirs[0][1], OpenMode.CREATE); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); /** * Configure with no custom counting lists @@ -77,7 +77,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new LuceneTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -106,7 +106,7 @@ RandomIndexWriter iw = new RandomIndexWriter(random, dirs[0][0], newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new LuceneTaxonomyWriter(dirs[0][1], + TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); PerDimensionIndexingParams iParams = new PerDimensionIndexingParams(); @@ -118,7 +118,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new LuceneTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -147,7 +147,7 @@ RandomIndexWriter iw = new RandomIndexWriter(random, dirs[0][0], newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new LuceneTaxonomyWriter(dirs[0][1], + TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); PerDimensionIndexingParams iParams = new PerDimensionIndexingParams(); @@ -161,7 +161,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new LuceneTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -198,7 +198,7 @@ RandomIndexWriter iw = new RandomIndexWriter(random, dirs[0][0], newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new LuceneTaxonomyWriter(dirs[0][1], OpenMode.CREATE); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); PerDimensionIndexingParams iParams = new PerDimensionIndexingParams(); iParams.addCategoryListParams(new CategoryPath("Band"), @@ -211,7 +211,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new LuceneTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -239,7 +239,7 @@ RandomIndexWriter iw = new RandomIndexWriter(random, dirs[0][0], newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new LuceneTaxonomyWriter(dirs[0][1], + TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); PerDimensionIndexingParams iParams = new PerDimensionIndexingParams(); @@ -256,7 +256,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new LuceneTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java (working copy) @@ -36,8 +36,8 @@ import org.apache.lucene.facet.search.results.FacetResultNode; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; import org.apache.lucene.facet.util.PartitionsUtils; /** @@ -87,7 +87,7 @@ RandomIndexWriter iw = new RandomIndexWriter(random, iDir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE)); - TaxonomyWriter tw = new LuceneTaxonomyWriter(tDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(tDir); prvt_add(iParams, iw, tw, "a", "b"); prvt_add(iParams, iw, tw, "a", "b", "1"); prvt_add(iParams, iw, tw, "a", "b", "1"); @@ -111,7 +111,7 @@ tw.close(); IndexSearcher is = newSearcher(ir); - LuceneTaxonomyReader tr = new LuceneTaxonomyReader(tDir); + DirectoryTaxonomyReader tr = new DirectoryTaxonomyReader(tDir); // Get all of the documents and run the query, then do different // facet counts and compare to control Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/index/streaming/CategoryParentsStreamTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/index/streaming/CategoryParentsStreamTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/index/streaming/CategoryParentsStreamTest.java (working copy) @@ -19,7 +19,7 @@ import org.apache.lucene.facet.index.streaming.CategoryListTokenizer; import org.apache.lucene.facet.index.streaming.CategoryParentsStream; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -50,7 +50,7 @@ @Test public void testStreamDefaultParams() throws IOException { Directory directory = newDirectory(); - TaxonomyWriter taxonomyWriter = new LuceneTaxonomyWriter( + TaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter( directory); CategoryParentsStream stream = new CategoryParentsStream( new CategoryAttributesStream(categoryContainer), @@ -77,7 +77,7 @@ @Test public void testStreamNonTopLevelParams() throws IOException { Directory directory = newDirectory(); - final TaxonomyWriter taxonomyWriter = new LuceneTaxonomyWriter( + final TaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter( directory); FacetIndexingParams indexingParams = new DefaultFacetIndexingParams() { @Override @@ -118,7 +118,7 @@ @Test public void testNoRetainableAttributes() throws IOException, FacetException { Directory directory = newDirectory(); - TaxonomyWriter taxonomyWriter = new LuceneTaxonomyWriter(directory); + TaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter(directory); new CategoryParentsStream(new CategoryAttributesStream(categoryContainer), taxonomyWriter, new DefaultFacetIndexingParams()); @@ -152,7 +152,7 @@ @Test public void testRetainableAttributes() throws IOException, FacetException { Directory directory = newDirectory(); - TaxonomyWriter taxonomyWriter = new LuceneTaxonomyWriter( + TaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter( directory); FacetIndexingParams indexingParams = new DefaultFacetIndexingParams(); Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/index/streaming/CategoryTokenizerTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/index/streaming/CategoryTokenizerTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/index/streaming/CategoryTokenizerTest.java (working copy) @@ -17,7 +17,7 @@ import org.apache.lucene.facet.index.streaming.CategoryTokenizer; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -47,7 +47,7 @@ @Test public void testTokensDefaultParams() throws IOException { Directory directory = newDirectory(); - TaxonomyWriter taxonomyWriter = new LuceneTaxonomyWriter( + TaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter( directory); DefaultFacetIndexingParams indexingParams = new DefaultFacetIndexingParams(); CategoryTokenizer tokenizer = new CategoryTokenizer( @@ -86,7 +86,7 @@ @Test public void testLongCategoryPath() throws IOException { Directory directory = newDirectory(); - TaxonomyWriter taxonomyWriter = new LuceneTaxonomyWriter( + TaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter( directory); List longCategory = new ArrayList(); Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/index/categorypolicy/OrdinalPolicyTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/index/categorypolicy/OrdinalPolicyTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/index/categorypolicy/OrdinalPolicyTest.java (working copy) @@ -10,7 +10,7 @@ import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -48,7 +48,7 @@ public void testNonTopLevelOrdinalPolicy() throws Exception { Directory dir = newDirectory(); TaxonomyWriter taxonomy = null; - taxonomy = new LuceneTaxonomyWriter(dir); + taxonomy = new DirectoryTaxonomyWriter(dir); int[] topLevelOrdinals = new int[10]; String[] topLevelStrings = new String[10]; Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/index/categorypolicy/PathPolicyTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/index/categorypolicy/PathPolicyTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/index/categorypolicy/PathPolicyTest.java (working copy) @@ -9,7 +9,7 @@ import org.apache.lucene.facet.index.categorypolicy.PathPolicy; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -54,7 +54,7 @@ public void testNonTopLevelPathPolicy() throws Exception { Directory dir = newDirectory(); TaxonomyWriter taxonomy = null; - taxonomy = new LuceneTaxonomyWriter(dir); + taxonomy = new DirectoryTaxonomyWriter(dir); CategoryPath[] topLevelPaths = new CategoryPath[10]; String[] topLevelStrings = new String[10]; Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/index/FacetsPayloadProcessorProviderTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/index/FacetsPayloadProcessorProviderTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/index/FacetsPayloadProcessorProviderTest.java (working copy) @@ -23,8 +23,8 @@ import org.apache.lucene.facet.search.results.FacetResult; import org.apache.lucene.facet.search.results.FacetResultNode; import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -68,7 +68,7 @@ private void verifyResults(Directory dir, Directory taxDir) throws IOException { IndexReader reader1 = IndexReader.open(dir); - LuceneTaxonomyReader taxReader = new LuceneTaxonomyReader(taxDir); + DirectoryTaxonomyReader taxReader = new DirectoryTaxonomyReader(taxDir); IndexSearcher searcher = newSearcher(reader1); FacetSearchParams fsp = new FacetSearchParams(); fsp.addFacetRequest(new CountFacetRequest(new CategoryPath("tag"), NUM_DOCS)); @@ -94,7 +94,7 @@ new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)); RandomIndexWriter writer = new RandomIndexWriter(random, dir, config); - LuceneTaxonomyWriter taxonomyWriter = new LuceneTaxonomyWriter(taxDir); + DirectoryTaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter(taxDir); for (int i = 1; i <= NUM_DOCS; i++) { Document doc = new Document(); List categoryPaths = new ArrayList(i + 1); Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/enhancements/TwoEnhancementsTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/enhancements/TwoEnhancementsTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/enhancements/TwoEnhancementsTest.java (working copy) @@ -21,7 +21,7 @@ import org.apache.lucene.facet.search.DrillDown; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -58,7 +58,7 @@ RandomIndexWriter indexWriter = new RandomIndexWriter(random, indexDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false))); - TaxonomyWriter taxo = new LuceneTaxonomyWriter(taxoDir); + TaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir); // a category document builder will add the categories to a document // once build() is called @@ -103,7 +103,7 @@ RandomIndexWriter indexWriter = new RandomIndexWriter(random, indexDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false))); - TaxonomyWriter taxo = new LuceneTaxonomyWriter(taxoDir); + TaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir); // a category document builder will add the categories to a document // once build() is called Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/enhancements/association/CustomAssociationPropertyTest.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/enhancements/association/CustomAssociationPropertyTest.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/enhancements/association/CustomAssociationPropertyTest.java (working copy) @@ -16,8 +16,8 @@ import org.apache.lucene.facet.index.attributes.CategoryAttributeImpl; import org.apache.lucene.facet.index.attributes.CategoryProperty; import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -59,7 +59,7 @@ RandomIndexWriter w = new RandomIndexWriter(random, iDir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.KEYWORD, false))); - LuceneTaxonomyWriter taxoW = new LuceneTaxonomyWriter(tDir); + DirectoryTaxonomyWriter taxoW = new DirectoryTaxonomyWriter(tDir); CategoryContainer cc = new CategoryContainer(); EnhancementsDocumentBuilder builder = new EnhancementsDocumentBuilder(taxoW, iParams); @@ -75,7 +75,7 @@ IndexReader reader = w.getReader(); w.close(); - LuceneTaxonomyReader taxo = new LuceneTaxonomyReader(tDir); + DirectoryTaxonomyReader taxo = new DirectoryTaxonomyReader(tDir); String field = iParams.getCategoryListParams(new CategoryPath("0")).getTerm().field(); AssociationsPayloadIterator api = new AssociationsPayloadIterator(reader, field); Index: lucene/contrib/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java =================================================================== --- lucene/contrib/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java (revision 1196597) +++ lucene/contrib/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java (working copy) @@ -14,8 +14,8 @@ import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.facet.taxonomy.TaxonomyReader.ChildrenArrays; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; import org.apache.lucene.util.SlowRAMDirectory; /** @@ -159,7 +159,7 @@ @Test public void testWriter() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); // Also check TaxonomyWriter.getSize() - see that the taxonomy's size // is what we expect it to be. @@ -175,7 +175,7 @@ @Test public void testWriterTwice() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); // run fillTaxonomy again - this will try to add the same categories // again, and check that we see the same ordinal paths again, not @@ -197,10 +197,10 @@ @Test public void testWriterTwice2() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); tw.close(); - tw = new LuceneTaxonomyWriter(indexDir); + tw = new DirectoryTaxonomyWriter(indexDir); // run fillTaxonomy again - this will try to add the same categories // again, and check that we see the same ordinals again, not different // ones, and that the number of categories hasn't grown by the new @@ -222,7 +222,7 @@ public void testWriterTwice3() throws Exception { Directory indexDir = newDirectory(); // First, create and fill the taxonomy - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); tw.close(); // Now, open the same taxonomy and add the same categories again. @@ -231,7 +231,7 @@ // all into memory and close it's reader. The bug was that it closed // the reader, but forgot that it did (because it didn't set the reader // reference to null). - tw = new LuceneTaxonomyWriter(indexDir); + tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); // Add one new category, just to make commit() do something: tw.addCategory(new CategoryPath("hi")); @@ -253,7 +253,7 @@ @Test public void testWriterSimpler() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); assertEquals(1, tw.getSize()); // the root only // Test that adding a new top-level category works assertEquals(1, tw.addCategory(new CategoryPath("a"))); @@ -297,12 +297,12 @@ @Test public void testRootOnly() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); // right after opening the index, it should already contain the // root, so have size 1: assertEquals(1, tw.getSize()); tw.close(); - TaxonomyReader tr = new LuceneTaxonomyReader(indexDir); + TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir); assertEquals(1, tr.getSize()); assertEquals(0, tr.getPath(0).length()); assertEquals(TaxonomyReader.INVALID_ORDINAL, tr.getParent(0)); @@ -319,9 +319,9 @@ @Test public void testRootOnly2() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); tw.commit(); - TaxonomyReader tr = new LuceneTaxonomyReader(indexDir); + TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir); assertEquals(1, tr.getSize()); assertEquals(0, tr.getPath(0).length()); assertEquals(TaxonomyReader.INVALID_ORDINAL, tr.getParent(0)); @@ -339,10 +339,10 @@ @Test public void testReaderBasic() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); tw.close(); - TaxonomyReader tr = new LuceneTaxonomyReader(indexDir); + TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir); // test TaxonomyReader.getSize(): assertEquals(expectedCategories.length, tr.getSize()); @@ -398,10 +398,10 @@ @Test public void testReaderParent() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); tw.close(); - TaxonomyReader tr = new LuceneTaxonomyReader(indexDir); + TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir); // check that the parent of the root ordinal is the invalid ordinal: assertEquals(TaxonomyReader.INVALID_ORDINAL, tr.getParent(0)); @@ -463,11 +463,11 @@ @Test public void testWriterParent1() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); tw.close(); - tw = new LuceneTaxonomyWriter(indexDir); - TaxonomyReader tr = new LuceneTaxonomyReader(indexDir); + tw = new DirectoryTaxonomyWriter(indexDir); + TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir); checkWriterParent(tr, tw); @@ -479,10 +479,10 @@ @Test public void testWriterParent2() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); tw.commit(); - TaxonomyReader tr = new LuceneTaxonomyReader(indexDir); + TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir); checkWriterParent(tr, tw); @@ -542,10 +542,10 @@ @Test public void testReaderParentArray() throws Exception { Directory indexDir = newDirectory(); - TaxonomyWriter tw = new LuceneTaxonomyWriter(indexDir); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir); fillTaxonomy(tw); tw.close(); - TaxonomyReader tr = new LuceneTaxonomyReader(indexDir); + TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir); int[] parents = tr.getParentArray(); assertEquals(tr.getSize(), parents.length); for (int i=0; i= copytr.getSize()); } else { @@ -188,8 +188,8 @@ // Check that all the new categories in the main taxonomy are in // lexicographic order. This isn't a requirement of our API, but happens // this way in our current implementation. - TaxonomyReader tr = new LuceneTaxonomyReader(dirs[0]); - TaxonomyReader copytr = new LuceneTaxonomyReader(copydirs[0]); + TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0]); + TaxonomyReader copytr = new DirectoryTaxonomyReader(copydirs[0]); if (tr.getSize() > copytr.getSize()) { String prev = tr.getPath(copytr.getSize()).toString(); for (int j=copytr.getSize()+1; jordinal mappings, used in TaxonomyWriter implementations - * (such as {@link LuceneTaxonomyWriter}). + * (such as {@link DirectoryTaxonomyWriter}). *

* It basically has put() methods for adding a mapping, and get() for looking * a mapping up the cache. The cache does not guarantee to hold Index: lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/writercache/lru/NameIntCacheLRU.java =================================================================== --- lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/writercache/lru/NameIntCacheLRU.java (revision 1196597) +++ lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/writercache/lru/NameIntCacheLRU.java (working copy) @@ -119,7 +119,7 @@ * If cache is full remove least recently used entries from cache. * Return true if anything was removed, false otherwise. * - * See comment in {@link LuceneTaxonomyWriter#addToCache(String, Integer)} + * See comment in {@link DirectoryTaxonomyWriter#addToCache(String, Integer)} * for an explanation why we clean 2/3rds of the cache, and not just one * entry. */ Index: lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyWriter.java =================================================================== --- lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyWriter.java (revision 1196597) +++ lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyWriter.java (working copy) @@ -2,9 +2,8 @@ import java.io.Closeable; import java.io.IOException; -import java.util.Map; -import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.util.TwoPhaseCommit; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -52,7 +51,7 @@ * * @lucene.experimental */ -public interface TaxonomyWriter extends Closeable { +public interface TaxonomyWriter extends Closeable, TwoPhaseCommit { /** * addCategory() adds a category with a given path name to the taxonomy, @@ -67,32 +66,6 @@ public int addCategory(CategoryPath categoryPath) throws IOException; /** - * Calling commit() ensures that all the categories written so far are - * visible to a reader that is opened (or reopened) after that call. - * When the index is closed(), commit() is also implicitly done. - */ - public void commit() throws IOException; - - /** - * Like commit(), but also store properties with the index. These properties - * are retrievable by {@link TaxonomyReader#getCommitUserData}. - * See {@link IndexWriter#commit(Map)}. - */ - public void commit(Map commitUserData) throws IOException; - - /** - * prepare most of the work needed for a two-phase commit. - * See {@link IndexWriter#prepareCommit}. - */ - public void prepareCommit() throws IOException; - - /** - * Like above, and also prepares to store user data with the index. - * See {@link IndexWriter#prepareCommit(Map)} - */ - public void prepareCommit(Map commitUserData) throws IOException; - - /** * getParent() returns the ordinal of the parent category of the category * with the given ordinal. *

@@ -108,8 +81,8 @@ * ordinal), an ArrayIndexOutOfBoundsException is thrown. However, it is * expected that getParent will only be called for ordinals which are * already known to be in the taxonomy. + * TODO (Facet): instead of a getParent(ordinal) method, consider having a *

- * TODO (Facet): instead of a getParent(ordinal) method, consider having a * getCategory(categorypath, prefixlen) which is similar to addCategory * except it doesn't add new categories; This method can be used to get * the ordinals of all prefixes of the given category, and it can use Index: lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/DirectoryTaxonomyWriter.java =================================================================== --- lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/DirectoryTaxonomyWriter.java (working copy) +++ lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/DirectoryTaxonomyWriter.java (working copy) @@ -60,29 +60,24 @@ */ /** - * {@link TaxonomyWriter} which uses a Lucene index to store the taxonomy + * {@link TaxonomyWriter} which uses a {@link Directory} to store the taxonomy * information on disk, and keeps an additional in-memory cache of some or all * categories. - *

- * By using a Lucene index to store the information on disk, rather than some - * specialized file format, we get for "free" Lucene's correctness (especially - * regarding multi-process concurrency), and the ability to write to any - * implementation of Directory (and not just the file system). - *

- * In addition to the permanently-stored Lucene index, efficiency dictates that - * we also keep an in-memory cache of recently seen or all - * categories, so that we do not need to go back to disk for every category - * addition to see which ordinal this category already has, if any. A - * {@link TaxonomyWriterCache} object determines the specific caching algorithm - * used. *

+ * In addition to the permanently-stored information in the {@link Directory}, + * efficiency dictates that we also keep an in-memory cache of recently + * seen or all categories, so that we do not need to go back to disk + * for every category addition to see which ordinal this category already has, + * if any. A {@link TaxonomyWriterCache} object determines the specific caching + * algorithm used. + *

* This class offers some hooks for extending classes to control the - * {@link IndexWriter} instance that is used. See {@link #openLuceneIndex} and - * {@link #closeLuceneIndex()} . + * {@link IndexWriter} instance that is used. See {@link #openIndexWriter} and + * {@link #closeIndexWriter()} . * * @lucene.experimental */ -public class LuceneTaxonomyWriter implements TaxonomyWriter { +public class DirectoryTaxonomyWriter implements TaxonomyWriter { protected IndexWriter indexWriter; private int nextID; @@ -167,12 +162,12 @@ * @throws IOException * if another error occurred. */ - public LuceneTaxonomyWriter(Directory directory, OpenMode openMode, + public DirectoryTaxonomyWriter(Directory directory, OpenMode openMode, TaxonomyWriterCache cache) throws CorruptIndexException, LockObtainFailedException, IOException { - openLuceneIndex(directory, openMode); + openIndexWriter(directory, openMode); reader = null; parentStreamField = new Field(Consts.FIELD_PAYLOADS, parentStream); @@ -214,14 +209,16 @@ * etc.
* NOTE: the instance this method returns will be closed upon calling * to {@link #close()}. If you wish to do something different, you should - * override {@link #closeLuceneIndex()}. + * override {@link #closeIndexWriter()}. * - * @param directory the {@link Directory} on top of wich an - * {@link IndexWriter} should be opened. - * @param openMode see {@link OpenMode} + * @param directory + * the {@link Directory} on top of which an {@link IndexWriter} + * should be opened. + * @param openMode + * see {@link OpenMode} */ - protected void openLuceneIndex (Directory directory, OpenMode openMode) - throws CorruptIndexException, LockObtainFailedException, IOException { + protected void openIndexWriter(Directory directory, OpenMode openMode) + throws IOException { // Make sure we use a MergePolicy which merges segments in-order and thus // keeps the doc IDs ordered as well (this is crucial for the taxonomy // index). @@ -246,7 +243,7 @@ * Creates a new instance with a default cached as defined by * {@link #defaultTaxonomyWriterCache()}. */ - public LuceneTaxonomyWriter(Directory directory, OpenMode openMode) + public DirectoryTaxonomyWriter(Directory directory, OpenMode openMode) throws CorruptIndexException, LockObtainFailedException, IOException { this(directory, openMode, defaultTaxonomyWriterCache()); } @@ -265,7 +262,7 @@ // convenience constructors: - public LuceneTaxonomyWriter(Directory d) + public DirectoryTaxonomyWriter(Directory d) throws CorruptIndexException, LockObtainFailedException, IOException { this(d, OpenMode.CREATE_OR_APPEND); @@ -277,7 +274,7 @@ * {@link Directory}. */ public synchronized void close() throws CorruptIndexException, IOException { - closeLuceneIndex(); + closeIndexWriter(); closeResources(); } @@ -312,9 +309,9 @@ /** * A hook for extending classes to control closing the {@link IndexWriter} - * returned by {@link #openLuceneIndex}. + * returned by {@link #openIndexWriter}. */ - protected void closeLuceneIndex() throws CorruptIndexException, IOException { + protected void closeIndexWriter() throws CorruptIndexException, IOException { if (indexWriter != null) { indexWriter.close(); indexWriter = null; @@ -557,8 +554,8 @@ private synchronized void refreshReader() throws IOException { if (reader != null) { - IndexReader r2 = reader.reopen(); - if (reader != r2) { + IndexReader r2 = IndexReader.openIfChanged(reader); + if (r2 != null) { reader.close(); reader = r2; } @@ -578,7 +575,7 @@ /** * Like commit(), but also store properties with the index. These properties - * are retrievable by {@link LuceneTaxonomyReader#getCommitUserData}. + * are retrievable by {@link DirectoryTaxonomyReader#getCommitUserData}. * See {@link TaxonomyWriter#commit(Map)}. */ public synchronized void commit(Map commitUserData) throws CorruptIndexException, IOException { @@ -998,4 +995,9 @@ return null; } + public void rollback() throws IOException { + indexWriter.rollback(); + refreshReader(); + } + } Index: lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/DirectoryTaxonomyReader.java =================================================================== --- lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/DirectoryTaxonomyReader.java (working copy) +++ lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/DirectoryTaxonomyReader.java (working copy) @@ -36,24 +36,21 @@ * limitations under the License. */ -/** - * LuceneTaxonomyReader is a {@link TaxonomyReader} which retrieves stored - * taxonomy information from a separate Lucene index. By using a Lucene index, - * rather than some specialized file format, we get for "free" its correctness - * (especially regarding concurrency), and the ability to save it on any - * implementation of Directory (and not just the file system). +/** + * A {@link TaxonomyReader} which retrieves stored taxonomy information from a + * {@link Directory}. *

* Reading from the on-disk index on every method call is too slow, so this - * implementation employs caching: Some methods cache recent requests and - * their results, while other methods prefetch all the data into memory - * and then provide answers directly from in-memory tables. See the - * documentation of individual methods for comments on their performance. + * implementation employs caching: Some methods cache recent requests and their + * results, while other methods prefetch all the data into memory and then + * provide answers directly from in-memory tables. See the documentation of + * individual methods for comments on their performance. * * @lucene.experimental */ -public class LuceneTaxonomyReader implements TaxonomyReader { +public class DirectoryTaxonomyReader implements TaxonomyReader { - private static final Logger logger = Logger.getLogger(LuceneTaxonomyReader.class.getName()); + private static final Logger logger = Logger.getLogger(DirectoryTaxonomyReader.class.getName()); private IndexReader indexReader; @@ -107,8 +104,7 @@ * @throws CorruptIndexException if the Taxonomy is corrupted. * @throws IOException if another error occurred. */ - public LuceneTaxonomyReader(Directory directory) - throws CorruptIndexException, IOException { + public DirectoryTaxonomyReader(Directory directory) throws IOException { this.indexReader = openIndexReader(directory); // These are the default cache sizes; they can be configured after @@ -345,8 +341,8 @@ // safely read indexReader without holding the write lock, because // no other thread can be writing at this time (this method is the // only possible writer, and it is "synchronized" to avoid this case). - IndexReader r2 = indexReader.reopen(); - if (indexReader != r2) { + IndexReader r2 = IndexReader.openIfChanged(indexReader); + if (r2 != null) { IndexReader oldreader = indexReader; // we can close the old searcher, but need to synchronize this // so that we don't close it in the middle that another routine Index: lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyWriter.java =================================================================== --- lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyWriter.java (revision 1196597) +++ lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyWriter.java (working copy) @@ -1,1001 +0,0 @@ -package org.apache.lucene.facet.taxonomy.lucene; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Map; - -import org.apache.lucene.analysis.KeywordAnalyzer; -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; -import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.Field.Index; -import org.apache.lucene.document.Field.Store; -import org.apache.lucene.index.CorruptIndexException; -import org.apache.lucene.index.FieldInfo.IndexOptions; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.IndexWriterConfig.OpenMode; -import org.apache.lucene.index.LogByteSizeMergePolicy; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.TermDocs; -import org.apache.lucene.index.TermEnum; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.LockObtainFailedException; -import org.apache.lucene.store.NativeFSLockFactory; -import org.apache.lucene.store.SimpleFSLockFactory; -import org.apache.lucene.util.Version; - -import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.writercache.TaxonomyWriterCache; -import org.apache.lucene.facet.taxonomy.writercache.cl2o.Cl2oTaxonomyWriterCache; -import org.apache.lucene.facet.taxonomy.writercache.lru.LruTaxonomyWriterCache; - -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * {@link TaxonomyWriter} which uses a Lucene index to store the taxonomy - * information on disk, and keeps an additional in-memory cache of some or all - * categories. - *

- * By using a Lucene index to store the information on disk, rather than some - * specialized file format, we get for "free" Lucene's correctness (especially - * regarding multi-process concurrency), and the ability to write to any - * implementation of Directory (and not just the file system). - *

- * In addition to the permanently-stored Lucene index, efficiency dictates that - * we also keep an in-memory cache of recently seen or all - * categories, so that we do not need to go back to disk for every category - * addition to see which ordinal this category already has, if any. A - * {@link TaxonomyWriterCache} object determines the specific caching algorithm - * used. - *

- * This class offers some hooks for extending classes to control the - * {@link IndexWriter} instance that is used. See {@link #openLuceneIndex} and - * {@link #closeLuceneIndex()} . - * - * @lucene.experimental - */ -public class LuceneTaxonomyWriter implements TaxonomyWriter { - - protected IndexWriter indexWriter; - private int nextID; - private char delimiter = Consts.DEFAULT_DELIMITER; - private SinglePositionTokenStream parentStream = new SinglePositionTokenStream(Consts.PAYLOAD_PARENT); - private Field parentStreamField; - private Field fullPathField; - - private TaxonomyWriterCache cache; - /** - * We call the cache "complete" if we know that every category in our - * taxonomy is in the cache. When the cache is not complete, and - * we can't find a category in the cache, we still need to look for it - * in the on-disk index; Therefore when the cache is not complete, we - * need to open a "reader" to the taxonomy index. - * The cache becomes incomplete if it was never filled with the existing - * categories, or if a put() to the cache ever returned true (meaning - * that some of the cached data was cleared). - */ - private boolean cacheIsComplete; - private IndexReader reader; - private int cacheMisses; - - /** - * setDelimiter changes the character that the taxonomy uses in its internal - * storage as a delimiter between category components. Do not use this - * method unless you really know what you are doing. It has nothing to do - * with whatever character the application may be using to represent - * categories for its own use. - *

- * If you do use this method, make sure you call it before any other methods - * that actually queries the taxonomy. Moreover, make sure you always pass - * the same delimiter for all LuceneTaxonomyWriter and LuceneTaxonomyReader - * objects you create for the same directory. - */ - public void setDelimiter(char delimiter) { - this.delimiter = delimiter; - } - - /** - * Forcibly unlocks the taxonomy in the named directory. - *

- * Caution: this should only be used by failure recovery code, when it is - * known that no other process nor thread is in fact currently accessing - * this taxonomy. - *

- * This method is unnecessary if your {@link Directory} uses a - * {@link NativeFSLockFactory} instead of the default - * {@link SimpleFSLockFactory}. When the "native" lock is used, a lock - * does not stay behind forever when the process using it dies. - */ - public static void unlock(Directory directory) throws IOException { - IndexWriter.unlock(directory); - } - - /** - * Construct a Taxonomy writer. - * - * @param directory - * The {@link Directory} in which to store the taxonomy. Note that - * the taxonomy is written directly to that directory (not to a - * subdirectory of it). - * @param openMode - * Specifies how to open a taxonomy for writing: APPEND - * means open an existing index for append (failing if the index does - * not yet exist). CREATE means create a new index (first - * deleting the old one if it already existed). - * APPEND_OR_CREATE appends to an existing index if there - * is one, otherwise it creates a new index. - * @param cache - * A {@link TaxonomyWriterCache} implementation which determines - * the in-memory caching policy. See for example - * {@link LruTaxonomyWriterCache} and {@link Cl2oTaxonomyWriterCache}. - * If null or missing, {@link #defaultTaxonomyWriterCache()} is used. - * @throws CorruptIndexException - * if the taxonomy is corrupted. - * @throws LockObtainFailedException - * if the taxonomy is locked by another writer. If it is known - * that no other concurrent writer is active, the lock might - * have been left around by an old dead process, and should be - * removed using {@link #unlock(Directory)}. - * @throws IOException - * if another error occurred. - */ - public LuceneTaxonomyWriter(Directory directory, OpenMode openMode, - TaxonomyWriterCache cache) - throws CorruptIndexException, LockObtainFailedException, - IOException { - - openLuceneIndex(directory, openMode); - reader = null; - - parentStreamField = new Field(Consts.FIELD_PAYLOADS, parentStream); - parentStreamField.setOmitNorms(true); - fullPathField = new Field(Consts.FULL, "", Store.YES, Index.NOT_ANALYZED_NO_NORMS); - fullPathField.setIndexOptions(IndexOptions.DOCS_ONLY); - - this.nextID = indexWriter.maxDoc(); - - if (cache==null) { - cache = defaultTaxonomyWriterCache(); - } - this.cache = cache; - - if (nextID == 0) { - cacheIsComplete = true; - // Make sure that the taxonomy always contain the root category - // with category id 0. - addCategory(new CategoryPath()); - refreshReader(); - } else { - // There are some categories on the disk, which we have not yet - // read into the cache, and therefore the cache is incomplete. - // We chose not to read all the categories into the cache now, - // to avoid terrible performance when a taxonomy index is opened - // to add just a single category. We will do it later, after we - // notice a few cache misses. - cacheIsComplete = false; - } - cacheMisses = 0; - } - - /** - * A hook for extensions of this class to provide their own - * {@link IndexWriter} implementation or instance. Extending classes can - * instantiate and configure the {@link IndexWriter} as they see fit, - * including setting a {@link org.apache.lucene.index.MergeScheduler}, or - * {@link org.apache.lucene.index.IndexDeletionPolicy}, different RAM size - * etc.
- * NOTE: the instance this method returns will be closed upon calling - * to {@link #close()}. If you wish to do something different, you should - * override {@link #closeLuceneIndex()}. - * - * @param directory the {@link Directory} on top of wich an - * {@link IndexWriter} should be opened. - * @param openMode see {@link OpenMode} - */ - protected void openLuceneIndex (Directory directory, OpenMode openMode) - throws CorruptIndexException, LockObtainFailedException, IOException { - // Make sure we use a MergePolicy which merges segments in-order and thus - // keeps the doc IDs ordered as well (this is crucial for the taxonomy - // index). - IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_30, - new KeywordAnalyzer()).setOpenMode(openMode).setMergePolicy( - new LogByteSizeMergePolicy()); - indexWriter = new IndexWriter(directory, config); - } - - // Currently overridden by a unit test that verifies that every index we open - // is close()ed. - /** - * Open an {@link IndexReader} from the {@link #indexWriter} member, by - * calling {@link IndexWriter#getReader()}. Extending classes can override - * this method to return their own {@link IndexReader}. - */ - protected IndexReader openReader() throws IOException { - return IndexReader.open(indexWriter, true); - } - - /** - * Creates a new instance with a default cached as defined by - * {@link #defaultTaxonomyWriterCache()}. - */ - public LuceneTaxonomyWriter(Directory directory, OpenMode openMode) - throws CorruptIndexException, LockObtainFailedException, IOException { - this(directory, openMode, defaultTaxonomyWriterCache()); - } - - /** - * Defines the default {@link TaxonomyWriterCache} to use in constructors - * which do not specify one. - *

- * The current default is {@link Cl2oTaxonomyWriterCache} constructed - * with the parameters (1024, 0.15f, 3), i.e., the entire taxonomy is - * cached in memory while building it. - */ - public static TaxonomyWriterCache defaultTaxonomyWriterCache() { - return new Cl2oTaxonomyWriterCache(1024, 0.15f, 3); - } - - // convenience constructors: - - public LuceneTaxonomyWriter(Directory d) - throws CorruptIndexException, LockObtainFailedException, - IOException { - this(d, OpenMode.CREATE_OR_APPEND); - } - - /** - * Frees used resources as well as closes the underlying {@link IndexWriter}, - * which commits whatever changes made to it to the underlying - * {@link Directory}. - */ - public synchronized void close() throws CorruptIndexException, IOException { - closeLuceneIndex(); - closeResources(); - } - - /** - * Returns the number of memory bytes used by the cache. - * @return Number of cache bytes in memory, for CL2O only; zero otherwise. - */ - public int getCacheMemoryUsage() { - if (this.cache == null || !(this.cache instanceof Cl2oTaxonomyWriterCache)) { - return 0; - } - return ((Cl2oTaxonomyWriterCache)this.cache).getMemoryUsage(); - } - - /** - * A hook for extending classes to close additional resources that were used. - * The default implementation closes the {@link IndexReader} as well as the - * {@link TaxonomyWriterCache} instances that were used.
- * NOTE: if you override this method, you should include a - * super.closeResources() call in your implementation. - */ - protected synchronized void closeResources() throws IOException { - if (reader != null) { - reader.close(); - reader = null; - } - if (cache != null) { - cache.close(); - cache = null; - } - } - - /** - * A hook for extending classes to control closing the {@link IndexWriter} - * returned by {@link #openLuceneIndex}. - */ - protected void closeLuceneIndex() throws CorruptIndexException, IOException { - if (indexWriter != null) { - indexWriter.close(); - indexWriter = null; - } - } - - /** - * Look up the given category in the cache and/or the on-disk storage, - * returning the category's ordinal, or a negative number in case the - * category does not yet exist in the taxonomy. - */ - protected int findCategory(CategoryPath categoryPath) throws IOException { - // If we can find the category in our cache, we can return the - // response directly from it: - int res = cache.get(categoryPath); - if (res >= 0) { - return res; - } - // If we know that the cache is complete, i.e., contains every category - // which exists, we can return -1 immediately. However, if the cache is - // not complete, we need to check the disk. - if (cacheIsComplete) { - return -1; - } - cacheMisses++; - // After a few cache misses, it makes sense to read all the categories - // from disk and into the cache. The reason not to do this on the first - // cache miss (or even when opening the writer) is that it will - // significantly slow down the case when a taxonomy is opened just to - // add one category. The idea only spending a long time on reading - // after enough time was spent on cache misses is known as a "online - // algorithm". - if (perhapsFillCache()) { - return cache.get(categoryPath); - } - - // We need to get an answer from the on-disk index. If a reader - // is not yet open, do it now: - if (reader == null) { - reader = openReader(); - } - - TermDocs docs = reader.termDocs(new Term(Consts.FULL, categoryPath - .toString(delimiter))); - if (!docs.next()) { - return -1; // category does not exist in taxonomy - } - // Note: we do NOT add to the cache the fact that the category - // does not exist. The reason is that our only use for this - // method is just before we actually add this category. If - // in the future this usage changes, we should consider caching - // the fact that the category is not in the taxonomy. - addToCache(categoryPath, docs.doc()); - return docs.doc(); - } - - /** - * Look up the given prefix of the given category in the cache and/or the - * on-disk storage, returning that prefix's ordinal, or a negative number in - * case the category does not yet exist in the taxonomy. - */ - private int findCategory(CategoryPath categoryPath, int prefixLen) - throws IOException { - int res = cache.get(categoryPath, prefixLen); - if (res >= 0) { - return res; - } - if (cacheIsComplete) { - return -1; - } - cacheMisses++; - if (perhapsFillCache()) { - return cache.get(categoryPath, prefixLen); - } - if (reader == null) { - reader = openReader(); - } - TermDocs docs = reader.termDocs(new Term(Consts.FULL, categoryPath - .toString(delimiter, prefixLen))); - if (!docs.next()) { - return -1; // category does not exist in taxonomy - } - addToCache(categoryPath, prefixLen, docs.doc()); - return docs.doc(); - } - - // TODO (Facet): addCategory() is synchronized. This means that if indexing is - // multi-threaded, a new category that needs to be written to disk (and - // potentially even trigger a lengthy merge) locks out other addCategory() - // calls - even those which could immediately return a cached value. - // We definitely need to fix this situation! - public synchronized int addCategory(CategoryPath categoryPath) - throws IOException { - // If the category is already in the cache and/or the taxonomy, we - // should return its existing ordinal: - int res = findCategory(categoryPath); - if (res < 0) { - // This is a new category, and we need to insert it into the index - // (and the cache). Actually, we might also need to add some of - // the category's ancestors before we can add the category itself - // (while keeping the invariant that a parent is always added to - // the taxonomy before its child). internalAddCategory() does all - // this recursively: - res = internalAddCategory(categoryPath, categoryPath.length()); - } - return res; - - } - - /** - * Add a new category into the index (and the cache), and return its new - * ordinal. - *

- * Actually, we might also need to add some of the category's ancestors - * before we can add the category itself (while keeping the invariant that a - * parent is always added to the taxonomy before its child). We do this by - * recursion. - */ - private int internalAddCategory(CategoryPath categoryPath, int length) - throws CorruptIndexException, IOException { - - // Find our parent's ordinal (recursively adding the parent category - // to the taxonomy if it's not already there). Then add the parent - // ordinal as payloads (rather than a stored field; payloads can be - // more efficiently read into memory in bulk by LuceneTaxonomyReader) - int parent; - if (length > 1) { - parent = findCategory(categoryPath, length - 1); - if (parent < 0) { - parent = internalAddCategory(categoryPath, length - 1); - } - } else if (length == 1) { - parent = TaxonomyReader.ROOT_ORDINAL; - } else { - parent = TaxonomyReader.INVALID_ORDINAL; - } - int id = addCategoryDocument(categoryPath, length, parent); - - return id; - } - - // Note that the methods calling addCategoryDocument() are synchornized, - // so this method is effectively synchronized as well, but we'll add - // synchronized to be on the safe side, and we can reuse class-local objects - // instead of allocating them every time - protected synchronized int addCategoryDocument(CategoryPath categoryPath, - int length, int parent) - throws CorruptIndexException, IOException { - // Before Lucene 2.9, position increments >=0 were supported, so we - // added 1 to parent to allow the parent -1 (the parent of the root). - // Unfortunately, starting with Lucene 2.9, after LUCENE-1542, this is - // no longer enough, since 0 is not encoded consistently either (see - // comment in SinglePositionTokenStream). But because we must be - // backward-compatible with existing indexes, we can't just fix what - // we write here (e.g., to write parent+2), and need to do a workaround - // in the reader (which knows that anyway only category 0 has a parent - // -1). - parentStream.set(parent+1); - Document d = new Document(); - d.add(parentStreamField); - - fullPathField.setValue(categoryPath.toString(delimiter, length)); - d.add(fullPathField); - - // Note that we do no pass an Analyzer here because the fields that are - // added to the Document are untokenized or contains their own TokenStream. - // Therefore the IndexWriter's Analyzer has no effect. - indexWriter.addDocument(d); - int id = nextID++; - - addToCache(categoryPath, length, id); - - // also add to the parent array - getParentArray().add(id, parent); - - return id; - } - - private static class SinglePositionTokenStream extends TokenStream { - private CharTermAttribute termAtt; - private PositionIncrementAttribute posIncrAtt; - private boolean returned; - public SinglePositionTokenStream(String word) { - termAtt = addAttribute(CharTermAttribute.class); - posIncrAtt = addAttribute(PositionIncrementAttribute.class); - termAtt.setEmpty().append(word); - returned = true; - } - /** - * Set the value we want to keep, as the position increment. - * Note that when TermPositions.nextPosition() is later used to - * retrieve this value, val-1 will be returned, not val. - *

- * IMPORTANT NOTE: Before Lucene 2.9, val>=0 were safe (for val==0, - * the retrieved position would be -1). But starting with Lucene 2.9, - * this unfortunately changed, and only val>0 are safe. val=0 can - * still be used, but don't count on the value you retrieve later - * (it could be 0 or -1, depending on circumstances or versions). - * This change is described in Lucene's JIRA: LUCENE-1542. - */ - public void set(int val) { - posIncrAtt.setPositionIncrement(val); - returned = false; - } - @Override - public boolean incrementToken() throws IOException { - if (returned) { - return false; - } - returned = true; - return true; - } - } - - private void addToCache(CategoryPath categoryPath, int id) - throws CorruptIndexException, IOException { - if (cache.put(categoryPath, id)) { - // If cache.put() returned true, it means the cache was limited in - // size, became full, so parts of it had to be cleared. - // Unfortunately we don't know which part was cleared - it is - // possible that a relatively-new category that hasn't yet been - // committed to disk (and therefore isn't yet visible in our - // "reader") was deleted from the cache, and therefore we must - // now refresh the reader. - // Because this is a slow operation, cache implementations are - // expected not to delete entries one-by-one but rather in bulk - // (LruTaxonomyWriterCache removes the 2/3rd oldest entries). - refreshReader(); - cacheIsComplete = false; - } - } - - private void addToCache(CategoryPath categoryPath, int prefixLen, int id) - throws CorruptIndexException, IOException { - if (cache.put(categoryPath, prefixLen, id)) { - refreshReader(); - cacheIsComplete = false; - } - } - - private synchronized void refreshReader() throws IOException { - if (reader != null) { - IndexReader r2 = reader.reopen(); - if (reader != r2) { - reader.close(); - reader = r2; - } - } - } - - /** - * Calling commit() ensures that all the categories written so far are - * visible to a reader that is opened (or reopened) after that call. - * When the index is closed(), commit() is also implicitly done. - * See {@link TaxonomyWriter#commit()} - */ - public synchronized void commit() throws CorruptIndexException, IOException { - indexWriter.commit(); - refreshReader(); - } - - /** - * Like commit(), but also store properties with the index. These properties - * are retrievable by {@link LuceneTaxonomyReader#getCommitUserData}. - * See {@link TaxonomyWriter#commit(Map)}. - */ - public synchronized void commit(Map commitUserData) throws CorruptIndexException, IOException { - indexWriter.commit(commitUserData); - refreshReader(); - } - - /** - * prepare most of the work needed for a two-phase commit. - * See {@link IndexWriter#prepareCommit}. - */ - public synchronized void prepareCommit() throws CorruptIndexException, IOException { - indexWriter.prepareCommit(); - } - - /** - * Like above, and also prepares to store user data with the index. - * See {@link IndexWriter#prepareCommit(Map)} - */ - public synchronized void prepareCommit(Map commitUserData) throws CorruptIndexException, IOException { - indexWriter.prepareCommit(commitUserData); - } - - /** - * getSize() returns the number of categories in the taxonomy. - *

- * Because categories are numbered consecutively starting with 0, it means - * the taxonomy contains ordinals 0 through getSize()-1. - *

- * Note that the number returned by getSize() is often slightly higher than - * the number of categories inserted into the taxonomy; This is because when - * a category is added to the taxonomy, its ancestors are also added - * automatically (including the root, which always get ordinal 0). - */ - synchronized public int getSize() { - return indexWriter.maxDoc(); - } - - private boolean alreadyCalledFillCache = false; - - /** - * Set the number of cache misses before an attempt is made to read the - * entire taxonomy into the in-memory cache. - *

- * LuceneTaxonomyWriter holds an in-memory cache of recently seen - * categories to speed up operation. On each cache-miss, the on-disk index - * needs to be consulted. When an existing taxonomy is opened, a lot of - * slow disk reads like that are needed until the cache is filled, so it - * is more efficient to read the entire taxonomy into memory at once. - * We do this complete read after a certain number (defined by this method) - * of cache misses. - *

- * If the number is set to 0, the entire taxonomy is read - * into the cache on first use, without fetching individual categories - * first. - *

- * Note that if the memory cache of choice is limited in size, and cannot - * hold the entire content of the on-disk taxonomy, then it is never - * read in its entirety into the cache, regardless of the setting of this - * method. - */ - public void setCacheMissesUntilFill(int i) { - cacheMissesUntilFill = i; - } - private int cacheMissesUntilFill = 11; - - private boolean perhapsFillCache() throws IOException { - // Note: we assume that we're only called when cacheIsComplete==false. - // TODO (Facet): parametrize this criterion: - if (cacheMisses < cacheMissesUntilFill) { - return false; - } - // If the cache was already filled (or we decided not to fill it because - // there was no room), there is no sense in trying it again. - if (alreadyCalledFillCache) { - return false; - } - alreadyCalledFillCache = true; - // TODO (Facet): we should probably completely clear the cache before starting - // to read it? - if (reader == null) { - reader = openReader(); - } - - if (!cache.hasRoom(reader.numDocs())) { - return false; - } - - CategoryPath cp = new CategoryPath(); - TermDocs td = reader.termDocs(); - Term fullPathTerm = new Term(Consts.FULL); - String field = fullPathTerm.field(); // needed so we can later use != - TermEnum terms = reader.terms(fullPathTerm); - // The check is done here to avoid checking it on every iteration of the - // below loop. A null term wlil be returned if there are no terms in the - // lexicon, or after the Consts.FULL term. However while the loop is - // executed we're safe, because we only iterate as long as there are next() - // terms. - if (terms.term() != null) { - do { - Term t = terms.term(); - if (t.field() != field) break; - // 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. - td.seek(t); - td.next(); - cp.clear(); - cp.add(t.text(), delimiter); - cache.put(cp, td.doc()); - } while (terms.next()); - } - - cacheIsComplete = true; - // No sense to keep the reader open - we will not need to read from it - // if everything is in the cache. - reader.close(); - reader = null; - return true; - } - - private ParentArray parentArray; - private synchronized ParentArray getParentArray() throws IOException { - if (parentArray==null) { - if (reader == null) { - reader = openReader(); - } - parentArray = new ParentArray(); - parentArray.refresh(reader); - } - return parentArray; - } - public int getParent(int ordinal) throws IOException { - // Note: the following if() just enforces that a user can never ask - // for the parent of a nonexistant category - even if the parent array - // was allocated bigger than it really needs to be. - if (ordinal >= getSize()) { - throw new ArrayIndexOutOfBoundsException(); - } - return getParentArray().getArray()[ordinal]; - } - - /** - * Take all the categories of one or more given taxonomies, and add them to - * the main taxonomy (this), if they are not already there. - *

- * Additionally, fill a mapping for each of the added taxonomies, - * mapping its ordinals to the ordinals in the enlarged main taxonomy. - * These mapping are saved into an array of OrdinalMap objects given by the - * user, one for each of the given taxonomies (not including "this", the main - * taxonomy). Often the first of these will be a MemoryOrdinalMap and the - * others will be a DiskOrdinalMap - see discussion in {OrdinalMap}. - *

- * Note that the taxonomies to be added are given as Directory objects, - * not opened TaxonomyReader/TaxonomyWriter objects, so if any of them are - * currently managed by an open TaxonomyWriter, make sure to commit() (or - * close()) it first. The main taxonomy (this) is an open TaxonomyWriter, - * and does not need to be commit()ed before this call. - */ - public void addTaxonomies(Directory[] taxonomies, OrdinalMap[] ordinalMaps) throws IOException { - // To prevent us stepping on the rest of this class's decisions on when - // to open a reader, and when not, we'll be opening a new reader instead - // of using the existing "reader" object: - IndexReader mainreader = openReader(); - TermEnum mainte = mainreader.terms(new Term(Consts.FULL)); - - IndexReader[] otherreaders = new IndexReader[taxonomies.length]; - TermEnum[] othertes = new TermEnum[taxonomies.length]; - for (int i=0; i0) { - String first=null; - for (int i=0; i0) { - first = currentOthers[i]; - } - } - int comp = 0; - if (currentMain==null || (comp = currentMain.compareTo(first))>0) { - // If 'first' is before currentMain, or currentMain is null, - // then 'first' is a new category and we need to add it to the - // main taxonomy. Then for all taxonomies with this 'first' - // category, we need to add the new category number to their - // map, and move to the next category in all of them. - cp.clear(); - cp.add(first, delimiter); - // We can call internalAddCategory() instead of addCategory() - // because we know the category hasn't been seen yet. - int newordinal = internalAddCategory(cp, cp.length()); - // TODO (Facet): we already had this term in our hands before, in nextTE... - Term t = new Term(Consts.FULL, first); - for (int i=0; i 0 */ { - // The currentMain doesn't appear in any of the other taxonomies - - // we don't need to do anything, just continue to the next one - currentMain = nextTE(mainte); - } - } - - // Close all the readers we've opened, and also tell the ordinal maps - // we're done adding to them - mainreader.close(); - for (int i=0; i - * addToTaxonomies() merges one or more taxonomies into the given taxonomy - * (this). An OrdinalMap is filled for each of the added taxonomies, - * containing the new ordinal (in the merged taxonomy) of each of the - * categories in the old taxonomy. - *

- * There exist two implementations of OrdinalMap: MemoryOrdinalMap and - * DiskOrdinalMap. As their names suggest, the former keeps the map in - * memory and the latter in a temporary disk file. Because these maps will - * later be needed one by one (to remap the counting lists), not all at the - * same time, it is recommended to put the first taxonomy's map in memory, - * and all the rest on disk (later to be automatically read into memory one - * by one, when needed). - */ - public static interface OrdinalMap { - /** - * Set the size of the map. This MUST be called before addMapping(). - * It is assumed (but not verified) that addMapping() will then be - * called exactly 'size' times, with different origOrdinals between 0 - * and size-1. - */ - public void setSize(int size) throws IOException; - public void addMapping(int origOrdinal, int newOrdinal) throws IOException; - /** - * Call addDone() to say that all addMapping() have been done. - * In some implementations this might free some resources. - */ - public void addDone() throws IOException; - /** - * Return the map from the taxonomy's original (consecutive) ordinals - * to the new taxonomy's ordinals. If the map has to be read from disk - * and ordered appropriately, it is done when getMap() is called. - * getMap() should only be called once, and only when the map is actually - * needed. Calling it will also free all resources that the map might - * be holding (such as temporary disk space), other than the returned int[]. - */ - public int[] getMap() throws IOException; - } - - /** - * {@link OrdinalMap} maintained in memory - */ - public static final class MemoryOrdinalMap implements OrdinalMap { - int[] map; - public void setSize(int taxonomySize) { - map = new int[taxonomySize]; - } - public void addMapping(int origOrdinal, int newOrdinal) { - map[origOrdinal] = newOrdinal; - } - public void addDone() { /* nothing to do */ } - public int[] getMap() { - return map; - } - } - - /** - * {@link OrdinalMap} maintained on file system - */ - public static final class DiskOrdinalMap implements OrdinalMap { - File tmpfile; - DataOutputStream out; - - public DiskOrdinalMap(File tmpfile) throws FileNotFoundException { - this.tmpfile = tmpfile; - out = new DataOutputStream(new BufferedOutputStream( - new FileOutputStream(tmpfile))); - } - - public void addMapping(int origOrdinal, int newOrdinal) throws IOException { - out.writeInt(origOrdinal); - out.writeInt(newOrdinal); - } - - public void setSize(int taxonomySize) throws IOException { - out.writeInt(taxonomySize); - } - - public void addDone() throws IOException { - if (out!=null) { - out.close(); - out = null; - } - } - - int[] map = null; - - public int[] getMap() throws IOException { - if (map!=null) { - return map; - } - addDone(); // in case this wasn't previously called - DataInputStream in = new DataInputStream(new BufferedInputStream( - new FileInputStream(tmpfile))); - map = new int[in.readInt()]; - // NOTE: The current code assumes here that the map is complete, - // i.e., every ordinal gets one and exactly one value. Otherwise, - // we may run into an EOF here, or vice versa, not read everything. - for (int i=0; i - * Reading from the on-disk index on every method call is too slow, so this - * implementation employs caching: Some methods cache recent requests and - * their results, while other methods prefetch all the data into memory - * and then provide answers directly from in-memory tables. See the - * documentation of individual methods for comments on their performance. - * - * @lucene.experimental - */ -public class LuceneTaxonomyReader implements TaxonomyReader { - - private static final Logger logger = Logger.getLogger(LuceneTaxonomyReader.class.getName()); - - private IndexReader indexReader; - - // The following lock is used to allow multiple threads to read from the - // index concurrently, while having them block during the very short - // critical moment of refresh() (see comments below). Note, however, that - // we only read from the index when we don't have the entry in our cache, - // and the caches are locked separately. - private ReadWriteLock indexReaderLock = new ReentrantReadWriteLock(); - - // The following are the limited-size LRU caches used to cache the latest - // results from getOrdinal() and getLabel(). - // Because LRUHashMap is not thread-safe, we need to synchronize on this - // object when using it. Unfortunately, this is not optimal under heavy - // contention because it means that while one thread is using the cache - // (reading or modifying) others are blocked from using it - or even - // starting to do benign things like calculating the hash function. A more - // efficient approach would be to use a non-locking (as much as possible) - // concurrent solution, along the lines of java.util.concurrent.ConcurrentHashMap - // but with LRU semantics. - // However, even in the current sub-optimal implementation we do not make - // the mistake of locking out readers while waiting for disk in a cache - // miss - below, we do not hold cache lock while reading missing data from - // disk. - private final LRUHashMap ordinalCache; - private final LRUHashMap categoryCache; - - // getParent() needs to be extremely efficient, to the point that we need - // to fetch all the data in advance into memory, and answer these calls - // from memory. Currently we use a large integer array, which is - // initialized when the taxonomy is opened, and potentially enlarged - // when it is refresh()ed. - // These arrays are not syncrhonized. Rather, the reference to the array - // is volatile, and the only writing operation (refreshPrefetchArrays) - // simply creates a new array and replaces the reference. The volatility - // of the reference ensures the correct atomic replacement and its - // visibility properties (the content of the array is visible when the - // new reference is visible). - private ParentArray parentArray; - - private char delimiter = Consts.DEFAULT_DELIMITER; - - private volatile boolean closed = false; - - /** - * Open for reading a taxonomy stored in a given {@link Directory}. - * @param directory - * The {@link Directory} in which to the taxonomy lives. Note that - * the taxonomy is read directly to that directory (not from a - * subdirectory of it). - * @throws CorruptIndexException if the Taxonomy is corrupted. - * @throws IOException if another error occurred. - */ - public LuceneTaxonomyReader(Directory directory) - throws CorruptIndexException, IOException { - this.indexReader = openIndexReader(directory); - - // These are the default cache sizes; they can be configured after - // construction with the cache's setMaxSize() method - ordinalCache = new LRUHashMap(4000); - categoryCache = new LRUHashMap(4000); - - // TODO (Facet): consider lazily create parent array when asked, not in the constructor - parentArray = new ParentArray(); - parentArray.refresh(indexReader); - } - - protected IndexReader openIndexReader(Directory directory) throws CorruptIndexException, IOException { - return IndexReader.open(directory); - } - - /** - * @throws AlreadyClosedException if this IndexReader is closed - */ - protected final void ensureOpen() throws AlreadyClosedException { - if (indexReader.getRefCount() <= 0) { - throw new AlreadyClosedException("this TaxonomyReader is closed"); - } - } - - /** - * setCacheSize controls the maximum allowed size of each of the caches - * used by {@link #getPath(int)} and {@link #getOrdinal(CategoryPath)}. - *

- * Currently, if the given size is smaller than the current size of - * a cache, it will not shrink, and rather we be limited to its current - * size. - * @param size the new maximum cache size, in number of entries. - */ - public void setCacheSize(int size) { - ensureOpen(); - synchronized(categoryCache) { - categoryCache.setMaxSize(size); - } - synchronized(ordinalCache) { - ordinalCache.setMaxSize(size); - } - } - - /** - * setDelimiter changes the character that the taxonomy uses in its - * internal storage as a delimiter between category components. Do not - * use this method unless you really know what you are doing. - *

- * If you do use this method, make sure you call it before any other - * methods that actually queries the taxonomy. Moreover, make sure you - * always pass the same delimiter for all LuceneTaxonomyWriter and - * LuceneTaxonomyReader objects you create. - */ - public void setDelimiter(char delimiter) { - ensureOpen(); - this.delimiter = delimiter; - } - - public int getOrdinal(CategoryPath categoryPath) throws IOException { - ensureOpen(); - if (categoryPath.length()==0) { - return ROOT_ORDINAL; - } - String path = categoryPath.toString(delimiter); - - // First try to find the answer in the LRU cache: - synchronized(ordinalCache) { - Integer res = ordinalCache.get(path); - if (res!=null) { - return res.intValue(); - } - } - - // If we're still here, we have a cache miss. We need to fetch the - // value from disk, and then also put it in the cache: - int ret = TaxonomyReader.INVALID_ORDINAL; - try { - indexReaderLock.readLock().lock(); - TermDocs docs = indexReader.termDocs(new Term(Consts.FULL, path)); - if (docs.next()) { - ret = docs.doc(); - } - } finally { - indexReaderLock.readLock().unlock(); - } - - // Put the new value in the cache. Note that it is possible that while - // we were doing the above fetching (without the cache locked), some - // other thread already added the same category to the cache. We do - // not care about this possibilty, as LRUCache replaces previous values - // of the same keys (it doesn't store duplicates). - synchronized(ordinalCache) { - // GB: new Integer(int); creates a new object each and every time. - // Integer.valueOf(int) might not (See JavaDoc). - ordinalCache.put(path, Integer.valueOf(ret)); - } - - return ret; - } - - public CategoryPath getPath(int ordinal) throws CorruptIndexException, IOException { - ensureOpen(); - // TODO (Facet): Currently, the LRU cache we use (categoryCache) holds - // strings with delimiters, not CategoryPath objects, so even if - // we have a cache hit, we need to process the string and build a new - // CategoryPath object every time. What is preventing us from putting - // the actual CategoryPath object in the cache is the fact that these - // objects are mutable. So we should create an immutable (read-only) - // interface that CategoryPath implements, and this method should - // return this interface, not the writable CategoryPath. - String label = getLabel(ordinal); - if (label==null) { - return null; - } - return new CategoryPath(label, delimiter); - } - - public boolean getPath(int ordinal, CategoryPath result) throws CorruptIndexException, IOException { - ensureOpen(); - String label = getLabel(ordinal); - if (label==null) { - return false; - } - result.clear(); - result.add(label, delimiter); - return true; - } - - private String getLabel(int catID) throws CorruptIndexException, IOException { - ensureOpen(); - // First try to find the answer in the LRU cache. It is very - // unfortunate that we need to allocate an Integer object here - - // it would have been better if we used a hash table specifically - // designed for int keys... - // GB: new Integer(int); creates a new object each and every time. - // Integer.valueOf(int) might not (See JavaDoc). - Integer catIDInteger = Integer.valueOf(catID); - - synchronized(categoryCache) { - String res = categoryCache.get(catIDInteger); - if (res!=null) { - return res; - } - } - - // If we're still here, we have a cache miss. We need to fetch the - // value from disk, and then also put it in the cache: - String ret; - try { - indexReaderLock.readLock().lock(); - // The taxonomy API dictates that if we get an invalid category - // ID, we should return null, If we don't check this here, we - // can some sort of an exception from the document() call below. - // NOTE: Currently, we *do not* cache this return value; There - // isn't much point to do so, because checking the validity of - // the docid doesn't require disk access - just comparing with - // the number indexReader.maxDoc(). - if (catID<0 || catID>=indexReader.maxDoc()) { - return null; - } - ret = indexReader.document(catID, Consts.fullPathSelector) - .get(Consts.FULL); - } finally { - indexReaderLock.readLock().unlock(); - } - // Put the new value in the cache. Note that it is possible that while - // we were doing the above fetching (without the cache locked), some - // other thread already added the same category to the cache. We do - // not care about this possibility, as LRUCache replaces previous - // values of the same keys (it doesn't store duplicates). - synchronized (categoryCache) { - categoryCache.put(catIDInteger, ret); - } - - return ret; - } - - public int getParent(int ordinal) { - ensureOpen(); - // Note how we don't need to hold the read lock to do the following, - // because the array reference is volatile, ensuring the correct - // visibility and ordering: if we get the new reference, the new - // data is also visible to this thread. - return getParentArray()[ordinal]; - } - - /** - * getParentArray() returns an int array of size getSize() listing the - * ordinal of the parent category of each category in the taxonomy. - *

- * The caller can hold on to the array it got indefinitely - it is - * guaranteed that no-one else will modify it. The other side of the - * same coin is that the caller must treat the array it got as read-only - * and not modify it, because other callers might have gotten the - * same array too, and getParent() calls are also answered from the - * same array. - *

- * The getParentArray() call is extremely efficient, merely returning - * a reference to an array that already exists. For a caller that plans - * to call getParent() for many categories, using getParentArray() and - * the array it returns is a somewhat faster approach because it avoids - * the overhead of method calls and volatile dereferencing. - *

- * If you use getParentArray() instead of getParent(), remember that - * the array you got is (naturally) not modified after a refresh(), - * so you should always call getParentArray() again after a refresh(). - */ - - public int[] getParentArray() { - ensureOpen(); - // Note how we don't need to hold the read lock to do the following, - // because the array reference is volatile, ensuring the correct - // visibility and ordering: if we get the new reference, the new - // data is also visible to this thread. - return parentArray.getArray(); - } - - // Note that refresh() is synchronized (it is the only synchronized - // method in this class) to ensure that it never gets called concurrently - // with itself. - public synchronized void refresh() throws IOException { - ensureOpen(); - /* - * Since refresh() can be a lengthy operation, it is very important that we - * avoid locking out all readers for its duration. This is why we don't hold - * the indexReaderLock write lock for the entire duration of this method. In - * fact, it is enough to hold it only during a single assignment! Other - * comments in this method will explain this. - */ - - // note that the lengthy operation indexReader.reopen() does not - // modify the reader, so we can do it without holding a lock. We can - // safely read indexReader without holding the write lock, because - // no other thread can be writing at this time (this method is the - // only possible writer, and it is "synchronized" to avoid this case). - IndexReader r2 = indexReader.reopen(); - if (indexReader != r2) { - IndexReader oldreader = indexReader; - // we can close the old searcher, but need to synchronize this - // so that we don't close it in the middle that another routine - // is reading from it. - indexReaderLock.writeLock().lock(); - indexReader = r2; - indexReaderLock.writeLock().unlock(); - // We can close the old reader, but need to be certain that we - // don't close it while another method is reading from it. - // Luckily, we can be certain of that even without putting the - // oldreader.close() in the locked section. The reason is that - // after lock() succeeded above, we know that all existing readers - // had finished (this is what a read-write lock ensures). New - // readers, starting after the unlock() we just did, already got - // the new indexReader we set above. So nobody can be possibly - // using the old indexReader, and we can close it: - oldreader.close(); - - // We prefetch some of the arrays to make requests much faster. - // Let's refresh these prefetched arrays; This refresh is much - // is made more efficient by assuming that it is enough to read - // the values for new categories (old categories could not have been - // changed or deleted) - // Note that this this done without the write lock being held, - // which means that it is possible that during a refresh(), a - // reader will have some methods (like getOrdinal and getCategory) - // return fresh information, while getParent() - // (only to be prefetched now) still return older information. - // We consider this to be acceptable. The important thing, - // however, is that refreshPrefetchArrays() itself writes to - // the arrays in a correct manner (see discussion there) - parentArray.refresh(indexReader); - - // Remove any INVALID_ORDINAL values from the ordinal cache, - // because it is possible those are now answered by the new data! - Iterator> i = ordinalCache.entrySet().iterator(); - while (i.hasNext()) { - Entry e = i.next(); - if (e.getValue().intValue() == INVALID_ORDINAL) { - i.remove(); - } - } - } - } - - public void close() throws IOException { - if (!closed) { - decRef(); - closed = true; - } - } - - /** Do the actual closing, free up resources */ - private void doClose() throws IOException { - indexReader.close(); - closed = true; - - parentArray = null; - childrenArrays = null; - categoryCache.clear(); - ordinalCache.clear(); - } - - public int getSize() { - ensureOpen(); - indexReaderLock.readLock().lock(); - try { - return indexReader.numDocs(); - } finally { - indexReaderLock.readLock().unlock(); - } - } - - public Map getCommitUserData() { - ensureOpen(); - return indexReader.getCommitUserData(); - } - - private ChildrenArrays childrenArrays; - Object childrenArraysRebuild = new Object(); - - public ChildrenArrays getChildrenArrays() { - ensureOpen(); - // Check if the taxonomy grew since we built the array, and if it - // did, create new (and larger) arrays and fill them as required. - // We do all this under a lock, two prevent to concurrent calls to - // needlessly do the same array building at the same time. - synchronized(childrenArraysRebuild) { - int num = getSize(); - int first; - if (childrenArrays==null) { - first = 0; - } else { - first = childrenArrays.getYoungestChildArray().length; - } - // If the taxonomy hasn't grown, we can return the existing object - // immediately - if (first == num) { - return childrenArrays; - } - // Otherwise, build new arrays for a new ChildrenArray object. - // These arrays start with an enlarged copy of the previous arrays, - // and then are modified to take into account the new categories: - int[] newYoungestChildArray = new int[num]; - int[] newOlderSiblingArray = new int[num]; - // In Java 6, we could just do Arrays.copyOf()... - if (childrenArrays!=null) { - System.arraycopy(childrenArrays.getYoungestChildArray(), 0, - newYoungestChildArray, 0, childrenArrays.getYoungestChildArray().length); - System.arraycopy(childrenArrays.getOlderSiblingArray(), 0, - newOlderSiblingArray, 0, childrenArrays.getOlderSiblingArray().length); - } - int[] parents = getParentArray(); - for (int i=first; i results = searchWithFacets(indexReader, taxo, iParams); Index: lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java =================================================================== --- lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java (revision 1196597) +++ lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java (working copy) @@ -21,7 +21,7 @@ import org.apache.lucene.facet.index.params.FacetIndexingParams; import org.apache.lucene.facet.index.params.PerDimensionIndexingParams; import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -140,7 +140,7 @@ IndexWriter iw = new IndexWriter(indexDir, new IndexWriterConfig( ExampleUtils.EXAMPLE_VER, SimpleUtils.analyzer).setOpenMode(OpenMode.CREATE)); // create and open a taxonomy writer - LuceneTaxonomyWriter taxo = new LuceneTaxonomyWriter(taxoDir, OpenMode.CREATE); + DirectoryTaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); index(iw, taxo, iParams, docTitles, docTexts, cPaths); } @@ -153,7 +153,7 @@ * on error (no detailed exception handling here for sample * simplicity */ - public static void index(IndexWriter iw, LuceneTaxonomyWriter taxo, + public static void index(IndexWriter iw, DirectoryTaxonomyWriter taxo, FacetIndexingParams iParams, String[] docTitles, String[] docTexts, CategoryPath[][] cPaths) throws Exception { Index: lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/association/AssociationSearcher.java =================================================================== --- lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/association/AssociationSearcher.java (revision 1196597) +++ lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/association/AssociationSearcher.java (working copy) @@ -11,7 +11,7 @@ import org.apache.lucene.facet.search.results.FacetResult; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -43,7 +43,7 @@ Directory taxoDir) throws Exception { // prepare index reader IndexReader indexReader = IndexReader.open(indexDir); - TaxonomyReader taxo = new LuceneTaxonomyReader(taxoDir); + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); AssociationIntSumFacetRequest facetRequest = new AssociationIntSumFacetRequest( new CategoryPath("tags"), 10); @@ -63,7 +63,7 @@ Directory taxoDir) throws Exception { // prepare index reader IndexReader indexReader = IndexReader.open(indexDir); - TaxonomyReader taxo = new LuceneTaxonomyReader(taxoDir); + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); AssociationFloatSumFacetRequest facetRequest = new AssociationFloatSumFacetRequest( new CategoryPath("genre"), 10); Index: lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/association/AssociationIndexer.java =================================================================== --- lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/association/AssociationIndexer.java (revision 1196597) +++ lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/association/AssociationIndexer.java (working copy) @@ -17,7 +17,7 @@ import org.apache.lucene.facet.index.CategoryDocumentBuilder; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -61,7 +61,7 @@ IndexWriter iw = new IndexWriter(indexDir, new IndexWriterConfig(ExampleUtils.EXAMPLE_VER, SimpleUtils.analyzer)); // create and open a taxonomy writer - TaxonomyWriter taxo = new LuceneTaxonomyWriter(taxoDir, OpenMode.CREATE); + TaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); // loop over sample documents int nDocsAdded = 0; Index: lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveSearcher.java =================================================================== --- lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveSearcher.java (revision 1196597) +++ lucene/contrib/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveSearcher.java (working copy) @@ -20,7 +20,7 @@ import org.apache.lucene.facet.search.results.FacetResult; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -55,7 +55,7 @@ */ public static List searchWithFacets (Directory indexDir, Directory taxoDir) throws Exception { // prepare index reader and taxonomy. - TaxonomyReader taxo = new LuceneTaxonomyReader(taxoDir); + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); IndexReader indexReader = IndexReader.open(indexDir); // prepare searcher to search against Index: lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/OpenTaxonomyReaderTask.java =================================================================== --- lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/OpenTaxonomyReaderTask.java (revision 1196597) +++ lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/OpenTaxonomyReaderTask.java (working copy) @@ -20,7 +20,7 @@ import java.io.IOException; import org.apache.lucene.benchmark.byTask.PerfRunData; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyReader; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyReader; /** * Open a taxonomy index reader. @@ -35,7 +35,7 @@ @Override public int doLogic() throws IOException { PerfRunData runData = getRunData(); - LuceneTaxonomyReader taxoReader = new LuceneTaxonomyReader(runData.getTaxonomyDir()); + DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(runData.getTaxonomyDir()); runData.setTaxonomyReader(taxoReader); // We transfer reference to the run data taxoReader.decRef(); Index: lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/OpenTaxonomyIndexTask.java =================================================================== --- lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/OpenTaxonomyIndexTask.java (revision 1196597) +++ lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/OpenTaxonomyIndexTask.java (working copy) @@ -18,7 +18,7 @@ */ import org.apache.lucene.benchmark.byTask.PerfRunData; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; import java.io.IOException; @@ -35,7 +35,7 @@ @Override public int doLogic() throws IOException { PerfRunData runData = getRunData(); - runData.setTaxonomyWriter(new LuceneTaxonomyWriter(runData.getTaxonomyDir())); + runData.setTaxonomyWriter(new DirectoryTaxonomyWriter(runData.getTaxonomyDir())); return 1; } Index: lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/CreateTaxonomyIndexTask.java =================================================================== --- lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/CreateTaxonomyIndexTask.java (revision 1196597) +++ lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/CreateTaxonomyIndexTask.java (working copy) @@ -18,7 +18,7 @@ */ import org.apache.lucene.benchmark.byTask.PerfRunData; -import org.apache.lucene.facet.taxonomy.lucene.LuceneTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.lucene.DirectoryTaxonomyWriter; import org.apache.lucene.index.IndexWriterConfig.OpenMode; import java.io.IOException; @@ -37,7 +37,7 @@ @Override public int doLogic() throws IOException { PerfRunData runData = getRunData(); - runData.setTaxonomyWriter(new LuceneTaxonomyWriter(runData.getTaxonomyDir(), OpenMode.CREATE)); + runData.setTaxonomyWriter(new DirectoryTaxonomyWriter(runData.getTaxonomyDir(), OpenMode.CREATE)); return 1; }