Fleshed out multi-threaded BTree tests a little more.

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_lsm_tree@1117 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/test/TreeIndexMultiThreadTestDriver.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/test/TreeIndexMultiThreadTestDriver.java
index e0b6b47..0e0d3c2 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/test/TreeIndexMultiThreadTestDriver.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/test/TreeIndexMultiThreadTestDriver.java
@@ -16,6 +16,7 @@
 package edu.uci.ics.hyracks.storage.am.common.test;
 
 import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
 import edu.uci.ics.hyracks.storage.am.common.datagen.DataGenThread;
@@ -38,9 +39,14 @@
         this.workerFactory = workerFactory;
         this.fieldSerdes = fieldSerdes;
         this.opSelector = new TestOperationSelector(ops, opProbs);
+    }      
+    
+    public void init(int fileId) throws HyracksDataException {
+    	index.create(fileId);
+    	index.open(fileId);
     }
     
-    public void run(int numThreads, int numRepeats, int numTuples, int batchSize) throws InterruptedException, TreeIndexException {
+    public long[] run(int numThreads, int numRepeats, int numTuples, int batchSize) throws InterruptedException, TreeIndexException {
         int numBatches = numTuples / batchSize;
         int threadNumBatches = numBatches / numThreads;
         if (threadNumBatches <= 0) {
@@ -69,6 +75,11 @@
             long end = System.currentTimeMillis();
             times[i] = end - start;
         }
+        return times;
+    }
+    
+    public void deinit() throws HyracksDataException {
+    	index.close();
     }
     
     // To allow subclasses to override the data gen params.
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeMultiThreadTest.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeMultiThreadTest.java
index c7e13f7..610df16 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeMultiThreadTest.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeMultiThreadTest.java
@@ -15,6 +15,9 @@
 
 package edu.uci.ics.hyracks.storage.am.btree.multithread;
 
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -36,15 +39,24 @@
 @SuppressWarnings("rawtypes")
 public class BTreeMultiThreadTest {    
     
-    private final int PAGE_SIZE = 8192;
-    //private final int PAGE_SIZE = 64;
-    private final int NUM_PAGES = 1000;
-    private final int MAX_OPEN_FILES = 10;
-    private final int HYRACKS_FRAME_SIZE = 32768;
+    protected final Logger LOGGER = Logger.getLogger(BTreeMultiThreadTest.class.getName());
+    
+    //private final int PAGE_SIZE = 8192;
+    //private final int PAGE_SIZE = 8192;
+    //private final int NUM_PAGES = 100;
+    //private final int MAX_OPEN_FILES = 10;
+    //private final int HYRACKS_FRAME_SIZE = 32768;
     
     private final BTreeTestWorkerFactory workerFactory = new BTreeTestWorkerFactory();
-    private final BTreeTestHarness harness = new BTreeTestHarness(PAGE_SIZE, NUM_PAGES, MAX_OPEN_FILES, HYRACKS_FRAME_SIZE);
+    //private final BTreeTestHarness harness = new BTreeTestHarness(PAGE_SIZE, NUM_PAGES, MAX_OPEN_FILES, HYRACKS_FRAME_SIZE);
+    private final BTreeTestHarness harness = new BTreeTestHarness();
 
+    // Machine-specific number of threads to use for testing.
+    private final int REGULAR_NUM_THREADS = Runtime.getRuntime().availableProcessors();
+    // Excessive number of threads for testing.
+    private final int EXCESSIVE_NUM_THREADS = Runtime.getRuntime().availableProcessors() * 4;
+    private final int NUM_TUPLES = 1000000;
+    
     @Before
     public void setUp() throws HyracksDataException {
         harness.setUp();
@@ -55,8 +67,11 @@
         harness.tearDown();
     }
     
-    @Test
-    public void firstTest() throws InterruptedException, HyracksDataException, TreeIndexException {        
+    private void runOneIntKeyAndValueTest(int numThreads) throws HyracksDataException, InterruptedException, TreeIndexException {
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.info("BTree MultiThread Test With One Int Key And Value Using " + numThreads + " Threads.");
+        }
+        
         ISerializerDeserializer[] fieldSerdes = new ISerializerDeserializer[] { IntegerSerializerDeserializer.INSTANCE, IntegerSerializerDeserializer.INSTANCE };
         ITypeTraits[] typeTraits = SerdeUtils.serdesToTypeTraits(fieldSerdes);
         int numKeyFields = 1;
@@ -70,10 +85,26 @@
         TestOperation[] ops = new TestOperation[] { TestOperation.INSERT };
         float[] opProbs = new float[] { 1.0f };
         
+        // 4 batches per thread.
+        int batchSize = (NUM_TUPLES / numThreads) / 4;
+        
         TreeIndexMultiThreadTestDriver driver = new TreeIndexMultiThreadTestDriver(btree, workerFactory, fieldSerdes, ops, opProbs);
+        driver.init(harness.getBTreeFileId());
+        long[] times = driver.run(REGULAR_NUM_THREADS, 1, NUM_TUPLES, batchSize);
+        driver.deinit();
         
-        driver.run(10, 1, 10000000, 1000);
-        
-        btree.close();
+        for (int i = 0; i < times.length; i++) {
+            System.out.println("TIME: " + times[i]);
+        }        
+    }
+    
+    @Test
+    public void oneIntKeyAndValueRegular() throws InterruptedException, HyracksDataException, TreeIndexException {        
+        runOneIntKeyAndValueTest(REGULAR_NUM_THREADS);
+    }
+    
+    @Test
+    public void oneIntKeyAndValueExcessive() throws InterruptedException, HyracksDataException, TreeIndexException {        
+        runOneIntKeyAndValueTest(EXCESSIVE_NUM_THREADS);
     }
 }
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeTestWorker.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeTestWorker.java
index 7896394..ce2592c 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeTestWorker.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeTestWorker.java
@@ -18,9 +18,15 @@
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 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.exceptions.BTreeNonExistentKeyException;
+import edu.uci.ics.hyracks.storage.am.btree.exceptions.BTreeNotUpdateableException;
+import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
+import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
 import edu.uci.ics.hyracks.storage.am.common.datagen.DataGenThread;
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 import edu.uci.ics.hyracks.storage.am.common.test.AbstractTreeIndexTestWorker;
 import edu.uci.ics.hyracks.storage.am.common.test.TestOperationSelector;
 import edu.uci.ics.hyracks.storage.am.common.test.TestOperationSelector.TestOperation;
@@ -32,19 +38,72 @@
     }
     
     @Override
