Fixed issues in bulkload cleanup in case of errors.
diff --git a/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java b/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
index 25d7b22..689843b 100644
--- a/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
+++ b/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
@@ -1025,7 +1025,8 @@
                 HyracksDataException {
             // New tuple should be strictly greater than last tuple.
             if (cmp.compare(tuple, prevTuple) <= 0) {
-                throw new UnsortedInputException("Input stream given to BTree bulk load is not sorted.");
+                throw new UnsortedInputException(
+                        "Input stream given to BTree bulk load is not sorted or has duplicates.");
             }
         }
 
diff --git a/hyracks/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java b/hyracks/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
index 3eea1b3..3557d73 100644
--- a/hyracks/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
+++ b/hyracks/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
@@ -499,8 +499,9 @@
         private final ILSMComponent component;
         private final BTreeBulkLoader bulkLoader;
         private final IIndexBulkLoader builder;
-        private boolean endHasBeenCalled = false;
+        private boolean cleanedUpArtifacts = false;
         private boolean isEmptyComponent = true;
+        private boolean endedBloomFilterLoad = false;
 
         public LSMBTreeBulkLoader(float fillFactor, boolean verifyInput, long numElementsHint, boolean checkIfEmptyIndex)
                 throws TreeIndexException, HyracksDataException {
@@ -524,9 +525,6 @@
 
         @Override
         public void add(ITupleReference tuple) throws IndexException, HyracksDataException {
-            if (isEmptyComponent) {
-                isEmptyComponent = false;
-            }
             try {
                 bulkLoader.add(tuple);
                 builder.add(tuple);
@@ -534,27 +532,39 @@
                 cleanupArtifacts();
                 throw e;
             }
+            if (isEmptyComponent) {
+                isEmptyComponent = false;
+            }
         }
 
         protected void cleanupArtifacts() throws HyracksDataException, IndexException {
-            if (!endHasBeenCalled) {
-                builder.end();
+            if (!cleanedUpArtifacts) {
+                cleanedUpArtifacts = true;
+                // We make sure to end the bloom filter load to release latches.
+                if (!endedBloomFilterLoad) {
+                    builder.end();
+                    endedBloomFilterLoad = true;
+                }
+                ((LSMBTreeImmutableComponent) component).getBTree().deactivate();
+                ((LSMBTreeImmutableComponent) component).getBTree().destroy();
+                ((LSMBTreeImmutableComponent) component).getBloomFilter().deactivate();
+                ((LSMBTreeImmutableComponent) component).getBloomFilter().destroy();
             }
-            ((LSMBTreeImmutableComponent) component).getBTree().deactivate();
-            ((LSMBTreeImmutableComponent) component).getBTree().destroy();
-            ((LSMBTreeImmutableComponent) component).getBloomFilter().deactivate();
-            ((LSMBTreeImmutableComponent) component).getBloomFilter().destroy();
         }
 
         @Override
         public void end() throws HyracksDataException, IndexException {
-            bulkLoader.end();
-            builder.end();
-            endHasBeenCalled = true;
-            if (isEmptyComponent) {
-                cleanupArtifacts();
-            } else {
-                lsmHarness.addBulkLoadedComponent(component);
+            if (!cleanedUpArtifacts) {
+                if (!endedBloomFilterLoad) {
+                    builder.end();
+                    endedBloomFilterLoad = true;
+                }
+                bulkLoader.end();
+                if (isEmptyComponent) {
+                    cleanupArtifacts();
+                } else {
+                    lsmHarness.addBulkLoadedComponent(component);
+                }
             }
         }
     }
diff --git a/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndex.java b/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndex.java
index bbb8459..3eae5a7 100644
--- a/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndex.java
+++ b/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndex.java
@@ -575,7 +575,7 @@
     public class LSMInvertedIndexBulkLoader implements IIndexBulkLoader {
         private final ILSMComponent component;
         private final IIndexBulkLoader invIndexBulkLoader;
-        private boolean exceptionCaught = false;
+        private boolean cleanedUpArtifacts = false;
         private boolean isEmptyComponent = true;
 
         public LSMInvertedIndexBulkLoader(float fillFactor, boolean verifyInput, long numElementsHint,
@@ -596,40 +596,38 @@
 
         @Override
         public void add(ITupleReference tuple) throws IndexException, HyracksDataException {
-            if (isEmptyComponent) {
-                isEmptyComponent = false;
-            }
             try {
                 invIndexBulkLoader.add(tuple);
             } catch (IndexException | HyracksDataException | RuntimeException e) {
-                handleException();
+                cleanupArtifacts();
                 throw e;
             }
+            if (isEmptyComponent) {
+                isEmptyComponent = false;
+            }
         }
 
-        protected void handleException() throws HyracksDataException {
-            exceptionCaught = true;
-            cleanupArtifacts();
-        }
-
         protected void cleanupArtifacts() throws HyracksDataException {
-            ((LSMInvertedIndexImmutableComponent) component).getInvIndex().deactivate();
-            ((LSMInvertedIndexImmutableComponent) component).getInvIndex().destroy();
-            ((LSMInvertedIndexImmutableComponent) component).getDeletedKeysBTree().deactivate();
-            ((LSMInvertedIndexImmutableComponent) component).getDeletedKeysBTree().destroy();
-            ((LSMInvertedIndexImmutableComponent) component).getBloomFilter().deactivate();
-            ((LSMInvertedIndexImmutableComponent) component).getBloomFilter().destroy();
+            if (!cleanedUpArtifacts) {
+                cleanedUpArtifacts = true;
+                ((LSMInvertedIndexImmutableComponent) component).getInvIndex().deactivate();
+                ((LSMInvertedIndexImmutableComponent) component).getInvIndex().destroy();
+                ((LSMInvertedIndexImmutableComponent) component).getDeletedKeysBTree().deactivate();
+                ((LSMInvertedIndexImmutableComponent) component).getDeletedKeysBTree().destroy();
+                ((LSMInvertedIndexImmutableComponent) component).getBloomFilter().deactivate();
+                ((LSMInvertedIndexImmutableComponent) component).getBloomFilter().destroy();
+            }
         }
 
         @Override
         public void end() throws IndexException, HyracksDataException {
-            if (!exceptionCaught) {
+            if (!cleanedUpArtifacts) {
                 invIndexBulkLoader.end();
-            }
-            if (isEmptyComponent) {
-                cleanupArtifacts();
-            } else {
-                lsmHarness.addBulkLoadedComponent(component);
+                if (isEmptyComponent) {
+                    cleanupArtifacts();
+                } else {
+                    lsmHarness.addBulkLoadedComponent(component);
+                }
             }
         }
     }
diff --git a/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTree.java b/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTree.java
index 2f631af..0b71373 100644
--- a/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTree.java
+++ b/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTree.java
@@ -412,6 +412,7 @@
     public class LSMRTreeBulkLoader implements IIndexBulkLoader {
         private final ILSMComponent component;
         private final IIndexBulkLoader bulkLoader;
+        private boolean cleanedUpArtifacts = false;
         private boolean isEmptyComponent = true;
 
         public LSMRTreeBulkLoader(float fillFactor, boolean verifyInput, long numElementsHint, boolean checkIfEmptyIndex)
@@ -432,34 +433,39 @@
 
         @Override
         public void add(ITupleReference tuple) throws HyracksDataException, IndexException {
-            if (isEmptyComponent) {
-                isEmptyComponent = false;
-            }
             try {
                 bulkLoader.add(tuple);
             } catch (IndexException | HyracksDataException | RuntimeException e) {
                 cleanupArtifacts();
                 throw e;
             }
+            if (isEmptyComponent) {
+                isEmptyComponent = false;
+            }
         }
 
         @Override
         public void end() throws HyracksDataException, IndexException {
-            bulkLoader.end();
-            if (isEmptyComponent) {
-                cleanupArtifacts();
-            } else {
-                lsmHarness.addBulkLoadedComponent(component);
+            if (!cleanedUpArtifacts) {
+                bulkLoader.end();
+                if (isEmptyComponent) {
+                    cleanupArtifacts();
+                } else {
+                    lsmHarness.addBulkLoadedComponent(component);
+                }
             }
         }
 
         protected void cleanupArtifacts() throws HyracksDataException {
-            ((LSMRTreeImmutableComponent) component).getRTree().deactivate();
-            ((LSMRTreeImmutableComponent) component).getRTree().destroy();
-            ((LSMRTreeImmutableComponent) component).getBTree().deactivate();
-            ((LSMRTreeImmutableComponent) component).getBTree().destroy();
-            ((LSMRTreeImmutableComponent) component).getBloomFilter().deactivate();
-            ((LSMRTreeImmutableComponent) component).getBloomFilter().destroy();
+            if (!cleanedUpArtifacts) {
+                cleanedUpArtifacts = true;
+                ((LSMRTreeImmutableComponent) component).getRTree().deactivate();
+                ((LSMRTreeImmutableComponent) component).getRTree().destroy();
+                ((LSMRTreeImmutableComponent) component).getBTree().deactivate();
+                ((LSMRTreeImmutableComponent) component).getBTree().destroy();
+                ((LSMRTreeImmutableComponent) component).getBloomFilter().deactivate();
+                ((LSMRTreeImmutableComponent) component).getBloomFilter().destroy();
+            }
         }
     }
 
diff --git a/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuples.java b/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuples.java
index 1bf9f58..0be497a 100644
--- a/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuples.java
+++ b/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuples.java
@@ -382,6 +382,7 @@
     public class LSMRTreeWithAntiMatterTuplesBulkLoader implements IIndexBulkLoader {
         private final ILSMComponent component;
         private final IIndexBulkLoader bulkLoader;
+        private boolean cleanedUpArtifacts = false;
         private boolean isEmptyComponent = true;
 
         public LSMRTreeWithAntiMatterTuplesBulkLoader(float fillFactor, boolean verifyInput, long numElementsHint,
@@ -402,30 +403,35 @@
 
         @Override
         public void add(ITupleReference tuple) throws HyracksDataException, IndexException {
-            if (isEmptyComponent) {
-                isEmptyComponent = false;
-            }
             try {
                 bulkLoader.add(tuple);
             } catch (IndexException | HyracksDataException | RuntimeException e) {
                 cleanupArtifacts();
                 throw e;
             }
+            if (isEmptyComponent) {
+                isEmptyComponent = false;
+            }
         }
 
         @Override
         public void end() throws HyracksDataException, IndexException {
-            bulkLoader.end();
-            if (isEmptyComponent) {
-                cleanupArtifacts();
-            } else {
-                lsmHarness.addBulkLoadedComponent(component);
+            if (!cleanedUpArtifacts) {
+                bulkLoader.end();
+                if (isEmptyComponent) {
+                    cleanupArtifacts();
+                } else {
+                    lsmHarness.addBulkLoadedComponent(component);
+                }
             }
         }
 
         protected void cleanupArtifacts() throws HyracksDataException {
-            ((LSMRTreeImmutableComponent) component).getRTree().deactivate();
-            ((LSMRTreeImmutableComponent) component).getRTree().destroy();
+            if (!cleanedUpArtifacts) {
+                cleanedUpArtifacts = true;
+                ((LSMRTreeImmutableComponent) component).getRTree().deactivate();
+                ((LSMRTreeImmutableComponent) component).getRTree().destroy();
+            }
         }
 
     }