Author: schor Date: Fri May 3 14:31:30 2013 New Revision: 1478810 URL: http://svn.apache.org/r1478810 Log: [UIMA-2434] test case: reuse existing iterators - is now supported. Verify concurrent mod exception when removing all. Fix impl to support resizing down for all 3 types of indexes, if they've grown. Fix impl to set concurrent modification flag. Update javadocs for moveToNext / Previous to indicate they may throw ConcurrentModificationException, and to say that moveToFirst/Last is OK after modification.
Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/FSIterator.java uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIntArrayIndex.java uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSRBTSetIndex.java uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSVectorIndex.java uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/internal/util/rb_trees/IntArrayRBT.java uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/FSIterator.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/FSIterator.java?rev=1478810&r1=1478809&r2=1478810&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/FSIterator.java (original) +++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/FSIterator.java Fri May 3 14:31:30 2013 @@ -19,6 +19,7 @@ package org.apache.uima.cas; +import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; @@ -84,23 +85,25 @@ public interface FSIterator<T extends Fe /** * Advance the iterator. This may invalidate the iterator. + * @exception ConcurrentModificationException if the underlying indexes being iterated over were modified */ void moveToNext(); /** * Move the iterator one element back. This may invalidate the iterator. + * @exception ConcurrentModificationException if the underlying indexes being iterated over were modified */ void moveToPrevious(); /** * Move the iterator to the first element. The iterator will be valid iff the underlying - * collection is non-empty. + * collection is non-empty. Allowed even if the underlying indexes being iterated over were modified. */ void moveToFirst(); /** * Move the iterator to the last element. The iterator will be valid iff the underlying collection - * is non-empty. + * is non-empty. Allowed even if the underlying indexes being iterated over were modified. */ void moveToLast(); @@ -112,6 +115,7 @@ public interface FSIterator<T extends Fe * * @param fs * The feature structure the iterator should be set to. + * @exception ConcurrentModificationException if the underlying indexes being iterated over were modified */ void moveTo(FeatureStructure fs); Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java?rev=1478810&r1=1478809&r2=1478810&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java (original) +++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java Fri May 3 14:31:30 2013 @@ -186,9 +186,12 @@ public class FSBagIndex extends FSLeafIn } public void flush() { - this.index.removeAllElements(); - // don't do this - some iterators/ indexes are holding references to the index, and don't pick up the new one. -// this.index = new IntVector(this.initialSize); + // done this way to reset to initial size if it grows + if (this.index.size() > this.initialSize) { + this.index = new IntVector(this.initialSize); + } else { + this.index.removeAllElements(); + } } public final boolean insert(int fs) { Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java?rev=1478810&r1=1478809&r2=1478810&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java (original) +++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java Fri May 3 14:31:30 2013 @@ -181,7 +181,9 @@ public class FSIndexRepositoryImpl imple // The IICP private IndexIteratorCachePair iicp; - // An array of integer arrays, one for each subtype. + // An array of ComparableIntPointerIterators, one for each subtype. + // Each instance of these has a Class.this kind of ref to a particular variety of FSLeafIndex (bag, set, sorted) corresponding to 1 type + // This array has the indexes for all the subtypes private ComparableIntPointerIterator[] indexes; int lastValidIndex; @@ -1409,12 +1411,12 @@ public class FSIndexRepositoryImpl imple */ public void removeAllExcludingSubtypes(Type type) { final int typeCode = ((TypeImpl) type).getCode(); + incrementIllegalIndexUpdateDetector(typeCode); // get a list of all indexes defined over this type // Includes indexes defined on supertypes of this type final ArrayList<IndexIteratorCachePair> allIndexesForType = this.indexArray[typeCode]; for (IndexIteratorCachePair iicp : allIndexesForType) { iicp.index.flush(); -// boolean fff = iicp.iteratorCache.get(0) == iicp.index; } } Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIntArrayIndex.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIntArrayIndex.java?rev=1478810&r1=1478809&r2=1478810&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIntArrayIndex.java (original) +++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIntArrayIndex.java Fri May 3 14:31:30 2013 @@ -155,9 +155,12 @@ public class FSIntArrayIndex<T extends F // The index, a vector of FS references. private IntVector index; + + final private int initialSize; FSIntArrayIndex(CASImpl cas, Type type, int initialSize, int indexType) { super(cas, type, indexType); + this.initialSize = initialSize; this.index = new IntVector(initialSize); } @@ -174,7 +177,12 @@ public class FSIntArrayIndex<T extends F } public void flush() { - this.index.removeAllElements(); + // do this way to reset size if it grew + if (this.index.size() > this.initialSize) { + this.index = new IntVector(initialSize); + } else { + this.index.removeAllElements(); + } } // public final boolean insert(int fs) { Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSRBTSetIndex.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSRBTSetIndex.java?rev=1478810&r1=1478809&r2=1478810&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSRBTSetIndex.java (original) +++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSRBTSetIndex.java Fri May 3 14:31:30 2013 @@ -56,7 +56,7 @@ class FSRBTSetIndex<T extends FeatureStr public void flush() { this.tree.flush(); -// this.tree = new CompIntArrayRBT(this); // not this way - some indexes/iterators are holding on to references to the old tree... +// this.tree = new CompIntArrayRBT(this); // not this way - iterators are holding on to references to the old tree... } /** Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSVectorIndex.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSVectorIndex.java?rev=1478810&r1=1478809&r2=1478810&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSVectorIndex.java (original) +++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSVectorIndex.java Fri May 3 14:31:30 2013 @@ -153,9 +153,11 @@ public class FSVectorIndex<T extends Fea } public void flush() { - this.index.removeAllElements(); - // not this way in case someone's holding on to a ref to the actual index object -// this.index = new IntVector(this.initialSize); + if (this.index.size() > this.initialSize) { + this.index = new IntVector(this.initialSize); + } else { + this.index.removeAllElements(); + } } public final boolean insert(int fs) { Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/internal/util/rb_trees/IntArrayRBT.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/internal/util/rb_trees/IntArrayRBT.java?rev=1478810&r1=1478809&r2=1478810&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/internal/util/rb_trees/IntArrayRBT.java (original) +++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/internal/util/rb_trees/IntArrayRBT.java Fri May 3 14:31:30 2013 @@ -397,6 +397,8 @@ public class IntArrayRBT { private static final int default_growth_factor = 2; private static final int default_multiplication_limit = 2000000; + + final private int initialSize; private int growth_factor; @@ -429,8 +431,10 @@ public class IntArrayRBT { initVars(); // Increase initialSize by one since we use one slot for sentinel. ++initialSize; + this.initialSize = initialSize; this.growth_factor = default_growth_factor; this.multiplication_limit = default_multiplication_limit; + setupArrays(); // Init the arrays. if (useklrp) { klrp = new int[initialSize << 2]; @@ -446,6 +450,23 @@ public class IntArrayRBT { setParent(NIL, NIL); this.color[NIL] = black; } + + private void setupArrays() { + // Init the arrays. + if (useklrp) { + klrp = new int[initialSize << 2]; + } else { + this.key = new int[initialSize]; + this.left = new int[initialSize]; + this.right = new int[initialSize]; + this.parent = new int[initialSize]; + } + this.color = new boolean[initialSize]; + setLeft(NIL, NIL); + setRight(NIL, NIL); + setParent(NIL, NIL); + this.color[NIL] = black; + } private void initVars() { this.root = NIL; @@ -457,6 +478,16 @@ public class IntArrayRBT { public void flush() { // All we do for flush is set the root to NIL and the size to 0. initVars(); + // and potentially release extra storage + if (useklrp) { + if (klrp.length > (initialSize << 2)) { + setupArrays(); + } + } else { + if (key.length > initialSize) { + setupArrays(); + } + } } public final int size() { Modified: uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java?rev=1478810&r1=1478809&r2=1478810&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java (original) +++ uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java Fri May 3 14:31:30 2013 @@ -781,18 +781,29 @@ public class IteratorTest extends TestCa FSIndex<FeatureStructure> subbagIndex = ir.getIndex(CASTestSetup.ANNOT_BAG_INDEX, this.subsentenceType); FSIndex<AnnotationFS> subsortedIndex = this.cas.getAnnotationIndex(this.subsentenceType); - ir.removeAllIncludingSubtypes(sentenceType); - FSIterator<FeatureStructure> setIt = setIndex.iterator(); FSIterator<FeatureStructure> bagIt = bagIndex.iterator(); FSIterator<AnnotationFS> sortedIt = sortedIndex.iterator(); - - // subindexes FSIterator<FeatureStructure> subsetIt = subsetIndex.iterator(); FSIterator<FeatureStructure> subbagIt = subbagIndex.iterator(); FSIterator<AnnotationFS> subsortedIt = subsortedIndex.iterator(); + verifyMoveToFirst(setIt, true); + verifyMoveToFirst(bagIt, true); + verifyMoveToFirst(sortedIt, true); + verifyMoveToFirst(subsetIt, true); + verifyMoveToFirst(subbagIt, true); + verifyMoveToFirst(subsortedIt, true); + + ir.removeAllIncludingSubtypes(sentenceType); + verifyConcMod(setIt); + verifyConcMod(bagIt); + verifyConcMod(sortedIt); + verifyConcMod(subsetIt); + verifyConcMod(subbagIt); + verifyConcMod(subsortedIt); + verifyMoveToFirst(setIt, false); verifyMoveToFirst(bagIt, false); verifyMoveToFirst(sortedIt, false); @@ -800,8 +811,6 @@ public class IteratorTest extends TestCa verifyMoveToFirst(subbagIt, false); verifyMoveToFirst(subsortedIt, false); -// addAnnotations(fsArray, ts.getType("Sentence")); -// addAnnotations(subFsArray, ts.getType("SubTypeOfSentence")); for (AnnotationFS fs : fsArray) { ir.addFS(fs); } @@ -818,14 +827,6 @@ public class IteratorTest extends TestCa ir.removeAllExcludingSubtypes(this.sentenceType); - setIt = setIndex.iterator(); - bagIt = bagIndex.iterator(); - sortedIt = sortedIndex.iterator(); - - subsetIt = subsetIndex.iterator(); - subbagIt = subbagIndex.iterator(); - subsortedIt = subsortedIndex.iterator(); - verifyHaveSubset(setIt, 91, subsentenceType); verifyHaveSubset(bagIt, 100, subsentenceType); verifyHaveSubset(sortedIt, 100, subsentenceType); @@ -839,14 +840,6 @@ public class IteratorTest extends TestCa ir.removeAllExcludingSubtypes(subsentenceType); - setIt = setIndex.iterator(); - bagIt = bagIndex.iterator(); - sortedIt = sortedIndex.iterator(); - - subsetIt = subsetIndex.iterator(); - subbagIt = subbagIndex.iterator(); - subsortedIt = subsortedIndex.iterator(); - verifyHaveSubset(setIt, 91, sentenceType); verifyHaveSubset(bagIt, 100, sentenceType); verifyHaveSubset(sortedIt, 100, sentenceType); @@ -855,6 +848,17 @@ public class IteratorTest extends TestCa verifyMoveToFirst(subsortedIt, false); } + + private void verifyConcMod(FSIterator<?> it) { + boolean caught = false; + try { + it.moveToNext(); + } catch (Exception e) { + caught = true; + } + assertTrue(caught); + } + public void testInvalidIndexRequest() { boolean exc = false;