changed lsmbtree insert semantics to be true insert rather than upsert

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_lsm_tree@1660 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java b/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
index aaa497b..634f1fa 100644
--- a/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
+++ b/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
@@ -26,8 +26,10 @@
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.api.io.FileReference;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+import edu.uci.ics.hyracks.storage.am.btree.exceptions.BTreeDuplicateKeyException;
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTree.BTreeBulkLoader;
+import edu.uci.ics.hyracks.storage.am.btree.impls.BTreeRangeSearchCursor;
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
@@ -45,7 +47,6 @@
 import edu.uci.ics.hyracks.storage.am.common.api.IndexType;
 import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
 import edu.uci.ics.hyracks.storage.am.common.impls.NoOpOperationCallback;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 import edu.uci.ics.hyracks.storage.am.lsm.common.api.ILSMComponentFinalizer;
 import edu.uci.ics.hyracks.storage.am.lsm.common.api.ILSMFileManager;
@@ -201,15 +202,48 @@
 
     @Override
     public boolean insertUpdateOrDelete(ITupleReference tuple, IIndexOpContext ictx) throws HyracksDataException,
-            TreeIndexException {
+            IndexException {
         LSMBTreeOpContext ctx = (LSMBTreeOpContext) ictx;
 
-        if (ctx.getIndexOp() == IndexOp.PHYSICALDELETE) {
-            ctx.memBTreeAccessor.delete(tuple);
-            return true;
+        switch (ctx.getIndexOp()) {
+            case PHYSICALDELETE:
+                ctx.memBTreeAccessor.delete(tuple);
+                break;
+            case INSERT:
+                insert(tuple, ctx);
+                break;
+            default:
+                ctx.memBTreeAccessor.upsert(tuple);
+                break;
         }
 
-        ctx.memBTreeAccessor.upsert(tuple);
+        return true;
+    }
+
+    private boolean insert(ITupleReference tuple, LSMBTreeOpContext ctx) throws HyracksDataException, IndexException {
+        MultiComparator comparator = MultiComparator.create(memBTree.getComparatorFactories());
+        LSMBTreeRangeSearchCursor searchCursor = new LSMBTreeRangeSearchCursor();
+        IIndexCursor memCursor = new BTreeRangeSearchCursor(ctx.memBTreeOpCtx.leafFrame, false);
+        RangePredicate predicate = new RangePredicate(tuple, tuple, true, true, comparator, comparator);
+
+        ctx.memBTreeAccessor.search(memCursor, predicate);
+        try {
+            if (memCursor.hasNext()) {
+                throw new BTreeDuplicateKeyException("Failed to insert key since key already exists.");
+            }
+        } finally {
+            memCursor.close();
+        }
+
+        lsmHarness.search(searchCursor, predicate, ctx, false);
+        try {
+            if (searchCursor.hasNext()) {
+                throw new BTreeDuplicateKeyException("Failed to insert key since key already exists.");
+            }
+        } finally {
+            searchCursor.close();
+        }
+        ctx.memBTreeAccessor.insert(tuple);
 
         return true;
     }
diff --git a/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTreeOpContext.java b/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTreeOpContext.java
index ca281ed..8e665cd 100644
--- a/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTreeOpContext.java
+++ b/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTreeOpContext.java
@@ -73,6 +73,7 @@
                 // Update will only be set if a previous attempt to delete or
                 // insert failed, so we must preserve the semantics of the
                 // previously requested operation.
+                setMemBTreeAccessor();
                 return;
 
             case INSERT:
diff --git a/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/LSMTreeIndexAccessor.java b/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/LSMTreeIndexAccessor.java
index de2bdcd..1630d2c 100644
--- a/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/LSMTreeIndexAccessor.java
+++ b/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/LSMTreeIndexAccessor.java
@@ -42,7 +42,7 @@
     @Override
     public void update(ITupleReference tuple) throws HyracksDataException, IndexException {
         // Update is the same as insert.
-        ctx.reset(IndexOp.INSERT);
+        ctx.reset(IndexOp.UPDATE);
         lsmHarness.insertUpdateOrDelete(tuple, ctx);
     }