| package org.apache.lucene.facet.taxonomy; |
| |
| /* |
| * 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. |
| */ |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| import org.apache.lucene.analysis.MockAnalyzer; |
| import org.apache.lucene.document.Document; |
| import org.apache.lucene.facet.FacetField; |
| import org.apache.lucene.facet.FacetResult; |
| import org.apache.lucene.facet.FacetTestCase; |
| import org.apache.lucene.facet.Facets; |
| import org.apache.lucene.facet.FacetsCollector; |
| import org.apache.lucene.facet.FacetsConfig; |
| import org.apache.lucene.facet.taxonomy.SearcherTaxonomyManager; |
| import org.apache.lucene.facet.taxonomy.SearcherTaxonomyManager.SearcherAndTaxonomy; |
| import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; |
| import org.apache.lucene.index.IndexWriter; |
| import org.apache.lucene.search.MatchAllDocsQuery; |
| import org.apache.lucene.store.Directory; |
| import org.apache.lucene.util.IOUtils; |
| import org.apache.lucene.util._TestUtil; |
| |
| public class TestSearcherTaxonomyManager extends FacetTestCase { |
| public void test() throws Exception { |
| Directory dir = newDirectory(); |
| Directory taxoDir = newDirectory(); |
| final IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()))); |
| final DirectoryTaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir); |
| final FacetsConfig config = new FacetsConfig(); |
| config.setMultiValued("field", true); |
| final AtomicBoolean stop = new AtomicBoolean(); |
| |
| // How many unique facets to index before stopping: |
| final int ordLimit = TEST_NIGHTLY ? 100000 : 6000; |
| |
| Thread indexer = new Thread() { |
| @Override |
| public void run() { |
| try { |
| Set<String> seen = new HashSet<String>(); |
| List<String> paths = new ArrayList<String>(); |
| while (true) { |
| Document doc = new Document(); |
| int numPaths = _TestUtil.nextInt(random(), 1, 5); |
| for(int i=0;i<numPaths;i++) { |
| String path; |
| if (!paths.isEmpty() && random().nextInt(5) != 4) { |
| // Use previous path |
| path = paths.get(random().nextInt(paths.size())); |
| } else { |
| // Create new path |
| path = null; |
| while (true) { |
| path = _TestUtil.randomRealisticUnicodeString(random()); |
| if (path.length() != 0 && !seen.contains(path)) { |
| seen.add(path); |
| paths.add(path); |
| break; |
| } |
| } |
| } |
| doc.add(new FacetField("field", path)); |
| } |
| try { |
| w.addDocument(config.build(tw, doc)); |
| } catch (IOException ioe) { |
| throw new RuntimeException(ioe); |
| } |
| |
| if (tw.getSize() >= ordLimit) { |
| break; |
| } |
| } |
| } finally { |
| stop.set(true); |
| } |
| } |
| }; |
| |
| final SearcherTaxonomyManager mgr = new SearcherTaxonomyManager(w, true, null, tw); |
| |
| Thread reopener = new Thread() { |
| @Override |
| public void run() { |
| while(!stop.get()) { |
| try { |
| // Sleep for up to 20 msec: |
| Thread.sleep(random().nextInt(20)); |
| |
| if (VERBOSE) { |
| System.out.println("TEST: reopen"); |
| } |
| |
| mgr.maybeRefresh(); |
| |
| if (VERBOSE) { |
| System.out.println("TEST: reopen done"); |
| } |
| } catch (Exception ioe) { |
| throw new RuntimeException(ioe); |
| } |
| } |
| } |
| }; |
| reopener.start(); |
| |
| indexer.start(); |
| |
| try { |
| while (!stop.get()) { |
| SearcherAndTaxonomy pair = mgr.acquire(); |
| try { |
| //System.out.println("search maxOrd=" + pair.taxonomyReader.getSize()); |
| FacetsCollector sfc = new FacetsCollector(); |
| pair.searcher.search(new MatchAllDocsQuery(), sfc); |
| Facets facets = getTaxonomyFacetCounts(pair.taxonomyReader, config, sfc); |
| FacetResult result = facets.getTopChildren(10, "field"); |
| if (pair.searcher.getIndexReader().numDocs() > 0) { |
| //System.out.println(pair.taxonomyReader.getSize()); |
| assertTrue(result.childCount > 0); |
| assertTrue(result.labelValues.length > 0); |
| } |
| |
| //if (VERBOSE) { |
| //System.out.println("TEST: facets=" + FacetTestUtils.toString(results.get(0))); |
| //} |
| } finally { |
| mgr.release(pair); |
| } |
| } |
| } finally { |
| indexer.join(); |
| reopener.join(); |
| } |
| |
| if (VERBOSE) { |
| System.out.println("TEST: now stop"); |
| } |
| |
| IOUtils.close(mgr, tw, w, taxoDir, dir); |
| } |
| |
| public void testReplaceTaxonomy() throws Exception { |
| Directory dir = newDirectory(); |
| Directory taxoDir = newDirectory(); |
| IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()))); |
| DirectoryTaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir); |
| |
| Directory taxoDir2 = newDirectory(); |
| DirectoryTaxonomyWriter tw2 = new DirectoryTaxonomyWriter(taxoDir2); |
| tw2.close(); |
| |
| SearcherTaxonomyManager mgr = new SearcherTaxonomyManager(w, true, null, tw); |
| w.addDocument(new Document()); |
| tw.replaceTaxonomy(taxoDir2); |
| taxoDir2.close(); |
| |
| try { |
| mgr.maybeRefresh(); |
| fail("should have hit exception"); |
| } catch (IllegalStateException ise) { |
| // expected |
| } |
| |
| IOUtils.close(mgr, tw, w, taxoDir, dir); |
| } |
| } |