added btree example app

git-svn-id: https://hyracks.googlecode.com/svn/trunk/hyracks@139 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/BTreeRegistryProvider.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/BTreeRegistryProvider.java
new file mode 100644
index 0000000..4c3c7524
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/BTreeRegistryProvider.java
@@ -0,0 +1,19 @@
+package edu.uci.ics.hyracks.examples.btree.helper;
+
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.BTreeRegistry;
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.IBTreeRegistryProvider;
+
+public class BTreeRegistryProvider implements IBTreeRegistryProvider {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final BTreeRegistryProvider INSTANCE = new BTreeRegistryProvider();
+
+    private BTreeRegistryProvider() {
+    }
+
+    @Override
+    public BTreeRegistry getBTreeRegistry() {
+        return RuntimeContext.getInstance().getBTreeRegistry();
+    }
+}
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/BufferCacheProvider.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/BufferCacheProvider.java
new file mode 100644
index 0000000..db1368d
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/BufferCacheProvider.java
@@ -0,0 +1,24 @@
+package edu.uci.ics.hyracks.examples.btree.helper;
+
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.IBufferCacheProvider;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.file.FileManager;
+
+public class BufferCacheProvider implements IBufferCacheProvider {
+    private static final long serialVersionUID = 1L;
+
+    public static final BufferCacheProvider INSTANCE = new BufferCacheProvider();
+
+    private BufferCacheProvider() {
+    }
+
+    @Override
+    public IBufferCache getBufferCache() {
+        return RuntimeContext.getInstance().getBufferCache();
+    }
+
+    @Override
+    public FileManager getFileManager() {
+        return RuntimeContext.getInstance().getFileManager();
+    }
+}
\ No newline at end of file
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/DataGenOperatorDescriptor.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/DataGenOperatorDescriptor.java
new file mode 100644
index 0000000..0ee9210
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/DataGenOperatorDescriptor.java
@@ -0,0 +1,148 @@
+package edu.uci.ics.hyracks.examples.btree.helper;
+
+import java.io.DataOutput;
+import java.nio.ByteBuffer;
+import java.util.HashSet;
+import java.util.Random;
+
+import edu.uci.ics.hyracks.api.context.IHyracksContext;
+import edu.uci.ics.hyracks.api.dataflow.IOperatorNodePushable;
+import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
+import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.api.job.IOperatorEnvironment;
+import edu.uci.ics.hyracks.api.job.JobSpecification;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender;
+import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.UTF8StringSerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.std.base.AbstractSingleActivityOperatorDescriptor;
+import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryOutputSourceOperatorNodePushable;
+
+public class DataGenOperatorDescriptor extends AbstractSingleActivityOperatorDescriptor{
+	
+	private static final long serialVersionUID = 1L;
+	private final int numRecords;
+			
+	private final int intMinVal;
+	private final int intMaxVal;
+	private final int maxStrLen;
+	private final int uniqueField;
+	private final long randomSeed;
+	
+	public DataGenOperatorDescriptor(JobSpecification spec, RecordDescriptor outputRecord, int numRecords, int uniqueField, int intMinVal, int intMaxVal, int maxStrLen, long randomSeed) {
+		super(spec, 0, 1);
+		this.numRecords = numRecords;		
+		this.uniqueField = uniqueField;
+		this.intMinVal = intMinVal;
+		this.intMaxVal = intMaxVal;
+		this.maxStrLen = maxStrLen;		
+		this.randomSeed = randomSeed;
+		recordDescriptors[0] = outputRecord;
+	}
+	
+	@Override
+	public IOperatorNodePushable createPushRuntime(IHyracksContext ctx,
+			IOperatorEnvironment env,
+			IRecordDescriptorProvider recordDescProvider, int partition,
+			int nPartitions) {
+		
+		final ByteBuffer outputFrame = ctx.getResourceManager().allocateFrame();
+		final FrameTupleAppender appender = new FrameTupleAppender(ctx);
+		final RecordDescriptor recDesc = recordDescriptors[0];
+		final ArrayTupleBuilder tb = new ArrayTupleBuilder(recDesc.getFields().length);
+		final Random rnd = new Random(randomSeed);		
+		final int maxUniqueAttempts = 20;
+		
+		return new AbstractUnaryOutputSourceOperatorNodePushable() {
+			
+			// for quick & dirty exclusion of duplicates
+			// WARNING: could contain numRecord entries and use a lot of memory
+			HashSet<String> stringHs = new HashSet<String>();
+			HashSet<Integer> intHs = new HashSet<Integer>();
+						
+			@Override
+            public void initialize() throws HyracksDataException {				
+				writer.open();
+				try {
+					appender.reset(outputFrame, true);
+					for(int i = 0; i < numRecords; i++) {
+						tb.reset();
+						for(int j = 0; j < recDesc.getFields().length; j++) {
+							genField(tb, j);                		
+						}                	
+
+						if (!appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize())) {
+							FrameUtils.flushFrame(outputFrame, writer);
+							appender.reset(outputFrame, true);
+							if (!appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize())) {
+								throw new IllegalStateException();
+							}
+						}
+					}
+					FrameUtils.flushFrame(outputFrame, writer);
+				}
+				finally {                
+					writer.close();
+				}
+            }
+			
+			private void genField(ArrayTupleBuilder tb, int fieldIndex) throws HyracksDataException {
+				DataOutput dos = tb.getDataOutput();
+				if(recDesc.getFields()[fieldIndex] instanceof IntegerSerializerDeserializer) {
+					int val = -1;
+					if(fieldIndex == uniqueField) {
+						int attempt = 0;
+						while(attempt < maxUniqueAttempts) {
+							int tmp = Math.abs(rnd.nextInt()) % (intMaxVal - intMinVal) + intMinVal;
+							if(intHs.contains(tmp)) attempt++;
+							else {
+								val = tmp;
+								intHs.add(val);
+								break;
+							}
+						}
+						if(attempt == maxUniqueAttempts) throw new HyracksDataException("MaxUnique attempts reached in datagen");
+					}
+					else {
+						val = Math.abs(rnd.nextInt()) % (intMaxVal - intMinVal) + intMinVal;						
+					}
+					recDesc.getFields()[fieldIndex].serialize(val, dos);
+					tb.addFieldEndOffset();
+				} else if (recDesc.getFields()[fieldIndex] instanceof UTF8StringSerializerDeserializer) {										
+					String val = null;
+					if(fieldIndex == uniqueField) {
+						int attempt = 0;
+						while(attempt < maxUniqueAttempts) {
+							String tmp = randomString(maxStrLen, rnd);
+							if(stringHs.contains(tmp)) attempt++;
+							else {
+								val = tmp;
+								stringHs.add(val);
+								break;
+							}
+						}
+						if(attempt == maxUniqueAttempts) throw new HyracksDataException("MaxUnique attempts reached in datagen");
+					}
+					else {
+						val = randomString(maxStrLen, rnd);
+					}
+					recDesc.getFields()[fieldIndex].serialize(val, dos);
+					tb.addFieldEndOffset();
+				} else {
+					throw new HyracksDataException("Type unsupported in data generator. Only integers and strings allowed");
+				}				
+			}
+			
+			private String randomString(int length, Random random) {
+		        String s = Long.toHexString(Double.doubleToLongBits(random.nextDouble()));
+		        StringBuilder strBuilder = new StringBuilder();
+		        for (int i = 0; i < s.length() && i < length; i++) {
+		            strBuilder.append(s.charAt(Math.abs(random.nextInt()) % s.length()));
+		        }
+		        return strBuilder.toString();
+		    }    
+		};
+	}	
+}
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/FileMappingProvider.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/FileMappingProvider.java
new file mode 100644
index 0000000..c63be46
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/FileMappingProvider.java
@@ -0,0 +1,36 @@
+package edu.uci.ics.hyracks.examples.btree.helper;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import edu.uci.ics.hyracks.storage.common.file.IFileMappingProvider;
+
+public class FileMappingProvider implements IFileMappingProvider {				
+	
+	private static final long serialVersionUID = 1L;
+	private int nextFileId = 0;
+	private Map<String, Integer> map = new Hashtable<String, Integer>();
+		
+	@Override
+	public Integer mapNameToFileId(String name, boolean create) {
+		Integer val = map.get(name);						
+		if(create) {
+			if(val == null) {
+				int ret = nextFileId;
+				map.put(name, nextFileId++);
+				return ret;
+			}
+			else {
+				return null; // create requested but value already exists				
+			}
+		}
+		else {
+			return val; // just return value
+		}			
+	}
+	
+	@Override
+	public void unmapName(String name) {
+		map.remove(name);
+	}
+}
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/FileMappingProviderProvider.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/FileMappingProviderProvider.java
new file mode 100644
index 0000000..4f2c8f4
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/FileMappingProviderProvider.java
@@ -0,0 +1,15 @@
+package edu.uci.ics.hyracks.examples.btree.helper;
+
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.IFileMappingProviderProvider;
+import edu.uci.ics.hyracks.storage.common.file.IFileMappingProvider;
+
+public class FileMappingProviderProvider implements IFileMappingProviderProvider {
+	private static final long serialVersionUID = 1L;
+	
+	public static final IFileMappingProviderProvider INSTANCE = new FileMappingProviderProvider();
+	
+	@Override
+	public IFileMappingProvider getFileMappingProvider() {
+		return RuntimeContext.getInstance().getFileMappingProvider();
+	}
+}
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/NCBootstrap.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/NCBootstrap.java
new file mode 100644
index 0000000..4be1349
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/NCBootstrap.java
@@ -0,0 +1,30 @@
+package edu.uci.ics.hyracks.examples.btree.helper;
+
+import java.util.logging.Logger;
+
+import edu.uci.ics.hyracks.api.application.IApplicationContext;
+import edu.uci.ics.hyracks.api.application.IBootstrap;
+
+public class NCBootstrap implements IBootstrap {
+    private static final Logger LOGGER = Logger.getLogger(NCBootstrap.class.getName());
+
+    private IApplicationContext appCtx;
+    
+    @Override
+    public void start() throws Exception {
+        LOGGER.info("Starting NC Bootstrap");
+        RuntimeContext.initialize();
+        LOGGER.info("Initialized RuntimeContext: " + RuntimeContext.getInstance());
+    }
+
+    @Override
+    public void stop() throws Exception {
+        LOGGER.info("Stopping Asterix NC Bootstrap");
+        RuntimeContext.deinitialize();
+    }
+
+    @Override
+    public void setApplicationContext(IApplicationContext appCtx) {
+        this.appCtx = appCtx;
+    }
+}
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/RuntimeContext.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/RuntimeContext.java
new file mode 100644
index 0000000..d542ed9
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/RuntimeContext.java
@@ -0,0 +1,70 @@
+package edu.uci.ics.hyracks.examples.btree.helper;
+
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.BTreeRegistry;
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.FileMappingProvider;
+import edu.uci.ics.hyracks.storage.common.buffercache.BufferCache;
+import edu.uci.ics.hyracks.storage.common.buffercache.ClockPageReplacementStrategy;
+import edu.uci.ics.hyracks.storage.common.buffercache.HeapBufferAllocator;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.file.FileManager;
+import edu.uci.ics.hyracks.storage.common.file.IFileMappingProvider;
+
+public class RuntimeContext {
+    private static RuntimeContext INSTANCE;
+
+    private FileManager fileManager;
+    private IBufferCache bufferCache;
+    private BTreeRegistry btreeRegistry;
+    private IFileMappingProvider fileMappingProvider;
+    
+    private RuntimeContext() {
+    }
+    
+    public static void initialize() {
+        if (INSTANCE != null) {
+            throw new IllegalStateException("Instance already initialized");
+        }
+        INSTANCE = new RuntimeContext();
+        INSTANCE.start();
+    }
+
+    public static void deinitialize() {
+        if (INSTANCE != null) {
+            INSTANCE.stop();
+            INSTANCE = null;
+        }
+    }
+
+    private void stop() {
+        bufferCache.close();
+        fileManager.close();
+    }
+
+    private void start() {
+        fileManager = new FileManager();
+        bufferCache = new BufferCache(new HeapBufferAllocator(), new ClockPageReplacementStrategy(), fileManager,
+                32768, 1024);
+        btreeRegistry = new BTreeRegistry();
+        fileMappingProvider = new FileMappingProvider();
+    }
+
+    public static RuntimeContext getInstance() {
+        return INSTANCE;
+    }
+
+    public IBufferCache getBufferCache() {
+        return bufferCache;
+    }
+
+    public FileManager getFileManager() {
+        return fileManager;
+    }
+
+    public BTreeRegistry getBTreeRegistry() {
+        return btreeRegistry;
+    }
+    
+    public IFileMappingProvider getFileMappingProvider() {
+    	return fileMappingProvider;
+    }
+}
\ No newline at end of file
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/resources/hyracks-deployment.properties b/hyracks-examples/btree-example/btreehelper/src/main/resources/hyracks-deployment.properties
new file mode 100644
index 0000000..ab0ecb3
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/resources/hyracks-deployment.properties
@@ -0,0 +1 @@
+nc.bootstrap.class=edu.uci.ics.hyracks.examples.btree.helper.NCBootstrap
\ No newline at end of file