You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2012/12/06 14:55:35 UTC

svn commit: r1417889 - in /lucene/dev/trunk/lucene: ./ facet/src/java/org/apache/lucene/facet/search/ facet/src/java/org/apache/lucene/facet/taxonomy/ facet/src/java/org/apache/lucene/facet/taxonomy/directory/ facet/src/test/org/apache/lucene/facet/sea...

Author: shaie
Date: Thu Dec  6 13:55:33 2012
New Revision: 1417889

URL: http://svn.apache.org/viewvc?rev=1417889&view=rev
Log:
LUCENE-4565: Consolidate ParentArray and ChildrenArrays into ParallelTaxonomyArrays

Added:
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParallelTaxonomyArrays.java
      - copied, changed from r1417362, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParentArray.java
Removed:
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/ChildrenArrays.java
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParentArray.java
Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyReader.java
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyWriter.java
    lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/params/MultiIteratorsPerCLParamsTest.java
    lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java
    lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Thu Dec  6 13:55:33 2012
@@ -64,6 +64,11 @@ Changes in backwards compatibility polic
   even if the commitData is the only thing that changes.
   (Shai Erera, Michael McCandless)
 
+* LUCENE-4565: TaxonomyReader.getParentArray and .getChildrenArrays consolidated
+  into one getParallelTaxonomyArrays(). You can obtain the 3 arrays that the
+  previous two methods returned by calling parents(), children() or siblings()
+  on the returned ParallelTaxonomyArrays. (Shai Erera)
+  
 New Features
 
 * LUCENE-4226: New experimental StoredFieldsFormat that compresses chunks of

Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java Thu Dec  6 13:55:33 2012
@@ -6,10 +6,10 @@ import java.util.ArrayList;
 import org.apache.lucene.facet.search.params.FacetRequest;
 import org.apache.lucene.facet.search.results.FacetResult;
 import org.apache.lucene.facet.search.results.FacetResultNode;
-import org.apache.lucene.facet.search.results.MutableFacetResultNode;
 import org.apache.lucene.facet.search.results.IntermediateFacetResult;
-import org.apache.lucene.facet.taxonomy.ChildrenArrays;
+import org.apache.lucene.facet.search.results.MutableFacetResultNode;
 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
+import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays;
 import org.apache.lucene.facet.util.ResultSortUtils;
 
 /*
@@ -123,9 +123,9 @@ public class TopKFacetResultsHandler ext
       MutableFacetResultNode parentResultNode, FacetArrays facetArrays, int offset) throws IOException {
     int partitionSize = facetArrays.getArraysLength();
     int endOffset = offset + partitionSize;
-    ChildrenArrays childrenArray = taxonomyReader.getChildrenArrays();
-    int[] youngestChild = childrenArray.getYoungestChildArray();
-    int[] olderSibling = childrenArray.getOlderSiblingArray();
+    ParallelTaxonomyArrays childrenArray = taxonomyReader.getParallelTaxonomyArrays();
+    int[] children = childrenArray.children();
+    int[] siblings = childrenArray.siblings();
     FacetResultNode reusable = null;
     int localDepth = 0;
     int depth = facetRequest.getDepth();
@@ -134,9 +134,9 @@ public class TopKFacetResultsHandler ext
     
     int tosOrdinal; // top of stack element
     
-    int yc = youngestChild[ordinal];
+    int yc = children[ordinal];
     while (yc >= endOffset) {
-      yc = olderSibling[yc];
+      yc = siblings[yc];
     }
     // make use of the fact that TaxonomyReader.INVALID_ORDINAL == -1, < endOffset
     // and it, too, can stop the loop.
@@ -161,7 +161,7 @@ public class TopKFacetResultsHandler ext
         // need to proceed to its sibling
         localDepth--;
         // change element now on top of stack to its sibling.
-        ordinalStack[localDepth] = olderSibling[ordinalStack[localDepth]];
+        ordinalStack[localDepth] = siblings[ordinalStack[localDepth]];
         continue;
       }
       // top of stack is not invalid, this is the first time we see it on top of stack.
@@ -187,9 +187,9 @@ public class TopKFacetResultsHandler ext
       }
       if (localDepth < depth) {
         // push kid of current tos
-        yc = youngestChild[tosOrdinal];
+        yc = children[tosOrdinal];
         while (yc >= endOffset) {
-          yc = olderSibling[yc];
+          yc = siblings[yc];
         }
         ordinalStack[++localDepth] = yc;
       } else { // localDepth == depth; current tos exhausted its possible children, mark this by pushing INVALID_ORDINAL

Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java Thu Dec  6 13:55:33 2012
@@ -4,16 +4,15 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.lucene.util.PriorityQueue;
-
 import org.apache.lucene.facet.search.params.FacetRequest;
 import org.apache.lucene.facet.search.params.FacetRequest.SortOrder;
 import org.apache.lucene.facet.search.results.FacetResult;
 import org.apache.lucene.facet.search.results.FacetResultNode;
-import org.apache.lucene.facet.search.results.MutableFacetResultNode;
 import org.apache.lucene.facet.search.results.IntermediateFacetResult;
-import org.apache.lucene.facet.taxonomy.ChildrenArrays;
+import org.apache.lucene.facet.search.results.MutableFacetResultNode;
 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
+import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays;
+import org.apache.lucene.util.PriorityQueue;
 import org.apache.lucene.util.collections.IntIterator;
 import org.apache.lucene.util.collections.IntToObjectMap;
 
@@ -141,9 +140,9 @@ public class TopKInEachNodeHandler exten
     }
 
     int endOffset = offset + partitionSize; // one past the largest ordinal in the partition
-    ChildrenArrays childrenArray = taxonomyReader.getChildrenArrays();
-    int[] youngestChild = childrenArray.getYoungestChildArray();
-    int[] olderSibling = childrenArray.getOlderSiblingArray();
+    ParallelTaxonomyArrays childrenArray = taxonomyReader.getParallelTaxonomyArrays();
+    int[] children = childrenArray.children();
+    int[] siblings = childrenArray.siblings();
     int totalNumOfDescendantsConsidered = 0; // total number of facets with value != 0, 
     // in the tree. These include those selected as top K in each node, and all the others that
     // were not. Not including rootNode
@@ -217,7 +216,7 @@ public class TopKInEachNodeHandler exten
      * we can continue to the older sibling of rootNode once the localDepth goes down, before we verify that 
      * it went that down)
      */
