Author: schor
Date: Fri Jun 24 21:22:42 2016
New Revision: 1750165

URL: http://svn.apache.org/viewvc?rev=1750165&view=rev
Log:
[UIMA-4664] fix more bugs in orderedFsSet_array impl.  toArray missing part of 
contract when array passed is > than needed. Fix validateA code to work 
multithreaded (not used except during debugging). Some variable renaming, added 
comments. Fix test for seeing if extra space was left over during bulk inserts. 
 Fix move to beginning / end in that case. InsertSpace had bug in setting 
a_firstUsedslot.  add some asserts.  insure a_firstUsedslot updated by 
shiftFreespaceDown and shiftFreespaceUp. Fix logic for maintaining 
lastRemovedPos

Modified:
    
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java

Modified: 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java
URL: 
http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java?rev=1750165&r1=1750164&r2=1750165&view=diff
==============================================================================
--- 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java
 (original)
+++ 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java
 Fri Jun 24 21:22:42 2016
@@ -189,6 +189,19 @@ public class OrderedFsSet_array implemen
         r[i++] = item;
       }
     }
+//    try { // debug
+      assert r.length == i;
+//    } catch (AssertionError e) { // debug
+//      System.err.format("size: %,d, final index: %,d, array length: %,d%n", 
size(), i, a.length );
+//      for (int di = 0; di < a.length; di++) {
+//        System.err.format("a[%,d] = %s%n", di, a[di]);
+//      }
+//      System.err.format("first used slot: %,d, next free slot: %,d batch 
size: %,d,"
+//          + " nullblockstart: %,d nullBlockEnd: %d, lastRemovedPos: %,d",
+//          a_firstUsedslot, a_nextFreeslot, batch.size(), nullBlockStart, 
nullBlockEnd,
+//          lastRemovedPos);
+//      throw e;
+//    }
     return r;
   }
 
@@ -204,6 +217,9 @@ public class OrderedFsSet_array implemen
         a1[i++] = (T) item;
       }
     }
+    if (i < a1.length) {
+      a1[i] = null;  // contract for toArray, when array bigger than items
+    }
     return a1;
   }
 
@@ -253,17 +269,22 @@ public class OrderedFsSet_array implemen
     modificationCount++;
   }
   
+  /** validate array
+   *    number of non-null elements == size
+   */
   // debug
   private void validateA() {
+    synchronized (batch) {
     int sz = 0;
     for (TOP item : a) {
       if (item != null) {
         sz++;
       }
     }
-    if (sz != size) {
-      System.out.println("debug ");
-    }
+//    if (sz != size) {
+//      System.out.format("debug error OrderedFsSet_array size(): %,d array 
non-null element count: %,d%n",
+//          size, sz);
+//    }
     assert sz == size;
     for (int i = 0; i < a_firstUsedslot; i++) {
       assert a[i] == null;
@@ -271,6 +292,7 @@ public class OrderedFsSet_array implemen
     for (int i = a_nextFreeslot; i < a.length; i++) {
       assert a[i] == null;
     }
+    }
   }
 
   private void ensureCapacity(int incr) {
@@ -322,6 +344,7 @@ public class OrderedFsSet_array implemen
     if (batch.size() != 0) {
 //      validateA();
       doProcessBatch();
+//      validateA();
     }
   }
   
@@ -350,7 +373,12 @@ public class OrderedFsSet_array implemen
           batchCountHistogram[31 - Integer.numberOfLeadingZeros(batchSize)] ++;
         }
         
-        int nbrNewSlots = 1;
+        /* the number of new empty slots created, 
+         *   may end up being larger than actually used because some of the 
items 
+         *   being inserted may already be in the array
+         *     - decreases as each item is actually inserted into the array
+         */
+        int nbrNewSlots = 1; // start at one, may increase
         
         if (batchSize > 1) {
           // Sort the items to add 
@@ -370,7 +398,7 @@ public class OrderedFsSet_array implemen
               }
             } else {
               prev = item;
-              nbrNewSlots++;
+              nbrNewSlots++;  // count of items that will actually be added; 
skips the duplicates
             }
           }
         } 
@@ -398,13 +426,14 @@ public class OrderedFsSet_array implemen
                                                                            // 
the new item goes one spot to the left of this
             - 1;  // inserts nulls at the insert point, shifting other cells 
down
     
+        int nbrNewSlotsRemaining = nbrNewSlots;  // will be decremented as 
slots are used
         // process first item
         insertItem(indexOfNewItem, itemToAdd);
 //        TOP prevItem = itemToAdd;
         if (indexOfNewItem + 1 == a_nextFreeslot) {
           highest = itemToAdd;
         }
