[ASTERIXDB-3320][RT] Ensure IIndexDataflowHelper's are closed

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
Ensure IIndexDataflowHelper's are closed when open() is called.

- When deactivating an index, return if it's already
  inactive.
- Don't decrement referenceCount if it's already <= 0.

Change-Id: I10624a7d5a2f983dbe2a038b57db3042e76e23c0
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17981
Reviewed-by: Wail Alkowaileet <wael.y.k@gmail.com>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/Info.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/Info.java
index fa0f14c..fab6321 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/Info.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/Info.java
@@ -20,7 +20,13 @@
 
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 public abstract class Info {
+
+    private static final Logger LOGGER = LogManager.getLogger();
+
     private final AtomicInteger referenceCount = new AtomicInteger();
     private volatile boolean isOpen;
 
@@ -33,7 +39,11 @@
     }
 
     public void untouch() {
-        referenceCount.decrementAndGet();
+        int currentRefCount = referenceCount.get();
+        if (currentRefCount <= 0) {
+            LOGGER.warn("trying to decrement ref count {} that is already <=0", currentRefCount);
+        }
+        referenceCount.updateAndGet(i -> i > 0 ? i - 1 : i);
     }
 
     public int getReferenceCount() {
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/LSMInsertDeleteOperatorNodePushable.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/LSMInsertDeleteOperatorNodePushable.java
index 829c9cc..5965e32 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/LSMInsertDeleteOperatorNodePushable.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/LSMInsertDeleteOperatorNodePushable.java
@@ -49,7 +49,6 @@
 import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
 import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallback;
 import org.apache.hyracks.storage.am.common.ophelpers.IndexOperation;
-import org.apache.hyracks.storage.am.common.util.ResourceReleaseUtils;
 import org.apache.hyracks.storage.am.lsm.common.api.ILSMComponentId;
 import org.apache.hyracks.storage.am.lsm.common.api.ILSMIndex;
 import org.apache.hyracks.storage.am.lsm.common.api.ILSMIndexAccessor;
@@ -106,6 +105,7 @@
 
             for (int i = 0; i < indexHelpers.length; i++) {
                 IIndexDataflowHelper indexHelper = indexHelpers[i];
+                indexHelpersOpen[i] = true;
                 indexHelper.open();
                 indexes[i] = indexHelper.getIndexInstance();
                 if (((ILSMIndex) indexes[i]).isAtomic() && isPrimary()) {
@@ -213,10 +213,7 @@
 
     @Override
     public void close() throws HyracksDataException {
-        Throwable failure = null;
-        for (IIndexDataflowHelper indexHelper : indexHelpers) {
-            failure = ResourceReleaseUtils.close(indexHelper, failure);
-        }
+        Throwable failure = closeIndexHelpers(null);
         if (writerOpen) {
             try {
                 writer.close();
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMIndexBulkLoadOperatorNodePushable.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMIndexBulkLoadOperatorNodePushable.java
index 367f670..733b06d 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMIndexBulkLoadOperatorNodePushable.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMIndexBulkLoadOperatorNodePushable.java
@@ -45,6 +45,7 @@
 
     protected final BulkLoadUsage usage;
     protected final IIndexDataflowHelper[] primaryIndexHelpers;
+    protected final boolean[] primaryIndexHelpersOpen;
     protected final IDatasetLifecycleManager datasetManager;
     protected final int datasetId;
     protected final int partition;
@@ -61,6 +62,7 @@
 
         if (priamryIndexDataflowHelperFactory != null) {
             primaryIndexHelpers = new IIndexDataflowHelper[partitions.length];
+            primaryIndexHelpersOpen = new boolean[partitions.length];
             primaryIndexes = new ILSMIndex[partitions.length];
             for (int i = 0; i < partitions.length; i++) {
                 primaryIndexHelpers[i] = priamryIndexDataflowHelperFactory
@@ -68,6 +70,7 @@
             }
         } else {
             primaryIndexHelpers = null;
+            primaryIndexHelpersOpen = null;
         }
         this.usage = usage;
         this.datasetId = datasetId;
@@ -86,6 +89,7 @@
             bulkLoaders[indexId] = targetIndex.createBulkLoader(fillFactor, verifyInput, numElementsHint,
                     checkIfEmptyIndex, parameters);
         } else {
+            primaryIndexHelpersOpen[indexId] = true;
             primaryIndexHelpers[indexId].open();
             primaryIndexes[indexId] = (ILSMIndex) primaryIndexHelpers[indexId].getIndexInstance();
             List<ILSMDiskComponent> primaryComponents = primaryIndexes[indexId].getDiskComponents();
@@ -109,7 +113,7 @@
             super.close();
         } finally {
             if (primaryIndexHelpers != null) {
-                closeIndexes(primaryIndexes, primaryIndexHelpers);
+                closeIndexes(primaryIndexes, primaryIndexHelpers, primaryIndexHelpersOpen);
             }
         }
     }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMPrimaryInsertOperatorNodePushable.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMPrimaryInsertOperatorNodePushable.java
index 7891312..7fb3369 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMPrimaryInsertOperatorNodePushable.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMPrimaryInsertOperatorNodePushable.java
@@ -57,6 +57,7 @@
 import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
 import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallback;
 import org.apache.hyracks.storage.am.common.ophelpers.IndexOperation;
+import org.apache.hyracks.storage.am.common.util.ResourceReleaseUtils;
 import org.apache.hyracks.storage.am.lsm.common.api.IFrameOperationCallback;
 import org.apache.hyracks.storage.am.lsm.common.api.IFrameTupleProcessor;
 import org.apache.hyracks.storage.am.lsm.common.api.ILSMComponentId;
@@ -82,6 +83,7 @@
 
 public class LSMPrimaryInsertOperatorNodePushable extends LSMIndexInsertUpdateDeleteOperatorNodePushable {
 
+    private final boolean[] keyIndexHelpersOpen;
     private final IIndexDataflowHelper[] keyIndexHelpers;
     private MultiComparator keySearchCmp;
     private RangePredicate searchPred;
@@ -116,6 +118,7 @@
         this.lsmAccessorForUniqunessChecks = new LSMTreeIndexAccessor[partitions.length];
         this.lsmAccessorForKeyIndexes = new LSMTreeIndexAccessor[partitions.length];
         this.keyIndexHelpers = new IIndexDataflowHelper[partitions.length];
+        this.keyIndexHelpersOpen = new boolean[partitions.length];
         this.processors = new IFrameTupleProcessor[partitions.length];
         if (keyIndexHelperFactory != null) {
             for (int i = 0; i < partitions.length; i++) {
@@ -220,6 +223,7 @@
             writerOpen = true;
             for (int i = 0; i < partitions.length; i++) {
                 IIndexDataflowHelper indexHelper = indexHelpers[i];
+                indexHelpersOpen[i] = true;
                 indexHelper.open();
                 indexes[i] = indexHelper.getIndexInstance();
                 IIndex index = indexes[i];
@@ -229,6 +233,7 @@
                 IIndexDataflowHelper keyIndexHelper = keyIndexHelpers[i];
                 IIndex indexForUniquessCheck;
                 if (keyIndexHelper != null) {
+                    keyIndexHelpersOpen[i] = true;
                     keyIndexHelper.open();
                     indexForUniquessCheck = keyIndexHelper.getIndexInstance();
                 } else {
@@ -326,8 +331,8 @@
     public void close() throws HyracksDataException {
         Throwable failure = CleanupUtils.destroy(null, cursors);
         failure = CleanupUtils.close(writer, failure);
-        failure = CleanupUtils.close(indexHelpers, failure);
-        failure = CleanupUtils.close(keyIndexHelpers, failure);
+        failure = closeIndexHelpers(failure);
+        failure = closeKeyIndexHelpers(failure);
         if (failure == null && !failed) {
             commitAtomicInsert();
         } else {
@@ -387,4 +392,13 @@
             }
         }
     }
+
+    private Throwable closeKeyIndexHelpers(Throwable failure) {
+        for (int i = 0; i < keyIndexHelpers.length; i++) {
+            if (keyIndexHelpersOpen[i]) {
+                failure = ResourceReleaseUtils.close(keyIndexHelpers[i], failure);
+            }
+        }
+        return failure;
+    }
 }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMPrimaryUpsertOperatorNodePushable.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMPrimaryUpsertOperatorNodePushable.java
index 71f699d..34371e1 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMPrimaryUpsertOperatorNodePushable.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMPrimaryUpsertOperatorNodePushable.java
@@ -302,6 +302,7 @@
                     (INcApplicationContext) ctx.getJobletContext().getServiceContext().getApplicationContext();
             for (int i = 0; i < indexHelpers.length; i++) {
                 IIndexDataflowHelper indexHelper = indexHelpers[i];
+                indexHelpersOpen[i] = true;
                 indexHelper.open();
                 indexes[i] = indexHelper.getIndexInstance();
                 if (((ILSMIndex) indexes[i]).isAtomic()) {
@@ -530,7 +531,7 @@
         Throwable failure = CleanupUtils.close(frameOpCallbacks, null);
         failure = CleanupUtils.destroy(failure, cursors);
         failure = CleanupUtils.close(writer, failure);
-        failure = CleanupUtils.close(indexHelpers, failure);
+        failure = closeIndexHelpers(failure);
         if (failure == null && !failed) {
             commitAtomicUpsert();
         } else {
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMSecondaryIndexBulkLoadNodePushable.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMSecondaryIndexBulkLoadNodePushable.java
index 64dce1e..21c3b27 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMSecondaryIndexBulkLoadNodePushable.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/LSMSecondaryIndexBulkLoadNodePushable.java
@@ -86,6 +86,7 @@
     @Override
     public void open() throws HyracksDataException {
         super.open();
+        //TODO(ali): ensure open()/close()
         primaryIndexHelper.open();
         primaryIndex = (ILSMIndex) primaryIndexHelper.getIndexInstance();
         secondaryIndexHelper.open();
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/misc/ConstantTupleSourceOperatorNodePushable.java b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/misc/ConstantTupleSourceOperatorNodePushable.java
index 785a330..932da99 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/misc/ConstantTupleSourceOperatorNodePushable.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/misc/ConstantTupleSourceOperatorNodePushable.java
@@ -44,10 +44,11 @@
     @Override
     public void initialize() throws HyracksDataException {
         FrameTupleAppender appender = new FrameTupleAppender(new VSizeFrame(ctx));
-        if (fieldSlots != null && tupleData != null && tupleSize > 0)
+        if (fieldSlots != null && tupleData != null && tupleSize > 0) {
             appender.append(fieldSlots, tupleData, 0, tupleSize);
-        writer.open();
+        }
         try {
+            writer.open();
             appender.write(writer, false);
         } catch (Throwable th) {
             writer.fail();
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexBulkLoadOperatorNodePushable.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexBulkLoadOperatorNodePushable.java
index f401e45..0206f20 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexBulkLoadOperatorNodePushable.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexBulkLoadOperatorNodePushable.java
@@ -49,6 +49,7 @@
     protected final long numElementsHint;
     protected final boolean checkIfEmptyIndex;
     protected final IIndexDataflowHelper[] indexHelpers;
+    protected final boolean[] indexHelpersOpen;
     protected final RecordDescriptor recDesc;
     protected final PermutingFrameTupleReference tuple = new PermutingFrameTupleReference();
     protected final ITupleFilterFactory tupleFilterFactory;
@@ -71,6 +72,7 @@
         this.storagePartitionId2Index = new Int2IntOpenHashMap();
         this.indexes = new IIndex[partitions.length];
         this.indexHelpers = new IIndexDataflowHelper[partitions.length];
+        this.indexHelpersOpen = new boolean[partitions.length];
         this.bulkLoaders = new IIndexBulkLoader[partitions.length];
         for (int i = 0; i < partitions.length; i++) {
             storagePartitionId2Index.put(partitions[i], i);
@@ -89,6 +91,7 @@
     public void open() throws HyracksDataException {
         accessor = new FrameTupleAccessor(recDesc);
         for (int i = 0; i < indexHelpers.length; i++) {
+            indexHelpersOpen[i] = true;
             indexHelpers[i].open();
             indexes[i] = indexHelpers[i].getIndexInstance();
             initializeBulkLoader(indexes[i], i);
@@ -133,7 +136,7 @@
             throw HyracksDataException.create(th);
         } finally {
             try {
-                closeIndexes(indexes, indexHelpers);
+                closeIndexes(indexes, indexHelpers, indexHelpersOpen);
             } finally {
                 writer.close();
             }
@@ -164,11 +167,11 @@
         }
     }
 
-    protected static void closeIndexes(IIndex[] indexes, IIndexDataflowHelper[] indexHelpers)
-            throws HyracksDataException {
+    protected static void closeIndexes(IIndex[] indexes, IIndexDataflowHelper[] indexHelpers,
+            boolean[] indexHelpersOpen) throws HyracksDataException {
         Throwable failure = null;
         for (int i = 0; i < indexes.length; i++) {
-            if (indexes[i] != null) {
+            if (indexes[i] != null || indexHelpersOpen[i]) {
                 failure = ResourceReleaseUtils.close(indexHelpers[i], failure);
             }
         }
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexInsertUpdateDeleteOperatorNodePushable.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexInsertUpdateDeleteOperatorNodePushable.java
index 10425f4..30c5a56 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexInsertUpdateDeleteOperatorNodePushable.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexInsertUpdateDeleteOperatorNodePushable.java
@@ -62,6 +62,7 @@
     protected final IIndex[] indexes;
     protected final IIndexAccessor[] indexAccessors;
     protected final IIndexDataflowHelper[] indexHelpers;
+    protected final boolean[] indexHelpersOpen;
     protected final IModificationOperationCallback[] modCallbacks;
     protected final IModificationOperationCallbackFactory modOpCallbackFactory;
     protected final ITupleFilterFactory tupleFilterFactory;
@@ -83,6 +84,7 @@
         this.modCallbacks = new IModificationOperationCallback[partitions.length];
         this.storagePartitionId2Index = new Int2IntOpenHashMap();
         this.indexHelpers = new IIndexDataflowHelper[partitions.length];
+        this.indexHelpersOpen = new boolean[partitions.length];
         for (int i = 0; i < partitions.length; i++) {
             storagePartitionId2Index.put(partitions[i], i);
             indexHelpers[i] = indexHelperFactory.create(ctx.getJobletContext().getServiceContext(), partitions[i]);
@@ -103,6 +105,7 @@
         try {
             for (int i = 0; i < indexHelpers.length; i++) {
                 IIndexDataflowHelper indexHelper = indexHelpers[i];
+                indexHelpersOpen[i] = true;
                 indexHelper.open();
                 indexes[i] = indexHelper.getIndexInstance();
                 LocalResource resource = indexHelper.getResource();
@@ -193,10 +196,10 @@
             if (writerOpen) {
                 writer.close();
             }
+        } catch (Throwable th) {
+            failure = th;
         } finally {
-            for (IIndexDataflowHelper indexHelper : indexHelpers) {
-                failure = ResourceReleaseUtils.close(indexHelper, failure);
-            }
+            failure = closeIndexHelpers(failure);
         }
         if (failure != null) {
             throw HyracksDataException.create(failure);
@@ -215,4 +218,15 @@
     public void flush() throws HyracksDataException {
         writer.flush();
     }
+
+    protected Throwable closeIndexHelpers(Throwable failure) {
+        //TODO(ali): should this be made similar to IndexSearchOperatorNodePushable.close()?
+        //TODO(ali): IIndexDataflowHelper.close() should be made idempotent and flags should be removed
+        for (int i = 0; i < indexHelpers.length; i++) {
+            if (indexHelpersOpen[i]) {
+                failure = ResourceReleaseUtils.close(indexHelpers[i], failure);
+            }
+        }
+        return failure;
+    }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexSearchOperatorNodePushable.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexSearchOperatorNodePushable.java
index 406dbc6..63ff2ed 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexSearchOperatorNodePushable.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexSearchOperatorNodePushable.java
@@ -80,6 +80,7 @@
 
     protected ISearchPredicate searchPred;
     protected final IIndexDataflowHelper[] indexHelpers;
+    protected final boolean[] indexHelpersOpen;
     protected IIndex[] indexes;
     protected IIndexAccessor[] indexAccessors;
     protected IIndexCursor[] cursors;
@@ -137,6 +138,7 @@
             storagePartitionId2Index.put(partitions[i], i);
         }
         this.indexHelpers = new IIndexDataflowHelper[partitions.length];
+        this.indexHelpersOpen = new boolean[partitions.length];
         this.indexes = new IIndex[partitions.length];
         this.indexAccessors = new IIndexAccessor[partitions.length];
         this.cursors = new IIndexCursor[partitions.length];
@@ -199,6 +201,7 @@
         IIndexAccessParameters[] iaps = new IndexAccessParameters[partitions.length];
 
         for (int i = 0; i < partitions.length; i++) {
+            indexHelpersOpen[i] = true;
             indexHelpers[i].open();
             indexes[i] = indexHelpers[i].getIndexInstance();
             searchCallbacks[i] = searchCallbackFactory
@@ -359,12 +362,16 @@
 
     private Throwable releaseResources(Throwable failure) {
         for (int i = 0; i < indexes.length; i++) {
-            // if index == null, then the index open was not successful
             try {
                 if (indexes[i] != null) {
                     failure = ResourceReleaseUtils.close(cursors[i], failure);
                     failure = CleanupUtils.destroy(failure, cursors[i], indexAccessors[i]);
                     failure = ResourceReleaseUtils.close(indexHelpers[i], failure);
+                } else if (indexHelpersOpen[i]) {
+                    // can mean the index was open, but getting the index instance failed (index == null)
+                    // or opening the index itself failed at some step during the open
+                    failure = ResourceReleaseUtils.close(indexHelpers[i], failure);
+                    //TODO(ali): IIndexDataflowHelper.close() should be made idempotent and flags should be removed
                 }
             } catch (Throwable th) {// NOSONAR ensure closing other indexes
                 // subsequently, the failure will be thrown
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/impls/AbstractTreeIndex.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/impls/AbstractTreeIndex.java
index 11368bf..a319c53 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/impls/AbstractTreeIndex.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/impls/AbstractTreeIndex.java
@@ -31,9 +31,12 @@
 import org.apache.hyracks.storage.common.buffercache.IBufferCache;
 import org.apache.hyracks.storage.common.buffercache.ICachedPage;
 import org.apache.hyracks.storage.common.file.BufferedFileHandle;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 public abstract class AbstractTreeIndex implements ITreeIndex {
 
+    private static final Logger LOGGER = LogManager.getLogger();
     public static final int MINIMAL_TREE_PAGE_COUNT = 2;
     public static final int MINIMAL_TREE_PAGE_COUNT_WITH_FILTER = 3;
     protected int rootPage = 1;
@@ -121,7 +124,8 @@
     @Override
     public synchronized void deactivate() throws HyracksDataException {
         if (!isActive) {
-            throw HyracksDataException.create(ErrorCode.CANNOT_DEACTIVATE_INACTIVE_INDEX);
+            LOGGER.warn("not deactivating already inactive index {}", this);
+            return;
         }
         freePageManager.close(HaltOnFailureCallback.INSTANCE);
         bufferCache.closeFile(fileId);
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/AbstractLSMIndex.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/AbstractLSMIndex.java
index 33fd38d..d9a3371 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/AbstractLSMIndex.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/AbstractLSMIndex.java
@@ -218,7 +218,8 @@
     @Override
     public synchronized void deactivate(boolean flush) throws HyracksDataException {
         if (!isActive) {
-            throw HyracksDataException.create(ErrorCode.CANNOT_DEACTIVATE_INACTIVE_INDEX);
+            LOGGER.warn("not deactivating already inactive index {}, flush requested:{}", this, flush);
+            return;
         }
         // The following member is used to prevent scheduling of new merges as memory components
         // get flushed. This now works only if the caller of deactivate waited for all IO