-    ordinalStack[++localDepth] = youngestChild[rootNode];
+    ordinalStack[++localDepth] = children[rootNode];
     siblingExplored[localDepth] = Integer.MAX_VALUE;  // we have not verified position wrt current partition
     siblingExplored[0] = -1; // as if rootNode resides to the left of current position
 
@@ -238,7 +237,7 @@ public class TopKInEachNodeHandler exten
         // its child, now just removed, would not have been pushed on it.
         // so the father is either inside the partition, or smaller ordinal
         if (siblingExplored[localDepth] < 0 ) {
-          ordinalStack[localDepth] = olderSibling[ordinalStack[localDepth]];
+          ordinalStack[localDepth] = siblings[ordinalStack[localDepth]];
           continue;
         } 
         // in this point, siblingExplored[localDepth] between 0 and number of bestSiblings
@@ -264,7 +263,7 @@ public class TopKInEachNodeHandler exten
         //tosOrdinal was not examined yet for its position relative to current partition
         // and the best K of current partition, among its siblings, have not been determined yet
         while (tosOrdinal >= endOffset) {
-          tosOrdinal = olderSibling[tosOrdinal];
+          tosOrdinal = siblings[tosOrdinal];
         }
         // now it is inside. Run it and all its siblings inside the partition through a heap
         // and in doing so, count them, find best K, and sum into residue
@@ -297,12 +296,12 @@ public class TopKInEachNodeHandler exten
               // update totalNumOfDescendants by the now excluded node and all its descendants
               totalNumOfDescendantsConsidered--; // reduce the 1 earned when the excluded node entered the heap
               // and now return it and all its descendants. These will never make it to FacetResult
-              totalNumOfDescendantsConsidered += countOnly (ac.ordinal, youngestChild, 
-                  olderSibling, arrays, partitionSize, offset, endOffset, localDepth, depth);
+              totalNumOfDescendantsConsidered += countOnly (ac.ordinal, children, 
+                  siblings, arrays, partitionSize, offset, endOffset, localDepth, depth);
               reusables[++tosReuslables] = ac;
             }
           }
-          tosOrdinal = olderSibling[tosOrdinal];  
+          tosOrdinal = siblings[tosOrdinal];  
         }
         // now pq has best K children of ordinals that belong to the given partition.   
         // Populate a new AACO with them.
@@ -343,7 +342,7 @@ public class TopKInEachNodeHandler exten
         ordinalStack[++localDepth] = TaxonomyReader.INVALID_ORDINAL;
         continue;
       }
-      ordinalStack[++localDepth] = youngestChild[tosOrdinal];
+      ordinalStack[++localDepth] = children[tosOrdinal];
       siblingExplored[localDepth] = Integer.MAX_VALUE;
     } // endof loop while stack is not empty
 

Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyReader.java?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyReader.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyReader.java Thu Dec  6 13:55:33 2012
@@ -5,6 +5,7 @@ import java.io.IOException;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays;
 import org.apache.lucene.store.AlreadyClosedException;
 
 /*
@@ -162,16 +163,10 @@ public abstract class TaxonomyReader imp
   }
   
   /**
-   * Returns a {@link ChildrenArrays} object which can be used together to
-   * efficiently enumerate the children of any category.
-   * <p>
-   * The caller can hold on to the object 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 object which it got (and the arrays it contains)
-   * as read-only and <b>not modify it</b>, because other callers might have
-   * gotten the same object too.
+   * Returns a {@link ParallelTaxonomyArrays} object which can be used to
+   * efficiently traverse the taxonomy tree.
    */