-        nbrNewSlots --;
+        nbrNewSlotsRemaining --;
         
         int bPos = i_batch - 1; // next after first one from end
         for (; bPos >= 0; bPos --) {
@@ -417,13 +446,14 @@ public class OrderedFsSet_array implemen
           if (pos >= 0) {
             continue;  // already in the list
           }
-          pos = (-pos) - 1;
+          pos = (-pos) - 1;  // pos is the insert point, new item goes 1 to 
left of this
               
-          indexOfNewItem = pos - 1;
+          indexOfNewItem = pos - 1;  // where the new item goes, 1 to left of 
insert point
           if (nullBlockStart == 0) {
             // this and all the rest of the elements are lower, insert in bulk
+            // because all are lower, none are in the array, so don't need the 
compare check
             insertItem(indexOfNewItem--, itemToAdd);
-            nbrNewSlots --;
+            nbrNewSlotsRemaining --;
             bPos--;
             
             for (;bPos >= 0; bPos--) {          
@@ -432,34 +462,37 @@ public class OrderedFsSet_array implemen
                 continue;
               }
               insertItem(indexOfNewItem--, itemToAdd);
-              nbrNewSlots --;  // do this way to respect skipped items due to 
== to prev        
+              nbrNewSlotsRemaining --;  // do this way to respect skipped 
items due to == to prev        
             }
             break;
           }
           
           if (indexOfNewItem == -1 || null != a[indexOfNewItem]) {
-            indexOfNewItem = shiftFreespaceDown(pos, nbrNewSlots) - 1;  // 
results in null being available at pos - 1
+            indexOfNewItem = shiftFreespaceDown(pos, nbrNewSlotsRemaining) - 
1;  // results in null being available at pos - 1
           }
           insertItem(indexOfNewItem, itemToAdd);
-          nbrNewSlots --;
+          nbrNewSlotsRemaining --;
         }
         
-        if (nbrNewSlots > 0) {
+        if (nbrNewSlotsRemaining > 0) {
           // have extra space left over due to dups not being added
           // If this space is not at beginning, move space to beginning or end 
(whichever is closer)
-          if (indexOfNewItem - nbrNewSlots > 0) { 
-            // space is not at beginning
+//          if (indexOfNewItem - nbrNewSlotsRemaining > 0) { 
+          if (nullBlockEnd != a_firstUsedslot) {
+          // space is not at beginning
           
             int mid = (a_nextFreeslot + a_firstUsedslot) >>> 1;  // overflow 
aware 
             if (indexOfNewItem < mid) {
-              // move to beginning
-              System.arraycopy(a, indexOfNewItem - nbrNewSlots, a, 0, 
nbrNewSlots);
-              a_firstUsedslot += nbrNewSlots;
+              shiftFreespaceDown(a_firstUsedslot, nbrNewSlotsRemaining);
+//              System.arraycopy(a, indexOfNewItem - nbrNewSlots, a, 0, 
nbrNewSlots);
+//              a_firstUsedslot += nbrNewSlots;
             } else {
-              // move to end
-              System.arraycopy(a, indexOfNewItem, a, indexOfNewItem - 
nbrNewSlots, a_nextFreeslot - indexOfNewItem);
-              Arrays.fill(a, a_nextFreeslot - nbrNewSlots, a_nextFreeslot, 
null);
-              a_nextFreeslot -= nbrNewSlots;
+              shiftFreespaceUp(a_nextFreeslot, nbrNewSlotsRemaining);
+              a_nextFreeslot -= nbrNewSlotsRemaining;
+//              // move to end
+//              System.arraycopy(a, indexOfNewItem, a, indexOfNewItem - 
nbrNewSlots, a_nextFreeslot - indexOfNewItem);
+//              Arrays.fill(a, a_nextFreeslot - nbrNewSlots, a_nextFreeslot, 
null);
+//              a_nextFreeslot -= nbrNewSlots;
             }
           }
         }
