Author: schor
Date: Thu Jun 23 17:26:36 2016
New Revision: 1749947

URL: http://svn.apache.org/viewvc?rev=1749947&view=rev
Log:
[UIMA-4664] fix bug in orderedFsSet_array impl - wrong test in if statement.

Add some tracing (disabled) (was used in tracking down bug).

Rename some local variables to distinugish insertPosition (generally points to 
an existing item, with the meaning, insert before this), and new item index - 
where the new added item is placed in the array.

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=1749947&r1=1749946&r2=1749947&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
 Thu Jun 23 17:26:36 2016
@@ -59,6 +59,7 @@ import org.apache.uima.jcas.cas.TOP;
  */
 public class OrderedFsSet_array implements NavigableSet<TOP> {
 //  public boolean specialDebug = false;
+  final private static boolean TRACE = false;
   final private static boolean MEASURE = false;
   final private static int DEFAULT_MIN_SIZE = 8;  // power of 2 please
   final private static int MAX_DOUBLE_SIZE = 1024 * 1024 * 4;  // 4 million, 
power of 2 please
@@ -106,6 +107,7 @@ public class OrderedFsSet_array implemen
   private int modificationCount = 0;
   private int lastRemovedPos = -1;
     
+  private StringBuilder tr = TRACE ? new StringBuilder() : null;
   public OrderedFsSet_array(Comparator<TOP> comparatorWithID, Comparator<TOP> 
comparatorWithoutID) {
     this.comparatorWithID = comparatorWithID;
     this.comparatorWithoutID = comparatorWithoutID;
@@ -392,12 +394,14 @@ public class OrderedFsSet_array implemen
         // there may be other elements in batch that duplicate; these won't be 
inserted, but 
         //   there will be space lost in this case
         
-        int newInsertPos = insertSpace(insertPosOfAddedSpace, nbrNewSlots) - 
1;  // inserts nulls at the insert point, shifting other cells down
+        int indexOfNewItem = insertSpace(insertPosOfAddedSpace, nbrNewSlots) 
// returns index of a non-null item
+                                                                           // 
the new item goes one spot to the left of this
+            - 1;  // inserts nulls at the insert point, shifting other cells 
down
     
         // process first item
-        insertItem(newInsertPos, itemToAdd);
+        insertItem(indexOfNewItem, itemToAdd);
 //        TOP prevItem = itemToAdd;
-        if (newInsertPos + 1 == a_nextFreeslot) {
+        if (indexOfNewItem + 1 == a_nextFreeslot) {
           highest = itemToAdd;
         }
         nbrNewSlots --;
@@ -415,10 +419,10 @@ public class OrderedFsSet_array implemen
           }
           pos = (-pos) - 1;
               
-          newInsertPos = pos - 1;
+          indexOfNewItem = pos - 1;
           if (nullBlockStart == 0) {
             // this and all the rest of the elements are lower, insert in bulk
-            insertItem(newInsertPos--, itemToAdd);
+            insertItem(indexOfNewItem--, itemToAdd);
             nbrNewSlots --;
             bPos--;
             
@@ -427,33 +431,33 @@ public class OrderedFsSet_array implemen
               if (itemToAdd == null) {
                 continue;
               }
-              insertItem(newInsertPos--, itemToAdd);
+              insertItem(indexOfNewItem--, itemToAdd);
               nbrNewSlots --;  // do this way to respect skipped items due to 
== to prev        
             }
             break;
           }
           
-          if (newInsertPos == -1 || null != a[newInsertPos]) {
-            newInsertPos = shiftFreespaceDown(pos, nbrNewSlots) - 1;  // 
results in null being available at pos - 1
+          if (indexOfNewItem == -1 || null != a[indexOfNewItem]) {
+            indexOfNewItem = shiftFreespaceDown(pos, nbrNewSlots) - 1;  // 
results in null being available at pos - 1
           }
-          insertItem(newInsertPos, itemToAdd);
+          insertItem(indexOfNewItem, itemToAdd);
           nbrNewSlots --;
         }
         
         if (nbrNewSlots > 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 (newInsertPos - nbrNewSlots > 0) { 
+          if (indexOfNewItem - nbrNewSlots > 0) { 
             // space is not at beginning
           
             int mid = (a_nextFreeslot + a_firstUsedslot) >>> 1;  // overflow 
aware 
-            if (newInsertPos < mid) {
+            if (indexOfNewItem < mid) {
               // move to beginning
-              System.arraycopy(a, newInsertPos - nbrNewSlots, a, 0, 
nbrNewSlots);
+              System.arraycopy(a, indexOfNewItem - nbrNewSlots, a, 0, 
nbrNewSlots);
               a_firstUsedslot += nbrNewSlots;
             } else {
               // move to end
-              System.arraycopy(a, newInsertPos, a, newInsertPos - nbrNewSlots, 
a_nextFreeslot - newInsertPos);
+              System.arraycopy(a, indexOfNewItem, a, indexOfNewItem - 
nbrNewSlots, a_nextFreeslot - indexOfNewItem);
               Arrays.fill(a, a_nextFreeslot - nbrNewSlots, a_nextFreeslot, 
null);
               a_nextFreeslot -= nbrNewSlots;
             }
@@ -468,15 +472,35 @@ public class OrderedFsSet_array implemen
     }
   }
   
-  private void insertItem(int newInsertPos, TOP itemToAdd) {
-    assert newInsertPos >= 0;
-    assert null == a[newInsertPos];
-    a[newInsertPos] = itemToAdd;
+  /**
+   * 
+   * @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];
+    } catch (AssertionError e) {
+      if (TRACE) {
+        System.err.println("OrderedFsSet_array caught assert.  array values 
around indexToUpdate: ");
+        for (int i = indexToUpdate - 2; i < indexToUpdate + 3; i++) {
+          if (i >= 0 && i < a.length) {
+            System.err.format("a[%,d]: %s%n", i, a[i].toString(2));
+          } else {
+            System.err.format("a[%,d}: out-of-range%n", i);
+          }
+        }
+        System.err.format("trace info: %n%s", tr);
+      }
+      throw e;
+    }
+    a[indexToUpdate] = itemToAdd;
     incrSize();
-    if (newInsertPos < a_firstUsedslot) {
-      a_firstUsedslot = newInsertPos;  
+    if (indexToUpdate < a_firstUsedslot) {
+      a_firstUsedslot = indexToUpdate;  
     }
-    if (nullBlockEnd == newInsertPos + 1) {
+    if (nullBlockEnd == indexToUpdate + 1) {
       nullBlockEnd --;
     }
   }
@@ -487,9 +511,14 @@ public class OrderedFsSet_array implemen
    * @param positionToInsert position containing a value, to free up by moving 
the current free block
    *                         so that the last free element is at that 
(adjusted up) position.          
    * @param nbrNewSlots
-   * @return adjusted positionToInsert
+   * @return adjusted positionToInsert, the free spot is just to the left of 
this position
    */
   private int insertSpace(int positionToInsert, int nbrNewSlots) {
+    if (TRACE) {
+      tr.setLength(0);
+      tr.append("Tracing OrderedFsSet_array\n");
+      tr.append(String.format("insertSpace called with positionToInsert: %,d 
nbrNewSlots: %,d%n", positionToInsert, nbrNewSlots));
+    }
     if (nbrNewSlots == 1) {
       int distanceFromLastRemoved = (lastRemovedPos == -1) 
                                       ? Integer.MAX_VALUE 
@@ -501,6 +530,9 @@ public class OrderedFsSet_array implemen
       boolean useFront = distanceFromFront < distanceFromEnd;
       boolean useLastRemoved = Math.abs(distanceFromLastRemoved) < (useFront ? 
distanceFromFront : distanceFromEnd);
       
+      if (TRACE) 
+        tr.append(String.format("distances: %d %d %d, useFront: %s 
useLastRemoved: %s%n",
+            distanceFromLastRemoved, distanceFromEnd, distanceFromFront, 
useFront, useLastRemoved));
       if (useLastRemoved) {  // due to find skipping over nulls, the 
distanceFromLastRemoved is never 0
         if (distanceFromLastRemoved > 0) {
           if (distanceFromLastRemoved != 1) { 
@@ -513,12 +545,17 @@ public class OrderedFsSet_array implemen
         } else {
           nullBlockStart = lastRemovedPos;
           lastRemovedPos = -1;
-          return shiftFreespaceDown(positionToInsert, nbrNewSlots);
+          int r = shiftFreespaceDown(positionToInsert, nbrNewSlots);
+          if (TRACE) 
+            tr.append(String.format("shiftFreespaceDown result was %,d%n", r));
+          return r;
         }
       }
       if (useFront) {
         nullBlockStart = a_firstUsedslot - 1;
-        if (null != a[nullBlockStart]) {
+//        if (null != a[nullBlockStart]) {
+        if (a_firstUsedslot != positionToInsert) {
+          // need to move the free slot if not already next to the insert 
position
           nullBlockEnd = a_firstUsedslot;
           shiftFreespaceUp(positionToInsert, nbrNewSlots);
         }
@@ -531,27 +568,35 @@ public class OrderedFsSet_array implemen
     nullBlockStart = a_nextFreeslot;
     nullBlockEnd = nullBlockStart + nbrNewSlots; 
     a_nextFreeslot += nbrNewSlots;
-    return shiftFreespaceDown(positionToInsert, nbrNewSlots);
+    int r = shiftFreespaceDown(positionToInsert, nbrNewSlots);
+    if (TRACE) {
+      tr.append(String.format("shiftFreespaceDown2 result was %,d, 
nullBlockStart: %,d nullBlockEnd: %,d a_nextFreeslot: %,d%n", 
+          r, nullBlockStart, nullBlockEnd, a_nextFreeslot));
+    }
+    return r;
   }
   
   /**
    * Shift a block of free space lower in the array.
-   * This is done by shifting the space at the insert point to the right by 
the nbrNewSlots
+   * This is done by shifting the space at the insert point
+   *   for length = start of free block - insert point 
+   *   to the right by the nbrNewSlots
    *   and then resetting (filling) the freed up space with null
    *   
    * Example:  u = used, f = free space
    * 
-   * before 
+   * before                      |--| 
    * uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuffffffffuuuuuuu
    *                             ^ insert point
-   * after
+   * after                               |--|
    * uuuuuuuuuuuuuuuuuuuuuuuuuuuuffffffffuuuuuuuuuuu
-   *                                    ^ insert point
+   *                                     ^ insert point
    *                                    
    * before 
+   * |------------------------------|
    * uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuffffffffuuuuuuu
    * ^ insert point
-   * after
+   * after   |------------------------------| 
    * ffffffffuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
    *        ^ insert point
    *                                    
@@ -581,6 +626,52 @@ public class OrderedFsSet_array implemen
     return newInsertPoint + nbrNewSlots;
   }
   
+  /**
+   * Shift a block of free space higher in the array.
+   * This is done by shifting the space at the insert point
+   *   of length = insert point - (end+1) of free block 
+   *   to the left by the nbrNewSlots
+   *   and then resetting (filling) the freed up space with null
+   *   
+   * Example:  u = used, f = free space
+   * 
+   * before              |-|   << block shifted 
+   * uuuuuuuuuuuuuuufffffuuuuuuuuuuuuuuuuuuuuuuuuuuu
+   *                        ^ insert point
+   * after          |-|   << block shifted
+   * uuuuuuuuuuuuuuuuuufffffuuuuuuuuuuuuuuuuuuu
+   *                        ^ insert point
+   *                                    
+   * before                                  |----|
+   * uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuffffuuuuuuu
+   *                                               ^ insert point
+   *     note: insert point is never beyond last because
+   *     those are added immediately
+   * after                               |----|
+   * uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuffffu
+   *                                               ^ insert point
+   *                                    
+   * before       |--|   
+   * uuuuuuuuuuuufuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
+   *                  ^ insert point
+   * after       |--|
+   * uuuuuuuuuuuuuuuufuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
+   *                  ^ insert point
+   *                                    
+   *                                    
+   *                                    
+   * move down by nbrNewSlots
+   * length to move = insert point - null block end (which is 1 plus index of 
last free)
+   * new insert point is the same as the old one (this points to a filled 
spot, prev spot is free)
+   * 
+   * fill goes from original null block end, for min(nbrNewSlots, length of 
move)
+   *   
+   * hidden param:  nullBlockEnd = 1 past end of last free slot
+   * @param newInsertPoint index of slot array, currently occupied, where an 
item is to be set into
+   * @param nbrNewSlots - the size of the inserted space
+   * @return the updated insert point, now moved up
+   */
+  
   private int shiftFreespaceUp(int newInsertPoint, int nbrNewSlots) {
     int lengthToMove = newInsertPoint - nullBlockEnd;
     System.arraycopy(a, nullBlockEnd, a, nullBlockStart, lengthToMove);


Reply via email to