/** Return a drill-down {@link Term} for a category. */ public static Term term(FacetIndexingParams iParams, CategoryPath path) { CategoryListParams clp = iParams.getCategoryListParams(path); char[] buffer = new char[path.fullPathLength()]; iParams.drillDownTermText(path, buffer); return new Term(clp.field, String.valueOf(buffer)); }
public void testConcurrency() throws Exception { final int ncats = atLeast(100000); // add many categories final int range = ncats * 3; // affects the categories selection final AtomicInteger numCats = new AtomicInteger(ncats); final Directory dir = newDirectory(); final ConcurrentHashMap<String, String> values = new ConcurrentHashMap<String, String>(); final double d = random().nextDouble(); final TaxonomyWriterCache cache; if (d < 0.7) { // this is the fastest, yet most memory consuming cache = new Cl2oTaxonomyWriterCache(1024, 0.15f, 3); } else if (TEST_NIGHTLY && d > 0.98) { // this is the slowest, but tests the writer concurrency when no caching is done. // only pick it during NIGHTLY tests, and even then, with very low chances. cache = NO_OP_CACHE; } else { // this is slower than CL2O, but less memory consuming, and exercises finding categories on // disk too. cache = new LruTaxonomyWriterCache(ncats / 10); } final DirectoryTaxonomyWriter tw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, cache); Thread[] addThreads = new Thread[atLeast(4)]; for (int z = 0; z < addThreads.length; z++) { addThreads[z] = new Thread() { @Override public void run() { Random random = random(); while (numCats.decrementAndGet() > 0) { try { int value = random.nextInt(range); CategoryPath cp = new CategoryPath( Integer.toString(value / 1000), Integer.toString(value / 10000), Integer.toString(value / 100000), Integer.toString(value)); int ord = tw.addCategory(cp); assertTrue( "invalid parent for ordinal " + ord + ", category " + cp, tw.getParent(ord) != -1); String l1 = cp.subpath(1).toString('/'); String l2 = cp.subpath(2).toString('/'); String l3 = cp.subpath(3).toString('/'); String l4 = cp.subpath(4).toString('/'); values.put(l1, l1); values.put(l2, l2); values.put(l3, l3); values.put(l4, l4); } catch (IOException e) { throw new RuntimeException(e); } } } }; } for (Thread t : addThreads) t.start(); for (Thread t : addThreads) t.join(); tw.close(); DirectoryTaxonomyReader dtr = new DirectoryTaxonomyReader(dir); assertEquals( "mismatch number of categories", values.size() + 1, dtr.getSize()); // +1 for root category int[] parents = dtr.getParallelTaxonomyArrays().parents(); for (String cat : values.keySet()) { CategoryPath cp = new CategoryPath(cat, '/'); assertTrue("category not found " + cp, dtr.getOrdinal(cp) > 0); int level = cp.length; int parentOrd = 0; // for root, parent is always virtual ROOT (ord=0) CategoryPath path = CategoryPath.EMPTY; for (int i = 0; i < level; i++) { path = cp.subpath(i + 1); int ord = dtr.getOrdinal(path); assertEquals("invalid parent for cp=" + path, parentOrd, parents[ord]); parentOrd = ord; // next level should have this parent } } dtr.close(); dir.close(); }