-  public abstract ChildrenArrays getChildrenArrays() throws IOException;
+  public abstract ParallelTaxonomyArrays getParallelTaxonomyArrays() throws IOException;
   
   /**
    * Retrieve user committed data.
@@ -195,7 +190,6 @@ public abstract class TaxonomyReader imp
    * Returns the ordinal of the parent category of the category with the given
    * ordinal, according to the following rules:
    * 
-   * 
    * <ul>
    * <li>If the given ordinal is the {@link #ROOT_ORDINAL}, an
    * {@link #INVALID_ORDINAL} is returned.
@@ -210,19 +204,7 @@ public abstract class TaxonomyReader imp
    *           available ordinal)
    */
   public abstract int getParent(int ordinal) throws IOException;
-  
-  /**
-   * Returns an {@code int[]} the size of the taxonomy listing the ordinal of
-   * the parent category of each category in the taxonomy.
-   * <p>
-   * 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 <b>not modify
-   * it</b>, because other callers might have gotten the same array too (and
-   * getParent() calls might be answered from the same array).
-   */
-  public abstract int[] getParentArray() throws IOException;
-  
+ 
   /**
    * Returns the path name of the category with the given ordinal. The path is
    * returned as a new CategoryPath object - to reuse an existing object, use

Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java Thu Dec  6 13:55:33 2012
@@ -6,7 +6,6 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.lucene.facet.taxonomy.CategoryPath;
-import org.apache.lucene.facet.taxonomy.ChildrenArrays;
 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
 import org.apache.lucene.facet.taxonomy.directory.Consts.LoadFullPathOnly;
 import org.apache.lucene.index.CorruptIndexException;
@@ -63,9 +62,7 @@ public class DirectoryTaxonomyReader ext
   private LRUHashMap<String, Integer> ordinalCache;
   private LRUHashMap<Integer, String> categoryCache;
 
-  // TODO: consolidate these objects into one ParentInfo or something?
-  private volatile ParentArray parentArray;
-  private volatile ChildrenArrays childrenArrays;
+  private volatile ParallelTaxonomyArrays taxoArrays;
 
   private char delimiter = Consts.DEFAULT_DELIMITER;
 
@@ -75,9 +72,8 @@ public class DirectoryTaxonomyReader ext
    * arrays.
    */
   DirectoryTaxonomyReader(DirectoryReader indexReader, DirectoryTaxonomyWriter taxoWriter,
-      LRUHashMap<String,Integer> ordinalCache,
-      LRUHashMap<Integer,String> categoryCache, ParentArray parentArray,
-      ChildrenArrays childrenArrays) throws IOException {
+      LRUHashMap<String,Integer> ordinalCache, LRUHashMap<Integer,String> categoryCache,
+      ParallelTaxonomyArrays taxoArrays) throws IOException {
     this.indexReader = indexReader;
     this.taxoWriter = taxoWriter;
     this.taxoEpoch = taxoWriter == null ? -1 : taxoWriter.getTaxonomyEpoch();
@@ -86,14 +82,7 @@ public class DirectoryTaxonomyReader ext
     this.ordinalCache = ordinalCache == null ? new LRUHashMap<String,Integer>(DEFAULT_CACHE_VALUE) : ordinalCache;
     this.categoryCache = categoryCache == null ? new LRUHashMap<Integer,String>(DEFAULT_CACHE_VALUE) : categoryCache;
     
-    this.parentArray = null;
-    this.childrenArrays = null;
-    if (parentArray != null) {
-      this.parentArray = new ParentArray(indexReader, parentArray);
-      if (childrenArrays != null) {
-        this.childrenArrays = new ChildrenArrays(this.parentArray.getArray(), childrenArrays);
-      }
-    }
+    this.taxoArrays = taxoArrays != null ? new ParallelTaxonomyArrays(indexReader, taxoArrays) : null;
   }
   
   /**
@@ -167,11 +156,20 @@ public class DirectoryTaxonomyReader ext
     return ret;
   }
   
+  private synchronized void initTaxoArrays() throws IOException {
+    if (taxoArrays == null) {
+      // 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);
+      taxoArrays = tmpArrays;
+    }
+  }
+  
   @Override
   protected void doClose() throws IOException {
     indexReader.close();
-    parentArray = null;
-    childrenArrays = null;
+    taxoArrays = null;
     // do not clear() the caches, as they may be used by other DTR instances.
     ordinalCache = null;
     categoryCache = null;
@@ -233,9 +231,9 @@ public class DirectoryTaxonomyReader ext
       if (recreated) {
         // if recreated, do not reuse anything from this instace. the information
         // will be lazily computed by the new instance when needed.
-        newtr = new DirectoryTaxonomyReader(r2, taxoWriter, null, null, null, null);
+        newtr = new DirectoryTaxonomyReader(r2, taxoWriter, null, null, null);
       } else {
-        newtr = new DirectoryTaxonomyReader(r2, taxoWriter, ordinalCache, categoryCache, parentArray, childrenArrays);
+        newtr = new DirectoryTaxonomyReader(r2, taxoWriter, ordinalCache, categoryCache, taxoArrays);
       }
       
       success = true;
@@ -265,16 +263,12 @@ public class DirectoryTaxonomyReader ext
   }
 
   @Override
-  public ChildrenArrays getChildrenArrays() throws IOException {
+  public ParallelTaxonomyArrays getParallelTaxonomyArrays() throws IOException {
     ensureOpen();
-    if (childrenArrays == null) {
-      synchronized (this) {
-        if (childrenArrays == null) {
-          childrenArrays = new ChildrenArrays(getParentArray());
-        }
-      }      
+    if (taxoArrays == null) {
+      initTaxoArrays();
     }
-    return childrenArrays;
+    return taxoArrays;
   }
 
   @Override
@@ -330,27 +324,13 @@ public class DirectoryTaxonomyReader ext
     return ret;
   }
 
-  // TODO: move to a ParentInfo class? (see TODO for parentArray)
   @Override
   public int getParent(int ordinal) throws IOException {
     ensureOpen();
-    return getParentArray()[ordinal];
+    return getParallelTaxonomyArrays().parents()[ordinal];
   }
 
   @Override
-  public int[] getParentArray() throws IOException {
-    ensureOpen();
-    if (parentArray == null) {
-      synchronized (this) {
-        if (parentArray == null) {
-          parentArray = new ParentArray(indexReader);
-        }
-      }
-    }
-    return parentArray.getArray();
-  }
-  
-  @Override
   public CategoryPath getPath(int ordinal) throws IOException {
     ensureOpen();
     // TODO (Facet): Currently, the LRU cache we use (getCategoryCache) holds

Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyWriter.java?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyWriter.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyWriter.java Thu Dec  6 13:55:33 2012
@@ -112,6 +112,12 @@ public class DirectoryTaxonomyWriter imp
   private int cacheMissesUntilFill = 11;
   private boolean shouldFillCache = true;
   
+  // even though lazily initialized, not volatile so that access to it is
+  // faster. we keep a volatile boolean init instead.
+  private ReaderManager readerManager;
+  private volatile boolean initializedReaderManager = false;
+  private volatile boolean shouldRefreshReaderManager;
+  
   /**
    * We call the cache "complete" if we know that every category in our
    * taxonomy is in the cache. When the cache is <B>not</B> complete, and
@@ -123,14 +129,10 @@ public class DirectoryTaxonomyWriter imp
    * that some of the cached data was cleared).
    */
   private volatile boolean cacheIsComplete;