@@ -473,14 +506,18 @@ public class OrderedFsSet_array implemen
   }
   
   /**
-   * 
+   * side effects:
+   *   increment size
+   *   reset a_firstUsedslot if adding in front
+   *   ( a_nextFreeslot not updated, because this method only called to 
inserting before end )
+   *   nullBlockEnd reduced conditionally
    * @param indexToUpdate - the index in the array to update with the item to 
add
    * @param itemToAdd -
    */
   private void insertItem(int indexToUpdate, TOP itemToAdd) {
     try {
-    assert indexToUpdate >= 0;
-    assert null == a[indexToUpdate];
+      assert indexToUpdate >= 0;
+      assert null == a[indexToUpdate];
     } catch (AssertionError e) {
       if (TRACE) {
         System.err.println("OrderedFsSet_array caught assert.  array values 
around indexToUpdate: ");
@@ -559,7 +596,7 @@ public class OrderedFsSet_array implemen
           nullBlockEnd = a_firstUsedslot;
           shiftFreespaceUp(positionToInsert, nbrNewSlots);
         }
-        a_firstUsedslot --;
+//        a_firstUsedslot --;  // not done here, done in insert routine
         return positionToInsert;
       }
     }
@@ -598,7 +635,14 @@ public class OrderedFsSet_array implemen
    * ^ insert point
    * after   |------------------------------| 
    * ffffffffuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
-   *        ^ insert point
+   *         ^ insert point
+   * before 
+   *     |------------------------------|
+   * ffffuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuffffffffuuuuuuu
+   *     ^ insert point
+   * after       |------------------------------| 
+   * ffffffffffffuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
+   *             ^ insert point
    *                                    
    * move up by nbrNewSlots
    * length to move = nullBlockStart - insert point
@@ -612,6 +656,8 @@ public class OrderedFsSet_array implemen
    * @return the updated insert point, now moved up
    */
   private int shiftFreespaceDown(int newInsertPoint, int nbrNewSlots) {
+    assert newInsertPoint >= 0;
+    assert nbrNewSlots >= 0;
     int lengthToMove = nullBlockStart - newInsertPoint;
     System.arraycopy(a, newInsertPoint, a, newInsertPoint + nbrNewSlots, 
lengthToMove);
     int lengthToClear = Math.min(nbrNewSlots, lengthToMove);
@@ -623,6 +669,9 @@ public class OrderedFsSet_array implemen
       movePctHistogram[lengthToMove* 10 / (a_nextFreeslot - a_firstUsedslot)] 
++;
       fillHistogram[32 - Integer.numberOfLeadingZeros(lengthToClear)] ++;
     }
+    if (newInsertPoint == a_firstUsedslot) {
+      a_firstUsedslot = newInsertPoint + nbrNewSlots;
+    }
     return newInsertPoint + nbrNewSlots;
   }
   
@@ -658,6 +707,12 @@ public class OrderedFsSet_array implemen
    * uuuuuuuuuuuuuuuufuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
    *                  ^ insert point
    *                                    
+   *     |--------|  before 
+   * ffffuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
+   *               ^ insert point
+   * |--------|
+   * uuuuuuuuuuffffuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
+   *               ^ insert point
    *                                    
    *                                    
    * move down by nbrNewSlots
@@ -673,12 +728,16 @@ public class OrderedFsSet_array implemen
    */
   
   private int shiftFreespaceUp(int newInsertPoint, int nbrNewSlots) {
+    boolean need2setFirstUsedslot = nullBlockEnd == a_firstUsedslot;
     int lengthToMove = newInsertPoint - nullBlockEnd;
     System.arraycopy(a, nullBlockEnd, a, nullBlockStart, lengthToMove);
     int lengthToClear = Math.min(nbrNewSlots, lengthToMove);
     Arrays.fill(a, newInsertPoint - lengthToClear, newInsertPoint, null);
     nullBlockStart = newInsertPoint - nbrNewSlots;
     nullBlockEnd = newInsertPoint;
+    if (need2setFirstUsedslot) {
+      a_firstUsedslot = 0;
+    }
     return newInsertPoint;
   }
     
@@ -806,8 +865,9 @@ public class OrderedFsSet_array implemen
     size --;
     modificationCount ++;
     if (size == 0) {
-      clearResets();
+      clearResets();  // also clears last removed pos
     } else {
+      // size is > 0
       if (pos == a_firstUsedslot) {
         do {  // removed the first used slot
           a_firstUsedslot ++;
@@ -821,10 +881,12 @@ public class OrderedFsSet_array implemen
       
       if (size < ((a_nextFreeslot - a_firstUsedslot) >> 1) &&
           size > 8) {
-        compressOutRemoves();
-      } else if (lastRemovedPos > a_firstUsedslot &&
-                 lastRemovedPos < (a_nextFreeslot - 1) ) {
-        lastRemovedPos = pos;
+        compressOutRemoves();  // also clears lastRemovedPos
+      } else {
+        // update lastRemovedPos
+        lastRemovedPos = (pos > a_firstUsedslot && pos < (a_nextFreeslot - 1))
+                           ? pos  // is a valid position 
+                           : -1;  // is not a valid position
       }
     }
     return true;
@@ -881,6 +943,13 @@ public class OrderedFsSet_array implemen
       return;
     }
     if (!shrinkCapacity()) {
+//      //debug 
+//      if (a_firstUsedslot == -1) {
+//        System.out.println("a_firstUsedslot was -1");
+//      }
+//      if (a_nextFreeslot == -1) {
+//        System.out.println("a_nextFreeslot was -1");
+//      }
       Arrays.fill(a, a_firstUsedslot, a_nextFreeslot, null);      
     }
     clearResets();


Reply via email to