Index: lucene/CHANGES.txt =================================================================== --- lucene/CHANGES.txt (revision 1457768) +++ lucene/CHANGES.txt (working copy) @@ -45,6 +45,10 @@ TieredMergePolicy. IndexWriterConfig setters now throw an exception when passed null if null is not a valid value. +* LUCENE-4849: Made ParallelTaxonomyArrays abstract with a concrete + implementation for DirectoryTaxonomyWriter/Reader. Also moved it under + o.a.l.facet.taxonomy. (Shai Erera) + New Features * LUCENE-4815: DrillSideways now allows more than one FacetRequest per Index: lucene/facet/src/java/org/apache/lucene/facet/search/DepthOneFacetResultsHandler.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/DepthOneFacetResultsHandler.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/search/DepthOneFacetResultsHandler.java (working copy) @@ -7,8 +7,8 @@ import java.util.Comparator; import org.apache.lucene.facet.search.FacetRequest.SortOrder; +import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays; import org.apache.lucene.util.PriorityQueue; /* Index: lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java (working copy) @@ -150,7 +150,7 @@ searcher.search(dsq, hitCollector); int numDims = drillDownDims.size(); - List[] drillSidewaysResults = (List[]) new List[numDims]; + List[] drillSidewaysResults = new List[numDims]; List drillDownResults = null; List mergedResults = new ArrayList(); Index: lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java (working copy) @@ -15,8 +15,8 @@ import org.apache.lucene.facet.search.FacetRequest.ResultMode; import org.apache.lucene.facet.search.FacetRequest.SortOrder; import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; +import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays; import org.apache.lucene.index.IndexReader; /* Index: lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java (working copy) @@ -5,8 +5,8 @@ import org.apache.lucene.facet.partitions.IntermediateFacetResult; import org.apache.lucene.facet.partitions.PartitionsFacetResultsHandler; +import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays; import org.apache.lucene.facet.util.ResultSortUtils; /* Index: lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java (working copy) @@ -9,8 +9,8 @@ import org.apache.lucene.facet.partitions.IntermediateFacetResult; import org.apache.lucene.facet.partitions.PartitionsFacetResultsHandler; import org.apache.lucene.facet.search.FacetRequest.SortOrder; +import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays; import org.apache.lucene.util.PriorityQueue; /* Index: lucene/facet/src/java/org/apache/lucene/facet/taxonomy/ParallelTaxonomyArrays.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/taxonomy/ParallelTaxonomyArrays.java (working copy) +++ lucene/facet/src/java/org/apache/lucene/facet/taxonomy/ParallelTaxonomyArrays.java (working copy) @@ -1,15 +1,6 @@ -package org.apache.lucene.facet.taxonomy.directory; +package org.apache.lucene.facet.taxonomy; -import java.io.IOException; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.CorruptIndexException; -import org.apache.lucene.index.DocsAndPositionsEnum; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.MultiFields; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.util.ArrayUtil; - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -32,12 +23,10 @@ *
    *
  • {@code parents}: {@code parents[i]} denotes the parent of category * ordinal {@code i}.
  • - *
  • {@code children}: {@code children[i]} denotes the youngest child of - * category ordinal {@code i}. The youngest child is defined as the category - * that was added last to the taxonomy as an immediate child of {@code i}.
  • + *
  • {@code children}: {@code children[i]} denotes a child of category ordinal + * {@code i}.
  • *
  • {@code siblings}: {@code siblings[i]} denotes the sibling of category - * ordinal {@code i}. The sibling is defined as the previous youngest child of - * {@code parents[i]}.
  • + * ordinal {@code i}. *
* * To traverse the taxonomy tree, you typically start with {@code children[0]} @@ -51,180 +40,24 @@ * * @lucene.experimental */ -public class ParallelTaxonomyArrays { +public abstract class ParallelTaxonomyArrays { - private final int[] parents; - - // the following two arrays are lazily intialized. note that we only keep a - // single boolean member as volatile, instead of declaring the arrays - // volatile. the code guarantees that only after the boolean is set to true, - // the arrays are returned. - private volatile boolean initializedChildren = false; - private int[] children, siblings; - - /** Used by {@link #add(int, int)} after the array grew. */ - private ParallelTaxonomyArrays(int[] parents) { - this.parents = parents; - } - - public ParallelTaxonomyArrays(IndexReader reader) throws IOException { - parents = new int[reader.maxDoc()]; - if (parents.length > 0) { - initParents(reader, 0); - // Starting Lucene 2.9, following the change LUCENE-1542, we can - // no longer reliably read the parent "-1" (see comment in - // LuceneTaxonomyWriter.SinglePositionTokenStream). We have no way - // to fix this in indexing without breaking backward-compatibility - // with existing indexes, so what we'll do instead is just - // hard-code the parent of ordinal 0 to be -1, and assume (as is - // indeed the case) that no other parent can be -1. - parents[0] = TaxonomyReader.INVALID_ORDINAL; - } - } - - public ParallelTaxonomyArrays(IndexReader reader, ParallelTaxonomyArrays copyFrom) throws IOException { - assert copyFrom != null; - - // note that copyParents.length may be equal to reader.maxDoc(). this is not a bug - // it may be caused if e.g. the taxonomy segments were merged, and so an updated - // NRT reader was obtained, even though nothing was changed. this is not very likely - // to happen. - int[] copyParents = copyFrom.parents(); - this.parents = new int[reader.maxDoc()]; - System.arraycopy(copyParents, 0, parents, 0, copyParents.length); - initParents(reader, copyParents.length); - - if (copyFrom.initializedChildren) { - initChildrenSiblings(copyFrom); - } - } - - private final synchronized void initChildrenSiblings(ParallelTaxonomyArrays copyFrom) { - if (!initializedChildren) { // must do this check ! - children = new int[parents.length]; - siblings = new int[parents.length]; - if (copyFrom != null) { - // called from the ctor, after we know copyFrom has initialized children/siblings - System.arraycopy(copyFrom.children(), 0, children, 0, copyFrom.children().length); - System.arraycopy(copyFrom.siblings(), 0, siblings, 0, copyFrom.siblings().length); - } - computeChildrenSiblings(parents, 0); - initializedChildren = true; - } - } - - private void computeChildrenSiblings(int[] parents, int first) { - // reset the youngest child of all ordinals. while this should be done only - // for the leaves, we don't know up front which are the leaves, so we reset - // all of them. - for (int i = first; i < parents.length; i++) { - children[i] = TaxonomyReader.INVALID_ORDINAL; - } - - // the root category has no parent, and therefore no siblings - if (first == 0) { - first = 1; - siblings[0] = TaxonomyReader.INVALID_ORDINAL; - } - - for (int i = first; i < parents.length; i++) { - // note that parents[i] is always < i, so the right-hand-side of - // the following line is already set when we get here - siblings[i] = children[parents[i]]; - children[parents[i]] = i; - } - } - - // Read the parents of the new categories - private void initParents(IndexReader reader, int first) throws IOException { - if (reader.maxDoc() == first) { - return; - } - - // it's ok to use MultiFields because we only iterate on one posting list. - // breaking it to loop over the leaves() only complicates code for no - // apparent gain. - DocsAndPositionsEnum positions = MultiFields.getTermPositionsEnum(reader, null, - Consts.FIELD_PAYLOADS, Consts.PAYLOAD_PARENT_BYTES_REF, - DocsAndPositionsEnum.FLAG_PAYLOADS); - - // shouldn't really happen, if it does, something's wrong - if (positions == null || positions.advance(first) == DocIdSetIterator.NO_MORE_DOCS) { - throw new CorruptIndexException("Missing parent data for category " + first); - } - - int num = reader.maxDoc(); - for (int i = first; i < num; i++) { - if (positions.docID() == i) { - if (positions.freq() == 0) { // shouldn't happen - throw new CorruptIndexException("Missing parent data for category " + i); - } - - parents[i] = positions.nextPosition(); - - if (positions.nextDoc() == DocIdSetIterator.NO_MORE_DOCS) { - if (i + 1 < num) { - throw new CorruptIndexException("Missing parent data for category "+ (i + 1)); - } - break; - } - } else { // this shouldn't happen - throw new CorruptIndexException("Missing parent data for category " + i); - } - } - } - /** - * Adds the given ordinal/parent info and returns either a new instance if the - * underlying array had to grow, or this instance otherwise. - *

- * NOTE: you should call this method from a thread-safe code. - */ - ParallelTaxonomyArrays add(int ordinal, int parentOrdinal) { - if (ordinal >= parents.length) { - int[] newarray = ArrayUtil.grow(parents, ordinal + 1); - newarray[ordinal] = parentOrdinal; - return new ParallelTaxonomyArrays(newarray); - } - parents[ordinal] = parentOrdinal; - return this; - } - - /** * Returns the parents array, where {@code parents[i]} denotes the parent of * category ordinal {@code i}. */ - public int[] parents() { - return parents; - } + public abstract int[] parents(); /** - * Returns the children array, where {@code children[i]} denotes the youngest - * child of category ordinal {@code i}. The youngest child is defined as the - * category that was added last to the taxonomy as an immediate child of - * {@code i}. + * Returns the children array, where {@code children[i]} denotes a child of + * category ordinal {@code i}. */ - public int[] children() { - if (!initializedChildren) { - initChildrenSiblings(null); - } - - // the array is guaranteed to be populated - return children; - } + public abstract int[] children(); /** * Returns the siblings array, where {@code siblings[i]} denotes the sibling - * of category ordinal {@code i}. The sibling is defined as the previous - * youngest child of {@code parents[i]}. + * of category ordinal {@code i}. */ - public int[] siblings() { - if (!initializedChildren) { - initChildrenSiblings(null); - } - - // the array is guaranteed to be populated - return siblings; - } + public abstract int[] siblings(); } Index: lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyReader.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyReader.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyReader.java (working copy) @@ -5,7 +5,6 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays; import org.apache.lucene.store.AlreadyClosedException; /* Index: lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java (working copy) @@ -7,6 +7,7 @@ import org.apache.lucene.facet.collections.LRUHashMap; import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.DirectoryReader; @@ -62,7 +63,7 @@ private LRUHashMap ordinalCache; private LRUHashMap categoryCache; - private volatile ParallelTaxonomyArrays taxoArrays; + private volatile TaxonomyIndexArrays taxoArrays; private char delimiter = Consts.DEFAULT_DELIMITER; @@ -73,7 +74,7 @@ */ DirectoryTaxonomyReader(DirectoryReader indexReader, DirectoryTaxonomyWriter taxoWriter, LRUHashMap ordinalCache, LRUHashMap categoryCache, - ParallelTaxonomyArrays taxoArrays) throws IOException { + TaxonomyIndexArrays taxoArrays) throws IOException { this.indexReader = indexReader; this.taxoWriter = taxoWriter; this.taxoEpoch = taxoWriter == null ? -1 : taxoWriter.getTaxonomyEpoch(); @@ -82,7 +83,7 @@ this.ordinalCache = ordinalCache == null ? new LRUHashMap(DEFAULT_CACHE_VALUE) : ordinalCache; this.categoryCache = categoryCache == null ? new LRUHashMap(DEFAULT_CACHE_VALUE) : categoryCache; - this.taxoArrays = taxoArrays != null ? new ParallelTaxonomyArrays(indexReader, taxoArrays) : null; + this.taxoArrays = taxoArrays != null ? new TaxonomyIndexArrays(indexReader, taxoArrays) : null; } /** @@ -130,7 +131,7 @@ // according to Java Concurrency in Practice, this might perform better on // some JVMs, because the array initialization doesn't happen on the // volatile member. - ParallelTaxonomyArrays tmpArrays = new ParallelTaxonomyArrays(indexReader); + TaxonomyIndexArrays tmpArrays = new TaxonomyIndexArrays(indexReader); taxoArrays = tmpArrays; } } Index: lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyWriter.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyWriter.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyWriter.java (working copy) @@ -129,7 +129,7 @@ */ private volatile boolean cacheIsComplete; private volatile boolean isClosed = false; - private volatile ParallelTaxonomyArrays taxoArrays; + private volatile TaxonomyIndexArrays taxoArrays; private volatile int nextID; /** Reads the commit data from a Directory. */ @@ -744,7 +744,7 @@ } } - private ParallelTaxonomyArrays getTaxoArrays() throws IOException { + private TaxonomyIndexArrays getTaxoArrays() throws IOException { if (taxoArrays == null) { synchronized (this) { if (taxoArrays == null) { @@ -754,7 +754,7 @@ // according to Java Concurrency, this might perform better on some // JVMs, since the object initialization doesn't happen on the // volatile member. - ParallelTaxonomyArrays tmpArrays = new ParallelTaxonomyArrays(reader); + TaxonomyIndexArrays tmpArrays = new TaxonomyIndexArrays(reader); taxoArrays = tmpArrays; } finally { readerManager.release(reader); Index: lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParallelTaxonomyArrays.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParallelTaxonomyArrays.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParallelTaxonomyArrays.java (working copy) @@ -1,230 +0,0 @@ -package org.apache.lucene.facet.taxonomy.directory; - -import java.io.IOException; - -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.CorruptIndexException; -import org.apache.lucene.index.DocsAndPositionsEnum; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.MultiFields; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.util.ArrayUtil; - -/* - * 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. - */ - -/** - * Returns 3 arrays for traversing the taxonomy: - *

    - *
  • {@code parents}: {@code parents[i]} denotes the parent of category - * ordinal {@code i}.
  • - *
  • {@code children}: {@code children[i]} denotes the youngest child of - * category ordinal {@code i}. The youngest child is defined as the category - * that was added last to the taxonomy as an immediate child of {@code i}.
  • - *
  • {@code siblings}: {@code siblings[i]} denotes the sibling of category - * ordinal {@code i}. The sibling is defined as the previous youngest child of - * {@code parents[i]}.
  • - *
- * - * To traverse the taxonomy tree, you typically start with {@code children[0]} - * (ordinal 0 is reserved for ROOT), and then depends if you want to do DFS or - * BFS, you call {@code children[children[0]]} or {@code siblings[children[0]]} - * and so forth, respectively. - * - *

- * NOTE: you are not expected to modify the values of the arrays, since - * the arrays are shared with other threads. - * - * @lucene.experimental - */ -public class ParallelTaxonomyArrays { - - private final int[] parents; - - // the following two arrays are lazily intialized. note that we only keep a - // single boolean member as volatile, instead of declaring the arrays - // volatile. the code guarantees that only after the boolean is set to true, - // the arrays are returned. - private volatile boolean initializedChildren = false; - private int[] children, siblings; - - /** Used by {@link #add(int, int)} after the array grew. */ - private ParallelTaxonomyArrays(int[] parents) { - this.parents = parents; - } - - public ParallelTaxonomyArrays(IndexReader reader) throws IOException { - parents = new int[reader.maxDoc()]; - if (parents.length > 0) { - initParents(reader, 0); - // Starting Lucene 2.9, following the change LUCENE-1542, we can - // no longer reliably read the parent "-1" (see comment in - // LuceneTaxonomyWriter.SinglePositionTokenStream). We have no way - // to fix this in indexing without breaking backward-compatibility - // with existing indexes, so what we'll do instead is just - // hard-code the parent of ordinal 0 to be -1, and assume (as is - // indeed the case) that no other parent can be -1. - parents[0] = TaxonomyReader.INVALID_ORDINAL; - } - } - - public ParallelTaxonomyArrays(IndexReader reader, ParallelTaxonomyArrays copyFrom) throws IOException { - assert copyFrom != null; - - // note that copyParents.length may be equal to reader.maxDoc(). this is not a bug - // it may be caused if e.g. the taxonomy segments were merged, and so an updated - // NRT reader was obtained, even though nothing was changed. this is not very likely - // to happen. - int[] copyParents = copyFrom.parents(); - this.parents = new int[reader.maxDoc()]; - System.arraycopy(copyParents, 0, parents, 0, copyParents.length); - initParents(reader, copyParents.length); - - if (copyFrom.initializedChildren) { - initChildrenSiblings(copyFrom); - } - } - - private final synchronized void initChildrenSiblings(ParallelTaxonomyArrays copyFrom) { - if (!initializedChildren) { // must do this check ! - children = new int[parents.length]; - siblings = new int[parents.length]; - if (copyFrom != null) { - // called from the ctor, after we know copyFrom has initialized children/siblings - System.arraycopy(copyFrom.children(), 0, children, 0, copyFrom.children().length); - System.arraycopy(copyFrom.siblings(), 0, siblings, 0, copyFrom.siblings().length); - } - computeChildrenSiblings(parents, 0); - initializedChildren = true; - } - } - - private void computeChildrenSiblings(int[] parents, int first) { - // reset the youngest child of all ordinals. while this should be done only - // for the leaves, we don't know up front which are the leaves, so we reset - // all of them. - for (int i = first; i < parents.length; i++) { - children[i] = TaxonomyReader.INVALID_ORDINAL; - } - - // the root category has no parent, and therefore no siblings - if (first == 0) { - first = 1; - siblings[0] = TaxonomyReader.INVALID_ORDINAL; - } - - for (int i = first; i < parents.length; i++) { - // note that parents[i] is always < i, so the right-hand-side of - // the following line is already set when we get here - siblings[i] = children[parents[i]]; - children[parents[i]] = i; - } - } - - // Read the parents of the new categories - private void initParents(IndexReader reader, int first) throws IOException { - if (reader.maxDoc() == first) { - return; - } - - // it's ok to use MultiFields because we only iterate on one posting list. - // breaking it to loop over the leaves() only complicates code for no - // apparent gain. - DocsAndPositionsEnum positions = MultiFields.getTermPositionsEnum(reader, null, - Consts.FIELD_PAYLOADS, Consts.PAYLOAD_PARENT_BYTES_REF, - DocsAndPositionsEnum.FLAG_PAYLOADS); - - // shouldn't really happen, if it does, something's wrong - if (positions == null || positions.advance(first) == DocIdSetIterator.NO_MORE_DOCS) { - throw new CorruptIndexException("Missing parent data for category " + first); - } - - int num = reader.maxDoc(); - for (int i = first; i < num; i++) { - if (positions.docID() == i) { - if (positions.freq() == 0) { // shouldn't happen - throw new CorruptIndexException("Missing parent data for category " + i); - } - - parents[i] = positions.nextPosition(); - - if (positions.nextDoc() == DocIdSetIterator.NO_MORE_DOCS) { - if (i + 1 < num) { - throw new CorruptIndexException("Missing parent data for category "+ (i + 1)); - } - break; - } - } else { // this shouldn't happen - throw new CorruptIndexException("Missing parent data for category " + i); - } - } - } - - /** - * Adds the given ordinal/parent info and returns either a new instance if the - * underlying array had to grow, or this instance otherwise. - *

- * NOTE: you should call this method from a thread-safe code. - */ - ParallelTaxonomyArrays add(int ordinal, int parentOrdinal) { - if (ordinal >= parents.length) { - int[] newarray = ArrayUtil.grow(parents, ordinal + 1); - newarray[ordinal] = parentOrdinal; - return new ParallelTaxonomyArrays(newarray); - } - parents[ordinal] = parentOrdinal; - return this; - } - - /** - * Returns the parents array, where {@code parents[i]} denotes the parent of - * category ordinal {@code i}. - */ - public int[] parents() { - return parents; - } - - /** - * Returns the children array, where {@code children[i]} denotes the youngest - * child of category ordinal {@code i}. The youngest child is defined as the - * category that was added last to the taxonomy as an immediate child of - * {@code i}. - */ - public int[] children() { - if (!initializedChildren) { - initChildrenSiblings(null); - } - - // the array is guaranteed to be populated - return children; - } - - /** - * Returns the siblings array, where {@code siblings[i]} denotes the sibling - * of category ordinal {@code i}. The sibling is defined as the previous - * youngest child of {@code parents[i]}. - */ - public int[] siblings() { - if (!initializedChildren) { - initChildrenSiblings(null); - } - - // the array is guaranteed to be populated - return siblings; - } - -} Index: lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/TaxonomyIndexArrays.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/TaxonomyIndexArrays.java (working copy) +++ lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/TaxonomyIndexArrays.java (working copy) @@ -2,6 +2,7 @@ import java.io.IOException; +import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.DocsAndPositionsEnum; @@ -28,30 +29,12 @@ */ /** - * Returns 3 arrays for traversing the taxonomy: - *

    - *
  • {@code parents}: {@code parents[i]} denotes the parent of category - * ordinal {@code i}.
  • - *
  • {@code children}: {@code children[i]} denotes the youngest child of - * category ordinal {@code i}. The youngest child is defined as the category - * that was added last to the taxonomy as an immediate child of {@code i}.
  • - *
  • {@code siblings}: {@code siblings[i]} denotes the sibling of category - * ordinal {@code i}. The sibling is defined as the previous youngest child of - * {@code parents[i]}.
  • - *
+ * A {@link ParallelTaxonomyArrays} that are initialized from the taxonomy + * index. * - * To traverse the taxonomy tree, you typically start with {@code children[0]} - * (ordinal 0 is reserved for ROOT), and then depends if you want to do DFS or - * BFS, you call {@code children[children[0]]} or {@code siblings[children[0]]} - * and so forth, respectively. - * - *

- * NOTE: you are not expected to modify the values of the arrays, since - * the arrays are shared with other threads. - * * @lucene.experimental */ -public class ParallelTaxonomyArrays { +class TaxonomyIndexArrays extends ParallelTaxonomyArrays { private final int[] parents; @@ -63,11 +46,11 @@ private int[] children, siblings; /** Used by {@link #add(int, int)} after the array grew. */ - private ParallelTaxonomyArrays(int[] parents) { + private TaxonomyIndexArrays(int[] parents) { this.parents = parents; } - public ParallelTaxonomyArrays(IndexReader reader) throws IOException { + public TaxonomyIndexArrays(IndexReader reader) throws IOException { parents = new int[reader.maxDoc()]; if (parents.length > 0) { initParents(reader, 0); @@ -82,7 +65,7 @@ } } - public ParallelTaxonomyArrays(IndexReader reader, ParallelTaxonomyArrays copyFrom) throws IOException { + public TaxonomyIndexArrays(IndexReader reader, TaxonomyIndexArrays copyFrom) throws IOException { assert copyFrom != null; // note that copyParents.length may be equal to reader.maxDoc(). this is not a bug @@ -99,7 +82,7 @@ } } - private final synchronized void initChildrenSiblings(ParallelTaxonomyArrays copyFrom) { + private final synchronized void initChildrenSiblings(TaxonomyIndexArrays copyFrom) { if (!initializedChildren) { // must do this check ! children = new int[parents.length]; siblings = new int[parents.length]; @@ -180,11 +163,11 @@ *

* NOTE: you should call this method from a thread-safe code. */ - ParallelTaxonomyArrays add(int ordinal, int parentOrdinal) { + TaxonomyIndexArrays add(int ordinal, int parentOrdinal) { if (ordinal >= parents.length) { int[] newarray = ArrayUtil.grow(parents, ordinal + 1); newarray[ordinal] = parentOrdinal; - return new ParallelTaxonomyArrays(newarray); + return new TaxonomyIndexArrays(newarray); } parents[ordinal] = parentOrdinal; return this; @@ -194,6 +177,7 @@ * Returns the parents array, where {@code parents[i]} denotes the parent of * category ordinal {@code i}. */ + @Override public int[] parents() { return parents; } @@ -204,6 +188,7 @@ * category that was added last to the taxonomy as an immediate child of * {@code i}. */ + @Override public int[] children() { if (!initializedChildren) { initChildrenSiblings(null); @@ -218,6 +203,7 @@ * of category ordinal {@code i}. The sibling is defined as the previous * youngest child of {@code parents[i]}. */ + @Override public int[] siblings() { if (!initializedChildren) { initChildrenSiblings(null); Index: lucene/facet/src/java/org/apache/lucene/facet/util/PrintTaxonomyStats.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/util/PrintTaxonomyStats.java (revision 1457768) +++ lucene/facet/src/java/org/apache/lucene/facet/util/PrintTaxonomyStats.java (working copy) @@ -22,9 +22,9 @@ import java.io.PrintStream; import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; Index: lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java (revision 1457768) +++ lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java (working copy) @@ -11,7 +11,6 @@ import org.apache.lucene.facet.SlowRAMDirectory; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays; import org.apache.lucene.store.Directory; import org.apache.lucene.store.LockObtainFailedException; import org.apache.lucene.store.RAMDirectory;