Changes to fix issue 803

commit b19cde423b858bf4964cba3c8b76b17a1d6b0300
Author: Young-Seok <kisskys@gmail.com>
Date:   Mon Sep 29 17:03:20 2014 -0700

Change-Id: Icbb1b71bfa263e67ad52cf61e831c614c630ea4b
Reviewed-on: http://fulliautomatix.ics.uci.edu:8443/142
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: abdullah alamoudi <bamousaa@gmail.com>
diff --git a/hyracks/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/AbstractMemoryLSMComponent.java b/hyracks/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/AbstractMemoryLSMComponent.java
index 3907bc1..2c59677 100644
--- a/hyracks/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/AbstractMemoryLSMComponent.java
+++ b/hyracks/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/AbstractMemoryLSMComponent.java
@@ -113,7 +113,8 @@
             case MODIFICATION:
                 if (isMutableComponent) {
                     writerCount--;
-                    if (state == ComponentState.READABLE_WRITABLE && isFull()) {
+                    //A failed operation should not change the component state since it's better for the failed operation's effect to be no-op.
+                    if (state == ComponentState.READABLE_WRITABLE && !failedOperation && isFull()) {
                         state = ComponentState.READABLE_UNWRITABLE;
                     }
                 } else {
diff --git a/hyracks/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/LSMHarness.java b/hyracks/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/LSMHarness.java
index fd4442f..d26854f 100644
--- a/hyracks/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/LSMHarness.java
+++ b/hyracks/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/LSMHarness.java
@@ -51,8 +51,8 @@
         fullMergeIsRequested = new AtomicBoolean();
     }
 
-    protected boolean getAndEnterComponents(ILSMIndexOperationContext ctx, LSMOperationType opType, boolean isTryOperation)
-            throws HyracksDataException {
+    protected boolean getAndEnterComponents(ILSMIndexOperationContext ctx, LSMOperationType opType,
+            boolean isTryOperation) throws HyracksDataException {
         synchronized (opTracker) {
             while (true) {
                 lsmIndex.getOperationalComponents(ctx);
@@ -90,7 +90,8 @@
         }
     }
 
-    protected boolean enterComponents(ILSMIndexOperationContext ctx, LSMOperationType opType) throws HyracksDataException {
+    protected boolean enterComponents(ILSMIndexOperationContext ctx, LSMOperationType opType)
+            throws HyracksDataException {
         List<ILSMComponent> components = ctx.getComponentHolder();
         int numEntered = 0;
         boolean entranceSuccessful = false;
@@ -197,8 +198,15 @@
                         break;
                 }
             } finally {
-                opTracker.afterOperation(lsmIndex, opType, ctx.getSearchOperationCallback(),
-                        ctx.getModificationCallback());
+                if (failedOperation && (opType == LSMOperationType.MODIFICATION || opType == LSMOperationType.FORCE_MODIFICATION)) {
+                    //When the operation failed, completeOperation() method must be called 
+                    //in order to decrement active operation count which was incremented in beforeOperation() method.
+                    opTracker.completeOperation(lsmIndex, opType, ctx.getSearchOperationCallback(),
+                            ctx.getModificationCallback());
+                } else {
+                    opTracker.afterOperation(lsmIndex, opType, ctx.getSearchOperationCallback(),
+                            ctx.getModificationCallback());
+                }
             }
         }
     }
@@ -219,6 +227,7 @@
 
     protected boolean modify(ILSMIndexOperationContext ctx, boolean tryOperation, ITupleReference tuple,
             LSMOperationType opType) throws HyracksDataException, IndexException {
+        boolean failedOperation = false;
         if (!getAndEnterComponents(ctx, opType, tryOperation)) {
             return false;
         }
@@ -227,8 +236,11 @@
             // The mutable component is always in the first index.
             AbstractMemoryLSMComponent mutableComponent = (AbstractMemoryLSMComponent) ctx.getComponentHolder().get(0);
             mutableComponent.setIsModified();
+        } catch (Exception e) {
+            failedOperation = true;
+            throw e;
         } finally {
-            exitComponents(ctx, opType, null, false);
+            exitComponents(ctx, opType, null, failedOperation);
         }
         return true;
     }