-    public void performOp(ITupleReference tuple, TestOperation op) throws HyracksDataException, TreeIndexException {
+    public void performOp(ITupleReference tuple, TestOperation op) throws HyracksDataException, TreeIndexException {        
+        BTree.BTreeAccessor accessor = (BTree.BTreeAccessor) indexAccessor;
+        ITreeIndexCursor searchCursor = accessor.createSearchCursor();
+        ITreeIndexCursor diskOrderScanCursor = accessor.createDiskOrderScanCursor();
+        MultiComparator cmp = accessor.getOpContext().cmp;
+        RangePredicate rangePred = new RangePredicate(tuple, tuple, true, true, cmp, cmp);
+        
         switch (op) {
             case INSERT:
                 try {
-                    indexAccessor.insert(tuple);
+                    accessor.insert(tuple);
                 } catch (BTreeDuplicateKeyException e) {
-                    // Ignore duplicate keys.
+                    // Ignore duplicate keys, since we get random tuples.
                 }
                 break;
                 
+            case DELETE:
+                try {
+                    accessor.delete(tuple);
+                } catch (BTreeNonExistentKeyException e) {
+                    // Ignore non-existant keys, since we get random tuples.
+                }
+                break;
+                
+            case UPDATE: 
+                try {
+                    accessor.update(tuple);
+                } catch (BTreeNotUpdateableException e) {
+                    // Ignore not updateable exception due to numKeys == numFields.
+                }
+                break;
+                
+            case POINT_SEARCH: 
+                searchCursor.reset();
+                rangePred.setLowKey(tuple, true);
+                rangePred.setHighKey(tuple, true);
+                accessor.search(searchCursor, rangePred);
+                consumeCursorTuples(searchCursor);
+                break;
+                
+            case ORDERED_SCAN:
+                searchCursor.reset();
+                rangePred.setLowKey(null, true);
+                rangePred.setHighKey(null, true);
+                accessor.search(searchCursor, rangePred);
+                consumeCursorTuples(searchCursor);
+                break;
+                
+            case DISKORDER_SCAN:
+                diskOrderScanCursor.reset();
+                accessor.diskOrderScan(diskOrderScanCursor);
+                consumeCursorTuples(diskOrderScanCursor);
+                break;                            
             
             default:
                 throw new HyracksDataException("Op " + op.toString() + " not supported.");
         }
     }
+    
+    private void consumeCursorTuples(ITreeIndexCursor cursor) throws HyracksDataException {
+        try {
+            while(cursor.hasNext()) {
+
+            }
+        } finally {
+            cursor.close();
+        }
+    }
 }