-  private volatile ReaderManager readerManager;
-  private volatile boolean shouldRefreshReaderManager;
   private volatile boolean isClosed = false;
-  private volatile ParentArray parentArray;
+  private volatile ParallelTaxonomyArrays taxoArrays;
   private volatile int nextID;
 
-//  private Map<String,String> commitData;
-  
   /** Reads the commit data from a Directory. */
   private static Map<String, String> readCommitData(Directory dir) throws IOException {
     SegmentInfos infos = new SegmentInfos();
@@ -308,13 +310,14 @@ public class DirectoryTaxonomyWriter imp
   
   /** Opens a {@link ReaderManager} from the internal {@link IndexWriter}. */
   private void initReaderManager() throws IOException {
-    if (readerManager == null) {
+    if (!initializedReaderManager) {
       synchronized (this) {
         // verify that the taxo-writer hasn't been closed on us.
         ensureOpen();
-        if (readerManager == null) {
+        if (!initializedReaderManager) {
           readerManager = new ReaderManager(indexWriter, false);
           shouldRefreshReaderManager = false;
+          initializedReaderManager = true;
         }
       }
     }
@@ -341,8 +344,6 @@ public class DirectoryTaxonomyWriter imp
     return new Cl2oTaxonomyWriterCache(1024, 0.15f, 3);
   }
 
-  // convenience constructors:
-
   public DirectoryTaxonomyWriter(Directory d) throws IOException {
     this(d, OpenMode.CREATE_OR_APPEND);
   }
@@ -375,9 +376,10 @@ public class DirectoryTaxonomyWriter imp
    * <code>super.closeResources()</code> call in your implementation.
    */
   protected synchronized void closeResources() throws IOException {
-    if (readerManager != null) {
+    if (initializedReaderManager) {
       readerManager.close();
       readerManager = null;
+      initializedReaderManager = false;
     }
     if (cache != null) {
       cache.close();
@@ -467,15 +469,19 @@ public class DirectoryTaxonomyWriter imp
     int doc = -1;
     DirectoryReader reader = readerManager.acquire();
     try {
+      TermsEnum termsEnum = null; // reuse
+      DocsEnum docs = null; // reuse
       final BytesRef catTerm = new BytesRef(categoryPath.toString(delimiter, prefixLen));
       for (AtomicReaderContext ctx : reader.leaves()) {
         Terms terms = ctx.reader().terms(Consts.FULL);
         if (terms != null) {
-          TermsEnum termsEnum = terms.iterator(null);
+          termsEnum = terms.iterator(termsEnum);
           if (termsEnum.seekExact(catTerm, true)) {
-            // TODO: is it really ok that null is passed here as liveDocs?
-            DocsEnum docs = termsEnum.docs(null, null, 0);
+            // liveDocs=null because the taxonomy has no deletes
+            docs = termsEnum.docs(null, docs, 0 /* freqs not required */);
+            // if the term was found, we know it has exactly one document.
             doc = docs.nextDoc() + ctx.docBase;
+            break;
           }
         }
       }
@@ -589,7 +595,7 @@ public class DirectoryTaxonomyWriter imp
     addToCache(categoryPath, length, id);
     
     // also add to the parent array
-    parentArray = getParentArray().add(id, parent);
+    taxoArrays = getTaxoArrays().add(id, parent);
 
     return id;
   }
@@ -657,7 +663,7 @@ public class DirectoryTaxonomyWriter imp
     // NOTE: since this method is sync'ed, it can call maybeRefresh, instead of
     // maybeRefreshBlocking. If ever this is changed, make sure to change the
     // call too.
-    if (shouldRefreshReaderManager && readerManager != null) {
+    if (shouldRefreshReaderManager && initializedReaderManager) {
       readerManager.maybeRefresh();
       shouldRefreshReaderManager = false;
     }
@@ -791,25 +797,30 @@ public class DirectoryTaxonomyWriter imp
         // initReaderManager called in parallel.
         readerManager.close();
         readerManager = null;
+        initializedReaderManager = false;
       }
     }
   }
 
-  private ParentArray getParentArray() throws IOException {
-    if (parentArray == null) {
+  private ParallelTaxonomyArrays getTaxoArrays() throws IOException {
+    if (taxoArrays == null) {
       synchronized (this) {
-        if (parentArray == null) {
+        if (taxoArrays == null) {
           initReaderManager();
           DirectoryReader reader = readerManager.acquire();
           try {
-            parentArray = new ParentArray(reader);
+            // 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);
+            taxoArrays = tmpArrays;
           } finally {
             readerManager.release(reader);
           }
         }
       }
     }
-    return parentArray;
+    return taxoArrays;
   }
   
   @Override
@@ -821,7 +832,7 @@ public class DirectoryTaxonomyWriter imp
     if (ordinal >= nextID) {
       throw new ArrayIndexOutOfBoundsException("requested ordinal is bigger than the largest ordinal in the taxonomy");
     }
-    return getParentArray().getArray()[ordinal];
+    return getTaxoArrays().parents()[ordinal];
   }
   
   /**

Copied: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParallelTaxonomyArrays.java (from r1417362, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParentArray.java)
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParallelTaxonomyArrays.java?p2=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParallelTaxonomyArrays.java&p1=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParentArray.java&r1=1417362&r2=1417889&rev=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParentArray.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/ParallelTaxonomyArrays.java Thu Dec  6 13:55:33 2012
@@ -28,22 +28,49 @@ import org.apache.lucene.util.ArrayUtil;
  */
 
 /**
+ * Returns 3 arrays for traversing the taxonomy:
+ * <ul>
+ * <li>{@code parents}: {@code parents[i]} denotes the parent of category
+ * ordinal {@code i}.</li>
+ * <li>{@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}.</li>
+ * <li>{@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]}.</li>
+ * </ul>
+ * 
+ * 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.
+ * 
+ * <p>
+ * <b>NOTE:</b> you are not expected to modify the values of the arrays, since
+ * the arrays are shared with other threads.
+ * 
  * @lucene.experimental
  */
-class ParentArray {
+public class ParallelTaxonomyArrays {
 
-  // TODO: maybe use PackedInts?
-  private final int[] parentOrdinals;
+  private final int[] parents;
 
-  /** Used by {@link #add(int, int)} when the array needs to grow. */
-  ParentArray(int[] parentOrdinals) {
-    this.parentOrdinals = parentOrdinals;
+  // 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 ParentArray(IndexReader reader) throws IOException {
-    parentOrdinals = new int[reader.maxDoc()];
-    if (parentOrdinals.length > 0) {
-      initFromReader(reader, 0);
+  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
@@ -51,25 +78,65 @@ class ParentArray {
       // 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.
-      parentOrdinals[0] = TaxonomyReader.INVALID_ORDINAL;
+      parents[0] = TaxonomyReader.INVALID_ORDINAL;
     }
   }
   
-  public ParentArray(IndexReader reader, ParentArray copyFrom) throws IOException {
+  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.getArray();
-    this.parentOrdinals = new int[reader.maxDoc()];
-    System.arraycopy(copyParents, 0, parentOrdinals, 0, copyParents.length);
-    initFromReader(reader, copyParents.length);
+    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 initFromReader(IndexReader reader, int first) throws IOException {
+  private void initParents(IndexReader reader, int first) throws IOException {
     if (reader.maxDoc() == first) {
       return;
     }
@@ -93,7 +160,7 @@ class ParentArray {
           throw new CorruptIndexException("Missing parent data for category " + i);
         }
         
-        parentOrdinals[i] = positions.nextPosition();
+        parents[i] = positions.nextPosition();
         
         if (positions.nextDoc() == DocIdSetIterator.NO_MORE_DOCS) {
           if (i + 1 < num) {
@@ -107,24 +174,57 @@ class ParentArray {
     }
   }
   
-  public int[] getArray() {
-    return parentOrdinals;
-  }
-  
   /**
    * Adds the given ordinal/parent info and returns either a new instance if the
    * underlying array had to grow, or this instance otherwise.
    * <p>
    * <b>NOTE:</b> you should call this method from a thread-safe code.
    */
-  ParentArray add(int ordinal, int parentOrdinal) {
-    if (ordinal >= parentOrdinals.length) {
-      int[] newarray = ArrayUtil.grow(parentOrdinals);
+  ParallelTaxonomyArrays add(int ordinal, int parentOrdinal) {
+    if (ordinal >= parents.length) {
+      int[] newarray = ArrayUtil.grow(parents);
       newarray[ordinal] = parentOrdinal;
-      return new ParentArray(newarray);
+      return new ParallelTaxonomyArrays(newarray);
     }
-    parentOrdinals[ordinal] = parentOrdinal;
+    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;
+  }
 
 }

Modified: lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/params/MultiIteratorsPerCLParamsTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/params/MultiIteratorsPerCLParamsTest.java?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/params/MultiIteratorsPerCLParamsTest.java (original)
+++ lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/params/MultiIteratorsPerCLParamsTest.java Thu Dec  6 13:55:33 2012
@@ -232,13 +232,15 @@ public class MultiIteratorsPerCLParamsTe
         CategoryPath cp = new CategoryPath(requestedPath.getComponent(0));
         parentOrdinal = taxo.getOrdinal(cp);
       }
-      parentArray = taxo.getParentArray();
+      parentArray = taxo.getParallelTaxonomyArrays().parents();
     }
 
+    @Override
     public boolean init() throws IOException {
       return superCLI.init();
     }
 
+    @Override
     public long nextCategory() throws IOException {
       long next;
       while ((next = superCLI.nextCategory()) <= Integer.MAX_VALUE
@@ -259,6 +261,7 @@ public class MultiIteratorsPerCLParamsTe
       return false;
     }
 
+    @Override
     public boolean skipTo(int docId) throws IOException {
       return superCLI.skipTo(docId);
     }

Modified: lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java (original)
+++ lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java Thu Dec  6 13:55:33 2012
@@ -9,6 +9,7 @@ import java.util.concurrent.atomic.Atomi
 
 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;
@@ -545,7 +546,7 @@ public class TestTaxonomyCombined extend
     fillTaxonomy(tw);
     tw.close();
     TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir);
-    int[] parents = tr.getParentArray();
+    int[] parents = tr.getParallelTaxonomyArrays().parents();
     assertEquals(tr.getSize(), parents.length);
     for (int i=0; i<tr.getSize(); i++) {
       assertEquals(tr.getParent(i), parents[i]);
@@ -566,10 +567,10 @@ public class TestTaxonomyCombined extend
     fillTaxonomy(tw);
     tw.close();
     TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir);
-    ChildrenArrays ca = tr.getChildrenArrays();
-    int[] youngestChildArray = ca.getYoungestChildArray();
+    ParallelTaxonomyArrays ca = tr.getParallelTaxonomyArrays();
+    int[] youngestChildArray = ca.children();
     assertEquals(tr.getSize(), youngestChildArray.length);
-    int[] olderSiblingArray = ca.getOlderSiblingArray();
+    int[] olderSiblingArray = ca.siblings();
     assertEquals(tr.getSize(), olderSiblingArray.length);
     for (int i=0; i<expectedCategories.length; i++) {
       // find expected children by looking at all expectedCategories
@@ -630,15 +631,15 @@ public class TestTaxonomyCombined extend
     fillTaxonomy(tw);
     tw.close();
     TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir);
-    ChildrenArrays ca = tr.getChildrenArrays();
-    int[] youngestChildArray = ca.getYoungestChildArray();
-    assertEquals(tr.getSize(), youngestChildArray.length);
-    int[] olderSiblingArray = ca.getOlderSiblingArray();
+    ParallelTaxonomyArrays ca = tr.getParallelTaxonomyArrays();
+    int[] children = ca.children();
+    assertEquals(tr.getSize(), children.length);
+    int[] olderSiblingArray = ca.siblings();
     assertEquals(tr.getSize(), olderSiblingArray.length);
         
     // test that the "youngest child" of every category is indeed a child:
     for (int i=0; i<tr.getSize(); i++) {
-      int youngestChild = youngestChildArray[i];
+      int youngestChild = children[i];
       if (youngestChild != TaxonomyReader.INVALID_ORDINAL) {
         assertEquals(i, tr.getParent(youngestChild));
       }
@@ -676,7 +677,7 @@ public class TestTaxonomyCombined extend
       if (j==i) { // no child found
         j=TaxonomyReader.INVALID_ORDINAL;
       }
-      assertEquals(j, youngestChildArray[i]);
+      assertEquals(j, children[i]);
     }
 
     // test that the "older sibling" is indeed the least oldest one - and
@@ -710,32 +711,32 @@ public class TestTaxonomyCombined extend
     tw.addCategory(new CategoryPath("hi", "there"));
     tw.commit();
     TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir);
-    ChildrenArrays ca = tr.getChildrenArrays();
+    ParallelTaxonomyArrays ca = tr.getParallelTaxonomyArrays();
     assertEquals(3, tr.getSize());
-    assertEquals(3, ca.getOlderSiblingArray().length);
-    assertEquals(3, ca.getYoungestChildArray().length);
-    assertTrue(Arrays.equals(new int[] { 1, 2, -1 }, ca.getYoungestChildArray()));
-    assertTrue(Arrays.equals(new int[] { -1, -1, -1 }, ca.getOlderSiblingArray()));
+    assertEquals(3, ca.siblings().length);
+    assertEquals(3, ca.children().length);
+    assertTrue(Arrays.equals(new int[] { 1, 2, -1 }, ca.children()));
+    assertTrue(Arrays.equals(new int[] { -1, -1, -1 }, ca.siblings()));
     tw.addCategory(new CategoryPath("hi", "ho"));
     tw.addCategory(new CategoryPath("hello"));
     tw.commit();
     // Before refresh, nothing changed..
-    ChildrenArrays newca = tr.getChildrenArrays();
+    ParallelTaxonomyArrays newca = tr.getParallelTaxonomyArrays();
     assertSame(newca, ca); // we got exactly the same object
     assertEquals(3, tr.getSize());
-    assertEquals(3, ca.getOlderSiblingArray().length);
-    assertEquals(3, ca.getYoungestChildArray().length);
+    assertEquals(3, ca.siblings().length);
+    assertEquals(3, ca.children().length);
     // After the refresh, things change:
     TaxonomyReader newtr = TaxonomyReader.openIfChanged(tr);
     assertNotNull(newtr);
     tr.close();
     tr = newtr;
-    ca = tr.getChildrenArrays();
+    ca = tr.getParallelTaxonomyArrays();
     assertEquals(5, tr.getSize());
-    assertEquals(5, ca.getOlderSiblingArray().length);
-    assertEquals(5, ca.getYoungestChildArray().length);
-    assertTrue(Arrays.equals(new int[] { 4, 3, -1, -1, -1 }, ca.getYoungestChildArray()));
-    assertTrue(Arrays.equals(new int[] { -1, -1, -1, 2, 1 }, ca.getOlderSiblingArray()));
+    assertEquals(5, ca.siblings().length);
+    assertEquals(5, ca.children().length);
+    assertTrue(Arrays.equals(new int[] { 4, 3, -1, -1, -1 }, ca.children()));
+    assertTrue(Arrays.equals(new int[] { -1, -1, -1, 2, 1 }, ca.siblings()));
     tw.close();
     tr.close();
     indexDir.close();
@@ -753,10 +754,10 @@ public class TestTaxonomyCombined extend
     twBase.commit();
     TaxonomyReader trBase = new DirectoryTaxonomyReader(indexDirBase);
 
-    final ChildrenArrays ca1 = trBase.getChildrenArrays();
+    final ParallelTaxonomyArrays ca1 = trBase.getParallelTaxonomyArrays();
     
     final int abOrd = trBase.getOrdinal(abPath);
-    final int abYoungChildBase1 = ca1.getYoungestChildArray()[abOrd]; 
+    final int abYoungChildBase1 = ca1.children()[abOrd]; 
     
     final int numCategories = atLeast(800);
     for (int i = 0; i < numCategories; i++) {
@@ -769,8 +770,8 @@ public class TestTaxonomyCombined extend
     trBase.close();
     trBase = newTaxoReader;
     
-    final ChildrenArrays ca2 = trBase.getChildrenArrays();
-    final int abYoungChildBase2 = ca2.getYoungestChildArray()[abOrd];
+    final ParallelTaxonomyArrays ca2 = trBase.getParallelTaxonomyArrays();
+    final int abYoungChildBase2 = ca2.children()[abOrd];
     
     int numRetries = atLeast(50);
     for (int retry = 0; retry < numRetries; retry++) {
@@ -808,9 +809,9 @@ public class TestTaxonomyCombined extend
         setPriority(1 + getPriority());
         try {
           while (!stop.get()) {
-            int lastOrd = tr.getParentArray().length - 1;
+            int lastOrd = tr.getParallelTaxonomyArrays().parents().length - 1;
             assertNotNull("path of last-ord " + lastOrd + " is not found!", tr.getPath(lastOrd));
-            assertChildrenArrays(tr.getChildrenArrays(), retry, retrieval[0]++);
+            assertChildrenArrays(tr.getParallelTaxonomyArrays(), retry, retrieval[0]++);
             sleep(10); // don't starve refresh()'s CPU, which sleeps every 50 bytes for 1 ms
           }
         } catch (Throwable e) {
@@ -819,13 +820,13 @@ public class TestTaxonomyCombined extend
         }
       }
 
-      private void assertChildrenArrays(ChildrenArrays ca, int retry, int retrieval) {
-        final int abYoungChild = ca.getYoungestChildArray()[abOrd];
+      private void assertChildrenArrays(ParallelTaxonomyArrays ca, int retry, int retrieval) {
+        final int abYoungChild = ca.children()[abOrd];
         assertTrue(
             "Retry "+retry+": retrieval: "+retrieval+": wrong youngest child for category "+abPath+" (ord="+abOrd+
             ") - must be either "+abYoungChildBase1+" or "+abYoungChildBase2+" but was: "+abYoungChild,
             abYoungChildBase1==abYoungChild ||
-            abYoungChildBase2==ca.getYoungestChildArray()[abOrd]);
+            abYoungChildBase2==ca.children()[abOrd]);
       }
     };
     thread.start();

Modified: lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java?rev=1417889&r1=1417888&r2=1417889&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java (original)
+++ lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java Thu Dec  6 13:55:33 2012
@@ -233,7 +233,7 @@ public class TestDirectoryTaxonomyReader
       // assert categories
       assertEquals(numCategories, reader.getSize());
       int roundOrdinal = reader.getOrdinal(new CategoryPath(Integer.toString(i)));
-      int[] parents = reader.getParentArray();
+      int[] parents = reader.getParallelTaxonomyArrays().parents();
       assertEquals(0, parents[roundOrdinal]); // round's parent is root
       for (int j = 0; j < numCats; j++) {
         int ord = reader.getOrdinal(new CategoryPath(Integer.toString(i), Integer.toString(j)));
@@ -268,7 +268,7 @@ public class TestDirectoryTaxonomyReader
     
     TaxonomyReader reader = new DirectoryTaxonomyReader(writer);
     assertEquals(1, reader.getSize());
-    assertEquals(1, reader.getParentArray().length);
+    assertEquals(1, reader.getParallelTaxonomyArrays().parents().length);
 
     // add category and call forceMerge -- this should flush IW and merge segments down to 1
     // in ParentArray.initFromReader, this used to fail assuming there are no parents.
@@ -281,7 +281,7 @@ public class TestDirectoryTaxonomyReader
     reader.close();
     reader = newtr;
     assertEquals(2, reader.getSize());
-    assertEquals(2, reader.getParentArray().length);
+    assertEquals(2, reader.getParallelTaxonomyArrays().parents().length);
     
     reader.close();
     writer.close();
@@ -315,7 +315,7 @@ public class TestDirectoryTaxonomyReader
     
     TaxonomyReader reader = new DirectoryTaxonomyReader(writer);
     assertEquals(2, reader.getSize());
-    assertEquals(2, reader.getParentArray().length);
+    assertEquals(2, reader.getParallelTaxonomyArrays().parents().length);
 
     // merge all the segments so that NRT reader thinks there's a change 
     iw.forceMerge(1);
@@ -326,7 +326,7 @@ public class TestDirectoryTaxonomyReader
     reader.close();
     reader = newtr;
     assertEquals(2, reader.getSize());
-    assertEquals(2, reader.getParentArray().length);
+    assertEquals(2, reader.getParallelTaxonomyArrays().parents().length);
     
     reader.close();
     writer.close();