diff --git a/.gitignore b/.gitignore
index 88f7bb1..86be6a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@
 repo
 logback.*.xml
 
+/.m2/
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index ce582d0..c1fa36b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -312,6 +312,21 @@
       <version>2.4.0</version>
     </dependency>
     <dependency>
+        <groupId>com.tinkerpop.rexster</groupId>
+        <artifactId>rexster-core</artifactId>
+        <version>2.4.0</version>
+    </dependency>
+    <dependency>
+        <groupId>com.tinkerpop.blueprints</groupId>
+        <artifactId>blueprints-test</artifactId>
+        <version>2.4.0</version>
+    </dependency>
+    <dependency>
+        <groupId>com.google.protobuf</groupId>
+        <artifactId>protobuf-java</artifactId>
+        <version>2.5.0</version>
+    </dependency>
+    <dependency>
       <groupId>com.hazelcast</groupId>
       <artifactId>hazelcast</artifactId>
       <version>3.0.2</version>
@@ -476,11 +491,11 @@
       <artifactId>packetstreamer-thrift</artifactId>
       <version>0.1.0</version>
     </dependency>
-    -->
     <dependency>
       <groupId>com.tinkerpop.blueprints.impls.ramcloud</groupId>
       <artifactId>blueprints-ramcloud-graph</artifactId>
       <version>2.5.0</version>
     </dependency>
+    -->
   </dependencies>
 </project>
diff --git a/src/apps/java/com/tinkerpop/blueprints/impls/ramcloud/FurnaceExamples.java b/src/apps/java/com/tinkerpop/blueprints/impls/ramcloud/FurnaceExamples.java
new file mode 100644
index 0000000..66cf8ea
--- /dev/null
+++ b/src/apps/java/com/tinkerpop/blueprints/impls/ramcloud/FurnaceExamples.java
@@ -0,0 +1,57 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.util.logging.Level;
+
+import com.tinkerpop.blueprints.Graph;
+import com.tinkerpop.furnace.generators.CommunityGenerator;
+import com.tinkerpop.furnace.generators.DistributionGenerator;
+import com.tinkerpop.furnace.generators.NormalDistribution;
+
+public class FurnaceExamples {
+
+  public FurnaceExamples() {
+    // TODO Auto-generated constructor stub
+  }
+
+  public static int generateCommunityGraph(Graph graph, String label) {
+    CommunityGenerator cg = new CommunityGenerator(label);
+    int numEdges;
+    
+    for(int i = 0; i<30; i++) {
+      graph.addVertex(null);
+    }
+    
+    cg.setCommunityDistribution(new NormalDistribution(2.0));
+    cg.setDegreeDistribution(new NormalDistribution(2.0));
+    numEdges = cg.generate(graph, 3, 60);
+    
+    return numEdges;
+  }
+  
+  public static int generateDistributionGraph(Graph graph, String label) {
+    DistributionGenerator dg = new DistributionGenerator(label);
+    int numEdges;
+    
+    for(int i = 0; i<10; i++) {
+      graph.addVertex(null);
+    }
+    
+    dg.setAllowLoops(true);
+    dg.setInDistribution(new NormalDistribution(2.0));
+    dg.setOutDistribution(new NormalDistribution(2.0));
+    numEdges = dg.generate(graph, 20);
+    
+    return numEdges;
+  }
+  
+  public static void main(String[] args) {
+    Graph graph = new RamCloudGraph(Level.FINER);
+    
+    //generateCommunityGraph(graph, "HippieCommune");
+    
+    //generateDistributionGraph(graph, "HippieRefuge");
+    
+    graph.shutdown();
+  }
+
+}
diff --git a/src/apps/java/com/tinkerpop/blueprints/impls/ramcloud/JUNGExamples.java b/src/apps/java/com/tinkerpop/blueprints/impls/ramcloud/JUNGExamples.java
new file mode 100644
index 0000000..86631b1
--- /dev/null
+++ b/src/apps/java/com/tinkerpop/blueprints/impls/ramcloud/JUNGExamples.java
@@ -0,0 +1,89 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.awt.Dimension;
+import java.util.logging.Level;
+
+import javax.swing.JFrame;
+
+import org.apache.commons.collections15.Transformer;
+
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Graph;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.oupls.jung.GraphJung;
+
+import edu.uci.ics.jung.algorithms.layout.BalloonLayout;
+import edu.uci.ics.jung.algorithms.layout.CircleLayout;
+import edu.uci.ics.jung.algorithms.layout.DAGLayout;
+import edu.uci.ics.jung.algorithms.layout.FRLayout;
+import edu.uci.ics.jung.algorithms.layout.FRLayout2;
+import edu.uci.ics.jung.algorithms.layout.ISOMLayout;
+import edu.uci.ics.jung.algorithms.layout.KKLayout;
+import edu.uci.ics.jung.algorithms.layout.Layout;
+import edu.uci.ics.jung.algorithms.scoring.PageRank;
+import edu.uci.ics.jung.visualization.BasicVisualizationServer;
+
+public class JUNGExamples {
+
+  public JUNGExamples() {
+    // TODO Auto-generated constructor stub
+  }
+  
+  public static void calculatePageRank(Graph graph) {
+    PageRank<Vertex,Edge> pageRank = new PageRank<Vertex, Edge>(new GraphJung(graph), 0.15d);
+    pageRank.evaluate();
+    
+    for (Vertex vertex : graph.getVertices()) {
+      System.out.println("The PageRank score of " + vertex + " is: " + pageRank.getVertexScore(vertex));
+    }
+  }
+
+  public static void displayGraph(Graph graph) {
+    GraphJung gj = new GraphJung(graph);
+    
+    Layout<Vertex, Edge> layout = new CircleLayout<Vertex, Edge>(gj);
+    layout.setSize(new Dimension(600, 600));
+    BasicVisualizationServer<Vertex, Edge> viz = new BasicVisualizationServer<Vertex, Edge>(layout);
+    viz.setPreferredSize(new Dimension(650, 650));
+
+    Transformer<Vertex, String> vertexLabelTransformer = new Transformer<Vertex, String>() {
+      public String transform(Vertex vertex) {
+        return (String) vertex.getProperty("name");
+      }
+    };
+
+    Transformer<Edge, String> edgeLabelTransformer = new Transformer<Edge, String>() {
+      public String transform(Edge edge) {
+        return edge.getLabel();
+      }
+    };
+
+    viz.getRenderContext().setEdgeLabelTransformer(edgeLabelTransformer);
+    viz.getRenderContext().setVertexLabelTransformer(vertexLabelTransformer);
+
+    JFrame frame = new JFrame("TinkerPop");
+    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+    frame.getContentPane().add(viz);
+    frame.pack();
+    frame.setVisible(true);
+    
+    try {
+      System.in.read();
+    } catch(Exception e) {
+      // poop
+    }
+  }
+  
+  public static void main(String[] args) {
+    Graph graph = new RamCloudGraph(Level.FINER);
+    
+    FurnaceExamples.generateDistributionGraph(graph, "ex");
+    
+    //calculatePageRank(graph);
+    
+    displayGraph(graph);
+    
+    graph.shutdown();
+  }
+
+}
diff --git a/src/main/cpp/edu_stanford_ramcloud_JRamCloud.cc b/src/main/cpp/edu_stanford_ramcloud_JRamCloud.cc
new file mode 100755
index 0000000..fc93cb4
--- /dev/null
+++ b/src/main/cpp/edu_stanford_ramcloud_JRamCloud.cc
@@ -0,0 +1,766 @@
+/* Copyright (c) 2013 Stanford University
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <RamCloud.h>
+#include <TableEnumerator.h>
+#include <Object.h>
+#include "edu_stanford_ramcloud_JRamCloud.h"
+#include "edu_stanford_ramcloud_JRamCloud_TableEnumerator.h"
+
+using namespace RAMCloud;
+
+/// Our JRamCloud java library is packaged under "edu.stanford.ramcloud".
+/// We will need this when using FindClass, etc.
+#define PACKAGE_PATH "edu/stanford/ramcloud/"
+
+#define check_null(var, msg)                                                \
+    if (var == NULL) {                                                      \
+        throw Exception(HERE, "JRamCloud: NULL returned: " msg "\n");       \
+    }
+
+/**
+ * This class provides a simple means of extracting C-style strings
+ * from a jstring and cleans up when the destructor is called. This
+ * avoids having to manually do the annoying GetStringUTFChars /
+ * ReleaseStringUTFChars dance. 
+ */
+class JStringGetter {
+  public:
+    JStringGetter(JNIEnv* env, jstring jString)
+        : env(env)
+        , jString(jString)
+        , string(env->GetStringUTFChars(jString, 0))
+    {
+        check_null(string, "GetStringUTFChars failed");
+    }
+    
+    ~JStringGetter()
+    {
+        if (string != NULL)
+            env->ReleaseStringUTFChars(jString, string);
+    }
+
+  private:    
+    JNIEnv* env;
+    jstring jString;
+
+  public:
+    const char* const string;
+};
+
+/**
+ * This class provides a simple means of accessing jbyteArrays as
+ * C-style void* buffers and cleans up when the destructor is called.
+ * This avoids having to manually do the annoying GetByteArrayElements /
+ * ReleaseByteArrayElements dance.
+ */
+class JByteArrayGetter {
+  public:
+    JByteArrayGetter(JNIEnv* env, jbyteArray jByteArray)
+        : env(env)
+        , jByteArray(jByteArray)
+        , pointer(static_cast<void*>(env->GetByteArrayElements(jByteArray, 0)))
+        , length(env->GetArrayLength(jByteArray))
+    {
+        check_null(pointer, "GetByteArrayElements failed");
+    }
+    
+    ~JByteArrayGetter()
+    {
+        if (pointer != NULL) {
+            env->ReleaseByteArrayElements(jByteArray,
+                                          reinterpret_cast<jbyte*>(pointer),
+                                          0);
+        }
+    }
+
+  private:    
+    JNIEnv* env;
+    jbyteArray jByteArray;
+
+  public:
+    void* const pointer;
+    const jsize length;
+};
+
+class JByteArrayReference {
+  public:
+    JByteArrayReference(JNIEnv* env, jbyteArray jByteArray)
+        : env(env)
+        , jByteArray(jByteArray)
+        , pointer(static_cast<const void*>(env->GetByteArrayElements(jByteArray, 0)))
+        , length(env->GetArrayLength(jByteArray))
+    {
+        check_null(pointer, "GetByteArrayElements failed");
+    }
+
+    ~JByteArrayReference()
+    {
+        if (pointer != NULL) {
+            env->ReleaseByteArrayElements(jByteArray,
+                                          (jbyte*)pointer,
+                                          JNI_ABORT);
+        }
+    }
+
+  private:
+    JNIEnv* env;
+    jbyteArray jByteArray;
+
+  public:
+    const void* const pointer;
+    const jsize length;
+};
+
+static RamCloud*
+getRamCloud(JNIEnv* env, jobject jRamCloud)
+{
+    const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud"));
+    const static jfieldID fieldId = env->GetFieldID(cls, "ramcloudObjectPointer", "J");
+    return reinterpret_cast<RamCloud*>(env->GetLongField(jRamCloud, fieldId));
+}
+
+static TableEnumerator*
+getTableEnumerator(JNIEnv* env, jobject jTableEnumerator)
+{
+    const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$TableEnumerator"));
+    const static jfieldID fieldId = env->GetFieldID(cls, "tableEnumeratorObjectPointer", "J");
+    return reinterpret_cast<TableEnumerator*>(env->GetLongField(jTableEnumerator, fieldId));    
+}
+
+static void
+createException(JNIEnv* env, jobject jRamCloud, const char* name)
+{
+    // Need to specify the full class name, including the package. To make it
+    // slightly more complicated, our exceptions are nested under the JRamCloud
+    // class.
+    string fullName = PACKAGE_PATH;
+    fullName += "JRamCloud$";
+    fullName += name;
+
+    // This would be much easier if we didn't make our Exception classes nested
+    // under JRamCloud since env->ThrowNew() could be used instead. The problem
+    // is that ThrowNew assumes a particular method signature that happens to
+    // be incompatible with the nested classes' signatures.
+    jclass cls = env->FindClass(fullName.c_str());
+    check_null(cls, "FindClass failed");
+
+    jmethodID methodId = env->GetMethodID(cls,
+                                          "<init>",
+                                          "(L" PACKAGE_PATH "JRamCloud;Ljava/lang/String;)V");
+    check_null(methodId, "GetMethodID failed");
+
+    jstring jString = env->NewStringUTF("");
+    check_null(jString, "NewStringUTF failed");
+
+    jthrowable exception = reinterpret_cast<jthrowable>(
+        env->NewObject(cls, methodId, jRamCloud, jString));
+    check_null(exception, "NewObject failed");
+
+    env->Throw(exception);
+}
+
+/**
+ * This macro is used to catch C++ exceptions and convert them into Java
+ * exceptions. Be sure to wrap the individual RamCloud:: calls in try blocks,
+ * rather than the entire methods, since doing so with functions that return
+ * non-void is a bad idea with undefined(?) behaviour. 
+ *
+ * _returnValue is the value that should be returned from the JNI function
+ * when an exception is caught and generated in Java. As far as I can tell,
+ * the exception fires immediately upon returning from the JNI method. I
+ * don't think anything else would make sense, but the JNI docs kind of
+ * suck.
+ */
+#define EXCEPTION_CATCHER(_returnValue)                                        \
+    catch (TableDoesntExistException& e) {                                     \
+        createException(env, jRamCloud, "TableDoesntExistException");          \
+        return _returnValue;                                                   \
+    } catch (ObjectDoesntExistException& e) {                                  \
+        createException(env, jRamCloud, "ObjectDoesntExistException");         \
+        return _returnValue;                                                   \
+    } catch (ObjectExistsException& e) {                                       \
+        createException(env, jRamCloud, "ObjectExistsException");              \
+        return _returnValue;                                                   \
+    } catch (WrongVersionException& e) {                                       \
+        createException(env, jRamCloud, "WrongVersionException");              \
+        return _returnValue;                                                   \
+    } catch (RejectRulesException& e) {                                        \
+        createException(env, jRamCloud, "RejectRulesException");               \
+        return _returnValue;                                                   \
+    } catch (InvalidObjectException& e) {                                      \
+        createException(env, jRamCloud, "InvalidObjectException");             \
+        return _returnValue;                                                   \
+    }
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    connect
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong 
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_connect(JNIEnv *env,
+                               jclass jRamCloud,
+                               jstring coordinatorLocator)
+{
+    JStringGetter locator(env, coordinatorLocator);
+    RamCloud* ramcloud = NULL;
+    try {
+        ramcloud = new RamCloud(locator.string);
+    } EXCEPTION_CATCHER(NULL);
+    return reinterpret_cast<jlong>(ramcloud);
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    disconnect
+ * Signature: (J)V
+ */
+JNIEXPORT void
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_disconnect(JNIEnv *env,
+                                  jclass jRamCloud,
+                                  jlong ramcloudObjectPointer)
+{
+    delete reinterpret_cast<RamCloud*>(ramcloudObjectPointer);
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    createTable
+ * Signature: (Ljava/lang/String;)I
+ */
+JNIEXPORT jlong
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_createTable__Ljava_lang_String_2(JNIEnv *env,
+                                                        jobject jRamCloud,
+                                                        jstring jTableName)
+{
+    return Java_edu_stanford_ramcloud_JRamCloud_createTable__Ljava_lang_String_2I(env,
+                                                            jRamCloud,
+                                                            jTableName,
+                                                            1);
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    createTable
+ * Signature: (Ljava/lang/String;I)I
+ */
+JNIEXPORT jlong
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_createTable__Ljava_lang_String_2I(JNIEnv *env,
+                                                         jobject jRamCloud,
+                                                         jstring jTableName,
+                                                         jint jServerSpan)
+{
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JStringGetter tableName(env, jTableName);
+    uint64_t tableId;
+    try {
+        tableId = ramcloud->createTable(tableName.string, jServerSpan);
+    } EXCEPTION_CATCHER(-1);
+    return static_cast<jlong>(tableId);
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    dropTable
+ * Signature: (Ljava/lang/String;)I
+ */
+JNIEXPORT void
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_dropTable(JNIEnv *env,
+                                 jobject jRamCloud,
+                                 jstring jTableName)
+{
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JStringGetter tableName(env, jTableName);
+    try {
+        ramcloud->dropTable(tableName.string);
+    } EXCEPTION_CATCHER();
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    getTableId
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_getTableId(JNIEnv *env,
+                                  jobject jRamCloud,
+                                  jstring jTableName)
+{
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JStringGetter tableName(env, jTableName);
+    uint64_t tableId;
+    try {
+        tableId = ramcloud->getTableId(tableName.string);
+    } EXCEPTION_CATCHER(-1);
+    return tableId;
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    read
+ * Signature: (J[B)LJRamCloud/Object;
+ */
+JNIEXPORT jobject
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_read__J_3B(JNIEnv *env,
+                                  jobject jRamCloud,
+                                  jlong jTableId,
+                                  jbyteArray jKey)
+{
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JByteArrayReference key(env, jKey);
+
+    Buffer buffer;
+    uint64_t version;
+    try {
+        ramcloud->read(jTableId, key.pointer, key.length, &buffer, NULL, &version);
+    } EXCEPTION_CATCHER(NULL);
+
+    jbyteArray jValue = env->NewByteArray(buffer.getTotalLength());
+    check_null(jValue, "NewByteArray failed");
+    JByteArrayGetter value(env, jValue);
+    buffer.copy(0, buffer.getTotalLength(), value.pointer);
+
+    // Note that using 'javap -s' on the class file will print out the method
+    // signatures (the third argument to GetMethodID).
+    const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$Object"));
+    check_null(cls, "FindClass failed");
+
+    const static jmethodID methodId = env->GetMethodID(cls,
+                                          "<init>",
+                                          "(L" PACKAGE_PATH "JRamCloud;[B[BJ)V");
+    check_null(methodId, "GetMethodID failed");
+
+    return env->NewObject(cls,
+                          methodId,
+                          jRamCloud,
+                          jKey,
+                          jValue,
+                          static_cast<jlong>(version));
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    read
+ * Signature: (J[BLJRamCloud/RejectRules;)LJRamCloud/Object;
+ */
+JNIEXPORT jobject
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_read__J_3BLJRamCloud_RejectRules_2(JNIEnv *env,
+                                                          jobject jRamCloud,
+                                                          jlong jTableId,
+                                                          jbyteArray jKey,
+                                                          jobject jRejectRules)
+{
+    // XXX-- implement me by generalising the other read() method.
+    return NULL;
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    multiRead
+ * Signature: ([Ledu/stanford/ramcloud/JRamCloud$multiReadObject;I)[Ledu/stanford/ramcloud/JRamCloud$Object;
+ */
+JNIEXPORT jobjectArray
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_multiRead(JNIEnv *env,   
+                                                        jobject jRamCloud,
+                                                        jobjectArray jmultiReadArray){
+
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    const jint requestNum = env->GetArrayLength(jmultiReadArray);
+    MultiReadObject objects[requestNum];
+    Tub<Buffer> values[requestNum];
+    jbyteArray jKey[requestNum];
+    MultiReadObject* requests[requestNum];
+
+    const static jclass jc_multiReadObject = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$multiReadObject"));
+    const static jfieldID jf_tableId = env->GetFieldID(jc_multiReadObject, "tableId", "J");
+    const static jfieldID jf_key = env->GetFieldID(jc_multiReadObject, "key", "[B");
+
+    for (int i = 0 ; i < requestNum ; i++){
+        jobject obj = env->GetObjectArrayElement(jmultiReadArray, i);
+        check_null(obj, "GetObjectArrayElement failed");
+        jlong jTableId = env->GetLongField(obj, jf_tableId);
+
+        jKey[i] = (jbyteArray)env->GetObjectField(obj, jf_key);
+
+        jbyte* data = env->GetByteArrayElements(jKey[i], NULL);
+        check_null(data, "GetByteArrayElements failed");
+
+        objects[i].tableId = jTableId;
+        objects[i].key = data;
+        objects[i].keyLength = env->GetArrayLength(jKey[i]);
+        objects[i].value = &values[i];
+        requests[i] = &objects[i];
+    }
+
+    try {
+        ramcloud->multiRead(requests, requestNum);
+    } EXCEPTION_CATCHER(NULL);
+    
+    const static jclass jc_RcObject = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$Object"));
+    check_null(jc_RcObject, "FindClass failed");
+    const static jmethodID jm_init = env->GetMethodID(jc_RcObject,
+                                        "<init>",
+                                        "(L" PACKAGE_PATH "JRamCloud;[B[BJ)V");
+
+    jobjectArray outJNIArray = env->NewObjectArray(requestNum, jc_RcObject , NULL);
+    check_null(outJNIArray, "NewObjectArray failed");
+    
+    for (int i = 0 ; i < requestNum ; i++) {
+	if (objects[i].status == 0) {
+	    jbyteArray jValue = env->NewByteArray(values[i].get()->getTotalLength());
+	    check_null(jValue, "NewByteArray failed");
+	    JByteArrayGetter value(env, jValue);
+	    values[i].get()->copy(0, values[i].get()->getTotalLength(), value.pointer);
+	    jobject obj = env->NewObject(jc_RcObject, jm_init, jRamCloud, jKey[i], jValue);
+	    check_null(obj, "NewObject failed");
+	    env->SetObjectArrayElement(outJNIArray, i, obj);
+	}
+	// keys are read only so no need to copy back to Java side: JNI_ABORT
+	env->ReleaseByteArrayElements(jKey[i], (jbyte *) objects[i].key, JNI_ABORT);
+    }
+    return outJNIArray;
+}
+
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    remove
+ * Signature: (J[B)J
+ */
+JNIEXPORT jlong
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_remove__J_3B(JNIEnv *env,
+                                    jobject jRamCloud,
+                                    jlong jTableId,
+                                    jbyteArray jKey)
+{
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JByteArrayReference key(env, jKey);
+    uint64_t version;
+    try {
+        ramcloud->remove(jTableId, key.pointer, key.length, NULL, &version);
+    } EXCEPTION_CATCHER(-1);
+    return static_cast<jlong>(version);
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    remove
+ * Signature: (J[BLJRamCloud/RejectRules;)J
+ */
+JNIEXPORT jlong
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_remove__J_3BLJRamCloud_RejectRules_2(JNIEnv *env,
+                                                           jobject jRamCloud,
+                                                           jlong jTableId,
+                                                           jbyteArray jKey,
+                                                           jobject jRejectRules)
+{
+    // XXX- handle RejectRules
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JByteArrayReference key(env, jKey);
+    uint64_t version;
+    try {
+        ramcloud->remove(jTableId, key.pointer, key.length, NULL, &version);
+    } EXCEPTION_CATCHER(-1);
+    return static_cast<jlong>(version);
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    write
+ * Signature: (J[B[B)J
+ */
+JNIEXPORT jlong
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_write__J_3B_3B(JNIEnv *env,
+                                      jobject jRamCloud,
+                                      jlong jTableId,
+                                      jbyteArray jKey,
+                                      jbyteArray jValue)
+{
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JByteArrayReference key(env, jKey);
+    JByteArrayGetter value(env, jValue);
+    uint64_t version;
+    try {
+        ramcloud->write(jTableId,
+                        key.pointer, key.length,
+                        value.pointer, value.length,
+                        NULL,
+                        &version);
+    } EXCEPTION_CATCHER(-1);
+    return static_cast<jlong>(version);
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    write
+ * Signature: (J[B[BLJRamCloud/RejectRules;)J
+ */
+JNIEXPORT jlong
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_write__J_3B_3BLJRamCloud_RejectRules_2(JNIEnv *env,
+                                                           jobject jRamCloud,
+                                                           jlong jTableId,
+                                                           jbyteArray jKey,
+                                                           jbyteArray jValue,
+                                                           jobject jRejectRules)
+{
+    // XXX- handle RejectRules    
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JByteArrayReference key(env, jKey);
+    JByteArrayGetter value(env, jValue);
+    RejectRules rules;
+    jclass ruleClass = env->GetObjectClass(jRejectRules);
+    jfieldID fid = env->GetFieldID(ruleClass, "doesntExist", "Z");
+    rules.doesntExist = (uint8_t) env->GetBooleanField(jRejectRules, fid);
+
+    fid = env->GetFieldID(ruleClass, "exists", "Z");
+    rules.exists = (uint8_t) env->GetBooleanField(jRejectRules, fid);
+
+    fid = env->GetFieldID(ruleClass, "givenVersion", "J");
+    rules.givenVersion = env->GetLongField(jRejectRules, fid);
+
+    fid = env->GetFieldID(ruleClass, "versionLeGiven", "Z");
+    rules.versionLeGiven = (uint8_t) env->GetBooleanField(jRejectRules, fid);
+
+    fid = env->GetFieldID(ruleClass, "versionNeGiven", "Z");
+    rules.versionNeGiven = (uint8_t) env->GetBooleanField(jRejectRules, fid);
+
+    uint64_t version;
+    try {
+        ramcloud->write(jTableId,
+                key.pointer, key.length,
+                value.pointer, value.length,
+                &rules,
+                &version);
+    }
+    EXCEPTION_CATCHER(-1);
+    return static_cast<jlong> (version);
+}
+
+JNIEXPORT jlong
+JNICALL Java_edu_stanford_ramcloud_JRamCloud_writeRule(JNIEnv *env,
+        jobject jRamCloud,
+        jlong jTableId,
+        jbyteArray jKey,
+        jbyteArray jValue,
+        jobject jRejectRules) {
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    JByteArrayReference key(env, jKey);
+    JByteArrayGetter value(env, jValue);
+    uint64_t version;
+    RejectRules rules = {};
+    const static jclass jc_RejectRules = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$RejectRules"));
+
+    const static jfieldID jf_doesntExist = env->GetFieldID(jc_RejectRules, "doesntExist", "Z");
+    check_null(jf_doesntExist, "doesentExist field id is null");
+    jboolean ruleBool;
+    ruleBool = env->GetBooleanField(jRejectRules, jf_doesntExist);
+    rules.doesntExist = ruleBool ? 1 : 0;
+
+    const static jfieldID jf_exists = env->GetFieldID(jc_RejectRules, "exists", "Z");
+    check_null(jf_exists, "exists field id is null");
+    ruleBool = env->GetBooleanField(jRejectRules, jf_exists);
+    rules.exists = ruleBool ? 1 : 0;
+
+    const static jfieldID jf_givenVersion = env->GetFieldID(jc_RejectRules, "givenVersion", "J");
+    check_null(jf_givenVersion, "givenVersion field id is null");
+    rules.givenVersion = env->GetLongField(jRejectRules, jf_givenVersion);
+
+    const static jfieldID jf_versionLeGiven = env->GetFieldID(jc_RejectRules, "versionLeGiven", "Z");
+    check_null(jf_versionLeGiven, "versionLeGiven field id is null");
+    ruleBool = env->GetBooleanField(jRejectRules, jf_versionLeGiven);
+    rules.versionLeGiven = ruleBool ? 1 : 0;
+
+    const static jfieldID jf_versionNeGiven = env->GetFieldID(jc_RejectRules, "versionNeGiven", "Z");
+    check_null(jf_versionNeGiven, "versionNeGiven field id is null");
+    ruleBool = env->GetBooleanField(jRejectRules, jf_versionNeGiven);
+    rules.versionNeGiven = ruleBool ? 1 : 0;
+    try {
+        ramcloud->write(jTableId,
+                key.pointer, key.length,
+                value.pointer, value.length,
+                &rules,
+                &version);
+    }
+    EXCEPTION_CATCHER(-1);
+    return static_cast<jlong> (version);
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud_TableEnumerator
+ * Method:    init
+ * Signature: (J)V
+ */
+JNIEXPORT jlong JNICALL Java_edu_stanford_ramcloud_JRamCloud_00024TableEnumerator_init(JNIEnv *env, 
+                                                                                      jobject jTableEnumerator, 
+                                                                                      jlong jTableId)
+{
+    const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$TableEnumerator"));
+    const static jfieldID fieldId = env->GetFieldID(cls, "ramCloudObjectPointer", "J");
+    RamCloud* ramcloud = reinterpret_cast<RamCloud*>(env->GetLongField(jTableEnumerator, fieldId));
+  
+    return reinterpret_cast<jlong>(new TableEnumerator(*ramcloud, jTableId));
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud_TableEnumerator
+ * Method:    hasNext
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_edu_stanford_ramcloud_JRamCloud_00024TableEnumerator_hasNext( JNIEnv *env, 
+                                                                                              jobject jTableEnumerator)
+{
+    TableEnumerator* tableEnum = getTableEnumerator(env, jTableEnumerator);
+    return static_cast<jboolean>(tableEnum->hasNext());
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud_TableEnumerator
+ * Method:    next
+ * Signature: ()Ledu/stanford/ramcloud/JRamCloud/Object;
+ */
+JNIEXPORT jobject JNICALL Java_edu_stanford_ramcloud_JRamCloud_00024TableEnumerator_next( JNIEnv *env, 
+                                                                                          jobject jTableEnumerator)
+{
+    TableEnumerator* tableEnum = getTableEnumerator(env, jTableEnumerator);
+
+    if(tableEnum->hasNext()) 
+    {
+        uint32_t size = 0;
+        const void* buffer = 0;
+        uint64_t version = 0;
+
+        tableEnum->next(&size, &buffer);
+        Object object(buffer, size);
+
+        jbyteArray jKey = env->NewByteArray(object.getKeyLength());
+        jbyteArray jValue = env->NewByteArray(object.getDataLength());
+        
+        JByteArrayGetter key(env, jKey);
+        JByteArrayGetter value(env, jValue);
+
+        memcpy(key.pointer, object.getKey(), object.getKeyLength());
+        memcpy(value.pointer, object.getData(), object.getDataLength());
+
+        version = object.getVersion();
+        
+        const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$Object"));
+        check_null(cls, "FindClass failed");
+        const static jmethodID methodId = env->GetMethodID(cls,
+                                          "<init>",
+                                          "(L" PACKAGE_PATH "JRamCloud;[B[BJ)V");
+        check_null(methodId, "GetMethodID failed");
+        return env->NewObject(cls,
+                              methodId,
+                              jTableEnumerator,
+                              jKey,
+                              jValue,
+                              static_cast<jlong>(version));        
+    } else 
+        return NULL;
+}
+
+/*
+ * Class:     edu_stanford_ramcloud_JRamCloud
+ * Method:    multiWrite
+ * Signature: ([Ledu/stanford/ramcloud/JRamCloud/MultiWriteObject;)[Ledu/stanford/ramcloud/JRamCloud/MultiWriteRspObject;
+ */
+JNIEXPORT jobjectArray JNICALL Java_edu_stanford_ramcloud_JRamCloud_multiWrite(JNIEnv *env, jobject jRamCloud, jobjectArray jmultiWriteArray) {
+    jint requestNum = env->GetArrayLength(jmultiWriteArray);
+    RamCloud* ramcloud = getRamCloud(env, jRamCloud);
+    Tub<MultiWriteObject> objects[requestNum];
+    MultiWriteObject *requests[requestNum];
+    RejectRules rules[requestNum];
+    jbyteArray jKey[requestNum];
+    jbyteArray jValue[requestNum];
+    
+    const static jclass jc_multiWriteObject = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$MultiWriteObject"));
+    const static jclass jc_RejectRules = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$RejectRules"));
+    const static jfieldID jf_tableId = env->GetFieldID(jc_multiWriteObject, "tableId", "J");
+    const static jfieldID jf_key = env->GetFieldID(jc_multiWriteObject, "key", "[B");
+    const static jfieldID jf_value = env->GetFieldID(jc_multiWriteObject, "value", "[B");
+    const static jfieldID jf_reject_rules = env->GetFieldID(jc_multiWriteObject, "rules", "L" PACKAGE_PATH "JRamCloud$RejectRules;");
+
+    const static jfieldID jf_doesntExist = env->GetFieldID(jc_RejectRules, "doesntExist", "Z");
+    check_null(jf_doesntExist, "doesentExist field id is null");
+    const static jfieldID jf_exists = env->GetFieldID(jc_RejectRules, "exists", "Z");
+    check_null(jf_exists, "exists field id is null");
+    const static jfieldID jf_givenVersion = env->GetFieldID(jc_RejectRules, "givenVersion", "J");
+    check_null(jf_givenVersion, "givenVersion field id is null");
+    const static jfieldID jf_versionLeGiven = env->GetFieldID(jc_RejectRules, "versionLeGiven", "Z");
+    check_null(jf_versionLeGiven, "versionLeGiven field id is null");
+    const static jfieldID jf_versionNeGiven = env->GetFieldID(jc_RejectRules, "versionNeGiven", "Z");
+    check_null(jf_versionNeGiven, "versionNeGiven field id is null");
+
+    for (int i = 0; i < requestNum; i++) {
+        jobject obj = env->GetObjectArrayElement(jmultiWriteArray, i);
+        check_null(obj, "multi write GetObjectArrayElement failed");
+
+        uint64_t tableId = env->GetLongField(obj, jf_tableId);
+
+        jKey[i] = (jbyteArray)env->GetObjectField(obj, jf_key);
+        jbyte* keyData = env->GetByteArrayElements(jKey[i], NULL);
+        uint16_t keyLength = env->GetArrayLength(jKey[i]);
+
+        jValue[i] = (jbyteArray)env->GetObjectField(obj, jf_value);
+        jbyte* valueData = env->GetByteArrayElements(jValue[i], NULL);
+        uint32_t valueLength = env->GetArrayLength(jValue[i]);
+
+        jobject jRejectRules = env->GetObjectField(obj, jf_reject_rules);
+        rules[i] = {};
+
+        if (jRejectRules != NULL) {
+            jboolean ruleBool;
+
+            ruleBool = env->GetBooleanField(jRejectRules, jf_doesntExist);
+            rules[i].doesntExist = ruleBool ? 1 : 0;
+
+            ruleBool = env->GetBooleanField(jRejectRules, jf_exists);
+            rules[i].exists = ruleBool ? 1 : 0;
+
+            rules[i].givenVersion = env->GetLongField(jRejectRules, jf_givenVersion);
+
+            ruleBool = env->GetBooleanField(jRejectRules, jf_versionLeGiven);
+            rules[i].versionLeGiven = ruleBool ? 1 : 0;
+
+            ruleBool = env->GetBooleanField(jRejectRules, jf_versionNeGiven);
+            rules[i].versionNeGiven = ruleBool ? 1 : 0;
+        }
+        objects[i].construct(tableId, keyData, keyLength, valueData, valueLength, &rules[i]);
+        requests[i] = objects[i].get();
+    }
+    try {
+        ramcloud->multiWrite(requests, requestNum);
+    } EXCEPTION_CATCHER(NULL);
+ 
+    const static jclass jc_RcObject = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$MultiWriteRspObject"));
+    check_null(jc_RcObject, "FindClass failed");
+    const static jmethodID jm_init = env->GetMethodID(jc_RcObject,
+                                        "<init>",
+                                        "(L" PACKAGE_PATH "JRamCloud;IJ)V");
+
+    jobjectArray outJNIArray = env->NewObjectArray(requestNum, jc_RcObject , NULL);
+    check_null(outJNIArray, "NewObjectArray failed");
+    
+    for (int i = 0 ; i < requestNum ; i++) {
+        jobject obj = env->NewObject(jc_RcObject, jm_init, jRamCloud, objects[i]->status, objects[i]->version);
+        check_null(obj, "NewObject failed");
+        env->SetObjectArrayElement(outJNIArray, i, obj);
+        env->ReleaseByteArrayElements(jKey[i], (jbyte *)requests[i]->key, JNI_ABORT);
+        env->ReleaseByteArrayElements(jValue[i], (jbyte *)requests[i]->value, JNI_ABORT);
+        objects[i].destroy();
+    }
+    return outJNIArray;
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/PerfMon.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/PerfMon.java
new file mode 100644
index 0000000..158a3c8
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/PerfMon.java
@@ -0,0 +1,747 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// Singleton class
+public final class PerfMon {
+    private static final ThreadLocal<PerfMon> instance = new ThreadLocal<PerfMon>() {
+	@Override
+	protected PerfMon initialValue() {
+	    return new PerfMon();
+	}
+    };
+
+   public final long measureAllTimeProp = Long.valueOf(System.getProperty("benchmark.measureAll", "0"));
+   private final static Logger log = LoggerFactory.getLogger(PerfMon.class);
+
+   private static final int debug = 0;
+
+   private long read_latency_sum;
+   private long read_latency_cnt;
+   private int read_flag;
+
+   private long multiread_latency_sum;
+   private long multiread_latency_cnt;
+   private int multiread_flag;
+
+   private long multiwrite_latency_sum;
+   private long multiwrite_latency_cnt;
+   private int multiwrite_flag;
+
+   private long indexread_latency_sum;
+   private long indexread_latency_cnt;
+   private int indexread_flag;
+
+   private long write_latency_sum;
+   private long write_latency_cnt;
+
+   private int write_flag;
+
+   private long indexwrite_latency_sum;
+   private long indexwrite_latency_cnt;
+   private int indexwrite_flag;
+
+   private long serialize_latency_sum;
+   private long serialize_latency_cnt;
+   private int ser_flag;
+
+   private long indexserialize_latency_sum;
+   private long indexserialize_latency_cnt;
+   private int indexser_flag;
+
+   private long proto_serialize_latency_sum;
+   private long proto_serialize_latency_cnt;
+   private int protoser_flag;
+
+   private long deserialize_latency_sum;
+   private long deserialize_latency_cnt;
+   private int deser_flag;
+
+   private long indexdeserialize_latency_sum;
+   private long indexdeserialize_latency_cnt;
+   private int indexdeser_flag;
+
+   private long proto_deserialize_latency_sum;
+   private long proto_deserialize_latency_cnt;
+   private int protodeser_flag;
+
+   private long addsw_time;
+   private long addport_time;
+   private long addlink_time;
+   private long addport_cnt;
+   private long addflowpath_time;
+   private long addflowentry_time;
+   private long addflowentry_cnt;
+
+   private long ser_time;
+   private long indexser_time;
+   private long protoser_time;
+
+   private long deser_time;
+   private long indexdeser_time;
+   private long protodeser_time;
+
+   private long write_time;
+   private long multiwrite_time;
+   private long write_condfails;
+   private long indexwrite_time;
+   private long indexwrite_condfails;
+   private long read_time;
+   private long multiread_time;
+   private long indexread_time;
+   private long read_whole_topology_time;
+
+   public static PerfMon getInstance() {
+        return instance.get();
+    }
+   private PerfMon(){
+   }
+
+   private void clear(){
+   	read_latency_sum=0L;
+   	read_latency_cnt=0L;
+	multiread_latency_sum=0L;
+   	multiread_latency_cnt=0L;
+	multiwrite_latency_sum=0L;
+   	multiwrite_latency_cnt=0L;
+   	indexread_latency_sum=0L;
+   	indexread_latency_cnt=0L;
+	write_latency_sum=0L;
+   	write_latency_cnt=0L;
+	indexwrite_latency_sum=0L;
+   	indexwrite_latency_cnt=0L;
+   	serialize_latency_sum=0L;
+   	serialize_latency_cnt=0L;
+	indexserialize_latency_sum=0L;
+   	indexserialize_latency_cnt=0L;
+   	deserialize_latency_sum=0L;
+   	deserialize_latency_cnt=0L;
+   	indexdeserialize_latency_sum=0L;
+   	indexdeserialize_latency_cnt=0L;
+	read_flag=multiread_flag=indexread_flag=write_flag=indexwrite_flag=deser_flag=indexdeser_flag=ser_flag=indexser_flag=0;
+	addflowpath_time = addflowentry_time = addflowentry_cnt = 0;
+	write_condfails = indexwrite_condfails = 0;
+	read_whole_topology_time = 0;
+	protoser_time = protodeser_time = 0;
+	proto_deserialize_latency_cnt = proto_deserialize_latency_sum = proto_serialize_latency_cnt = proto_serialize_latency_sum = 0;
+        //log.error("flag cleared");
+   }
+
+   private long getSum(){
+       return read_latency_sum + multiread_latency_sum + indexread_latency_sum + write_latency_sum + indexwrite_latency_sum + serialize_latency_sum + indexserialize_latency_sum + deserialize_latency_sum + indexdeserialize_latency_sum;
+   }
+
+   public void addswitch_start(){
+        if(measureAllTimeProp==0)
+		return;
+
+	clear();
+	addsw_time = System.nanoTime();
+   }
+   public void addswitch_end(){
+        if(measureAllTimeProp==0)
+		return;
+
+        long delta;
+        long sum;
+
+        delta = System.nanoTime() - addsw_time;
+	sum = getSum();
+        log.error("Performance add_switch {}"
+        	+ " read {} ({})"
+        	+ " multiread {} ({})"
+        	+ " index_read {} ({})"
+        	+ " write {} ({})"
+        	+ " multiwrite {} ({})"
+        	+ " index_write {} ({})"
+        	+ " serialize {} ({})"
+        	+ " indexserialize {} ({})"
+        	+ " proto_serialize {} ({})"
+        	+ " deserialize {} ({})"
+        	+ " indexdeserialize {} ({})"
+        	+ " proto_deserialize {} ({})"
+        	+ " rwsd total {} other {} ({})"
+        	+ " writefail ({}) indexwritefail({})",
+	       delta,
+	       read_latency_sum, read_latency_cnt,
+	       multiread_latency_sum, multiread_latency_cnt,
+	       indexread_latency_sum, indexread_latency_cnt,
+	       write_latency_sum, write_latency_cnt,
+	       multiwrite_latency_sum, multiwrite_latency_cnt,
+	       indexwrite_latency_sum, indexwrite_latency_cnt,
+	       serialize_latency_sum, serialize_latency_cnt,
+	       indexserialize_latency_sum, indexserialize_latency_cnt,
+	       proto_serialize_latency_sum, proto_serialize_latency_cnt,
+	       deserialize_latency_sum, deserialize_latency_cnt,
+	       indexdeserialize_latency_sum, indexdeserialize_latency_cnt,
+	       proto_deserialize_latency_sum, proto_deserialize_latency_cnt,
+	       sum, delta - sum, (delta - sum) * 100.0 / (delta),
+	       write_condfails, indexwrite_condfails);
+   }
+   public void addport_start(){
+        if(measureAllTimeProp==0)
+		return;
+	clear();
+        addport_cnt = 0;
+	addport_time = System.nanoTime();
+   }
+   public void addport_incr(){
+        if(measureAllTimeProp==0)
+		return;
+        addport_cnt ++;
+   }
+   public void addport_end(){
+        if(measureAllTimeProp==0)
+		return;
+        long delta;
+        long sum;
+        delta = System.nanoTime() - addport_time;
+	sum = getSum();
+        log.error("Performance add_port {} ( {} ports )"
+        	+ " read {} ({})"
+        	+ " multiread {} ({})"
+        	+ " index_read {} ({})"
+        	+ " write {} ({})"
+        	+ " multiwrite {} ({})"
+        	+ " index_write {} ({})"
+        	+ " serialize {} ({})"
+        	+ " indexserialize {} ({})"
+        	+ " proto_serialize {} ({})"
+        	+ " deserialize {} ({})"
+        	+ " indexdeserialize {} ({})"
+        	+ " proto_deserialize {} ({})"
+        	+ " rwsd total {} other {} ({})"
+        	+ " writefail ({}) indexwritefail({})",
+	       delta, addport_cnt,
+	       read_latency_sum, read_latency_cnt,
+	       multiread_latency_sum, multiread_latency_cnt,
+	       indexread_latency_sum, indexread_latency_cnt,
+	       write_latency_sum, write_latency_cnt,
+	       multiwrite_latency_sum, multiwrite_latency_cnt,
+	       indexwrite_latency_sum, indexwrite_latency_cnt,
+	       serialize_latency_sum, serialize_latency_cnt,
+	       indexserialize_latency_sum, indexserialize_latency_cnt,
+	       proto_serialize_latency_sum, proto_serialize_latency_cnt,
+	       deserialize_latency_sum, deserialize_latency_cnt,
+	       indexdeserialize_latency_sum, indexdeserialize_latency_cnt,
+	       proto_deserialize_latency_sum, proto_deserialize_latency_cnt,
+	       sum, delta - sum, (delta - sum) * 100.0 / (delta),
+	       write_condfails, indexwrite_condfails);
+   }
+   public void addlink_start(){
+        if(measureAllTimeProp==0)
+		return;
+	clear();
+	addlink_time = System.nanoTime();
+   }
+   public void addlink_end(){
+        if(measureAllTimeProp==0)
+		return;
+        long delta;
+        long sum;
+        delta = System.nanoTime() - addlink_time;
+	sum = getSum();
+        log.error("Performance add_link {}"
+        	+ " read {} ({})"
+        	+ " multiread {} ({})"
+        	+ " index_read {} ({})"
+        	+ " write {} ({})"
+        	+ " multiwrite {} ({})"
+        	+ " index_write {} ({})"
+        	+ " serialize {} ({})"
+        	+ " indexserialize {} ({})"
+        	+ " proto_serialize {} ({})"
+        	+ " deserialize {} ({})"
+        	+ " indexdeserialize {} ({})"
+        	+ " proto_deserialize {} ({})"
+        	+ " rwsd total {} other {} ({})"
+        	+ " writefail ({}) indexwritefail({})",
+	       delta,
+	       read_latency_sum, read_latency_cnt,
+	       multiread_latency_sum, multiread_latency_cnt,
+	       indexread_latency_sum, indexread_latency_cnt,
+	       write_latency_sum, write_latency_cnt,
+	       multiwrite_latency_sum, multiwrite_latency_cnt,
+	       indexwrite_latency_sum, indexwrite_latency_cnt,
+	       serialize_latency_sum, serialize_latency_cnt,
+	       indexserialize_latency_sum, indexserialize_latency_cnt,
+	       proto_serialize_latency_sum, proto_serialize_latency_cnt,
+	       deserialize_latency_sum, deserialize_latency_cnt,
+	       indexdeserialize_latency_sum, indexdeserialize_latency_cnt,
+	       proto_deserialize_latency_sum, proto_deserialize_latency_cnt,
+	       sum, delta - sum, (delta - sum) * 100.0 / (delta),
+	       write_condfails, indexwrite_condfails);
+   }
+
+   public void addflowpath_start(){
+	if(measureAllTimeProp==0) return;
+	clear();
+	addflowpath_time = System.nanoTime();
+   }
+   public void addflowpath_end(){
+       if(measureAllTimeProp==0) return;
+       long delta;
+       long sum;
+       delta = System.nanoTime() - addflowpath_time;
+       sum = getSum();
+       log.error("Performance add_flowpath {}"
+        	+ " read {} ({})"
+        	+ " multiread {} ({})"
+        	+ " index_read {} ({})"
+        	+ " write {} ({})"
+        	+ " multiwrite {} ({})"
+        	+ " index_write {} ({})"
+        	+ " serialize {} ({})"
+        	+ " indexserialize {} ({})"
+        	+ " proto_serialize {} ({})"
+        	+ " deserialize {} ({})"
+        	+ " indexdeserialize {} ({})"
+        	+ " proto_deserialize {} ({})"
+        	+ " rwsd total {} other {} ({})"
+        	+ " writefail ({}) indexwritefail({})",
+	       delta,
+	       read_latency_sum, read_latency_cnt,
+	       multiread_latency_sum, multiread_latency_cnt,
+	       indexread_latency_sum, indexread_latency_cnt,
+	       write_latency_sum, write_latency_cnt,
+	       multiwrite_latency_sum, multiwrite_latency_cnt,
+	       indexwrite_latency_sum, indexwrite_latency_cnt,
+	       serialize_latency_sum, serialize_latency_cnt,
+	       indexserialize_latency_sum, indexserialize_latency_cnt,
+	       proto_serialize_latency_sum, proto_serialize_latency_cnt,
+	       deserialize_latency_sum, deserialize_latency_cnt,
+	       indexdeserialize_latency_sum, indexdeserialize_latency_cnt,
+	       proto_deserialize_latency_sum, proto_deserialize_latency_cnt,
+	       sum, delta - sum, (delta - sum) * 100.0 / (delta),
+	       write_condfails, indexwrite_condfails);
+   }
+
+   public void addflowentry_start(){
+       if(measureAllTimeProp==0) return;
+	clear();
+	if ( debug==1 )
+		log.error("addflowentry_start");
+	addflowentry_time = System.nanoTime();
+   }
+   public void addflowentry_incr(){
+       if(measureAllTimeProp==0) return;
+       addflowentry_cnt++;
+   }
+   public void addflowentry_end(){
+       if(measureAllTimeProp==0) return;
+       long delta;
+       long sum;
+       delta = System.nanoTime() - addflowentry_time;
+       sum = getSum();
+       log.error("Performance add_flowentry {} ( {} flows )"
+        	+ " read {} ({})"
+        	+ " multiread {} ({})"
+        	+ " index_read {} ({})"
+        	+ " write {} ({})"
+        	+ " multiwrite {} ({})"
+        	+ " index_write {} ({})"
+        	+ " serialize {} ({})"
+        	+ " indexserialize {} ({})"
+        	+ " proto_serialize {} ({})"
+        	+ " deserialize {} ({})"
+        	+ " indexdeserialize {} ({})"
+        	+ " proto_deserialize {} ({})"
+        	+ " rwsd total {} other {} ({})"
+        	+ " writefail ({}) indexwritefail({})",
+	       delta, addflowentry_cnt,
+	       read_latency_sum, read_latency_cnt,
+	       multiread_latency_sum, multiread_latency_cnt,
+	       indexread_latency_sum, indexread_latency_cnt,
+	       write_latency_sum, write_latency_cnt,
+	       multiwrite_latency_sum, multiwrite_latency_cnt,
+	       indexwrite_latency_sum, indexwrite_latency_cnt,
+	       serialize_latency_sum, serialize_latency_cnt,
+	       indexserialize_latency_sum, indexserialize_latency_cnt,
+	       proto_serialize_latency_sum, proto_serialize_latency_cnt,
+	       deserialize_latency_sum, deserialize_latency_cnt,
+	       indexdeserialize_latency_sum, indexdeserialize_latency_cnt,
+	       proto_deserialize_latency_sum, proto_deserialize_latency_cnt,
+	       sum, delta - sum, (delta - sum) * 100.0 / (delta),
+	       write_condfails, indexwrite_condfails);
+   }
+
+   public void read_whole_topology_start(){
+       if(measureAllTimeProp==0) return;
+	if ( debug==1 )
+	    log.error("read_whole_topology_start");
+
+	clear();
+	read_whole_topology_time = System.nanoTime();
+   }
+   public void read_whole_topology_end(){
+       if(measureAllTimeProp==0) return;
+       long delta;
+       long sum;
+       delta = System.nanoTime() - read_whole_topology_time;
+       sum = getSum();
+       log.error("Performance read_whole_topology {}"
+        	+ " read {} ({})"
+        	+ " multiread {} ({})"
+        	+ " index_read {} ({})"
+        	+ " write {} ({})"
+        	+ " multiwrite {} ({})"
+        	+ " index_write {} ({})"
+        	+ " serialize {} ({})"
+        	+ " indexserialize {} ({})"
+        	+ " proto_serialize {} ({})"
+        	+ " deserialize {} ({})"
+        	+ " indexdeserialize {} ({})"
+        	+ " proto_deserialize {} ({})"
+        	+ " rwsd total {} other {} ({})"
+        	+ " writefail ({}) indexwritefail({})",
+	       delta,
+	       read_latency_sum, read_latency_cnt,
+	       multiread_latency_sum, multiread_latency_cnt,
+	       indexread_latency_sum, indexread_latency_cnt,
+	       write_latency_sum, write_latency_cnt,
+	       multiwrite_latency_sum, multiwrite_latency_cnt,
+	       indexwrite_latency_sum, indexwrite_latency_cnt,
+	       serialize_latency_sum, serialize_latency_cnt,
+	       indexserialize_latency_sum, indexserialize_latency_cnt,
+	       proto_serialize_latency_sum, proto_serialize_latency_cnt,
+	       deserialize_latency_sum, deserialize_latency_cnt,
+	       indexdeserialize_latency_sum, indexdeserialize_latency_cnt,
+	       proto_deserialize_latency_sum, proto_deserialize_latency_cnt,
+	       sum, delta - sum, (delta - sum) * 100.0 / (delta),
+	       write_condfails, indexwrite_condfails);
+   }
+
+
+   public void read_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("read_start {}", key);
+        if ( read_flag != 0){
+            log.error("read_start called twice");
+	}
+	read_flag = 1;
+
+	read_time=System.nanoTime();
+   }
+   public void read_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("read_end {}", key);
+
+	read_latency_sum += System.nanoTime() - read_time;
+	read_latency_cnt ++;
+
+        if ( read_flag != 1){
+            log.error("read_end called before read_start");
+	}
+	read_flag = 0;
+   }
+   public void multiread_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("multiread_start {}", key);
+	if ( multiread_flag != 0){
+            log.error("multiread_start called twice");
+	}
+	multiread_flag = 1;
+
+	multiread_time=System.nanoTime();
+   }
+   public void multiread_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+	multiread_latency_sum += System.nanoTime() - multiread_time;
+        multiread_latency_cnt ++;
+
+	if ( debug==1 )
+            log.error("multiread_end {}", key);
+        if ( multiread_flag != 1){
+            log.error("multiread_end called before multiread_start");
+	}
+	multiread_flag = 0;
+   }
+   public void multiwrite_start(String key){
+       if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+           log.error("multiwrite_start {}", key);
+	if ( multiwrite_flag != 0){
+           log.error("multiwrite_start called twice");
+	}
+	multiwrite_flag = 1;
+
+	multiwrite_time=System.nanoTime();
+  }
+  public void multiwrite_end(String key){
+       if(measureAllTimeProp==0)
+		return;
+
+	multiwrite_latency_sum += System.nanoTime() - multiwrite_time;
+       multiwrite_latency_cnt ++;
+
+	if ( debug==1 )
+           log.error("multiwrite_end {}", key);
+       if ( multiwrite_flag != 1){
+           log.error("multiwrite_end called before multiwrite_start");
+	}
+	multiwrite_flag = 0;
+  }
+   public void indexread_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("indexread_start {}", key);
+        if ( indexread_flag != 0){
+            log.error("indexread_start called twice");
+	}
+	indexread_flag = 1;
+
+    	indexread_time=System.nanoTime();
+   }
+   public void indexread_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+	indexread_latency_sum += System.nanoTime() - indexread_time;
+        indexread_latency_cnt ++;
+
+	if ( debug==1 )
+            log.error("indexread_end {}", key);
+        if ( indexread_flag != 1){
+            log.error("indexread_end called before indexread_start");
+	}
+	indexread_flag = 0;
+   }
+   public void write_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("write start_{}", key);
+        if ( write_flag != 0){
+            log.error("write_start called twice");
+	}
+	write_flag = 1;
+
+	write_time = System.nanoTime();
+   }
+   public void write_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+        write_latency_sum += System.nanoTime() - write_time;
+        write_latency_cnt ++;
+
+        if ( debug==1 )
+            log.error("write_end {}", key);
+        if ( write_flag != 1){
+            log.error("write_end called before write_start");
+	}
+	write_flag = 0;
+   }
+   public void write_condfail(String key){
+       if(measureAllTimeProp==0)
+		return;
+       write_condfails++;
+   }
+
+   public void indexwrite_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("index_write start {}", key);
+        if ( indexwrite_flag != 0){
+            log.error("indexwrite_start called twice");
+	}
+	indexwrite_flag = 1;
+	indexwrite_time = System.nanoTime();
+   }
+   public void indexwrite_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+	indexwrite_latency_sum += System.nanoTime() - indexwrite_time;
+        indexwrite_latency_cnt ++;
+
+        if ( debug==1 )
+            log.error("indexwrite_end {}", key);
+        if ( indexwrite_flag != 1){
+            log.error("indexwrite_end called before indexwrite_start");
+	}
+	indexwrite_flag = 0;
+   }
+   public void indexwrite_condfail(String key){
+       if(measureAllTimeProp==0)
+		return;
+       indexwrite_condfails++;
+   }
+
+   public void ser_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("ser_start {}", key);
+        if ( ser_flag != 0 ){
+            	log.error("ser_start called twice");
+	}
+	ser_flag = 1;
+
+	ser_time = System.nanoTime();
+   }
+   public void ser_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+	serialize_latency_sum += System.nanoTime() - ser_time;
+        serialize_latency_cnt ++;
+
+        if ( debug==1 )
+            log.error("ser_end {}", key);
+        if ( ser_flag != 1 ){
+            	log.error("ser_end called before ser_start");
+	}
+	ser_flag = 0;
+   }
+
+   public void indexser_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+	indexser_time = System.nanoTime();
+
+	if ( debug==1 )
+            log.error("indexser_start {}", key);
+        if ( indexser_flag != 0 ){
+            	log.error("indexser_start called twice");
+	}
+	indexser_flag = 1;
+   }
+   public void indexser_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+	indexserialize_latency_sum += System.nanoTime() - indexser_time;
+        indexserialize_latency_cnt ++;
+
+        if ( debug==1 )
+            log.error("indexser_end {}", key);
+        if ( indexser_flag != 1 ){
+            	log.error("indexser_end called before indexser_start");
+	}
+	indexser_flag = 0;
+
+   }
+
+   public void deser_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("deser_start {}", key);
+        if ( deser_flag != 0){
+            log.error("deser_start called twice");
+	}
+	deser_flag = 1;
+
+	deser_time = System.nanoTime();
+   }
+   public void deser_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+        deserialize_latency_sum += System.nanoTime() - deser_time;
+        deserialize_latency_cnt ++;
+
+        if ( debug==1 )
+            log.error("deser_end {}", key);
+        if ( deser_flag != 1){
+            log.error("deser_end called before deser_start");
+	}
+	deser_flag = 0;
+   }
+
+   public void indexdeser_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+	if ( debug==1 )
+            log.error("indexdeser_start {}", key);
+        if ( indexdeser_flag != 0){
+            log.error("indexdeser_start called twice");
+	}
+	indexdeser_flag = 1;
+
+	indexdeser_time = System.nanoTime();
+   }
+   public void indexdeser_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+
+        indexdeserialize_latency_sum += System.nanoTime() - indexdeser_time;
+        indexdeserialize_latency_cnt ++;
+
+        if ( debug==1 )
+            log.error("indexdeser_end {}", key);
+        if ( indexdeser_flag != 1){
+            log.error("indexdeser_end called before indexdeser_start");
+	}
+	indexdeser_flag = 0;
+   }
+
+   public void protoser_start(String key){
+       if(measureAllTimeProp==0)
+	   return;
+
+       if ( debug==1 )
+	   log.error("protoser_start {}", key);
+       if ( protoser_flag != 0){
+	   log.error("protoser_start called twice");
+       }
+       protoser_flag = 1;
+
+       protoser_time = System.nanoTime();
+   }
+   public void protoser_end(String key){
+       if(measureAllTimeProp==0)
+	   return;
+
+       proto_serialize_latency_sum += System.nanoTime() - protoser_time;
+       proto_serialize_latency_cnt ++;
+
+       if ( debug==1 )
+	   log.error("protoser_end {}", key);
+       if ( protoser_flag != 1){
+	   log.error("protoser_end called before protoser_start");
+       }
+       protoser_flag = 0;
+   }
+   public void protodeser_start(String key){
+       if(measureAllTimeProp==0)
+	   return;
+       if ( debug==1 )
+	   log.error("protodeser_start {}", key);
+       if ( protodeser_flag != 0){
+	   log.error("protoser_start called twice");
+       }
+       protodeser_flag = 1;
+
+       protodeser_time = System.nanoTime();
+   }
+   public void protodeser_end(String key){
+       if(measureAllTimeProp==0)
+	   return;
+
+       proto_deserialize_latency_sum += System.nanoTime() - protodeser_time;
+       proto_deserialize_latency_cnt ++;
+
+       if ( debug==1 )
+	   log.error("protodeser_end {}", key);
+       if ( protodeser_flag != 1){
+	   log.error("protodeser_end called before protodeser_start");
+       }
+       protodeser_flag = 0;
+   }
+
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/PerfMon.java.hashversion b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/PerfMon.java.hashversion
new file mode 100644
index 0000000..9847cbd
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/PerfMon.java.hashversion
@@ -0,0 +1,290 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import sun.reflect.Reflection;
+
+
+public final class PerfMon {
+   private static final PerfMon instance = new PerfMon();
+   public final long measureAllTimeProp = Long.valueOf(System.getProperty("benchmark.measureAll", "0"));
+   private final static Logger log = LoggerFactory.getLogger(PerfMon.class);
+
+   private static final int debug = 0;
+
+   private static long read_latency_sum;
+   private static long read_latency_cnt;
+   private static int read_flag;
+
+   private static long write_latency_sum;
+   private static long write_latency_cnt;
+   private static int write_flag;
+
+   private static long serialize_latency_sum;
+   private static long serialize_latency_cnt;
+   private static HashMap<String, Long> ser_flag = new HashMap<String, Long>();
+   //private static int ser_flag;
+
+   private static long deserialize_latency_sum;
+   private static long deserialize_latency_cnt;
+   private static int deser_flag;
+
+   private static long addsw_time;
+   private static long addport_time;
+   private static long addlink_time;
+   private static long addport_cnt;
+   private static HashMap<String, Long> ser_time = new HashMap<String, Long>();
+   private static HashMap<String, Long> deser_time = new HashMap<String, Long>();
+   private static HashMap<String, Long> write_time = new HashMap<String, Long>();
+   private static HashMap<String, Long> read_time = new HashMap<String, Long>();
+
+   public static PerfMon getInstance() {
+        return instance;
+    }
+   private PerfMon(){
+   }
+
+   private void clear(){
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+   	read_latency_sum=0L;
+   	read_latency_cnt=0L;
+   	write_latency_sum=0L;
+   	write_latency_cnt=0L;
+   	serialize_latency_sum=0L;
+   	serialize_latency_cnt=0L;
+   	deserialize_latency_sum=0L;
+   	deserialize_latency_cnt=0L;
+	read_flag=write_flag=deser_flag=0;
+        for (Iterator<Map.Entry<String, Long>> it = ser_flag.entrySet().iterator(); it.hasNext(); ) {
+            Map.Entry<String, Long> entry = it.next();
+	    entry.setValue(0L);
+        }
+        //log.error("flag cleared");
+   }
+   public void addswitch_start(){
+        if(measureAllTimeProp==0)
+		return;
+
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	clear();
+	addsw_time = System.nanoTime();
+   }
+   public void addswitch_end(){
+        if(measureAllTimeProp==0)
+		return;
+
+        long delta;
+        long sum;
+
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+        delta = System.nanoTime() - addsw_time;
+        sum = read_latency_sum + write_latency_sum + serialize_latency_sum +  deserialize_latency_sum;
+        log.error("Performance add_switch {} read {} ({}) write {} ({}) serialize {} ({}) deserialize {} ({}) rwsd total {} other {} ({})", 
+	delta, read_latency_sum, read_latency_cnt, write_latency_sum, write_latency_cnt, serialize_latency_sum, serialize_latency_cnt, deserialize_latency_sum, deserialize_latency_cnt, sum, delta-sum, ((float)(delta-sum))*100.0/((float) delta));
+   }
+   public void addport_start(){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	clear();
+        addport_cnt = 0;
+	addport_time = System.nanoTime();
+   }
+   public void addport_incr(){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	clear();
+       addport_cnt ++;
+   }
+   public void addport_end(){
+        if(measureAllTimeProp==0)
+		return;
+        long delta;
+        long sum;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+        delta = System.nanoTime() - addport_time;
+        sum = read_latency_sum + write_latency_sum + serialize_latency_sum +  deserialize_latency_sum;
+        log.error("Performance add_port {} ( {} ports ) read {} ({}) write {} ({}) serialize {} ({}) deserialize {} ({}) rwsd total {} other {} ({})", 
+	delta, addport_cnt, read_latency_sum, read_latency_cnt, write_latency_sum, write_latency_cnt, serialize_latency_sum, serialize_latency_cnt, deserialize_latency_sum, deserialize_latency_cnt, sum, delta-sum, ((float)(delta-sum))*100.0/((float) delta));
+   }
+   public void addlink_start(){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	clear();
+	addlink_time = System.nanoTime();
+   }
+   public void addlink_end(){
+        if(measureAllTimeProp==0)
+		return;
+        long delta;
+        long sum;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+        delta = System.nanoTime() - addlink_time;
+        sum = read_latency_sum + write_latency_sum + serialize_latency_sum +  deserialize_latency_sum;
+        log.error("Performance add_link {} read {} ({}) write {} ({}) serialize {} ({}) deserialize {} ({}) rwsd total {} other {} ({})", 
+	delta, read_latency_sum, read_latency_cnt, write_latency_sum, write_latency_cnt, serialize_latency_sum, serialize_latency_cnt, deserialize_latency_sum, deserialize_latency_cnt, sum, delta-sum, ((float)(delta-sum))*100.0/((float) delta));
+   }
+
+   public void read_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        } 
+	if ( debug==1 )
+            log.error("read start {}", key);
+	read_time.put(key, System.nanoTime());
+	//read_time = System.nanoTime();
+        if ( read_flag != 0){
+            log.error("read is already started");
+	}
+	read_flag = 1;
+   }
+   public void read_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+        long delta;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+        //read_latency_sum += System.nanoTime() - read_time;
+	if ( debug==1 )
+            log.error("read end {}", key);
+        delta = System.nanoTime() - read_time.get(key);
+        read_latency_sum += delta;
+        read_latency_cnt ++;
+        if ( read_flag != 1){
+            log.error("read is not started");
+	}
+	read_flag = 0;
+   }
+   public void write_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	if ( debug==1 )
+            log.error("write start {}", key);
+	write_time.put(key, System.nanoTime());
+	//write_time = System.nanoTime();
+        if ( write_flag != 0){
+            log.error("write is already started");
+	}
+	write_flag = 1;
+   }
+   public void write_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	if ( debug==1 )
+            log.error("write end {}", key);
+        write_latency_sum += (System.nanoTime() - write_time.get(key));
+        //write_latency_sum += System.nanoTime() - write_time;
+        write_latency_cnt ++;
+        if ( write_flag != 1){
+            log.error("write is not started");
+	}
+	write_flag = 0;
+   }
+   public void ser_add(long time){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+        serialize_latency_sum += time;
+        serialize_latency_cnt ++;
+   }
+   public void ser_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	//ser_time = System.nanoTime();
+	if ( debug==1 )
+            log.error("ser start {}", key);
+	ser_time.put(key, System.nanoTime());
+//        log.error("ser {} start at {} flag {}", key, ser_time, ser_flag);
+        if ( ser_flag.containsKey(key) ){
+        	if ( ser_flag.get(key) != 0L){
+            		log.error("ser {} sarted but has been already started", key);
+		}
+	}
+	ser_flag.put(key, 1L);
+   }
+   public void ser_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	if ( debug==1 )
+            log.error("ser end {}", key);
+        //serialize_latency_sum += System.nanoTime() - ser_time;
+        serialize_latency_sum += (System.nanoTime() - ser_time.get(key));
+        serialize_latency_cnt ++;
+ //       log.error("ser {} end at {} flag {}", key, ser_time, ser_flag);
+        if ( ser_flag.containsKey(key) ){
+        	if ( ser_flag.get(key) != 1L){
+            		log.error("ser {} ended but hasn't started", key);
+		}
+	}
+	ser_flag.put(key, 0L);
+   }
+   public void deser_start(String key){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	if ( debug==1 )
+            log.error("deser start {}", key);
+	deser_time.put(key, System.nanoTime());
+	//deser_time = System.nanoTime();
+        if ( deser_flag != 0){
+            log.error("deser is already started");
+	}
+	deser_flag = 1;
+   }
+   public void deser_end(String key){
+        if(measureAllTimeProp==0)
+		return;
+        if(! Thread.currentThread().getName().equals("main")){
+		return;
+        }
+	if ( debug==1 )
+            log.error("deser end {}", key);
+        //deserialize_latency_sum += System.nanoTime() - deser_time;
+        deserialize_latency_sum += System.nanoTime() - deser_time.get(key);
+        deserialize_latency_cnt ++;
+        if ( deser_flag != 1){
+            log.error("deser is not started");
+	}
+	deser_flag = 0;
+   }
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudEdge.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudEdge.java
new file mode 100644
index 0000000..d61c2a4
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudEdge.java
@@ -0,0 +1,222 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.core.util.Base64;
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.ExceptionFactory;
+import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
+import edu.stanford.ramcloud.JRamCloud;
+
+public class RamCloudEdge extends RamCloudElement implements Edge {
+
+    private final static Logger log = LoggerFactory.getLogger(RamCloudGraph.class);
+    private RamCloudVertex outVertex;
+    private RamCloudVertex inVertex;
+    private String label;
+    private byte[] rcKey;
+    private RamCloudGraph graph;
+
+    public RamCloudEdge(RamCloudVertex outVertex, RamCloudVertex inVertex, String label, RamCloudGraph graph) {
+	super(edgeToRcKey(outVertex, inVertex, label), graph.edgePropTableId, graph);
+
+	this.outVertex = outVertex;
+	this.inVertex = inVertex;
+	this.label = label;
+	this.rcKey = edgeToRcKey(outVertex, inVertex, label);
+	this.graph = graph;
+    }
+
+    public RamCloudEdge(byte[] rcKey, RamCloudGraph graph) {
+	super(rcKey, graph.edgePropTableId, graph);
+
+	ByteBuffer edgeId = ByteBuffer.wrap(rcKey).order(ByteOrder.LITTLE_ENDIAN);
+	outVertex = new RamCloudVertex(edgeId.getLong(), graph);
+	inVertex = new RamCloudVertex(edgeId.getLong(), graph);
+	label = new String(rcKey, 16, rcKey.length - 16);
+
+	this.rcKey = rcKey;
+	this.graph = graph;
+    }
+
+    private static byte[] edgeToRcKey(RamCloudVertex outVertex, RamCloudVertex inVertex, String label) {
+	return ByteBuffer.allocate(16 + label.length()).order(ByteOrder.LITTLE_ENDIAN).putLong((Long) outVertex.getId()).putLong((Long) inVertex.getId()).put(label.getBytes()).array();
+    }
+
+    @Override
+    public Vertex getVertex(Direction direction) throws IllegalArgumentException {
+	if (direction.equals(Direction.OUT)) {
+	    return outVertex;
+	} else if (direction.equals(Direction.IN)) {
+	    return inVertex;
+	} else {
+	    throw ExceptionFactory.bothIsNotSupported();
+	}
+    }
+
+    @Override
+    public String getLabel() {
+	return label;
+    }
+
+    public boolean isLoop() {
+	return outVertex.equals(inVertex);
+    }
+
+    public Vertex getNeighbor(Vertex vertex) {
+	if (outVertex.equals(vertex)) {
+	    return inVertex;
+	} else if (inVertex.equals(vertex)) {
+	    return outVertex;
+	} else {
+	    return null;
+	}
+    }
+
+    @Override
+    public void remove() {
+	if (isLoop()) {
+	    outVertex.removeEdgeFromAdjList(this);
+	} else {
+	    outVertex.removeEdgeFromAdjList(this);
+	    inVertex.removeEdgeFromAdjList(this);
+	}
+
+	super.remove();
+    }
+
+    void removeProperties() {
+	super.remove();
+    }
+
+    @Override
+    public Object getId() {
+	return new String(Base64.encode(rcKey));
+    }
+
+    public boolean exists() {
+	boolean edgePropTableEntryExists;
+	boolean outVertexEntryExists;
+	boolean inVertexEntryExists;
+
+	PerfMon pm = PerfMon.getInstance();
+	try {
+	    JRamCloud edgeTable = graph.getRcClient();
+	    pm.read_start("RamCloudEdge exists()");
+	    edgeTable.read(graph.edgePropTableId, rcKey);
+	    pm.read_end("RamCloudEdge exists()");
+	    edgePropTableEntryExists = true;
+	} catch (Exception e) {
+	    pm.read_end("RamCloudEdge exists()");
+	    // Edge property table entry does not exist
+	    edgePropTableEntryExists = false;
+	}
+
+	outVertexEntryExists = outVertex.getEdgeSet().contains(this);
+
+	if (!outVertex.equals(inVertex)) {
+	    inVertexEntryExists = inVertex.getEdgeSet().contains(this);
+	} else {
+	    inVertexEntryExists = outVertexEntryExists;
+	}
+
+	if (edgePropTableEntryExists && outVertexEntryExists && inVertexEntryExists) {
+	    return true;
+	} else if (!edgePropTableEntryExists && !outVertexEntryExists && !inVertexEntryExists) {
+	    return false;
+	} else {
+	    log.warn("{}: Detected RamCloudGraph inconsistency: edgePropTableEntryExists={}, outVertexEntryExists={}, inVertexEntryExists={}.", this, edgePropTableEntryExists, outVertexEntryExists, inVertexEntryExists);
+	    return true;
+	}
+    }
+
+    public void create() throws Exception {
+	// TODO: Existence check costs extra (presently 3 reads), could use option to turn on/off
+	if (!exists()) {
+		PerfMon pm = PerfMon.getInstance();
+		// create edge property table
+		JRamCloud edgeTable = graph.getRcClient();
+	        pm.write_start("RamCloudEdge create()");
+		edgeTable.write(graph.edgePropTableId, rcKey, ByteBuffer.allocate(0).array());
+	        pm.write_end("RamCloudEdge create()");
+
+		boolean addSucc = outVertex.addEdgeToAdjList(this);
+		if ( !addSucc ) {
+		    edgeTable.remove(graph.edgePropTableId, rcKey);
+		    throw ExceptionFactory.edgeWithIdAlreadyExist(rcKey);
+		}
+		if (!isLoop()) {
+		    addSucc = inVertex.addEdgeToAdjList(this);
+		    if ( !addSucc ) {
+			edgeTable.remove(graph.edgePropTableId, rcKey);
+			outVertex.removeEdgeFromAdjList(this);
+			throw ExceptionFactory.edgeWithIdAlreadyExist(rcKey);
+		    }
+		}
+	} else {
+	    throw ExceptionFactory.edgeWithIdAlreadyExist(rcKey);
+	}
+    }
+
+    public static boolean isValidEdgeId(byte[] id) {
+	if (id == null) {
+	    return false;
+	}
+	if (id.length == 0) {
+	    return false;
+	}
+
+	ByteBuffer edgeId = ByteBuffer.wrap(id);
+	try {
+	    edgeId.getLong();
+	} catch (BufferUnderflowException e) {
+	    return false;
+	}
+
+	try {
+	    edgeId.getLong();
+	} catch (BufferUnderflowException e) {
+	    return false;
+	}
+
+	if (edgeId.remaining() == 0) {
+	    return false;
+	}
+
+	return true;
+    }
+
+    @Override
+    public int hashCode() {
+	return Arrays.hashCode(rcKey);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+	if (this == obj) {
+	    return true;
+	}
+	if (obj == null) {
+	    return false;
+	}
+	if (getClass() != obj.getClass()) {
+	    return false;
+	}
+	RamCloudEdge other = (RamCloudEdge) obj;
+	return Arrays.equals(rcKey, other.rcKey);
+    }
+
+    @Override
+    public String toString() {
+	return "RamCloudEdge [outVertex=" + outVertex + ", inVertex=" + inVertex
+		+ ", label=" + label + "]";
+    }
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudElement.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudElement.java
new file mode 100644
index 0000000..15ec580
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudElement.java
@@ -0,0 +1,300 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.esotericsoftware.kryo2.Kryo;
+import com.esotericsoftware.kryo2.io.ByteBufferInput;
+import com.esotericsoftware.kryo2.io.Output;
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Element;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.ExceptionFactory;
+import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
+
+import edu.stanford.ramcloud.JRamCloud;
+
+public class RamCloudElement implements Element, Serializable {
+
+    private final static Logger log = LoggerFactory.getLogger(RamCloudGraph.class);
+    private byte[] rcPropTableKey;
+    private long rcPropTableId;
+    private RamCloudGraph graph;
+
+    private static final ThreadLocal<Kryo> kryo = new ThreadLocal<Kryo>() {
+        @Override
+        protected Kryo initialValue() {
+                 Kryo kryo = new Kryo();
+                 kryo.setRegistrationRequired(true);
+                 kryo.register(String.class);
+                 kryo.register(Long.class);
+                 kryo.register(Integer.class);
+                 kryo.register(Short.class);
+                 kryo.register(Byte.class);
+                 kryo.register(TreeMap.class);
+                 kryo.register(ArrayList.class);
+                 kryo.setReferences(false);
+                 return kryo;
+        }
+    };
+
+    public RamCloudElement() {
+    }
+
+    public RamCloudElement(byte[] rcPropTableKey, long rcPropTableId, RamCloudGraph graph) {
+	this.rcPropTableKey = rcPropTableKey;
+	this.rcPropTableId = rcPropTableId;
+	this.graph = graph;
+    }
+
+    protected Map<String, Object> getPropertyMap() {
+	JRamCloud.Object propTableEntry;
+
+	PerfMon pm = PerfMon.getInstance();
+	try {
+	    JRamCloud vertTable = graph.getRcClient();
+	    pm.read_start("RamCloudElement getPropertyMap()");
+	    propTableEntry = vertTable.read(rcPropTableId, rcPropTableKey);
+	    pm.read_end("RamCloudElement getPropertyMap()");
+	    if (propTableEntry.value.length > 1024 * 1024 * 0.9) {
+		log.warn("Element[id={}] property map size is near 1MB limit!", new String(rcPropTableKey));
+	    }
+	} catch (Exception e) {
+	    pm.read_end("RamCloudElement getPropertyMap()");
+	    log.warn("Element does not have a property table entry!");
+	    return null;
+	}
+
+	return convertRcBytesToPropertyMap(propTableEntry.value);
+    }
+
+    public static Map<String, Object> convertRcBytesToPropertyMapEx(byte[] byteArray) {
+	if (byteArray == null) {
+	    log.warn("Got a null byteArray argument");
+	    return null;
+	} else if (byteArray.length != 0) {
+	    PerfMon pm = PerfMon.getInstance();
+	    pm.deser_start("RamCloudElement convertRcBytesToPropertyMapEx()");
+	    ByteBufferInput input = new ByteBufferInput(byteArray);
+	    TreeMap map = kryo.get().readObject(input, TreeMap.class);
+	    pm.deser_end("RamCloudElement convertRcBytesToPropertyMapEx()");
+	    return map;
+	} else {
+	    return new TreeMap<String, Object>();
+	}
+    }
+
+    public Map<String, Object> convertRcBytesToPropertyMap(byte[] byteArray) {
+	if (byteArray == null) {
+	    log.warn("Got a null byteArray argument");
+	    return null;
+	} else if (byteArray.length != 0) {
+	    PerfMon pm = PerfMon.getInstance();
+	    long startTime = 0;
+	    if(RamCloudGraph.measureSerializeTimeProp == 1) {
+		startTime = System.nanoTime();
+	    }
+	    pm.deser_start("RamCloudElement convertRcBytesToPropertyMap()");
+	    ByteBufferInput input = new ByteBufferInput(byteArray);
+	    TreeMap map = kryo.get().readObject(input, TreeMap.class);
+	    pm.deser_end("RamCloudElement convertRcBytesToPropertyMap()");
+	    if(RamCloudGraph.measureSerializeTimeProp == 1) {
+            	long endTime = System.nanoTime();
+            	log.error("Performance element kryo deserialization key {} {} size {}", this, endTime - startTime, byteArray.length);
+	    }
+	    return map;
+	} else {
+	    return new TreeMap<String, Object>();
+	}
+    }
+
+    private void setPropertyMap(Map<String, Object> map) {
+	byte[] rcValue;
+	PerfMon pm = PerfMon.getInstance();
+
+	long startKryoTime = 0;
+	if(RamCloudGraph.measureSerializeTimeProp == 1) {
+	    startKryoTime = System.nanoTime();
+	}
+	pm.ser_start("RamCloudElement setPropertyMap()");
+	byte[] rcTemp = new byte[1024*1024];
+	Output output = new Output(rcTemp);
+	kryo.get().writeObject(output, map);
+	long midKryoTime = 0;
+	if(RamCloudGraph.measureSerializeTimeProp == 1) {
+	    midKryoTime = System.nanoTime();
+	}
+	rcValue = output.toBytes();
+	pm.ser_end("RamCloudElement setPropertyMap()");
+	if(RamCloudGraph.measureSerializeTimeProp == 1) {
+        	long endKryoTime = System.nanoTime();
+        	log.error("Performance element kryo serialization key {} mid {}, total {}, size {}", this, midKryoTime - startKryoTime, endKryoTime - startKryoTime, rcValue.length);
+	}
+
+	long startTime = 0;
+	JRamCloud vertTable = graph.getRcClient();
+	if (graph.measureRcTimeProp == 1) {
+	    startTime = System.nanoTime();
+	}
+	pm.write_start("RamCloudElement setPropertyMap()");
+	vertTable.write(rcPropTableId, rcPropTableKey, rcValue);
+	pm.write_end("RamCloudElement setPropertyMap()");
+	if (graph.measureRcTimeProp == 1) {
+	    long endTime = System.nanoTime();
+	    log.error("Performance setPropertyMap write time key {} {}", this, endTime - startTime);
+	}
+    }
+
+    @Override
+    public <T> T getProperty(String key) {
+	Map<String, Object> map = getPropertyMap();
+	return (T) map.get(key);
+    }
+
+    @Override
+    public Set<String> getPropertyKeys() {
+	Map<String, Object> map = getPropertyMap();
+	return map.keySet();
+    }
+
+    public Map<String, Object> getProperties() {
+	return getPropertyMap();
+    }
+    public void setProperties(Map<String, Object> properties) {
+        Map<String, Object> map = getPropertyMap();
+        Map<String, Object> oldValueMap = new HashMap<String, Object>(map.size());
+        for (Map.Entry<String, Object> property : properties.entrySet()) {
+            String key = property.getKey();
+            if (key == null) {
+                throw ExceptionFactory.propertyKeyCanNotBeNull();
+            }
+
+            if (key.equals("")) {
+                throw ExceptionFactory.propertyKeyCanNotBeEmpty();
+            }
+
+            if (key.equals("id")) {
+                throw ExceptionFactory.propertyKeyIdIsReserved();
+            }
+
+            if (this instanceof RamCloudEdge && key.equals("label")) {
+                throw ExceptionFactory.propertyKeyLabelIsReservedForEdges();
+            }
+            Object value = property.getValue();
+            if (value == null) {
+                throw ExceptionFactory.propertyValueCanNotBeNull();
+            }
+
+            oldValueMap.put(key, map.put(key, value));
+
+        }
+        setPropertyMap(map);
+
+        // TODO use multi-write
+        for (Map.Entry<String, Object> oldProperty : oldValueMap.entrySet()) {
+            String key = oldProperty.getKey();
+            Object oldValue = oldProperty.getValue();
+            Object value = map.get(key);
+            if (this instanceof RamCloudVertex) {
+                RamCloudKeyIndex keyIndex = new RamCloudKeyIndex(graph.kidxVertTableId, key, value, graph, Vertex.class);
+                keyIndex.autoUpdate(key, value, oldValue, this);
+            } else {
+                RamCloudKeyIndex keyIndex = new RamCloudKeyIndex(graph.kidxVertTableId, key, value, graph, Edge.class);
+                keyIndex.autoUpdate(key, value, oldValue, this);
+            }
+        }
+    }
+
+    @Override
+    public void setProperty(String key, Object value) {
+	Object oldValue;
+	if (value == null) {
+	    throw ExceptionFactory.propertyValueCanNotBeNull();
+	}
+
+	if (key == null) {
+	    throw ExceptionFactory.propertyKeyCanNotBeNull();
+	}
+
+	if (key.equals("")) {
+	    throw ExceptionFactory.propertyKeyCanNotBeEmpty();
+	}
+
+	if (key.equals("id")) {
+	    throw ExceptionFactory.propertyKeyIdIsReserved();
+	}
+
+	if (this instanceof RamCloudEdge && key.equals("label")) {
+	    throw ExceptionFactory.propertyKeyLabelIsReservedForEdges();
+	}
+
+	long startTime = 0;
+	if (graph.measureBPTimeProp == 1) {
+	    startTime = System.nanoTime();
+	}
+
+	Map<String, Object> map = getPropertyMap();
+	oldValue = map.put(key, value);
+	setPropertyMap(map);
+
+	boolean ret = false;
+	if (this instanceof RamCloudVertex) {
+	    RamCloudKeyIndex keyIndex = new RamCloudKeyIndex(graph.kidxVertTableId, key, value, graph, Vertex.class);
+	    ret = keyIndex.autoUpdate(key, value, oldValue, this);
+	} else {
+	    RamCloudKeyIndex keyIndex = new RamCloudKeyIndex(graph.kidxVertTableId, key, value, graph, Edge.class);
+	    keyIndex.autoUpdate(key, value, oldValue, this);
+	}
+
+	if (graph.measureBPTimeProp == 1) {
+	    long endTime = System.nanoTime();
+	    if (ret) {
+		log.error("Performance vertex setProperty(key {}) which is index total time {}", key, endTime - startTime);
+	    } else {
+		log.error("Performance vertex setProperty(key {}) does not index time {}", key, endTime - startTime);
+	    }
+	}
+
+    }
+
+    @Override
+    public <T> T removeProperty(String key) {
+	Map<String, Object> map = getPropertyMap();
+	T retVal = (T) map.remove(key);
+	setPropertyMap(map);
+	if (this instanceof RamCloudVertex) {
+	    RamCloudKeyIndex keyIndex = new RamCloudKeyIndex(graph.kidxVertTableId, key, retVal, graph, Vertex.class);
+	    keyIndex.autoRemove(key, retVal.toString(), this);
+	} else {
+	    RamCloudKeyIndex keyIndex = new RamCloudKeyIndex(graph.kidxVertTableId, key, retVal, graph, Edge.class);
+	    keyIndex.autoRemove(key, retVal.toString(), this);
+	}
+
+	return retVal;
+    }
+
+    @Override
+    public void remove() {
+	graph.getRcClient().remove(rcPropTableId, rcPropTableKey);
+    }
+
+    @Override
+    public Object getId() {
+	// TODO Auto-generated method stub
+	return null;
+    }
+
+    @Override
+    public String toString() {
+	return "RamCloudElement [rcPropTableKey=" + Arrays.toString(rcPropTableKey)
+		+ ", rcPropTableId=" + rcPropTableId + "]";
+    }
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudGraph.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudGraph.java
new file mode 100644
index 0000000..8247bc8
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudGraph.java
@@ -0,0 +1,710 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.core.util.Base64;
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Element;
+import com.tinkerpop.blueprints.Features;
+import com.tinkerpop.blueprints.GraphQuery;
+import com.tinkerpop.blueprints.Index;
+import com.tinkerpop.blueprints.IndexableGraph;
+import com.tinkerpop.blueprints.KeyIndexableGraph;
+import com.tinkerpop.blueprints.Parameter;
+import com.tinkerpop.blueprints.TransactionalGraph;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.DefaultGraphQuery;
+import com.tinkerpop.blueprints.util.ExceptionFactory;
+import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
+
+import edu.stanford.ramcloud.JRamCloud;
+import edu.stanford.ramcloud.JRamCloud.MultiWriteObject;
+
+public class RamCloudGraph implements IndexableGraph, KeyIndexableGraph, TransactionalGraph, Serializable {
+    private final static Logger log = LoggerFactory.getLogger(RamCloudGraph.class);
+
+    private static final ThreadLocal<JRamCloud> RamCloudThreadLocal = new ThreadLocal<JRamCloud>();
+
+    protected long vertTableId; //(vertex_id) --> ( (n,d,ll,l), (n,d,ll,l), ... )
+    protected long vertPropTableId; //(vertex_id) -> ( (kl,k,vl,v), (kl,k,vl,v), ... )
+    protected long edgePropTableId; //(edge_id) -> ( (kl,k,vl,v), (kl,k,vl,v), ... )
+    protected long idxVertTableId;
+    protected long idxEdgeTableId;
+    protected long kidxVertTableId;
+    protected long kidxEdgeTableId;
+    protected long instanceTableId;
+    private String VERT_TABLE_NAME = "verts";
+    private String EDGE_PROP_TABLE_NAME = "edge_props";
+    private String VERT_PROP_TABLE_NAME = "vert_props";
+    private String IDX_VERT_TABLE_NAME = "idx_vert";
+    private String IDX_EDGE_TABLE_NAME = "idx_edge";
+    private String KIDX_VERT_TABLE_NAME = "kidx_vert";
+    private String KIDX_EDGE_TABLE_NAME = "kidx_edge";
+    private final String INSTANCE_TABLE_NAME = "instance";
+    private long instanceId;
+    private AtomicLong nextVertexId;
+    private final long INSTANCE_ID_RANGE = 100000;
+    private String coordinatorLocation;
+    private static final Features FEATURES = new Features();
+    public final long measureBPTimeProp = Long.valueOf(System.getProperty("benchmark.measureBP", "0"));
+    public final long measureRcTimeProp = Long.valueOf(System.getProperty("benchmark.measureRc", "0"));
+    public static final long measureSerializeTimeProp = Long.valueOf(System.getProperty("benchmark.measureSerializeTimeProp", "0"));
+
+
+    public final Set<String> indexedKeys = new HashSet<String>();
+
+    static {
+	FEATURES.supportsSerializableObjectProperty = true;
+	FEATURES.supportsBooleanProperty = true;
+	FEATURES.supportsDoubleProperty = true;
+	FEATURES.supportsFloatProperty = true;
+	FEATURES.supportsIntegerProperty = true;
+	FEATURES.supportsPrimitiveArrayProperty = true;
+	FEATURES.supportsUniformListProperty = true;
+	FEATURES.supportsMixedListProperty = true;
+	FEATURES.supportsLongProperty = true;
+	FEATURES.supportsMapProperty = true;
+	FEATURES.supportsStringProperty = true;
+
+	FEATURES.supportsDuplicateEdges = false;
+	FEATURES.supportsSelfLoops = false;
+	FEATURES.isPersistent = false;
+	FEATURES.isWrapper = false;
+	FEATURES.supportsVertexIteration = true;
+	FEATURES.supportsEdgeIteration = true;
+	FEATURES.supportsVertexIndex = true;
+	FEATURES.supportsEdgeIndex = false;
+	FEATURES.ignoresSuppliedIds = true;
+	FEATURES.supportsTransactions = false;
+	FEATURES.supportsIndices = false;
+	FEATURES.supportsKeyIndices = true;
+	FEATURES.supportsVertexKeyIndex = true;
+	FEATURES.supportsEdgeKeyIndex = false;
+	FEATURES.supportsEdgeRetrieval = true;
+	FEATURES.supportsVertexProperties = true;
+	FEATURES.supportsEdgeProperties = true;
+	FEATURES.supportsThreadedTransactions = false;
+    }
+
+    static {
+	System.loadLibrary("edu_stanford_ramcloud_JRamCloud");
+    }
+
+    private RamCloudGraph() {
+    }
+
+
+    public RamCloudGraph(String coordinatorLocation) {
+	this.coordinatorLocation = coordinatorLocation;
+
+	JRamCloud rcClient = getRcClient();
+
+	vertTableId = rcClient.createTable(VERT_TABLE_NAME);
+	vertPropTableId = rcClient.createTable(VERT_PROP_TABLE_NAME);
+	edgePropTableId = rcClient.createTable(EDGE_PROP_TABLE_NAME);
+	idxVertTableId = rcClient.createTable(IDX_VERT_TABLE_NAME);
+	idxEdgeTableId = rcClient.createTable(IDX_EDGE_TABLE_NAME);
+	kidxVertTableId = rcClient.createTable(KIDX_VERT_TABLE_NAME);
+	kidxEdgeTableId = rcClient.createTable(KIDX_EDGE_TABLE_NAME);
+	instanceTableId = rcClient.createTable(INSTANCE_TABLE_NAME);
+
+	log.info( "Connected to coordinator at {}", coordinatorLocation);
+	log.debug("VERT_TABLE:{}, VERT_PROP_TABLE:{}, EDGE_PROP_TABLE:{}, IDX_VERT_TABLE:{}, IDX_EDGE_TABLE:{}, KIDX_VERT_TABLE:{}, KIDX_EDGE_TABLE:{}", vertTableId, vertPropTableId, edgePropTableId, idxVertTableId, idxEdgeTableId, kidxVertTableId, kidxEdgeTableId);
+	nextVertexId = new AtomicLong(-1);
+        initInstance();
+    }
+
+    public JRamCloud getRcClient() {
+	JRamCloud rcClient = RamCloudThreadLocal.get();
+	if (rcClient == null) {
+	    rcClient = new JRamCloud(coordinatorLocation);
+	    RamCloudThreadLocal.set(rcClient);
+	}
+	return rcClient;
+    }
+
+    @Override
+    public Features getFeatures() {
+	return FEATURES;
+    }
+
+    private Long parseVertexId(Object id) {
+	Long longId;
+	if (id == null) {
+	    longId = nextVertexId.incrementAndGet();
+	} else if (id instanceof Integer) {
+	    longId = ((Integer) id).longValue();
+	} else if (id instanceof Long) {
+	    longId = (Long) id;
+	} else if (id instanceof String) {
+	    try {
+		longId = Long.parseLong((String) id, 10);
+	    } catch (NumberFormatException e) {
+		log.warn("ID argument {} of type {} is not a parseable long number: {}", id, id.getClass(), e);
+		return null;
+	    }
+	} else if (id instanceof byte[]) {
+	    try {
+		longId = ByteBuffer.wrap((byte[]) id).getLong();
+	    } catch (BufferUnderflowException e) {
+		log.warn("ID argument {} of type {} is not a parseable long number: {}", id, id.getClass(), e);
+		return null;
+	    }
+	} else {
+	    log.warn("ID argument {} of type {} is not supported. Returning null.", id, id.getClass());
+	    return null;
+	}
+	return longId;
+    }
+
+    @Override
+    public Vertex addVertex(Object id) {
+	long startTime = 0;
+	long Tstamp1 = 0;
+	long Tstamp2 = 0;
+
+	if (measureBPTimeProp == 1) {
+	    startTime = System.nanoTime();
+	}
+	Long longId = parseVertexId(id);
+	if (longId == null)
+	    return null;
+	if (measureBPTimeProp == 1) {
+	    Tstamp1 = System.nanoTime();
+	}
+	RamCloudVertex newVertex = new RamCloudVertex(longId, this);
+	if (measureBPTimeProp == 1) {
+	    Tstamp2 = System.nanoTime();
+	    log.error("Performance addVertex [id={}] : Calling create at {}", longId, Tstamp2);
+	}
+
+	try {
+	    newVertex.create();
+	    if (measureBPTimeProp == 1) {
+		long endTime = System.nanoTime();
+		log.error("Performance addVertex [id={}] : genid {} newVerex {} create {} total time {}", longId, Tstamp1 - startTime, Tstamp2 - Tstamp1, endTime - Tstamp2, endTime - startTime);
+	    }
+	    log.info("Added vertex: [id={}]", longId);
+	    return newVertex;
+	} catch (IllegalArgumentException e) {
+	    log.error("Tried to create vertex failed {" + newVertex + "}", e);
+	    return null;
+	}
+    }
+
+    public List<RamCloudVertex> addVertices(Iterable<Object> ids) {
+	log.info("addVertices start");
+	List<RamCloudVertex> vertices = new LinkedList<RamCloudVertex>();
+
+	for (Object id: ids) {
+	    Long longId = parseVertexId(id);
+	    if (longId == null)
+		return null;
+	    RamCloudVertex v = new RamCloudVertex(longId, this);
+	    if (v.exists()) {
+		log.error("ramcloud vertex id: {} already exists", v.getId());
+		throw ExceptionFactory.vertexWithIdAlreadyExists(v.getId());
+	    }
+	    vertices.add(v);
+	}
+	MultiWriteObject multiWriteObjects[] = new MultiWriteObject[vertices.size() * 2];
+	for (int i=0; i < vertices.size(); i++) {
+	    RamCloudVertex v = vertices.get(i);
+	    multiWriteObjects[i*2] = new MultiWriteObject(vertTableId, v.rcKey, ByteBuffer.allocate(0).array(), null);
+	    multiWriteObjects[i*2+1] = new MultiWriteObject(vertPropTableId, v.rcKey, ByteBuffer.allocate(0).array(), null);
+	}
+	try {
+		PerfMon pm = PerfMon.getInstance();
+		pm.multiwrite_start("RamCloudVertex create()");
+	    getRcClient().multiWrite(multiWriteObjects);
+		pm.multiwrite_end("RamCloudVertex create()");
+	    log.info("ramcloud vertices are created");
+	} catch (Exception e) {
+	    log.error("Tried to create vertices failed {}", e);
+	    return null;
+	}
+	log.info("addVertices end (success)");
+	return vertices;
+    }
+
+    private final void initInstance() {
+        //long incrementValue = 1;
+        JRamCloud.Object instanceEntry = null;
+        JRamCloud rcClient = getRcClient();
+        try {
+            instanceEntry = rcClient.read(instanceTableId, "nextInstanceId".getBytes());
+        } catch (Exception e) {
+            if (e instanceof JRamCloud.ObjectDoesntExistException) {
+                instanceId = 0;
+                rcClient.write(instanceTableId, "nextInstanceId".getBytes(), ByteBuffer.allocate(0).array());
+            }
+        }
+        if (instanceEntry != null) {
+	    long curInstanceId = 1;
+	    for (int i = 0 ; i < 100 ; i++) {
+		Map<String, Long> propMap = null;
+		if (instanceEntry.value == null) {
+		    log.warn("Got a null byteArray argument");
+		    return;
+		} else if (instanceEntry.value.length != 0) {
+		    try {
+			ByteArrayInputStream bais = new ByteArrayInputStream(instanceEntry.value);
+			ObjectInputStream ois = new ObjectInputStream(bais);
+			propMap = (Map<String, Long>) ois.readObject();
+		    } catch (IOException e) {
+			log.error("Got an exception while deserializing element's property map: ", e);
+			return;
+		    } catch (ClassNotFoundException e) {
+			log.error("Got an exception while deserializing element's property map: ", e);
+			return;
+		    }
+		} else {
+		    propMap = new HashMap<String, Long>();
+		}
+
+		if (propMap.containsKey(INSTANCE_TABLE_NAME)) {
+		    curInstanceId = propMap.get(INSTANCE_TABLE_NAME) + 1;
+		}
+
+		propMap.put(INSTANCE_TABLE_NAME, curInstanceId);
+
+		byte[] rcValue = null;
+		try {
+		    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		    ObjectOutputStream oot = new ObjectOutputStream(baos);
+		    oot.writeObject(propMap);
+		    rcValue = baos.toByteArray();
+		} catch (IOException e) {
+		    log.error("Got an exception while serializing element's property map", e);
+		    return;
+		}
+		JRamCloud.RejectRules rules = rcClient.new RejectRules();
+		rules.setNeVersion(instanceEntry.version);
+		try {
+		    rcClient.writeRule(instanceTableId, "nextInstanceId".getBytes(), rcValue, rules);
+		    instanceId = curInstanceId;
+		    break;
+		} catch (Exception ex) {
+		    log.debug("Cond. Write increment Vertex property: ", ex);
+		    instanceEntry = rcClient.read(instanceTableId, "nextInstanceId".getBytes());
+		    continue;
+		}
+	    }
+	}
+
+	nextVertexId.compareAndSet(-1, instanceId * INSTANCE_ID_RANGE);
+    }
+
+    @Override
+    public Vertex getVertex(Object id) throws IllegalArgumentException {
+	Long longId;
+
+	if (id == null) {
+	    throw ExceptionFactory.vertexIdCanNotBeNull();
+	} else if (id instanceof Integer) {
+	    longId = ((Integer) id).longValue();
+	} else if (id instanceof Long) {
+	    longId = (Long) id;
+	} else if (id instanceof String) {
+	    try {
+		longId = Long.parseLong((String) id, 10);
+	    } catch (NumberFormatException e) {
+		log.warn("ID argument {} of type {} is not a parseable long number: {}", id, id.getClass(), e);
+		return null;
+	    }
+	} else if (id instanceof byte[]) {
+	    try {
+		longId = ByteBuffer.wrap((byte[]) id).getLong();
+	    } catch (BufferUnderflowException e) {
+		log.warn("ID argument {} of type {} is not a parseable long number: {}", id, id.getClass(), e);
+		return null;
+	    }
+	} else {
+	    log.warn("ID argument {} of type {} is not supported. Returning null.", id, id.getClass());
+	    return null;
+	}
+
+	RamCloudVertex vertex = new RamCloudVertex(longId, this);
+
+	if (vertex.exists()) {
+	    return vertex;
+	} else {
+	    return null;
+	}
+    }
+
+    @Override
+    public void removeVertex(Vertex vertex) {
+	((RamCloudVertex) vertex).remove();
+    }
+
+    @Override
+    public Iterable<Vertex> getVertices() {
+	JRamCloud.TableEnumerator tableEnum = getRcClient().new TableEnumerator(vertPropTableId);
+	List<Vertex> vertices = new LinkedList<Vertex>();
+
+	while (tableEnum.hasNext()) {
+		vertices.add(new RamCloudVertex(tableEnum.next().key, this));
+	}
+
+	return vertices;
+    }
+
+    @Override
+    public Iterable<Vertex> getVertices(String key, Object value) {
+	long startTime = 0;
+	long Tstamp1 = 0;
+	long Tstamp2 = 0;
+	long Tstamp3 = 0;
+	if (measureBPTimeProp == 1) {
+	    startTime = System.nanoTime();
+	    log.error("Performance getVertices(key {}) start at {}", key, startTime);
+	}
+
+	List<Vertex> vertices = new ArrayList<Vertex>();
+	List<Object> vertexList = null;
+
+	JRamCloud vertTable = getRcClient();
+	if (measureBPTimeProp == 1) {
+	    Tstamp1 = System.nanoTime();
+	    log.error("Performance getVertices(key {}) Calling indexedKeys.contains(key) at {}", key, Tstamp1);
+	}
+
+
+	if (indexedKeys.contains(key)) {
+	    PerfMon pm = PerfMon.getInstance();
+	    if (measureBPTimeProp == 1) {
+	      Tstamp2 = System.nanoTime();
+	      log.error("Performance getVertices(key {}) Calling new RamCloudKeyIndex at {}", key, Tstamp2);
+	    }
+	    RamCloudKeyIndex KeyIndex = new RamCloudKeyIndex(kidxVertTableId, key, value, this, Vertex.class);
+	    if (measureBPTimeProp == 1) {
+	      Tstamp3 = System.nanoTime();
+	      log.error("Performance getVertices(key {}) Calling KeyIndex.GetElmIdListForPropValue at {}", key, Tstamp3);
+	    }
+	    vertexList = KeyIndex.getElmIdListForPropValue(value.toString());
+	    if (vertexList == null) {
+		if (measureBPTimeProp == 1) {
+		    long endTime = System.nanoTime();
+		    log.error("Performance getVertices(key {}) does not exists : getRcClient {} indexedKeys.contains(key) {} new_RamCloudKeyIndex {} KeyIndex.get..Value {} total {} diff {}", key, Tstamp1-startTime, Tstamp2-Tstamp1,Tstamp3-Tstamp2, endTime-Tstamp3, endTime - startTime, (endTime-startTime)- (Tstamp1-startTime)- (Tstamp2-Tstamp1)- (Tstamp3-Tstamp2)-(endTime-Tstamp3));
+		}
+		return vertices;
+	    }
+
+	    final int mreadMax = 400;
+	    final int size = Math.min(mreadMax, vertexList.size());
+	    JRamCloud.multiReadObject vertPropTableMread[] = new JRamCloud.multiReadObject[size];
+
+	    int vertexNum = 0;
+	    for (Object vert : vertexList) {
+		byte[] rckey =
+			ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong((Long) vert).array();
+		vertPropTableMread[vertexNum] = new JRamCloud.multiReadObject(vertPropTableId, rckey);
+		if (vertexNum >= (mreadMax - 1)) {
+		    pm.multiread_start("RamCloudGraph getVertices()");
+		    JRamCloud.Object outvertPropTable[] =
+			    vertTable.multiRead(vertPropTableMread);
+		    pm.multiread_end("RamCloudGraph getVertices()");
+		    for (int i = 0; i < outvertPropTable.length; i++) {
+			if (outvertPropTable[i] != null) {
+			    vertices.add(new RamCloudVertex(outvertPropTable[i].key, this));
+			}
+		    }
+		    vertexNum = 0;
+		    continue;
+		}
+		vertexNum++;
+	    }
+
+	    if (vertexNum != 0) {
+		JRamCloud.multiReadObject mread_leftover[] = Arrays.copyOf(vertPropTableMread, vertexNum);
+
+		long startTime2 = 0;
+		if (measureRcTimeProp == 1) {
+		    startTime2 = System.nanoTime();
+		}
+		pm.multiread_start("RamCloudGraph getVertices()");
+		JRamCloud.Object outvertPropTable[] = vertTable.multiRead(mread_leftover);
+		pm.multiread_end("RamCloudGraph getVertices()");
+		if (measureRcTimeProp == 1) {
+		    long endTime2 = System.nanoTime();
+		    log.error("Performance index multiread(key {}, number {}) time {}", key, vertexNum, endTime2 - startTime2);
+		}
+		for (int i = 0; i < outvertPropTable.length; i++) {
+		    if (outvertPropTable[i] != null) {
+			vertices.add(new RamCloudVertex(outvertPropTable[i].key, this));
+		    }
+		}
+	    }
+	} else {
+
+	    JRamCloud.TableEnumerator tableEnum = getRcClient().new TableEnumerator(vertPropTableId);
+	    JRamCloud.Object tableEntry;
+
+	    while (tableEnum.hasNext()) {
+		tableEntry = tableEnum.next();
+		if (tableEntry != null) {
+		    //XXX remove temp
+		    // RamCloudVertex temp = new RamCloudVertex(tableEntry.key, this);
+		    Map<String, Object> propMap = RamCloudElement.convertRcBytesToPropertyMapEx(tableEntry.value);
+		    if (propMap.containsKey(key) && propMap.get(key).equals(value)) {
+			vertices.add(new RamCloudVertex(tableEntry.key, this));
+		    }
+		}
+	    }
+	}
+
+	if (measureBPTimeProp == 1) {
+		long endTime = System.nanoTime();
+		log.error("Performance getVertices exists total time {}.", endTime - startTime);
+	}
+
+	return vertices;
+    }
+
+    @Override
+    public Edge addEdge(Object id, Vertex outVertex, Vertex inVertex, String label) throws IllegalArgumentException {
+	log.info("Adding edge: [id={}, outVertex={}, inVertex={}, label={}]", id, outVertex, inVertex, label);
+
+	if (label == null) {
+	    throw ExceptionFactory.edgeLabelCanNotBeNull();
+	}
+
+	RamCloudEdge newEdge = new RamCloudEdge((RamCloudVertex) outVertex, (RamCloudVertex) inVertex, label, this);
+
+	for (int i = 0; i < 5 ;i++) {
+	    try {
+		newEdge.create();
+		return newEdge;
+	    } catch (Exception e) {
+		log.warn("Tried to create edge failed: {" + newEdge + "}: ", e);
+
+		if (e instanceof NoSuchElementException) {
+		    log.error("addEdge RETRYING {}", i);
+		    continue;
+		}
+	    }
+	}
+	return null;
+    }
+
+    public List<Edge> addEdges(Iterable<Edge> edgeEntities) throws IllegalArgumentException {
+	//TODO WIP: need multi-write
+	log.info("addEdges start");
+	ArrayList<Edge> edges = new ArrayList<Edge>();
+	for (Edge edge: edgeEntities) {
+	    edges.add(addEdge(null, edge.getVertex(Direction.OUT), edge.getVertex(Direction.IN), edge.getLabel()));
+	}
+	log.info("addVertices end");
+	return edges;
+    }
+
+    public void setProperties(Map<RamCloudVertex, Map<String, Object>> properties) {
+	// TODO WIP: need multi-write
+	log.info("setProperties start");
+	for (Map.Entry<RamCloudVertex, Map<String, Object>> e: properties.entrySet()) {
+	    e.getKey().setProperties(e.getValue());
+	}
+	log.info("setProperties end");
+    }
+
+    @Override
+    public Edge getEdge(Object id) throws IllegalArgumentException {
+	byte[] bytearrayId;
+
+	if (id == null) {
+	    throw ExceptionFactory.edgeIdCanNotBeNull();
+	} else if (id instanceof byte[]) {
+	    bytearrayId = (byte[]) id;
+	} else if (id instanceof String) {
+	    bytearrayId = Base64.decode(((String) id));
+	} else {
+	    log.warn("ID argument {} of type {} is not supported. Returning null.", id, id.getClass());
+	    return null;
+	}
+
+	if (!RamCloudEdge.isValidEdgeId(bytearrayId)) {
+	    log.warn("ID argument {} of type {} is malformed. Returning null.", id, id.getClass());
+	    return null;
+	}
+
+	RamCloudEdge edge = new RamCloudEdge(bytearrayId, this);
+
+	if (edge.exists()) {
+	    return edge;
+	} else {
+	    return null;
+	}
+    }
+
+    @Override
+    public void removeEdge(Edge edge) {
+	edge.remove();
+    }
+
+    @Override
+    public Iterable<Edge> getEdges() {
+	JRamCloud.TableEnumerator tableEnum = getRcClient().new TableEnumerator(edgePropTableId);
+	List<Edge> edges = new ArrayList<Edge>();
+
+	while (tableEnum.hasNext()) {
+	    edges.add(new RamCloudEdge(tableEnum.next().key, this));
+	}
+
+	return edges;
+    }
+
+    @Override
+    public Iterable<Edge> getEdges(String key, Object value) {
+	JRamCloud.TableEnumerator tableEnum = getRcClient().new TableEnumerator(edgePropTableId);
+	List<Edge> edges = new ArrayList<Edge>();
+	JRamCloud.Object tableEntry;
+
+	while (tableEnum.hasNext()) {
+	    tableEntry = tableEnum.next();
+		// FIXME temp
+		//RamCloudEdge temp = new RamCloudEdge(tableEntry.key, this);
+	    Map<String, Object> propMap = RamCloudElement.convertRcBytesToPropertyMapEx(tableEntry.value);
+	    if (propMap.containsKey(key) && propMap.get(key).equals(value)) {
+		edges.add(new RamCloudEdge(tableEntry.key, this));
+	    }
+	}
+
+	return edges;
+    }
+
+    @Override
+    public GraphQuery query() {
+	return new DefaultGraphQuery(this);
+    }
+
+    @Override
+    public void shutdown() {
+	JRamCloud rcClient = getRcClient();
+	rcClient.dropTable(VERT_TABLE_NAME);
+	rcClient.dropTable(VERT_PROP_TABLE_NAME);
+	rcClient.dropTable(EDGE_PROP_TABLE_NAME);
+	rcClient.dropTable(IDX_VERT_TABLE_NAME);
+	rcClient.dropTable(IDX_EDGE_TABLE_NAME);
+	rcClient.dropTable(KIDX_VERT_TABLE_NAME);
+	rcClient.dropTable(KIDX_EDGE_TABLE_NAME);
+	rcClient.disconnect();
+    }
+
+    @Override
+    public void stopTransaction(Conclusion conclusion) {
+	// TODO Auto-generated method stub
+    }
+
+    @Override
+    public void commit() {
+	// TODO Auto-generated method stub
+    }
+
+    @Override
+    public void rollback() {
+	// TODO Auto-generated method stub
+    }
+
+    @Override
+    public <T extends Element> void dropKeyIndex(String key, Class<T> elementClass) {
+	throw new UnsupportedOperationException("Not supported yet.");
+	//FIXME how to dropKeyIndex
+	//new RamCloudKeyIndex(kidxVertTableId, key, this, elementClass);
+	//getIndexedKeys(key, elementClass).removeIndex();
+    }
+
+    @Override
+    public <T extends Element> void createKeyIndex(String key,
+	    Class<T> elementClass, Parameter... indexParameters) {
+	if (key == null) {
+	    return;
+	}
+	if (this.indexedKeys.contains(key)) {
+	    return;
+	}
+	this.indexedKeys.add(key);
+    }
+
+    @Override
+    public <T extends Element> Set< String> getIndexedKeys(Class< T> elementClass) {
+	if (null != this.indexedKeys) {
+	    return new HashSet<String>(this.indexedKeys);
+	} else {
+	    return Collections.emptySet();
+	}
+    }
+
+    @Override
+    public <T extends Element> Index<T> createIndex(String indexName,
+	    Class<T> indexClass, Parameter... indexParameters) {
+	throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public <T extends Element> Index<T> getIndex(String indexName, Class<T> indexClass) {
+	throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Iterable<Index<? extends Element>> getIndices() {
+	throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public void dropIndex(String indexName) {
+	throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public String toString() {
+	return getClass().getSimpleName().toLowerCase() + "[vertices:" + ((List<Vertex>)getVertices()).size() + " edges:" + ((List<Edge>)getEdges()).size() + "]";
+    }
+
+    public static void main(String[] args) {
+	RamCloudGraph graph = new RamCloudGraph();
+
+	Vertex a = graph.addVertex(null);
+	Vertex b = graph.addVertex(null);
+	Vertex c = graph.addVertex(null);
+	Vertex d = graph.addVertex(null);
+	Vertex e = graph.addVertex(null);
+	Vertex f = graph.addVertex(null);
+	Vertex g = graph.addVertex(null);
+
+	graph.addEdge(null, a, a, "friend");
+	graph.addEdge(null, a, b, "friend1");
+	graph.addEdge(null, a, b, "friend2");
+	graph.addEdge(null, a, b, "friend3");
+	graph.addEdge(null, a, c, "friend");
+	graph.addEdge(null, a, d, "friend");
+	graph.addEdge(null, a, e, "friend");
+	graph.addEdge(null, a, f, "friend");
+	graph.addEdge(null, a, g, "friend");
+
+	graph.shutdown();
+    }
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudGraphProtos.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudGraphProtos.java
new file mode 100644
index 0000000..9a126eb
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudGraphProtos.java
@@ -0,0 +1,3861 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: ramcloudgraph.proto
+
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+public final class RamCloudGraphProtos {
+  private RamCloudGraphProtos() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface EdgeListProtoBufOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // repeated .RamCloudGraph.EdgeProtoBuf edge = 1;
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf> 
+        getEdgeList();
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf getEdge(int index);
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    int getEdgeCount();
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    java.util.List<? extends com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder> 
+        getEdgeOrBuilderList();
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder getEdgeOrBuilder(
+        int index);
+  }
+  /**
+   * Protobuf type {@code RamCloudGraph.EdgeListProtoBuf}
+   */
+  public static final class EdgeListProtoBuf extends
+      com.google.protobuf.GeneratedMessage
+      implements EdgeListProtoBufOrBuilder {
+    // Use EdgeListProtoBuf.newBuilder() to construct.
+    private EdgeListProtoBuf(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private EdgeListProtoBuf(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final EdgeListProtoBuf defaultInstance;
+    public static EdgeListProtoBuf getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public EdgeListProtoBuf getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private EdgeListProtoBuf(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+                edge_ = new java.util.ArrayList<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf>();
+                mutable_bitField0_ |= 0x00000001;
+              }
+              edge_.add(input.readMessage(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.PARSER, extensionRegistry));
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+          edge_ = java.util.Collections.unmodifiableList(edge_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeListProtoBuf_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeListProtoBuf_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<EdgeListProtoBuf> PARSER =
+        new com.google.protobuf.AbstractParser<EdgeListProtoBuf>() {
+      public EdgeListProtoBuf parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new EdgeListProtoBuf(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<EdgeListProtoBuf> getParserForType() {
+      return PARSER;
+    }
+
+    // repeated .RamCloudGraph.EdgeProtoBuf edge = 1;
+    public static final int EDGE_FIELD_NUMBER = 1;
+    private java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf> edge_;
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    public java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf> getEdgeList() {
+      return edge_;
+    }
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    public java.util.List<? extends com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder> 
+        getEdgeOrBuilderList() {
+      return edge_;
+    }
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    public int getEdgeCount() {
+      return edge_.size();
+    }
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf getEdge(int index) {
+      return edge_.get(index);
+    }
+    /**
+     * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+     */
+    public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder getEdgeOrBuilder(
+        int index) {
+      return edge_.get(index);
+    }
+
+    private void initFields() {
+      edge_ = java.util.Collections.emptyList();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      for (int i = 0; i < getEdgeCount(); i++) {
+        if (!getEdge(i).isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      for (int i = 0; i < edge_.size(); i++) {
+        output.writeMessage(1, edge_.get(i));
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      for (int i = 0; i < edge_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, edge_.get(i));
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code RamCloudGraph.EdgeListProtoBuf}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBufOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeListProtoBuf_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeListProtoBuf_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf.Builder.class);
+      }
+
+      // Construct using com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getEdgeFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        if (edgeBuilder_ == null) {
+          edge_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+        } else {
+          edgeBuilder_.clear();
+        }
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeListProtoBuf_descriptor;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf getDefaultInstanceForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf.getDefaultInstance();
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf build() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf buildPartial() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf result = new com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf(this);
+        int from_bitField0_ = bitField0_;
+        if (edgeBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) == 0x00000001)) {
+            edge_ = java.util.Collections.unmodifiableList(edge_);
+            bitField0_ = (bitField0_ & ~0x00000001);
+          }
+          result.edge_ = edge_;
+        } else {
+          result.edge_ = edgeBuilder_.build();
+        }
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf) {
+          return mergeFrom((com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf other) {
+        if (other == com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf.getDefaultInstance()) return this;
+        if (edgeBuilder_ == null) {
+          if (!other.edge_.isEmpty()) {
+            if (edge_.isEmpty()) {
+              edge_ = other.edge_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+            } else {
+              ensureEdgeIsMutable();
+              edge_.addAll(other.edge_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.edge_.isEmpty()) {
+            if (edgeBuilder_.isEmpty()) {
+              edgeBuilder_.dispose();
+              edgeBuilder_ = null;
+              edge_ = other.edge_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+              edgeBuilder_ = 
+                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+                   getEdgeFieldBuilder() : null;
+            } else {
+              edgeBuilder_.addAllMessages(other.edge_);
+            }
+          }
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        for (int i = 0; i < getEdgeCount(); i++) {
+          if (!getEdge(i).isInitialized()) {
+            
+            return false;
+          }
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // repeated .RamCloudGraph.EdgeProtoBuf edge = 1;
+      private java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf> edge_ =
+        java.util.Collections.emptyList();
+      private void ensureEdgeIsMutable() {
+        if (!((bitField0_ & 0x00000001) == 0x00000001)) {
+          edge_ = new java.util.ArrayList<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf>(edge_);
+          bitField0_ |= 0x00000001;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilder<
+          com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder> edgeBuilder_;
+
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf> getEdgeList() {
+        if (edgeBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(edge_);
+        } else {
+          return edgeBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public int getEdgeCount() {
+        if (edgeBuilder_ == null) {
+          return edge_.size();
+        } else {
+          return edgeBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf getEdge(int index) {
+        if (edgeBuilder_ == null) {
+          return edge_.get(index);
+        } else {
+          return edgeBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder setEdge(
+          int index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf value) {
+        if (edgeBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureEdgeIsMutable();
+          edge_.set(index, value);
+          onChanged();
+        } else {
+          edgeBuilder_.setMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder setEdge(
+          int index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder builderForValue) {
+        if (edgeBuilder_ == null) {
+          ensureEdgeIsMutable();
+          edge_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          edgeBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder addEdge(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf value) {
+        if (edgeBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureEdgeIsMutable();
+          edge_.add(value);
+          onChanged();
+        } else {
+          edgeBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder addEdge(
+          int index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf value) {
+        if (edgeBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureEdgeIsMutable();
+          edge_.add(index, value);
+          onChanged();
+        } else {
+          edgeBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder addEdge(
+          com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder builderForValue) {
+        if (edgeBuilder_ == null) {
+          ensureEdgeIsMutable();
+          edge_.add(builderForValue.build());
+          onChanged();
+        } else {
+          edgeBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder addEdge(
+          int index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder builderForValue) {
+        if (edgeBuilder_ == null) {
+          ensureEdgeIsMutable();
+          edge_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          edgeBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder addAllEdge(
+          java.lang.Iterable<? extends com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf> values) {
+        if (edgeBuilder_ == null) {
+          ensureEdgeIsMutable();
+          super.addAll(values, edge_);
+          onChanged();
+        } else {
+          edgeBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder clearEdge() {
+        if (edgeBuilder_ == null) {
+          edge_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+          onChanged();
+        } else {
+          edgeBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public Builder removeEdge(int index) {
+        if (edgeBuilder_ == null) {
+          ensureEdgeIsMutable();
+          edge_.remove(index);
+          onChanged();
+        } else {
+          edgeBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder getEdgeBuilder(
+          int index) {
+        return getEdgeFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder getEdgeOrBuilder(
+          int index) {
+        if (edgeBuilder_ == null) {
+          return edge_.get(index);  } else {
+          return edgeBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public java.util.List<? extends com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder> 
+           getEdgeOrBuilderList() {
+        if (edgeBuilder_ != null) {
+          return edgeBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(edge_);
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder addEdgeBuilder() {
+        return getEdgeFieldBuilder().addBuilder(
+            com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder addEdgeBuilder(
+          int index) {
+        return getEdgeFieldBuilder().addBuilder(
+            index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .RamCloudGraph.EdgeProtoBuf edge = 1;</code>
+       */
+      public java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder> 
+           getEdgeBuilderList() {
+        return getEdgeFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilder<
+          com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder> 
+          getEdgeFieldBuilder() {
+        if (edgeBuilder_ == null) {
+          edgeBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+              com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder>(
+                  edge_,
+                  ((bitField0_ & 0x00000001) == 0x00000001),
+                  getParentForChildren(),
+                  isClean());
+          edge_ = null;
+        }
+        return edgeBuilder_;
+      }
+
+      // @@protoc_insertion_point(builder_scope:RamCloudGraph.EdgeListProtoBuf)
+    }
+
+    static {
+      defaultInstance = new EdgeListProtoBuf(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:RamCloudGraph.EdgeListProtoBuf)
+  }
+
+  public interface EdgeProtoBufOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required uint64 neighborId = 1;
+    /**
+     * <code>required uint64 neighborId = 1;</code>
+     */
+    boolean hasNeighborId();
+    /**
+     * <code>required uint64 neighborId = 1;</code>
+     */
+    long getNeighborId();
+
+    // required bool outgoing = 2;
+    /**
+     * <code>required bool outgoing = 2;</code>
+     */
+    boolean hasOutgoing();
+    /**
+     * <code>required bool outgoing = 2;</code>
+     */
+    boolean getOutgoing();
+
+    // required string label = 3;
+    /**
+     * <code>required string label = 3;</code>
+     */
+    boolean hasLabel();
+    /**
+     * <code>required string label = 3;</code>
+     */
+    java.lang.String getLabel();
+    /**
+     * <code>required string label = 3;</code>
+     */
+    com.google.protobuf.ByteString
+        getLabelBytes();
+  }
+  /**
+   * Protobuf type {@code RamCloudGraph.EdgeProtoBuf}
+   */
+  public static final class EdgeProtoBuf extends
+      com.google.protobuf.GeneratedMessage
+      implements EdgeProtoBufOrBuilder {
+    // Use EdgeProtoBuf.newBuilder() to construct.
+    private EdgeProtoBuf(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private EdgeProtoBuf(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final EdgeProtoBuf defaultInstance;
+    public static EdgeProtoBuf getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public EdgeProtoBuf getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private EdgeProtoBuf(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              neighborId_ = input.readUInt64();
+              break;
+            }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              outgoing_ = input.readBool();
+              break;
+            }
+            case 26: {
+              bitField0_ |= 0x00000004;
+              label_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeProtoBuf_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeProtoBuf_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<EdgeProtoBuf> PARSER =
+        new com.google.protobuf.AbstractParser<EdgeProtoBuf>() {
+      public EdgeProtoBuf parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new EdgeProtoBuf(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<EdgeProtoBuf> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required uint64 neighborId = 1;
+    public static final int NEIGHBORID_FIELD_NUMBER = 1;
+    private long neighborId_;
+    /**
+     * <code>required uint64 neighborId = 1;</code>
+     */
+    public boolean hasNeighborId() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required uint64 neighborId = 1;</code>
+     */
+    public long getNeighborId() {
+      return neighborId_;
+    }
+
+    // required bool outgoing = 2;
+    public static final int OUTGOING_FIELD_NUMBER = 2;
+    private boolean outgoing_;
+    /**
+     * <code>required bool outgoing = 2;</code>
+     */
+    public boolean hasOutgoing() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required bool outgoing = 2;</code>
+     */
+    public boolean getOutgoing() {
+      return outgoing_;
+    }
+
+    // required string label = 3;
+    public static final int LABEL_FIELD_NUMBER = 3;
+    private java.lang.Object label_;
+    /**
+     * <code>required string label = 3;</code>
+     */
+    public boolean hasLabel() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>required string label = 3;</code>
+     */
+    public java.lang.String getLabel() {
+      java.lang.Object ref = label_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          label_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string label = 3;</code>
+     */
+    public com.google.protobuf.ByteString
+        getLabelBytes() {
+      java.lang.Object ref = label_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        label_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      neighborId_ = 0L;
+      outgoing_ = false;
+      label_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasNeighborId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasOutgoing()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasLabel()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeUInt64(1, neighborId_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBool(2, outgoing_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, getLabelBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeUInt64Size(1, neighborId_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(2, outgoing_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, getLabelBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code RamCloudGraph.EdgeProtoBuf}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBufOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeProtoBuf_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeProtoBuf_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.Builder.class);
+      }
+
+      // Construct using com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        neighborId_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        outgoing_ = false;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        label_ = "";
+        bitField0_ = (bitField0_ & ~0x00000004);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_EdgeProtoBuf_descriptor;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf getDefaultInstanceForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.getDefaultInstance();
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf build() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf buildPartial() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf result = new com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.neighborId_ = neighborId_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.outgoing_ = outgoing_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.label_ = label_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf) {
+          return mergeFrom((com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf other) {
+        if (other == com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf.getDefaultInstance()) return this;
+        if (other.hasNeighborId()) {
+          setNeighborId(other.getNeighborId());
+        }
+        if (other.hasOutgoing()) {
+          setOutgoing(other.getOutgoing());
+        }
+        if (other.hasLabel()) {
+          bitField0_ |= 0x00000004;
+          label_ = other.label_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasNeighborId()) {
+          
+          return false;
+        }
+        if (!hasOutgoing()) {
+          
+          return false;
+        }
+        if (!hasLabel()) {
+          
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required uint64 neighborId = 1;
+      private long neighborId_ ;
+      /**
+       * <code>required uint64 neighborId = 1;</code>
+       */
+      public boolean hasNeighborId() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required uint64 neighborId = 1;</code>
+       */
+      public long getNeighborId() {
+        return neighborId_;
+      }
+      /**
+       * <code>required uint64 neighborId = 1;</code>
+       */
+      public Builder setNeighborId(long value) {
+        bitField0_ |= 0x00000001;
+        neighborId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required uint64 neighborId = 1;</code>
+       */
+      public Builder clearNeighborId() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        neighborId_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required bool outgoing = 2;
+      private boolean outgoing_ ;
+      /**
+       * <code>required bool outgoing = 2;</code>
+       */
+      public boolean hasOutgoing() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required bool outgoing = 2;</code>
+       */
+      public boolean getOutgoing() {
+        return outgoing_;
+      }
+      /**
+       * <code>required bool outgoing = 2;</code>
+       */
+      public Builder setOutgoing(boolean value) {
+        bitField0_ |= 0x00000002;
+        outgoing_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required bool outgoing = 2;</code>
+       */
+      public Builder clearOutgoing() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        outgoing_ = false;
+        onChanged();
+        return this;
+      }
+
+      // required string label = 3;
+      private java.lang.Object label_ = "";
+      /**
+       * <code>required string label = 3;</code>
+       */
+      public boolean hasLabel() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>required string label = 3;</code>
+       */
+      public java.lang.String getLabel() {
+        java.lang.Object ref = label_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          label_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string label = 3;</code>
+       */
+      public com.google.protobuf.ByteString
+          getLabelBytes() {
+        java.lang.Object ref = label_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          label_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string label = 3;</code>
+       */
+      public Builder setLabel(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        label_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string label = 3;</code>
+       */
+      public Builder clearLabel() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        label_ = getDefaultInstance().getLabel();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string label = 3;</code>
+       */
+      public Builder setLabelBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        label_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:RamCloudGraph.EdgeProtoBuf)
+    }
+
+    static {
+      defaultInstance = new EdgeProtoBuf(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:RamCloudGraph.EdgeProtoBuf)
+  }
+
+  public interface PropertyListProtoBufOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // repeated .RamCloudGraph.PropertyProtoBuf property = 1;
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf> 
+        getPropertyList();
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf getProperty(int index);
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    int getPropertyCount();
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    java.util.List<? extends com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder> 
+        getPropertyOrBuilderList();
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder getPropertyOrBuilder(
+        int index);
+  }
+  /**
+   * Protobuf type {@code RamCloudGraph.PropertyListProtoBuf}
+   */
+  public static final class PropertyListProtoBuf extends
+      com.google.protobuf.GeneratedMessage
+      implements PropertyListProtoBufOrBuilder {
+    // Use PropertyListProtoBuf.newBuilder() to construct.
+    private PropertyListProtoBuf(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private PropertyListProtoBuf(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final PropertyListProtoBuf defaultInstance;
+    public static PropertyListProtoBuf getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public PropertyListProtoBuf getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private PropertyListProtoBuf(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+                property_ = new java.util.ArrayList<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf>();
+                mutable_bitField0_ |= 0x00000001;
+              }
+              property_.add(input.readMessage(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.PARSER, extensionRegistry));
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+          property_ = java.util.Collections.unmodifiableList(property_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyListProtoBuf_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyListProtoBuf_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<PropertyListProtoBuf> PARSER =
+        new com.google.protobuf.AbstractParser<PropertyListProtoBuf>() {
+      public PropertyListProtoBuf parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new PropertyListProtoBuf(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<PropertyListProtoBuf> getParserForType() {
+      return PARSER;
+    }
+
+    // repeated .RamCloudGraph.PropertyProtoBuf property = 1;
+    public static final int PROPERTY_FIELD_NUMBER = 1;
+    private java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf> property_;
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    public java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf> getPropertyList() {
+      return property_;
+    }
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    public java.util.List<? extends com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder> 
+        getPropertyOrBuilderList() {
+      return property_;
+    }
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    public int getPropertyCount() {
+      return property_.size();
+    }
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf getProperty(int index) {
+      return property_.get(index);
+    }
+    /**
+     * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+     */
+    public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder getPropertyOrBuilder(
+        int index) {
+      return property_.get(index);
+    }
+
+    private void initFields() {
+      property_ = java.util.Collections.emptyList();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      for (int i = 0; i < getPropertyCount(); i++) {
+        if (!getProperty(i).isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      for (int i = 0; i < property_.size(); i++) {
+        output.writeMessage(1, property_.get(i));
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      for (int i = 0; i < property_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, property_.get(i));
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code RamCloudGraph.PropertyListProtoBuf}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBufOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyListProtoBuf_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyListProtoBuf_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf.Builder.class);
+      }
+
+      // Construct using com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getPropertyFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        if (propertyBuilder_ == null) {
+          property_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+        } else {
+          propertyBuilder_.clear();
+        }
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyListProtoBuf_descriptor;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf getDefaultInstanceForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf.getDefaultInstance();
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf build() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf buildPartial() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf result = new com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf(this);
+        int from_bitField0_ = bitField0_;
+        if (propertyBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) == 0x00000001)) {
+            property_ = java.util.Collections.unmodifiableList(property_);
+            bitField0_ = (bitField0_ & ~0x00000001);
+          }
+          result.property_ = property_;
+        } else {
+          result.property_ = propertyBuilder_.build();
+        }
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf) {
+          return mergeFrom((com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf other) {
+        if (other == com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf.getDefaultInstance()) return this;
+        if (propertyBuilder_ == null) {
+          if (!other.property_.isEmpty()) {
+            if (property_.isEmpty()) {
+              property_ = other.property_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+            } else {
+              ensurePropertyIsMutable();
+              property_.addAll(other.property_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.property_.isEmpty()) {
+            if (propertyBuilder_.isEmpty()) {
+              propertyBuilder_.dispose();
+              propertyBuilder_ = null;
+              property_ = other.property_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+              propertyBuilder_ = 
+                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+                   getPropertyFieldBuilder() : null;
+            } else {
+              propertyBuilder_.addAllMessages(other.property_);
+            }
+          }
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        for (int i = 0; i < getPropertyCount(); i++) {
+          if (!getProperty(i).isInitialized()) {
+            
+            return false;
+          }
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyListProtoBuf) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // repeated .RamCloudGraph.PropertyProtoBuf property = 1;
+      private java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf> property_ =
+        java.util.Collections.emptyList();
+      private void ensurePropertyIsMutable() {
+        if (!((bitField0_ & 0x00000001) == 0x00000001)) {
+          property_ = new java.util.ArrayList<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf>(property_);
+          bitField0_ |= 0x00000001;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilder<
+          com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder> propertyBuilder_;
+
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf> getPropertyList() {
+        if (propertyBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(property_);
+        } else {
+          return propertyBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public int getPropertyCount() {
+        if (propertyBuilder_ == null) {
+          return property_.size();
+        } else {
+          return propertyBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf getProperty(int index) {
+        if (propertyBuilder_ == null) {
+          return property_.get(index);
+        } else {
+          return propertyBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder setProperty(
+          int index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf value) {
+        if (propertyBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensurePropertyIsMutable();
+          property_.set(index, value);
+          onChanged();
+        } else {
+          propertyBuilder_.setMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder setProperty(
+          int index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder builderForValue) {
+        if (propertyBuilder_ == null) {
+          ensurePropertyIsMutable();
+          property_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          propertyBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder addProperty(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf value) {
+        if (propertyBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensurePropertyIsMutable();
+          property_.add(value);
+          onChanged();
+        } else {
+          propertyBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder addProperty(
+          int index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf value) {
+        if (propertyBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensurePropertyIsMutable();
+          property_.add(index, value);
+          onChanged();
+        } else {
+          propertyBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder addProperty(
+          com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder builderForValue) {
+        if (propertyBuilder_ == null) {
+          ensurePropertyIsMutable();
+          property_.add(builderForValue.build());
+          onChanged();
+        } else {
+          propertyBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder addProperty(
+          int index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder builderForValue) {
+        if (propertyBuilder_ == null) {
+          ensurePropertyIsMutable();
+          property_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          propertyBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder addAllProperty(
+          java.lang.Iterable<? extends com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf> values) {
+        if (propertyBuilder_ == null) {
+          ensurePropertyIsMutable();
+          super.addAll(values, property_);
+          onChanged();
+        } else {
+          propertyBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder clearProperty() {
+        if (propertyBuilder_ == null) {
+          property_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+          onChanged();
+        } else {
+          propertyBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public Builder removeProperty(int index) {
+        if (propertyBuilder_ == null) {
+          ensurePropertyIsMutable();
+          property_.remove(index);
+          onChanged();
+        } else {
+          propertyBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder getPropertyBuilder(
+          int index) {
+        return getPropertyFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder getPropertyOrBuilder(
+          int index) {
+        if (propertyBuilder_ == null) {
+          return property_.get(index);  } else {
+          return propertyBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public java.util.List<? extends com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder> 
+           getPropertyOrBuilderList() {
+        if (propertyBuilder_ != null) {
+          return propertyBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(property_);
+        }
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder addPropertyBuilder() {
+        return getPropertyFieldBuilder().addBuilder(
+            com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder addPropertyBuilder(
+          int index) {
+        return getPropertyFieldBuilder().addBuilder(
+            index, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .RamCloudGraph.PropertyProtoBuf property = 1;</code>
+       */
+      public java.util.List<com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder> 
+           getPropertyBuilderList() {
+        return getPropertyFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilder<
+          com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder> 
+          getPropertyFieldBuilder() {
+        if (propertyBuilder_ == null) {
+          propertyBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+              com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder>(
+                  property_,
+                  ((bitField0_ & 0x00000001) == 0x00000001),
+                  getParentForChildren(),
+                  isClean());
+          property_ = null;
+        }
+        return propertyBuilder_;
+      }
+
+      // @@protoc_insertion_point(builder_scope:RamCloudGraph.PropertyListProtoBuf)
+    }
+
+    static {
+      defaultInstance = new PropertyListProtoBuf(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:RamCloudGraph.PropertyListProtoBuf)
+  }
+
+  public interface PropertyProtoBufOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required string key = 1;
+    /**
+     * <code>required string key = 1;</code>
+     */
+    boolean hasKey();
+    /**
+     * <code>required string key = 1;</code>
+     */
+    java.lang.String getKey();
+    /**
+     * <code>required string key = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getKeyBytes();
+
+    // required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;
+    /**
+     * <code>required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;</code>
+     */
+    boolean hasValueType();
+    /**
+     * <code>required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;</code>
+     */
+    com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type getValueType();
+
+    // optional string string_value = 3;
+    /**
+     * <code>optional string string_value = 3;</code>
+     */
+    boolean hasStringValue();
+    /**
+     * <code>optional string string_value = 3;</code>
+     */
+    java.lang.String getStringValue();
+    /**
+     * <code>optional string string_value = 3;</code>
+     */
+    com.google.protobuf.ByteString
+        getStringValueBytes();
+
+    // optional int32 int32_value = 4;
+    /**
+     * <code>optional int32 int32_value = 4;</code>
+     */
+    boolean hasInt32Value();
+    /**
+     * <code>optional int32 int32_value = 4;</code>
+     */
+    int getInt32Value();
+
+    // optional int64 int64_value = 5;
+    /**
+     * <code>optional int64 int64_value = 5;</code>
+     */
+    boolean hasInt64Value();
+    /**
+     * <code>optional int64 int64_value = 5;</code>
+     */
+    long getInt64Value();
+
+    // optional double double_value = 6;
+    /**
+     * <code>optional double double_value = 6;</code>
+     */
+    boolean hasDoubleValue();
+    /**
+     * <code>optional double double_value = 6;</code>
+     */
+    double getDoubleValue();
+
+    // optional float float_value = 7;
+    /**
+     * <code>optional float float_value = 7;</code>
+     */
+    boolean hasFloatValue();
+    /**
+     * <code>optional float float_value = 7;</code>
+     */
+    float getFloatValue();
+
+    // optional bool bool_value = 8;
+    /**
+     * <code>optional bool bool_value = 8;</code>
+     */
+    boolean hasBoolValue();
+    /**
+     * <code>optional bool bool_value = 8;</code>
+     */
+    boolean getBoolValue();
+  }
+  /**
+   * Protobuf type {@code RamCloudGraph.PropertyProtoBuf}
+   */
+  public static final class PropertyProtoBuf extends
+      com.google.protobuf.GeneratedMessage
+      implements PropertyProtoBufOrBuilder {
+    // Use PropertyProtoBuf.newBuilder() to construct.
+    private PropertyProtoBuf(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private PropertyProtoBuf(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final PropertyProtoBuf defaultInstance;
+    public static PropertyProtoBuf getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public PropertyProtoBuf getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private PropertyProtoBuf(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              key_ = input.readBytes();
+              break;
+            }
+            case 16: {
+              int rawValue = input.readEnum();
+              com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type value = com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(2, rawValue);
+              } else {
+                bitField0_ |= 0x00000002;
+                valueType_ = value;
+              }
+              break;
+            }
+            case 26: {
+              bitField0_ |= 0x00000004;
+              stringValue_ = input.readBytes();
+              break;
+            }
+            case 32: {
+              bitField0_ |= 0x00000008;
+              int32Value_ = input.readInt32();
+              break;
+            }
+            case 40: {
+              bitField0_ |= 0x00000010;
+              int64Value_ = input.readInt64();
+              break;
+            }
+            case 49: {
+              bitField0_ |= 0x00000020;
+              doubleValue_ = input.readDouble();
+              break;
+            }
+            case 61: {
+              bitField0_ |= 0x00000040;
+              floatValue_ = input.readFloat();
+              break;
+            }
+            case 64: {
+              bitField0_ |= 0x00000080;
+              boolValue_ = input.readBool();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyProtoBuf_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyProtoBuf_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<PropertyProtoBuf> PARSER =
+        new com.google.protobuf.AbstractParser<PropertyProtoBuf>() {
+      public PropertyProtoBuf parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new PropertyProtoBuf(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<PropertyProtoBuf> getParserForType() {
+      return PARSER;
+    }
+
+    /**
+     * Protobuf enum {@code RamCloudGraph.PropertyProtoBuf.Type}
+     */
+    public enum Type
+        implements com.google.protobuf.ProtocolMessageEnum {
+      /**
+       * <code>STRING = 1;</code>
+       */
+      STRING(0, 1),
+      /**
+       * <code>INT32 = 2;</code>
+       */
+      INT32(1, 2),
+      /**
+       * <code>INT64 = 3;</code>
+       */
+      INT64(2, 3),
+      /**
+       * <code>DOUBLE = 4;</code>
+       */
+      DOUBLE(3, 4),
+      /**
+       * <code>FLOAT = 5;</code>
+       */
+      FLOAT(4, 5),
+      /**
+       * <code>BOOL = 6;</code>
+       */
+      BOOL(5, 6),
+      ;
+
+      /**
+       * <code>STRING = 1;</code>
+       */
+      public static final int STRING_VALUE = 1;
+      /**
+       * <code>INT32 = 2;</code>
+       */
+      public static final int INT32_VALUE = 2;
+      /**
+       * <code>INT64 = 3;</code>
+       */
+      public static final int INT64_VALUE = 3;
+      /**
+       * <code>DOUBLE = 4;</code>
+       */
+      public static final int DOUBLE_VALUE = 4;
+      /**
+       * <code>FLOAT = 5;</code>
+       */
+      public static final int FLOAT_VALUE = 5;
+      /**
+       * <code>BOOL = 6;</code>
+       */
+      public static final int BOOL_VALUE = 6;
+
+
+      public final int getNumber() { return value; }
+
+      public static Type valueOf(int value) {
+        switch (value) {
+          case 1: return STRING;
+          case 2: return INT32;
+          case 3: return INT64;
+          case 4: return DOUBLE;
+          case 5: return FLOAT;
+          case 6: return BOOL;
+          default: return null;
+        }
+      }
+
+      public static com.google.protobuf.Internal.EnumLiteMap<Type>
+          internalGetValueMap() {
+        return internalValueMap;
+      }
+      private static com.google.protobuf.Internal.EnumLiteMap<Type>
+          internalValueMap =
+            new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+              public Type findValueByNumber(int number) {
+                return Type.valueOf(number);
+              }
+            };
+
+      public final com.google.protobuf.Descriptors.EnumValueDescriptor
+          getValueDescriptor() {
+        return getDescriptor().getValues().get(index);
+      }
+      public final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptorForType() {
+        return getDescriptor();
+      }
+      public static final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptor() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.getDescriptor().getEnumTypes().get(0);
+      }
+
+      private static final Type[] VALUES = values();
+
+      public static Type valueOf(
+          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+        if (desc.getType() != getDescriptor()) {
+          throw new java.lang.IllegalArgumentException(
+            "EnumValueDescriptor is not for this type.");
+        }
+        return VALUES[desc.getIndex()];
+      }
+
+      private final int index;
+      private final int value;
+
+      private Type(int index, int value) {
+        this.index = index;
+        this.value = value;
+      }
+
+      // @@protoc_insertion_point(enum_scope:RamCloudGraph.PropertyProtoBuf.Type)
+    }
+
+    private int bitField0_;
+    // required string key = 1;
+    public static final int KEY_FIELD_NUMBER = 1;
+    private java.lang.Object key_;
+    /**
+     * <code>required string key = 1;</code>
+     */
+    public boolean hasKey() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required string key = 1;</code>
+     */
+    public java.lang.String getKey() {
+      java.lang.Object ref = key_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          key_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string key = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getKeyBytes() {
+      java.lang.Object ref = key_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        key_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;
+    public static final int VALUE_TYPE_FIELD_NUMBER = 2;
+    private com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type valueType_;
+    /**
+     * <code>required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;</code>
+     */
+    public boolean hasValueType() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;</code>
+     */
+    public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type getValueType() {
+      return valueType_;
+    }
+
+    // optional string string_value = 3;
+    public static final int STRING_VALUE_FIELD_NUMBER = 3;
+    private java.lang.Object stringValue_;
+    /**
+     * <code>optional string string_value = 3;</code>
+     */
+    public boolean hasStringValue() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional string string_value = 3;</code>
+     */
+    public java.lang.String getStringValue() {
+      java.lang.Object ref = stringValue_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          stringValue_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string string_value = 3;</code>
+     */
+    public com.google.protobuf.ByteString
+        getStringValueBytes() {
+      java.lang.Object ref = stringValue_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        stringValue_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // optional int32 int32_value = 4;
+    public static final int INT32_VALUE_FIELD_NUMBER = 4;
+    private int int32Value_;
+    /**
+     * <code>optional int32 int32_value = 4;</code>
+     */
+    public boolean hasInt32Value() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional int32 int32_value = 4;</code>
+     */
+    public int getInt32Value() {
+      return int32Value_;
+    }
+
+    // optional int64 int64_value = 5;
+    public static final int INT64_VALUE_FIELD_NUMBER = 5;
+    private long int64Value_;
+    /**
+     * <code>optional int64 int64_value = 5;</code>
+     */
+    public boolean hasInt64Value() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>optional int64 int64_value = 5;</code>
+     */
+    public long getInt64Value() {
+      return int64Value_;
+    }
+
+    // optional double double_value = 6;
+    public static final int DOUBLE_VALUE_FIELD_NUMBER = 6;
+    private double doubleValue_;
+    /**
+     * <code>optional double double_value = 6;</code>
+     */
+    public boolean hasDoubleValue() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>optional double double_value = 6;</code>
+     */
+    public double getDoubleValue() {
+      return doubleValue_;
+    }
+
+    // optional float float_value = 7;
+    public static final int FLOAT_VALUE_FIELD_NUMBER = 7;
+    private float floatValue_;
+    /**
+     * <code>optional float float_value = 7;</code>
+     */
+    public boolean hasFloatValue() {
+      return ((bitField0_ & 0x00000040) == 0x00000040);
+    }
+    /**
+     * <code>optional float float_value = 7;</code>
+     */
+    public float getFloatValue() {
+      return floatValue_;
+    }
+
+    // optional bool bool_value = 8;
+    public static final int BOOL_VALUE_FIELD_NUMBER = 8;
+    private boolean boolValue_;
+    /**
+     * <code>optional bool bool_value = 8;</code>
+     */
+    public boolean hasBoolValue() {
+      return ((bitField0_ & 0x00000080) == 0x00000080);
+    }
+    /**
+     * <code>optional bool bool_value = 8;</code>
+     */
+    public boolean getBoolValue() {
+      return boolValue_;
+    }
+
+    private void initFields() {
+      key_ = "";
+      valueType_ = com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type.STRING;
+      stringValue_ = "";
+      int32Value_ = 0;
+      int64Value_ = 0L;
+      doubleValue_ = 0D;
+      floatValue_ = 0F;
+      boolValue_ = false;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasKey()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasValueType()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getKeyBytes());
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeEnum(2, valueType_.getNumber());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, getStringValueBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeInt32(4, int32Value_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeInt64(5, int64Value_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeDouble(6, doubleValue_);
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        output.writeFloat(7, floatValue_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        output.writeBool(8, boolValue_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getKeyBytes());
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(2, valueType_.getNumber());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, getStringValueBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(4, int32Value_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(5, int64Value_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeDoubleSize(6, doubleValue_);
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeFloatSize(7, floatValue_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(8, boolValue_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code RamCloudGraph.PropertyProtoBuf}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBufOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyProtoBuf_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyProtoBuf_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Builder.class);
+      }
+
+      // Construct using com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        key_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        valueType_ = com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type.STRING;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        stringValue_ = "";
+        bitField0_ = (bitField0_ & ~0x00000004);
+        int32Value_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000008);
+        int64Value_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000010);
+        doubleValue_ = 0D;
+        bitField0_ = (bitField0_ & ~0x00000020);
+        floatValue_ = 0F;
+        bitField0_ = (bitField0_ & ~0x00000040);
+        boolValue_ = false;
+        bitField0_ = (bitField0_ & ~0x00000080);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_PropertyProtoBuf_descriptor;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf getDefaultInstanceForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.getDefaultInstance();
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf build() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf buildPartial() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf result = new com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.key_ = key_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.valueType_ = valueType_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.stringValue_ = stringValue_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.int32Value_ = int32Value_;
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000010;
+        }
+        result.int64Value_ = int64Value_;
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000020;
+        }
+        result.doubleValue_ = doubleValue_;
+        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+          to_bitField0_ |= 0x00000040;
+        }
+        result.floatValue_ = floatValue_;
+        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+          to_bitField0_ |= 0x00000080;
+        }
+        result.boolValue_ = boolValue_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf) {
+          return mergeFrom((com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf other) {
+        if (other == com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.getDefaultInstance()) return this;
+        if (other.hasKey()) {
+          bitField0_ |= 0x00000001;
+          key_ = other.key_;
+          onChanged();
+        }
+        if (other.hasValueType()) {
+          setValueType(other.getValueType());
+        }
+        if (other.hasStringValue()) {
+          bitField0_ |= 0x00000004;
+          stringValue_ = other.stringValue_;
+          onChanged();
+        }
+        if (other.hasInt32Value()) {
+          setInt32Value(other.getInt32Value());
+        }
+        if (other.hasInt64Value()) {
+          setInt64Value(other.getInt64Value());
+        }
+        if (other.hasDoubleValue()) {
+          setDoubleValue(other.getDoubleValue());
+        }
+        if (other.hasFloatValue()) {
+          setFloatValue(other.getFloatValue());
+        }
+        if (other.hasBoolValue()) {
+          setBoolValue(other.getBoolValue());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasKey()) {
+          
+          return false;
+        }
+        if (!hasValueType()) {
+          
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required string key = 1;
+      private java.lang.Object key_ = "";
+      /**
+       * <code>required string key = 1;</code>
+       */
+      public boolean hasKey() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required string key = 1;</code>
+       */
+      public java.lang.String getKey() {
+        java.lang.Object ref = key_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          key_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string key = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getKeyBytes() {
+        java.lang.Object ref = key_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          key_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string key = 1;</code>
+       */
+      public Builder setKey(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        key_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string key = 1;</code>
+       */
+      public Builder clearKey() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        key_ = getDefaultInstance().getKey();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string key = 1;</code>
+       */
+      public Builder setKeyBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        key_ = value;
+        onChanged();
+        return this;
+      }
+
+      // required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;
+      private com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type valueType_ = com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type.STRING;
+      /**
+       * <code>required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;</code>
+       */
+      public boolean hasValueType() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;</code>
+       */
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type getValueType() {
+        return valueType_;
+      }
+      /**
+       * <code>required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;</code>
+       */
+      public Builder setValueType(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        bitField0_ |= 0x00000002;
+        valueType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required .RamCloudGraph.PropertyProtoBuf.Type value_type = 2;</code>
+       */
+      public Builder clearValueType() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        valueType_ = com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.PropertyProtoBuf.Type.STRING;
+        onChanged();
+        return this;
+      }
+
+      // optional string string_value = 3;
+      private java.lang.Object stringValue_ = "";
+      /**
+       * <code>optional string string_value = 3;</code>
+       */
+      public boolean hasStringValue() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional string string_value = 3;</code>
+       */
+      public java.lang.String getStringValue() {
+        java.lang.Object ref = stringValue_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          stringValue_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string string_value = 3;</code>
+       */
+      public com.google.protobuf.ByteString
+          getStringValueBytes() {
+        java.lang.Object ref = stringValue_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          stringValue_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string string_value = 3;</code>
+       */
+      public Builder setStringValue(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        stringValue_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string string_value = 3;</code>
+       */
+      public Builder clearStringValue() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        stringValue_ = getDefaultInstance().getStringValue();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string string_value = 3;</code>
+       */
+      public Builder setStringValueBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        stringValue_ = value;
+        onChanged();
+        return this;
+      }
+
+      // optional int32 int32_value = 4;
+      private int int32Value_ ;
+      /**
+       * <code>optional int32 int32_value = 4;</code>
+       */
+      public boolean hasInt32Value() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional int32 int32_value = 4;</code>
+       */
+      public int getInt32Value() {
+        return int32Value_;
+      }
+      /**
+       * <code>optional int32 int32_value = 4;</code>
+       */
+      public Builder setInt32Value(int value) {
+        bitField0_ |= 0x00000008;
+        int32Value_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 int32_value = 4;</code>
+       */
+      public Builder clearInt32Value() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        int32Value_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // optional int64 int64_value = 5;
+      private long int64Value_ ;
+      /**
+       * <code>optional int64 int64_value = 5;</code>
+       */
+      public boolean hasInt64Value() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
+      }
+      /**
+       * <code>optional int64 int64_value = 5;</code>
+       */
+      public long getInt64Value() {
+        return int64Value_;
+      }
+      /**
+       * <code>optional int64 int64_value = 5;</code>
+       */
+      public Builder setInt64Value(long value) {
+        bitField0_ |= 0x00000010;
+        int64Value_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 int64_value = 5;</code>
+       */
+      public Builder clearInt64Value() {
+        bitField0_ = (bitField0_ & ~0x00000010);
+        int64Value_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // optional double double_value = 6;
+      private double doubleValue_ ;
+      /**
+       * <code>optional double double_value = 6;</code>
+       */
+      public boolean hasDoubleValue() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
+      }
+      /**
+       * <code>optional double double_value = 6;</code>
+       */
+      public double getDoubleValue() {
+        return doubleValue_;
+      }
+      /**
+       * <code>optional double double_value = 6;</code>
+       */
+      public Builder setDoubleValue(double value) {
+        bitField0_ |= 0x00000020;
+        doubleValue_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional double double_value = 6;</code>
+       */
+      public Builder clearDoubleValue() {
+        bitField0_ = (bitField0_ & ~0x00000020);
+        doubleValue_ = 0D;
+        onChanged();
+        return this;
+      }
+
+      // optional float float_value = 7;
+      private float floatValue_ ;
+      /**
+       * <code>optional float float_value = 7;</code>
+       */
+      public boolean hasFloatValue() {
+        return ((bitField0_ & 0x00000040) == 0x00000040);
+      }
+      /**
+       * <code>optional float float_value = 7;</code>
+       */
+      public float getFloatValue() {
+        return floatValue_;
+      }
+      /**
+       * <code>optional float float_value = 7;</code>
+       */
+      public Builder setFloatValue(float value) {
+        bitField0_ |= 0x00000040;
+        floatValue_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional float float_value = 7;</code>
+       */
+      public Builder clearFloatValue() {
+        bitField0_ = (bitField0_ & ~0x00000040);
+        floatValue_ = 0F;
+        onChanged();
+        return this;
+      }
+
+      // optional bool bool_value = 8;
+      private boolean boolValue_ ;
+      /**
+       * <code>optional bool bool_value = 8;</code>
+       */
+      public boolean hasBoolValue() {
+        return ((bitField0_ & 0x00000080) == 0x00000080);
+      }
+      /**
+       * <code>optional bool bool_value = 8;</code>
+       */
+      public boolean getBoolValue() {
+        return boolValue_;
+      }
+      /**
+       * <code>optional bool bool_value = 8;</code>
+       */
+      public Builder setBoolValue(boolean value) {
+        bitField0_ |= 0x00000080;
+        boolValue_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool bool_value = 8;</code>
+       */
+      public Builder clearBoolValue() {
+        bitField0_ = (bitField0_ & ~0x00000080);
+        boolValue_ = false;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:RamCloudGraph.PropertyProtoBuf)
+    }
+
+    static {
+      defaultInstance = new PropertyProtoBuf(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:RamCloudGraph.PropertyProtoBuf)
+  }
+
+  public interface IndexBlobOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // repeated int64 vertexId = 1;
+    /**
+     * <code>repeated int64 vertexId = 1;</code>
+     */
+    java.util.List<java.lang.Long> getVertexIdList();
+    /**
+     * <code>repeated int64 vertexId = 1;</code>
+     */
+    int getVertexIdCount();
+    /**
+     * <code>repeated int64 vertexId = 1;</code>
+     */
+    long getVertexId(int index);
+  }
+  /**
+   * Protobuf type {@code RamCloudGraph.IndexBlob}
+   */
+  public static final class IndexBlob extends
+      com.google.protobuf.GeneratedMessage
+      implements IndexBlobOrBuilder {
+    // Use IndexBlob.newBuilder() to construct.
+    private IndexBlob(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private IndexBlob(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final IndexBlob defaultInstance;
+    public static IndexBlob getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public IndexBlob getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private IndexBlob(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+                vertexId_ = new java.util.ArrayList<java.lang.Long>();
+                mutable_bitField0_ |= 0x00000001;
+              }
+              vertexId_.add(input.readInt64());
+              break;
+            }
+            case 10: {
+              int length = input.readRawVarint32();
+              int limit = input.pushLimit(length);
+              if (!((mutable_bitField0_ & 0x00000001) == 0x00000001) && input.getBytesUntilLimit() > 0) {
+                vertexId_ = new java.util.ArrayList<java.lang.Long>();
+                mutable_bitField0_ |= 0x00000001;
+              }
+              while (input.getBytesUntilLimit() > 0) {
+                vertexId_.add(input.readInt64());
+              }
+              input.popLimit(limit);
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+          vertexId_ = java.util.Collections.unmodifiableList(vertexId_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_IndexBlob_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_IndexBlob_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<IndexBlob> PARSER =
+        new com.google.protobuf.AbstractParser<IndexBlob>() {
+      public IndexBlob parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new IndexBlob(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<IndexBlob> getParserForType() {
+      return PARSER;
+    }
+
+    // repeated int64 vertexId = 1;
+    public static final int VERTEXID_FIELD_NUMBER = 1;
+    private java.util.List<java.lang.Long> vertexId_;
+    /**
+     * <code>repeated int64 vertexId = 1;</code>
+     */
+    public java.util.List<java.lang.Long>
+        getVertexIdList() {
+      return vertexId_;
+    }
+    /**
+     * <code>repeated int64 vertexId = 1;</code>
+     */
+    public int getVertexIdCount() {
+      return vertexId_.size();
+    }
+    /**
+     * <code>repeated int64 vertexId = 1;</code>
+     */
+    public long getVertexId(int index) {
+      return vertexId_.get(index);
+    }
+
+    private void initFields() {
+      vertexId_ = java.util.Collections.emptyList();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      for (int i = 0; i < vertexId_.size(); i++) {
+        output.writeInt64(1, vertexId_.get(i));
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      {
+        int dataSize = 0;
+        for (int i = 0; i < vertexId_.size(); i++) {
+          dataSize += com.google.protobuf.CodedOutputStream
+            .computeInt64SizeNoTag(vertexId_.get(i));
+        }
+        size += dataSize;
+        size += 1 * getVertexIdList().size();
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code RamCloudGraph.IndexBlob}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlobOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_IndexBlob_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_IndexBlob_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob.class, com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob.Builder.class);
+      }
+
+      // Construct using com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        vertexId_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.internal_static_RamCloudGraph_IndexBlob_descriptor;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob getDefaultInstanceForType() {
+        return com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob.getDefaultInstance();
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob build() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob buildPartial() {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob result = new com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob(this);
+        int from_bitField0_ = bitField0_;
+        if (((bitField0_ & 0x00000001) == 0x00000001)) {
+          vertexId_ = java.util.Collections.unmodifiableList(vertexId_);
+          bitField0_ = (bitField0_ & ~0x00000001);
+        }
+        result.vertexId_ = vertexId_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob) {
+          return mergeFrom((com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob other) {
+        if (other == com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob.getDefaultInstance()) return this;
+        if (!other.vertexId_.isEmpty()) {
+          if (vertexId_.isEmpty()) {
+            vertexId_ = other.vertexId_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+          } else {
+            ensureVertexIdIsMutable();
+            vertexId_.addAll(other.vertexId_);
+          }
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // repeated int64 vertexId = 1;
+      private java.util.List<java.lang.Long> vertexId_ = java.util.Collections.emptyList();
+      private void ensureVertexIdIsMutable() {
+        if (!((bitField0_ & 0x00000001) == 0x00000001)) {
+          vertexId_ = new java.util.ArrayList<java.lang.Long>(vertexId_);
+          bitField0_ |= 0x00000001;
+         }
+      }
+      /**
+       * <code>repeated int64 vertexId = 1;</code>
+       */
+      public java.util.List<java.lang.Long>
+          getVertexIdList() {
+        return java.util.Collections.unmodifiableList(vertexId_);
+      }
+      /**
+       * <code>repeated int64 vertexId = 1;</code>
+       */
+      public int getVertexIdCount() {
+        return vertexId_.size();
+      }
+      /**
+       * <code>repeated int64 vertexId = 1;</code>
+       */
+      public long getVertexId(int index) {
+        return vertexId_.get(index);
+      }
+      /**
+       * <code>repeated int64 vertexId = 1;</code>
+       */
+      public Builder setVertexId(
+          int index, long value) {
+        ensureVertexIdIsMutable();
+        vertexId_.set(index, value);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated int64 vertexId = 1;</code>
+       */
+      public Builder addVertexId(long value) {
+        ensureVertexIdIsMutable();
+        vertexId_.add(value);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated int64 vertexId = 1;</code>
+       */
+      public Builder addAllVertexId(
+          java.lang.Iterable<? extends java.lang.Long> values) {
+        ensureVertexIdIsMutable();
+        super.addAll(values, vertexId_);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated int64 vertexId = 1;</code>
+       */
+      public Builder clearVertexId() {
+        vertexId_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:RamCloudGraph.IndexBlob)
+    }
+
+    static {
+      defaultInstance = new IndexBlob(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:RamCloudGraph.IndexBlob)
+  }
+
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_RamCloudGraph_EdgeListProtoBuf_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_RamCloudGraph_EdgeListProtoBuf_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_RamCloudGraph_EdgeProtoBuf_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_RamCloudGraph_EdgeProtoBuf_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_RamCloudGraph_PropertyListProtoBuf_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_RamCloudGraph_PropertyListProtoBuf_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_RamCloudGraph_PropertyProtoBuf_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_RamCloudGraph_PropertyProtoBuf_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_RamCloudGraph_IndexBlob_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_RamCloudGraph_IndexBlob_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\023ramcloudgraph.proto\022\rRamCloudGraph\"=\n\020" +
+      "EdgeListProtoBuf\022)\n\004edge\030\001 \003(\0132\033.RamClou" +
+      "dGraph.EdgeProtoBuf\"C\n\014EdgeProtoBuf\022\022\n\nn" +
+      "eighborId\030\001 \002(\004\022\020\n\010outgoing\030\002 \002(\010\022\r\n\005lab" +
+      "el\030\003 \002(\t\"I\n\024PropertyListProtoBuf\0221\n\010prop" +
+      "erty\030\001 \003(\0132\037.RamCloudGraph.PropertyProto" +
+      "Buf\"\243\002\n\020PropertyProtoBuf\022\013\n\003key\030\001 \002(\t\0228\n" +
+      "\nvalue_type\030\002 \002(\0162$.RamCloudGraph.Proper" +
+      "tyProtoBuf.Type\022\024\n\014string_value\030\003 \001(\t\022\023\n" +
+      "\013int32_value\030\004 \001(\005\022\023\n\013int64_value\030\005 \001(\003\022",
+      "\024\n\014double_value\030\006 \001(\001\022\023\n\013float_value\030\007 \001" +
+      "(\002\022\022\n\nbool_value\030\010 \001(\010\"I\n\004Type\022\n\n\006STRING" +
+      "\020\001\022\t\n\005INT32\020\002\022\t\n\005INT64\020\003\022\n\n\006DOUBLE\020\004\022\t\n\005" +
+      "FLOAT\020\005\022\010\n\004BOOL\020\006\"\035\n\tIndexBlob\022\020\n\010vertex" +
+      "Id\030\001 \003(\003B>\n\'com.tinkerpop.blueprints.imp" +
+      "ls.ramcloudB\023RamCloudGraphProtos"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+        public com.google.protobuf.ExtensionRegistry assignDescriptors(
+            com.google.protobuf.Descriptors.FileDescriptor root) {
+          descriptor = root;
+          internal_static_RamCloudGraph_EdgeListProtoBuf_descriptor =
+            getDescriptor().getMessageTypes().get(0);
+          internal_static_RamCloudGraph_EdgeListProtoBuf_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_RamCloudGraph_EdgeListProtoBuf_descriptor,
+              new java.lang.String[] { "Edge", });
+          internal_static_RamCloudGraph_EdgeProtoBuf_descriptor =
+            getDescriptor().getMessageTypes().get(1);
+          internal_static_RamCloudGraph_EdgeProtoBuf_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_RamCloudGraph_EdgeProtoBuf_descriptor,
+              new java.lang.String[] { "NeighborId", "Outgoing", "Label", });
+          internal_static_RamCloudGraph_PropertyListProtoBuf_descriptor =
+            getDescriptor().getMessageTypes().get(2);
+          internal_static_RamCloudGraph_PropertyListProtoBuf_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_RamCloudGraph_PropertyListProtoBuf_descriptor,
+              new java.lang.String[] { "Property", });
+          internal_static_RamCloudGraph_PropertyProtoBuf_descriptor =
+            getDescriptor().getMessageTypes().get(3);
+          internal_static_RamCloudGraph_PropertyProtoBuf_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_RamCloudGraph_PropertyProtoBuf_descriptor,
+              new java.lang.String[] { "Key", "ValueType", "StringValue", "Int32Value", "Int64Value", "DoubleValue", "FloatValue", "BoolValue", });
+          internal_static_RamCloudGraph_IndexBlob_descriptor =
+            getDescriptor().getMessageTypes().get(4);
+          internal_static_RamCloudGraph_IndexBlob_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_RamCloudGraph_IndexBlob_descriptor,
+              new java.lang.String[] { "VertexId", });
+          return null;
+        }
+      };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudIndex.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudIndex.java
new file mode 100644
index 0000000..075c749
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudIndex.java
@@ -0,0 +1,535 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.tinkerpop.blueprints.CloseableIterable;
+import com.tinkerpop.blueprints.Element;
+import com.tinkerpop.blueprints.Index;
+import com.tinkerpop.blueprints.util.ExceptionFactory;
+import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
+import com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob;
+import com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.IndexBlob.Builder;
+
+import edu.stanford.ramcloud.JRamCloud;
+
+// FIXME Index instance should be representing an Index table, not a IndexTable K-V pair
+public class RamCloudIndex<T extends Element> implements Index<T>, Serializable {
+
+    private final static Logger log = LoggerFactory.getLogger(RamCloudGraph.class);
+    protected RamCloudGraph graph;
+    private long tableId;
+    private String indexName;
+    protected byte[] rcKey;
+    private Class<T> indexClass;
+    // FIXME this should not be defined here
+    private long indexVersion;
+
+//    private static final ThreadLocal<Kryo> kryo = new ThreadLocal<Kryo>() {
+//        @Override
+//        protected Kryo initialValue() {
+//                 Kryo kryo = new Kryo();
+//                 kryo.setRegistrationRequired(true);
+//                 kryo.register(Long.class);
+//                 kryo.register(String.class);
+//                 kryo.register(TreeMap.class);
+//                 kryo.register(ArrayList.class);
+//                 kryo.setReferences(false);
+//                 return kryo;
+//        }
+//    };
+
+
+    public RamCloudIndex(long tableId, String indexName, Object propValue, RamCloudGraph graph, Class<T> indexClass) {
+	this.tableId = tableId;
+	this.graph = graph;
+	this.rcKey = indexToRcKey(indexName, propValue);
+	this.indexName = indexName;
+	this.indexClass = indexClass;
+    }
+
+    public RamCloudIndex(long tableId, byte[] rcKey, RamCloudGraph graph, Class<T> indexClass) {
+	this.tableId = tableId;
+	this.graph = graph;
+	this.rcKey = rcKey;
+	this.indexName = rcKeyToIndexName(rcKey);
+	this.indexClass = indexClass;
+    }
+
+    public boolean exists() {
+	PerfMon pm = PerfMon.getInstance();
+
+	try {
+	    JRamCloud.Object vertTableEntry;
+	    JRamCloud vertTable = graph.getRcClient();
+
+	    //vertTableEntry = graph.getRcClient().read(tableId, rcKey);
+	    pm.indexread_start("RamCloudIndex exists()");
+	    vertTableEntry = vertTable.read(tableId, rcKey);
+	    pm.indexread_end("RamCloudIndex exists()");
+	    indexVersion = vertTableEntry.version;
+	    return true;
+	} catch (Exception e) {
+	    pm.indexread_end("RamCloudIndex exists()");
+	    log.debug("IndexTable entry for {} does not exists(): {}@{} [{}]", indexName, new String(rcKey), tableId, this);
+	    return false;
+	}
+    }
+
+    public void create() {
+	if (!exists()) {
+	    PerfMon pm = PerfMon.getInstance();
+	    try {
+		JRamCloud rcClient = graph.getRcClient();
+		JRamCloud.RejectRules rules = rcClient.new RejectRules();
+		rules.setExists();
+
+		//graph.getRcClient().writeRule(tableId, rcKey, ByteBuffer.allocate(0).array(), rules);
+		pm.indexwrite_start("RamCloudIndex create()");
+		rcClient.writeRule(tableId, rcKey, ByteBuffer.allocate(0).array(), rules);
+		pm.indexwrite_end("RamCloudIndex create()");
+	    } catch (Exception e) {
+		pm.indexwrite_end("RamCloudIndex create()");
+		log.info(toString() + ": Write create index list: ", e);
+	    }
+	}
+    }
+
+    public static byte[] indexToRcKey(String key, Object propValue) {
+	try {
+	    String s = key + "=" + propValue;
+	    return ByteBuffer.allocate(s.getBytes().length).put(s.getBytes("UTF-8")).array();
+	} catch (UnsupportedEncodingException ex) {
+	    log.error("indexToRcKey({}, {}) failed with exception {}", key, propValue, ex);
+	}
+	return null;
+    }
+
+    public static String rcKeyToIndexName(byte[] rcKey) {
+	try {
+	    String s = new String(rcKey, "UTF-8");
+	    return s.substring(0, s.indexOf('='));
+	} catch (UnsupportedEncodingException ex) {
+	    log.error("rcKeyToIndexName({}) failed with exception {}", rcKey, ex);
+	}
+	return null;
+    }
+    public static String rcKeyToPropName(byte[] rcKey) {
+	try {
+	    String s = new String(rcKey, "UTF-8");
+	    return s.substring(s.indexOf('=')+1);
+	} catch (UnsupportedEncodingException ex) {
+	    log.error("rcKeyToPropName({}) failed with exception {}", rcKey, ex);
+	}
+	return null;
+    }
+
+    @Override
+    public String getIndexName() {
+	return this.indexName;
+    }
+
+    @Override
+    public Class<T> getIndexClass() {
+	return this.indexClass;
+    }
+
+    @Override
+    public void put(String key, Object value, T element) {
+	getSetProperty(key, value, element.getId());
+    }
+
+    public void getSetProperty(String key, Object propValue, Object elmId) {
+	if (elmId == null) {
+	    // FIXME Throw appropriate Exception
+	    log.error("Element Id cannot be null");
+	    return;
+	    //throw ExceptionFactory.vertexIdCanNotBeNull();
+	    //throw ExceptionFactory.edgeIdCanNotBeNull();
+	}
+
+	long startTime = 0;
+	if (graph.measureBPTimeProp == 1) {
+	    startTime = System.nanoTime();
+	}
+
+	create();
+
+	// FIXME give more meaningful loop variable
+	for (int i = 0; i < 100; i++) {
+	    Map<Object, List<Object>> map = readIndexPropertyMapFromDB();
+	    List<Object> values = map.get(propValue);
+	    if (values == null) {
+		values = new ArrayList<Object>();
+		map.put(propValue, values);
+	    }
+	    if (!values.contains(elmId)) {
+		values.add(elmId);
+	    }
+
+            //Masa commented out the following measurement b/c Serialization delay is measured in onvertIndexPropertyMapToRcBytes(map)
+	    //long serStartTime = System.nanoTime();
+	    byte[] rcValue = convertIndexPropertyMapToRcBytes(map);
+	    //if(RamCloudGraph.measureSerializeTimeProp == 1) {
+	    //	long serEndTime = System.nanoTime();
+	    //	log.error("Performance index kryo serialization [id={}] {} size {}", elmId, serEndTime - serStartTime, rcValue.length);
+            //}
+
+	    if (rcValue.length != 0) {
+		if (writeWithRules(rcValue)) {
+		    break;
+		} else {
+		    log.debug("getSetProperty(String {}, Object {}) cond. write failure RETRYING {}", propValue, elmId, i+1);
+		    if (i == 100) {
+			log.error("getSetProperty(String {}, Object {}) cond. write failure Gaveup RETRYING", propValue, elmId);
+		    }
+		}
+	    }
+	}
+
+	if (graph.measureBPTimeProp == 1) {
+	    long endTime = System.nanoTime();
+	    log.error("Performance index setProperty total time {}", endTime - startTime);
+	}
+    }
+
+    @Override
+    public CloseableIterable<T> get(String string, Object value) {
+	// FIXME Do we need this implemented
+	throw new RuntimeException("Not implemented yet");
+	//return getElmIdListForPropValue(value);
+    }
+
+    @Override
+    public CloseableIterable<T> query(String string, Object o) {
+	throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public long count(String key, Object value) {
+	Map<Object, List<Object>> map = readIndexPropertyMapFromDB();
+	List<Object> values = map.get(value);
+	if (null == values) {
+	    return 0;
+	} else {
+	    return values.size();
+	}
+    }
+
+    @Override
+    public void remove(String propName, Object propValue, T element) {
+
+	if (propName == null) {
+	    throw ExceptionFactory.propertyKeyCanNotBeNull();
+	}
+
+	if (propName.equals("")) {
+	    throw ExceptionFactory.propertyKeyCanNotBeEmpty();
+	}
+
+	if (propName.equals("id")) {
+	    throw ExceptionFactory.propertyKeyIdIsReserved();
+	}
+
+	if (!propName.equals(indexName)) {
+	    log.error("Index name mismatch indexName:{}, remove({},{},...). SOMETHING IS WRONG", indexName, propName, propValue);
+	}
+
+	// FIXME better loop variable name
+	final int MAX_RETRYS = 100;
+	for (int i = 0; i < MAX_RETRYS; ++i) {
+	    Map<Object, List<Object>> map = readIndexPropertyMapFromDB();
+
+	    if (map.containsKey(propValue)) {
+		List<Object> idList = map.get(propValue);
+		if (null != idList) {
+		    idList.remove(element.getId());
+		    if (idList.isEmpty()) {
+			log.debug("remove({},{},...) called, and list became empty.", propName, propValue);
+			map.remove(propValue);
+		    }
+		}
+	    } else {
+		// propValue not found
+		log.warn("remove({},{},...) called on '{}' index table, but was not found on index. SOMETHING MAY BE WRONG", propName, propValue, this.indexName);
+		// no change to DB so exit now
+		return;
+	    }
+	    //long startTime = System.nanoTime();
+	    //if(RamCloudGraph.measureSerializeTimeProp == 1) {
+	    //   pm.ser_start("SC");
+	    //}
+	    byte[] rcValue = convertIndexPropertyMapToRcBytes(map);
+	    //if(RamCloudGraph.measureSerializeTimeProp == 1) {
+	    //    pm.ser_end("SC");
+	    	//long endTime = System.nanoTime();
+		//pm.ser_add(endTime - startTime);
+	    	//log.error("Performance index kryo serialization for removal key {} {} size {}", element, endTime - startTime, rcValue.length);
+	    //}
+
+	    if (rcValue.length == 0) {
+		return;
+	    }
+
+	    if (writeWithRules(rcValue)) {
+		break;
+	    } else {
+		log.debug("remove({}, {}, T element) write failure RETRYING {}", propName, propValue, (i + 1));
+		if (i + 1 == MAX_RETRYS) {
+		    log.error("remove({}, {}, T element) write failed completely. gave up RETRYING", propName, propValue);
+		}
+	    }
+	}
+
+    }
+
+    public void removeElement(T element) {
+	removeElement(this.tableId, element, this.graph);
+    }
+
+    // FIXME this methods should not be defined here
+    public <T extends Element> void removeElement(long tableId, T element, RamCloudGraph graph) {
+	JRamCloud.TableEnumerator tableEnum = graph.getRcClient().new TableEnumerator(tableId);
+
+	while (tableEnum.hasNext()) {
+	    JRamCloud.Object tableEntry = tableEnum.next();
+	    Map<Object, List<Object>> indexValMap = convertRcBytesToIndexPropertyMap(tableEntry.value);
+
+	    boolean madeChange = false;
+	    Iterator<Map.Entry<Object, List<Object>>> indexValMapIt = indexValMap.entrySet().iterator();
+	    while (indexValMapIt.hasNext()) {
+		Map.Entry<Object, List<Object>> entry = indexValMapIt.next();
+		List<Object> idList = entry.getValue();
+		madeChange |= idList.remove(element.getId());
+		if (idList.isEmpty()) {
+		    madeChange = true;
+		    indexValMapIt.remove();
+		}
+	    }
+	    if (madeChange == false) {
+		continue;
+	    }
+
+	    byte[] rcValue = convertIndexPropertyMapToRcBytes(indexValMap);
+	    if (rcValue.length == 0) {
+		// nothing to write
+		continue;
+	    }
+	    if (writeWithRules(tableId, tableEntry.key, rcValue, tableEntry.version, graph)) {
+		// cond. write success
+		continue;
+	    } else {
+		// cond. write failure
+		log.debug("removeElement({}, {}, ...) cond. key/value write failure RETRYING", tableId, element );
+		// FIXME Dirty hack
+		final int RETRY_MAX = 100;
+		for (int retry = RETRY_MAX; retry >= 0; --retry) {
+		    RamCloudKeyIndex idx = new RamCloudKeyIndex(tableId, tableEntry.key, graph, element.getClass());
+		    Map<Object, List<Object>> rereadMap = idx.readIndexPropertyMapFromDB();
+
+		    boolean madeChangeOnRetry = false;
+		    Iterator<Map.Entry<Object, List<Object>>> rereadIndexValMapIt = rereadMap.entrySet().iterator();
+		    while (rereadIndexValMapIt.hasNext()) {
+			Map.Entry<Object, List<Object>> entry = rereadIndexValMapIt.next();
+			List<Object> idList = entry.getValue();
+			madeChangeOnRetry |= idList.remove(element.getId());
+			if (idList.isEmpty()) {
+			    madeChangeOnRetry = true;
+			    rereadIndexValMapIt.remove();
+			}
+		    }
+		    if (madeChangeOnRetry == false) {
+			log.debug("removeElement({}, {}, ...) no more write required. SOMETHING MAY BE WRONG", tableId, element);
+			break;
+		    }
+
+		    if (idx.writeWithRules(convertIndexPropertyMapToRcBytes(rereadMap))) {
+			log.debug("removeElement({}, {}, ...) cond. key/value {} write failure RETRYING {}", tableId, element, rereadMap, RETRY_MAX - retry);
+			// cond. re-write success
+			break;
+		    }
+		    if (retry == 0) {
+			log.error("removeElement({}, {}, ...) cond. write failed completely. Gave up RETRYING", tableId, element);
+			// XXX may be we should throw some kind of exception here?
+		    }
+		}
+	    }
+	}
+    }
+
+    public Map<Object, List<Object>> readIndexPropertyMapFromDB() {
+	//log.debug("getIndexPropertyMap() ");
+	JRamCloud.Object propTableEntry;
+	long startTime = 0;
+	PerfMon pm = PerfMon.getInstance();
+
+	try {
+	    JRamCloud vertTable = graph.getRcClient();
+	    if (graph.measureRcTimeProp == 1) {
+		startTime = System.nanoTime();
+	    }
+	    //propTableEntry = graph.getRcClient().read(tableId, rcKey);
+	    pm.indexread_start("RamCloudIndex readIndexPropertyMapFromDB()");
+	    propTableEntry = vertTable.read(tableId, rcKey);
+	    pm.indexread_end("RamCloudIndex readIndexPropertyMapFromDB()");
+	    if (graph.measureRcTimeProp == 1) {
+		long endTime = System.nanoTime();
+		log.error("Performance readIndexPropertyMapFromDB(indexName {}) read time {}", indexName, endTime - startTime);
+	    }
+	    indexVersion = propTableEntry.version;
+	} catch (Exception e) {
+	    pm.indexread_end("RamCloudIndex readIndexPropertyMapFromDB()");
+	    indexVersion = 0;
+	    if (graph.measureRcTimeProp == 1) {
+		long endTime = System.nanoTime();
+		log.error("Performance readIndexPropertyMapFromDB(indexName {}) exception read time {}", indexName, endTime - startTime);
+	    }
+	    log.warn("readIndexPropertyMapFromDB() Element does not have a index property table entry! tableId :" + tableId + " indexName : " + indexName + " ", e);
+	    return null;
+	}
+
+	return convertRcBytesToIndexPropertyMap(propTableEntry.value);
+    }
+
+    public Map<Object, List<Object>> convertRcBytesToIndexPropertyMap(byte[] byteArray) {
+	if (byteArray == null) {
+	    log.error("Got a null byteArray argument");
+	    return null;
+	} else if (byteArray.length != 0) {
+	    PerfMon pm = PerfMon.getInstance();
+            long startTime = 0;
+            if(RamCloudGraph.measureSerializeTimeProp == 1) {
+        	startTime = System.nanoTime();
+            }
+	    pm.indexdeser_start("RamCloudIndex convertRcBytesToIndexPropertyMap()");
+	    IndexBlob blob;
+	    TreeMap<Object, List<Object>> map = new TreeMap<Object, List<Object>>();
+	    try {
+		blob = IndexBlob.parseFrom(byteArray);
+		List const_list = blob.getVertexIdList();
+		ArrayList list = new ArrayList<>(const_list);
+//		ByteBufferInput input = new ByteBufferInput(byteArray);
+//		ArrayList list = kryo.get().readObject(input, ArrayList.class);
+		map.put(rcKeyToPropName(rcKey), list);
+	    } catch (InvalidProtocolBufferException e) {
+		log.error("{" + toString() + "}: Read malformed edge list: ", e);
+	    } finally {
+		pm.indexdeser_end("RamCloudIndex convertRcBytesToIndexPropertyMap()");
+	    }
+            if(RamCloudGraph.measureSerializeTimeProp == 1) {
+            	long endTime = System.nanoTime();
+                log.error("Performance index kryo deserialization [id=N/A] {} size {}", endTime - startTime, byteArray.length);
+            }
+	    return map;
+	} else {
+	    return new TreeMap<Object, List<Object>>();
+	}
+    }
+
+    public static byte[] convertIndexPropertyMapToRcBytes(Map<Object, List<Object>> map) {
+	PerfMon pm = PerfMon.getInstance();
+	long startTime = 0;
+	if(RamCloudGraph.measureSerializeTimeProp == 1) {
+	    startTime = System.nanoTime();
+	}
+	byte[] bytes;
+
+	pm.indexser_start("RamCloudIndex convertIndexPropertyMapToRcBytes()");
+	Builder builder = IndexBlob.newBuilder();
+	if ( map.values().size() != 0 ) {
+		List<Long> vtxIds = (List)map.values().iterator().next();
+		builder.addAllVertexId(vtxIds);
+	}
+	IndexBlob blob = builder.build();
+	bytes = blob.toByteArray();
+//	ByteBufferOutput output = new ByteBufferOutput(1024*1024);
+//	if ( map.values().size() == 0 ) {
+//	    kryo.get().writeObject(output, new ArrayList<Object>());
+//	} else {
+//	    kryo.get().writeObject(output, vtxIds);
+//	}
+//	bytes = output.toBytes();
+        pm.indexser_end("RamCloudIndex convertIndexPropertyMapToRcBytes()");
+	if(RamCloudGraph.measureSerializeTimeProp == 1) {
+        	long endTime = System.nanoTime();
+		log.error("Performance index ProtoBuff serialization {}, size={}", endTime - startTime, bytes);
+	}
+	return bytes;
+    }
+
+    protected boolean writeWithRules(byte[] rcValue) {
+	return writeWithRules(this.tableId, this.rcKey, rcValue, this.indexVersion, this.graph);
+    }
+
+    private static boolean writeWithRules(long tableId, byte[] rcKey, byte[] rcValue, long expectedVersion, RamCloudGraph graph) {
+	JRamCloud.RejectRules rules = graph.getRcClient().new RejectRules();
+
+	if (expectedVersion == 0) {
+	    rules.setExists();
+	} else {
+	    rules.setNeVersion(expectedVersion);
+	}
+
+	PerfMon pm = PerfMon.getInstance();
+	try {
+	    JRamCloud vertTable = graph.getRcClient();
+	    pm.indexwrite_start("RamCloudIndex writeWithRules()");
+	    vertTable.writeRule(tableId, rcKey, rcValue, rules);
+	    pm.indexwrite_end("RamCloudIndex writeWithRules()");
+	} catch (Exception e) {
+            pm.indexwrite_end("RamCloudIndex writeWithRules()");
+            pm.indexwrite_condfail("RamCloudIndex writeWithRules()");
+	    log.debug("Cond. Write index property: {} failed {} expected version: {}", rcKeyToIndexName(rcKey), e, expectedVersion);
+	    return false;
+	}
+	return true;
+    }
+
+    public List<Object> getElmIdListForPropValue(Object propValue) {
+	Map<Object, List<Object>> map = readIndexPropertyMapFromDB();
+	if (map == null) {
+	    log.debug("IndexPropertyMap was null. {} : {}", indexName, propValue);
+	    return null;
+	}
+	return map.get(propValue);
+    }
+
+    public Set<Object> getIndexPropertyKeys() {
+	Map<Object, List<Object>> map = readIndexPropertyMapFromDB();
+	return map.keySet();
+    }
+
+    public <T> T removeIndexProperty(String key) {
+	for (int i = 0; i < 100; ++i) {
+	    Map<Object, List<Object>> map = readIndexPropertyMapFromDB();
+	    T retVal = (T) map.remove(key);
+	    byte[] rcValue = convertIndexPropertyMapToRcBytes(map);
+	    if (rcValue.length != 0) {
+		if (writeWithRules(rcValue)) {
+		    return retVal;
+		} else {
+		    log.debug("removeIndexProperty({}) cond. key/value write failure RETRYING {}", tableId, (i + 1));
+		}
+	    }
+	}
+	log.error("removeIndexProperty({}) cond. key/value write failure gave up RETRYING", tableId);
+	// XXX ?Is this correct
+	return null;
+    }
+
+    public void removeIndex() {
+	log.info("Removing Index: {} was version {} [{}]", indexName, indexVersion, this);
+	graph.getRcClient().remove(tableId, rcKey);
+    }
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudKeyIndex.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudKeyIndex.java
new file mode 100644
index 0000000..d19b7e5
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudKeyIndex.java
@@ -0,0 +1,52 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import com.tinkerpop.blueprints.Element;
+
+public class RamCloudKeyIndex<T extends RamCloudElement> extends RamCloudIndex<T> implements Serializable {
+    public RamCloudKeyIndex(long tableId, String indexName, Object propValue, RamCloudGraph graph, Class<T> indexClass) {
+	super(tableId, indexName, propValue, graph, indexClass);
+    }
+    
+    public RamCloudKeyIndex(long tableId, byte[] rcKey, RamCloudGraph graph, Class<T> indexClass) {
+	super(tableId, rcKey, graph, indexClass);
+    }
+
+    public boolean autoUpdate(final String key, final Object newValue, final Object oldValue, final T element) {
+	if (graph.indexedKeys.contains(key)) {
+	    if (oldValue != null) {
+		this.remove(key, oldValue, element);
+	    }
+	    this.put(key, newValue, element);
+	    return true;
+	} else {
+	    return false;
+	}
+    }
+
+    public void autoRemove(final String key, final Object oldValue, final T element) {
+	if (graph.indexedKeys.contains(key)) {
+	    this.remove(key, oldValue, element);
+	}
+    }
+
+    public long reIndexElements(final RamCloudGraph graph, final Iterable<? extends Element> elements, final Set<String> keys) {
+	long counter = 0;
+	for (final Element element : elements) {
+	    for (final String key : keys) {
+		final Object value = element.removeProperty(key);
+		if (null != value) {
+		    counter++;
+		    element.setProperty(key, value);
+		}
+	    }
+	}
+	return counter;
+    }
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudVertex.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudVertex.java
new file mode 100644
index 0000000..9597f7e
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/RamCloudVertex.java
@@ -0,0 +1,498 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.VertexQuery;
+import com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeListProtoBuf;
+import com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraphProtos.EdgeProtoBuf;
+import com.tinkerpop.blueprints.util.DefaultVertexQuery;
+import com.tinkerpop.blueprints.util.ExceptionFactory;
+import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
+
+import edu.stanford.ramcloud.JRamCloud;
+import edu.stanford.ramcloud.JRamCloud.MultiWriteObject;
+import edu.stanford.ramcloud.JRamCloud.RejectRules;
+import edu.stanford.ramcloud.JRamCloud.WrongVersionException;
+
+public class RamCloudVertex extends RamCloudElement implements Vertex, Serializable {
+
+	private final static Logger log = LoggerFactory.getLogger(RamCloudGraph.class);
+	private static final long serialVersionUID = 7526472295622776147L;
+	protected long id;
+	protected byte[] rcKey;
+	private RamCloudGraph graph;
+
+	private Versioned<EdgeListProtoBuf> cachedAdjEdgeList;
+
+	public RamCloudVertex(long id, RamCloudGraph graph) {
+		super(idToRcKey(id), graph.vertPropTableId, graph);
+
+		this.id = id;
+		this.rcKey = idToRcKey(id);
+		this.graph = graph;
+		this.cachedAdjEdgeList = null;
+	}
+
+	public RamCloudVertex(byte[] rcKey, RamCloudGraph graph) {
+		super(rcKey, graph.vertPropTableId, graph);
+
+		this.id = rcKeyToId(rcKey);
+		this.rcKey = rcKey;
+		this.graph = graph;
+		this.cachedAdjEdgeList = null;
+	}
+
+
+	/*
+	 * Vertex interface implementation
+	 */
+	@Override
+	public Edge addEdge(String label, Vertex inVertex) {
+		return graph.addEdge(null, this, inVertex, label);
+	}
+
+	@Override
+	public Iterable<Edge> getEdges(Direction direction, String... labels) {
+		return new ArrayList<Edge>(getEdgeList(direction, labels));
+	}
+
+	@Override
+	public Iterable<Vertex> getVertices(Direction direction, String... labels) {
+		List<RamCloudEdge> edges = getEdgeList(direction, labels);
+		List<Vertex> neighbors = new LinkedList<Vertex>();
+		for (RamCloudEdge edge : edges) {
+			neighbors.add(edge.getNeighbor(this));
+		}
+		return neighbors;
+	}
+
+	@Override
+	public VertexQuery query() {
+		return new DefaultVertexQuery(this);
+	}
+
+	/*
+	 * RamCloudElement overridden methods
+	 */
+	@Override
+	public Object getId() {
+		return id;
+	}
+
+	@Override
+	public void remove() {
+		Set<RamCloudEdge> edges = getEdgeSet();
+
+		// neighbor vertex -> List of Edges to remove
+		Map<RamCloudVertex, List<RamCloudEdge>> vertexToEdgesMap = new HashMap<RamCloudVertex, List<RamCloudEdge>>( edges.size() );
+
+		// Batch edges together by neighbor vertex
+		for (RamCloudEdge edge : edges) {
+			RamCloudVertex neighbor = (RamCloudVertex) edge.getNeighbor(this);
+			List<RamCloudEdge> edgeList = vertexToEdgesMap.get(neighbor);
+
+			if (edgeList == null) {
+				edgeList = new LinkedList<RamCloudEdge>();
+			}
+
+			edgeList.add(edge);
+			vertexToEdgesMap.put(neighbor, edgeList);
+		}
+
+		// Remove batches of edges at a time by neighbor vertex
+		for (Entry<RamCloudVertex, List<RamCloudEdge>> entry : vertexToEdgesMap.entrySet()) {
+			// Skip over loopback edges to ourself
+			if (!entry.getKey().equals(this)) {
+				entry.getKey().removeEdgesFromAdjList(entry.getValue());
+			}
+
+			// Remove this batch of edges from the edge property table
+			for (RamCloudEdge edge : entry.getValue()) {
+				edge.removeProperties();
+			}
+		}
+
+		Map<String,Object> props = this.getPropertyMap();
+		for( Map.Entry<String,Object> entry : props.entrySet() ) {
+			if ( !graph.indexedKeys.contains(entry.getKey() ) ) continue;
+			RamCloudKeyIndex keyIndex = new RamCloudKeyIndex(graph.kidxVertTableId, entry.getKey(), entry.getValue(), graph, Vertex.class);
+			keyIndex.remove(entry.getKey(), entry.getValue(), this);
+		}
+
+		// Remove ourselves entirely from the vertex table
+		graph.getRcClient().remove(graph.vertTableId, rcKey);
+
+		super.remove();
+	}
+
+	/*
+	 * Object overridden methods
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj == null) {
+			return false;
+		}
+		if (getClass() != obj.getClass()) {
+			return false;
+		}
+		RamCloudVertex other = (RamCloudVertex) obj;
+		return (id == other.id);
+	}
+
+	@Override
+	public int hashCode() {
+		return Long.valueOf(id).hashCode();
+	}
+
+	@Override
+	public String toString() {
+		return "RamCloudVertex [id=" + id + "]";
+	}
+
+	/*
+	 * RamCloudVertex specific methods
+	 */
+	private static byte[] idToRcKey(long id) {
+		return ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(id).array();
+	}
+
+	private static long rcKeyToId(byte[] rcKey) {
+		return ByteBuffer.wrap(rcKey).order(ByteOrder.LITTLE_ENDIAN).getLong();
+	}
+
+	boolean addEdgeToAdjList(RamCloudEdge edge) {
+		List<RamCloudEdge> edgesToAdd = new ArrayList<RamCloudEdge>(1);
+		edgesToAdd.add(edge);
+		return addEdgesToAdjList(edgesToAdd);
+	}
+	boolean removeEdgeFromAdjList(RamCloudEdge edge) {
+		List<RamCloudEdge> edgesToRemove = new ArrayList<RamCloudEdge>(1);
+		edgesToRemove.add(edge);
+		return removeEdgesFromAdjList(edgesToRemove);
+	}
+
+	private boolean addEdgesToAdjList(List<RamCloudEdge> edgesToAdd) {
+		return updateEdgeAdjList(edgesToAdd, true);
+	}
+	private boolean removeEdgesFromAdjList(List<RamCloudEdge> edgesToAdd) {
+		return updateEdgeAdjList(edgesToAdd, false);
+	}
+
+	/** Conditionally update Adj. Edge List
+	 * @return true if EdgeAdjList was logically modified.(Cache update does not imply true return)
+	 */
+	private boolean updateEdgeAdjList(List<RamCloudEdge> edgesToModify, boolean add) {
+		PerfMon pm = PerfMon.getInstance();
+		JRamCloud rcClient = graph.getRcClient();
+		final int MAX_RETRIES = 100;
+		for (int retry = 1 ; retry <= MAX_RETRIES ; ++retry ) {
+			Set<RamCloudEdge> edges;
+			long expected_version = 0L;
+			if ( this.cachedAdjEdgeList == null ) {
+				edges = new HashSet<RamCloudEdge>();
+			} else {
+				expected_version = this.cachedAdjEdgeList.getVersion();
+				if ( expected_version == 0L && add == false ) {
+					updateCachedAdjEdgeList();
+					expected_version = this.cachedAdjEdgeList.getVersion();
+				}
+				edges = buildEdgeSetFromProtobuf(this.cachedAdjEdgeList.getValue(), Direction.BOTH);
+			}
+			if ( expected_version == 0L && add == false ) {
+				updateCachedAdjEdgeList();
+				expected_version = this.cachedAdjEdgeList.getVersion();
+				edges = buildEdgeSetFromProtobuf(this.cachedAdjEdgeList.getValue(), Direction.BOTH);
+			}
+			//log.debug( (add?"Adding":"Removing") + " edges to: {"+ edges+ "}");
+
+			try {
+				if ( add ) {
+					if (edges.addAll(edgesToModify) == false) {
+						log.warn("{}: There aren't any changes to edges ({})", this, edgesToModify);
+						return false;
+					}
+				} else {
+					if (edges.removeAll(edgesToModify) == false) {
+						log.warn("{}: There aren't any changes to edges ({})", this, edgesToModify);
+						return false;
+					}
+				}
+
+				EdgeListProtoBuf edgeList = buildProtoBufFromEdgeSet(edges);
+				JRamCloud.RejectRules rules = rcClient.new RejectRules();
+				if ( expected_version == 0L ) {
+					rules.setExists();
+				} else {
+					rules.setNeVersion(expected_version);
+				}
+				pm.write_start("RAMCloudVertex updateEdgeAdjList()");
+				long updated_version = rcClient.writeRule(graph.vertTableId, rcKey, edgeList.toByteArray(), rules);
+				pm.write_end("RAMCloudVertex updateEdgeAdjList()");
+				this.cachedAdjEdgeList.setValue(edgeList, updated_version);
+				return true;
+			} catch (UnsupportedOperationException e) {
+				pm.write_end("RAMCloudVertex updateEdgeAdjList()");
+				pm.write_condfail("RAMCloudVertex updateEdgeAdjList()");
+				log.error("{" + toString() + "}: Failed to modify a set of edges ({" + edgesToModify + "}): ", e);
+				return false;
+			} catch (ClassCastException e) {
+				pm.write_end("RAMCloudVertex updateEdgeAdjList()");
+				pm.write_condfail("RAMCloudVertex updateEdgeAdjList()");
+				log.error("{" + toString() + "}: Failed to modify a set of edges ({" + edgesToModify + "}): ", e);
+				return false;
+			} catch (NullPointerException e) {
+				pm.write_end("RAMCloudVertex updateEdgeAdjList()");
+				pm.write_condfail("RAMCloudVertex updateEdgeAdjList()");
+				log.error("{" + toString() + "}: Failed to modify a set of edges ({" + edgesToModify + "}): ", e);
+				return false;
+			} catch (Exception e) {
+				pm.write_end("RAMCloudVertex updateEdgeAdjList()");
+				pm.write_condfail("RAMCloudVertex updateEdgeAdjList()");
+				// FIXME Workaround for native method exception declaration bug
+				if ( e instanceof WrongVersionException ) {
+					log.debug("Conditional Updating EdgeList failed for {} RETRYING {}", this, retry);
+					//log.debug("Conditional Updating EdgeList failed for {} modifing {} RETRYING [{}]", this, edgesToModify, retry);
+					updateCachedAdjEdgeList();
+				} else {
+					log.debug("Cond. Write to modify adj edge list failed, exception thrown", e);
+					updateCachedAdjEdgeList();
+				}
+			}
+		}
+		log.error("Conditional Updating EdgeList failed for {} gave up RETRYING", this);
+		return false;
+	}
+
+	/** Get all adj.edge list
+	 * Method is exposed to package namespace to do Vertex removal efficiently;
+	 */
+	Set<RamCloudEdge> getEdgeSet() {
+		return getVersionedEdgeSet(Direction.BOTH).getValue();
+	}
+
+	private Versioned<EdgeListProtoBuf> updateCachedAdjEdgeList() {
+		JRamCloud.Object vertTableEntry;
+		EdgeListProtoBuf edgeList;
+
+		PerfMon pm = PerfMon.getInstance();
+		try {
+			JRamCloud vertTable = graph.getRcClient();
+			pm.read_start("RamCloudVertex updateCachedAdjEdgeList()");
+			vertTableEntry = vertTable.read(graph.vertTableId, rcKey);
+			pm.read_end("RamCloudVertex updateCachedAdjEdgeList()");
+		} catch (Exception e) {
+			pm.read_end("RamCloudVertex updateCachedAdjEdgeList()");
+			log.error("{" + toString() + "}: Error reading vertex table entry: ", e);
+			return null;
+		}
+
+		try {
+			pm.protodeser_start("RamCloudVertex updateCachedAdjEdgeList()");
+			edgeList = EdgeListProtoBuf.parseFrom(vertTableEntry.value);
+			Versioned<EdgeListProtoBuf> updatedEdgeList = new Versioned<EdgeListProtoBuf>(edgeList, vertTableEntry.version);
+			this.cachedAdjEdgeList = updatedEdgeList;
+			pm.protodeser_end("RamCloudVertex updateCachedAdjEdgeList()");
+			return updatedEdgeList;
+		} catch (InvalidProtocolBufferException e) {
+			pm.protodeser_end("RamCloudVertex updateCachedAdjEdgeList()");
+			log.error("{" + toString() + "}: Read malformed edge list: ", e);
+			return null;
+		}
+	}
+
+	private Versioned<Set<RamCloudEdge>> getVersionedEdgeSet(Direction direction, String... labels) {
+		Versioned<EdgeListProtoBuf> cachedEdgeList = updateCachedAdjEdgeList();
+		return new Versioned<Set<RamCloudEdge>>(buildEdgeSetFromProtobuf(cachedEdgeList.getValue(), direction, labels), cachedEdgeList.getVersion() );
+	}
+
+	private Set<RamCloudEdge> buildEdgeSetFromProtobuf(EdgeListProtoBuf edgeList,
+			Direction direction, String... labels) {
+		PerfMon pm = PerfMon.getInstance();
+		long startTime = 0;
+		if(RamCloudGraph.measureSerializeTimeProp == 1) {
+		    startTime = System.nanoTime();
+		}
+		pm.protodeser_start("RamCloudVertex buildEdgeSetFromProtobuf()");
+		Set<RamCloudEdge> edgeSet = new HashSet<RamCloudEdge>( edgeList.getEdgeCount() );
+		for (EdgeProtoBuf edge : edgeList.getEdgeList()) {
+			if ((direction.equals(Direction.BOTH) || (edge.getOutgoing() ^ direction.equals(Direction.IN)))
+					&& (labels.length == 0 || Arrays.asList(labels).contains(edge.getLabel()))) {
+				RamCloudVertex  neighbor = new RamCloudVertex(edge.getNeighborId(), graph);
+				if (edge.getOutgoing()) {
+					edgeSet.add(new RamCloudEdge(this, neighbor, edge.getLabel(), graph));
+				} else {
+					edgeSet.add(new RamCloudEdge(neighbor, this, edge.getLabel(), graph));
+				}
+			}
+		}
+		pm.protodeser_end("RamCloudVertex buildEdgeSetFromProtobuf()");
+		if(RamCloudGraph.measureSerializeTimeProp == 1) {
+                 	long endTime = System.nanoTime();
+                	log.error("Performance buildEdgeSetFromProtobuf key {}, {}, size={}", this, endTime - startTime, edgeList.getSerializedSize());
+		}
+		return edgeSet;
+	}
+
+
+
+	private EdgeListProtoBuf buildProtoBufFromEdgeSet(Set<RamCloudEdge> edgeSet) {
+		PerfMon pm = PerfMon.getInstance();
+		long startTime = 0;
+		if(RamCloudGraph.measureSerializeTimeProp == 1) {
+		    startTime = System.nanoTime();
+		}
+
+		pm.protoser_start("RamCloudVertex buildProtoBufFromEdgeSet()");
+
+		EdgeListProtoBuf.Builder edgeListBuilder = EdgeListProtoBuf.newBuilder();
+		EdgeProtoBuf.Builder edgeBuilder = EdgeProtoBuf.newBuilder();
+
+		for (Edge edge : edgeSet) {
+			if (edge.getVertex(Direction.OUT).equals(this) || edge.getVertex(Direction.IN).equals(this)) {
+				if (edge.getVertex(Direction.OUT).equals(edge.getVertex(Direction.IN))) {
+					edgeBuilder.setNeighborId(id);
+					edgeBuilder.setOutgoing(true);
+					edgeBuilder.setLabel(edge.getLabel());
+					edgeListBuilder.addEdge(edgeBuilder.build());
+
+					edgeBuilder.setOutgoing(false);
+					edgeListBuilder.addEdge(edgeBuilder.build());
+				} else {
+					if (edge.getVertex(Direction.OUT).equals(this)) {
+						edgeBuilder.setNeighborId((Long) edge.getVertex(Direction.IN).getId());
+						edgeBuilder.setOutgoing(true);
+						edgeBuilder.setLabel(edge.getLabel());
+						edgeListBuilder.addEdge(edgeBuilder.build());
+					} else {
+						edgeBuilder.setNeighborId((Long) edge.getVertex(Direction.OUT).getId());
+						edgeBuilder.setOutgoing(false);
+						edgeBuilder.setLabel(edge.getLabel());
+						edgeListBuilder.addEdge(edgeBuilder.build());
+					}
+				}
+			} else {
+				log.warn("{}: Tried to add an edge unowned by this vertex ({})", this, edge);
+			}
+		}
+
+		EdgeListProtoBuf buf = edgeListBuilder.build();
+		pm.protoser_end("RamCloudVertex buildProtoBufFromEdgeSet");
+		if(RamCloudGraph.measureSerializeTimeProp == 1) {
+                	long endTime = System.nanoTime();
+                	log.error("Performance buildProtoBufFromEdgeSet key {}, {}, size={}", this, endTime - startTime, buf.getSerializedSize());
+		}
+		return buf;
+	}
+
+	@Deprecated
+	private List<RamCloudEdge> getEdgeList() {
+		return getEdgeList(Direction.BOTH);
+	}
+
+	private List<RamCloudEdge> getEdgeList(Direction direction, String... labels) {
+
+		Versioned<EdgeListProtoBuf> cachedEdgeList = updateCachedAdjEdgeList();
+		PerfMon pm = PerfMon.getInstance();
+		pm.protodeser_start("RamCloudVertex getEdgeList()");
+
+		List<RamCloudEdge> edgeList = new ArrayList<RamCloudEdge>(cachedEdgeList.getValue().getEdgeCount());
+
+		for (EdgeProtoBuf edge : cachedEdgeList.getValue().getEdgeList()) {
+			if ((direction.equals(Direction.BOTH) || (edge.getOutgoing() ^ direction.equals(Direction.IN)))
+					&& (labels.length == 0 || Arrays.asList(labels).contains(edge.getLabel()))) {
+				RamCloudVertex neighbor = new RamCloudVertex(edge.getNeighborId(), graph);
+				if (edge.getOutgoing()) {
+					edgeList.add(new RamCloudEdge(this, neighbor, edge.getLabel(), graph));
+				} else {
+					edgeList.add(new RamCloudEdge(neighbor, this, edge.getLabel(), graph));
+				}
+			}
+		}
+		pm.protodeser_end("RamCloudVertex getEdgeList()");
+
+		return edgeList;
+	}
+
+	protected boolean exists() {
+		boolean vertTableEntryExists = false;
+		boolean vertPropTableEntryExists = false;
+
+		PerfMon pm = PerfMon.getInstance();
+	        JRamCloud vertTable = graph.getRcClient();
+		try {
+		        pm.read_start("RamCloudVertex exists()");
+			vertTable.read(graph.vertTableId, rcKey);
+			pm.read_end("RamCloudVertex exists()");
+			vertTableEntryExists = true;
+		} catch (Exception e) {
+			// Vertex table entry does not exist
+		        pm.read_end("RamCloudVertex exists()");
+		}
+
+		try {
+			pm.read_start("RamCloudVertex exists()");
+			vertTable.read(graph.vertPropTableId, rcKey);
+		        pm.read_end("RamCloudVertex exists()");
+			vertPropTableEntryExists = true;
+		} catch (Exception e) {
+			// Vertex property table entry does not exist
+		        pm.read_end("RamCloudVertex exists()");
+		}
+
+		if (vertTableEntryExists && vertPropTableEntryExists) {
+			return true;
+		} else if (!vertTableEntryExists && !vertPropTableEntryExists) {
+			return false;
+		} else {
+			log.warn("{}: Detected RamCloudGraph inconsistency: vertTableEntryExists={}, vertPropTableEntryExists={}.", this, vertTableEntryExists, vertPropTableEntryExists);
+			return true;
+		}
+	}
+
+	protected void create() throws IllegalArgumentException {
+		// TODO: Existence check costs extra (presently 2 reads), could use option to turn on/off
+		if (!exists()) {
+			PerfMon pm = PerfMon.getInstance();
+			JRamCloud vertTable = graph.getRcClient();
+			MultiWriteObject[] mwo = new MultiWriteObject[2];
+			mwo[0] = new MultiWriteObject(graph.vertTableId, rcKey, ByteBuffer.allocate(0).array(), null);
+			mwo[1] = new MultiWriteObject(graph.vertPropTableId, rcKey, ByteBuffer.allocate(0).array(), null);
+			pm.multiwrite_start("RamCloudVertex create()");
+			vertTable.multiWrite(mwo);
+			pm.multiwrite_end("RamCloudVertex create()");
+		} else {
+			throw ExceptionFactory.vertexWithIdAlreadyExists(id);
+		}
+	}
+
+	public void debugPrintEdgeList() {
+		List<RamCloudEdge> edgeList = getEdgeList();
+
+		log.debug("{}: Debug Printing Edge List...", this);
+		for (RamCloudEdge edge : edgeList) {
+			System.out.println(edge.toString());
+		}
+	}
+}
diff --git a/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/Versioned.java b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/Versioned.java
new file mode 100644
index 0000000..270ad5c
--- /dev/null
+++ b/src/main/java/com/tinkerpop/blueprints/impls/ramcloud/Versioned.java
@@ -0,0 +1,26 @@
+package com.tinkerpop.blueprints.impls.ramcloud;
+
+public class Versioned<T> {
+	private T value;
+	private long version;
+
+	public Versioned(T value) {
+		this(value, 0L);
+	}
+
+	public Versioned(T value, long version) {
+		this.value = value;
+		this.version = version;
+	}
+
+	public T getValue() {
+		return value;
+	}
+	public long getVersion() {
+		return version;
+	}
+	public void setValue(T value, long version) {
+		this.value = value;
+		this.version = version;
+	}
+}
diff --git a/src/main/java/com/tinkerpop/rexster/config/RamCloudGraphConfiguration.java b/src/main/java/com/tinkerpop/rexster/config/RamCloudGraphConfiguration.java
new file mode 100644
index 0000000..08fe9f2
--- /dev/null
+++ b/src/main/java/com/tinkerpop/rexster/config/RamCloudGraphConfiguration.java
@@ -0,0 +1,15 @@
+package com.tinkerpop.rexster.config;
+
+import com.tinkerpop.blueprints.Graph;
+import com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraph;
+import com.tinkerpop.rexster.config.GraphConfiguration;
+import org.apache.commons.configuration.Configuration;
+
+
+public class RamCloudGraphConfiguration implements GraphConfiguration {
+
+    public Graph configureGraphInstance(final Configuration properties) throws GraphConfigurationException {
+        return new RamCloudGraph("fast+udp:host=127.0.0.1,port=12246");
+    }
+
+}
diff --git a/src/main/java/edu/stanford/ramcloud/JRamCloud.java b/src/main/java/edu/stanford/ramcloud/JRamCloud.java
new file mode 100755
index 0000000..fef2b12
--- /dev/null
+++ b/src/main/java/edu/stanford/ramcloud/JRamCloud.java
@@ -0,0 +1,430 @@
+/* Copyright (c) 2013 Stanford University
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package edu.stanford.ramcloud;
+
+/*
+ * This class provides Java bindings for RAMCloud. Right now it is a rather
+ * simple subset of what RamCloud.h defines.
+ *
+ * Running ``javah'' on this file will generate a C header file with the
+ * appropriate JNI function definitions. The glue interfacing to the C++
+ * RAMCloud library can be found in JRamCloud.cc.
+ *
+ * For JNI information, the IBM tutorials and Android developer docs are much
+ * better than Sun's at giving an overall intro:
+ *      http://www.ibm.com/developerworks/java/tutorials/j-jni/section4.html
+ *      http://developer.android.com/training/articles/perf-jni.html
+ */
+public class JRamCloud {
+    static {
+        System.loadLibrary("edu_stanford_ramcloud_JRamCloud");
+    }
+
+    /// Pointer to the underlying C++ RAMCloud object associated with this
+    /// object.
+    private long ramcloudObjectPointer = 0;
+
+    /**
+     * See src/RejectRules.h.
+     */
+    public class RejectRules {
+	private long givenVersion;
+        private boolean doesntExist;
+        private boolean exists;
+        private boolean versionLeGiven;
+        private boolean versionNeGiven;
+
+        public RejectRules() {
+            this.givenVersion = -1;
+            this.exists = this.doesntExist = this.versionLeGiven = this.versionNeGiven = false;
+        }
+
+        public void setLeVersion(long version) {
+            setVersion(version);
+            this.versionLeGiven = true;
+        }
+
+        public void setExists() {
+            this.exists = true;
+        }
+
+        public void setDoesntExists() {
+            this.doesntExist = true;
+        }
+
+        public void setNeVersion(long version) {
+            setVersion(version);
+            this.versionNeGiven = true;
+        }
+
+        private void setVersion(long version) {
+            this.givenVersion = version;
+        }	
+    }
+    
+    public static class multiReadObject {
+        long tableId;
+        byte[] key;
+        
+        public multiReadObject(long _tableId, byte[] _key){
+            tableId = _tableId;
+            key = _key;
+        }
+    }
+    
+    public static class MultiWriteObject {
+        long tableId;
+        byte[] key;
+        byte[] value;
+        RejectRules rules;
+
+        public MultiWriteObject(long tableId, byte[] key, byte[] value, RejectRules rules) {
+            this.tableId = tableId;
+            this.key = key;
+            this.value = value;
+            this.rules = rules;
+        }
+    }
+
+    public class MultiWriteRspObject {
+        private int status;
+        private long version;
+
+        public MultiWriteRspObject(int status, long version) {
+            this.status = status;
+            this.version = version;
+        }
+        public int getStatus() {
+            return status;
+        }
+
+        public long getVersion() {
+            return version;
+        }
+    }
+
+    /**
+     * This class is returned by Read operations. It encapsulates the entire
+     * object, including the key, value, and version.
+     *
+     * It mostly exists because Java doesn't support primitive out parameters
+     * or multiple return values, and we don't know the object's size ahead of
+     * time, so passing in a fixed-length array would be problematic.
+     */
+    public class Object {
+        Object(byte[] _key, byte[] _value, long _version)
+        {
+            key = _key;
+            value = _value;
+            version = _version;
+        }
+
+        public String
+        getKey()
+        {
+            return new String(key);
+        }
+
+        public String
+        getValue()
+        {
+            return new String(value);
+        }
+
+        final public byte[] key;
+        final public byte[] value;
+        final public long version;
+    }
+
+    public class TableEnumerator {
+        private long tableEnumeratorObjectPointer = 0;
+        private long ramCloudObjectPointer = 0;
+        
+        public TableEnumerator(long tableId)
+        {
+            ramCloudObjectPointer = ramcloudObjectPointer;
+            tableEnumeratorObjectPointer = init(tableId);
+        }
+        
+        private native long init(long tableId);
+        public native boolean hasNext();
+        public native Object next();
+    }
+
+    /**
+     * Connect to the RAMCloud cluster specified by the given coordinator's
+     * service locator string. This causes the JNI code to instantiate the
+     * underlying RamCloud C++ object.
+     */
+    public
+    JRamCloud(String coordinatorLocator)
+    {
+        ramcloudObjectPointer = connect(coordinatorLocator);
+    }
+
+    /**
+     * Disconnect from the RAMCloud cluster. This causes the JNI code to
+     * destroy the underlying RamCloud C++ object.
+     */
+    public void
+    disconnect()
+    {
+        if (ramcloudObjectPointer != 0) {
+            disconnect(ramcloudObjectPointer);
+            ramcloudObjectPointer = 0;
+        }
+    }
+
+    /**
+     * This method is called by the garbage collector before destroying the
+     * object. The user really should have called disconnect, but in case
+     * they did not, be sure to clean up after them.
+     */
+    public void
+    finalize()
+    {
+        System.err.println("warning: JRamCloud::disconnect() was not called " +
+                           "prior to the finalizer. You should disconnect " +
+                           "your JRamCloud object when you're done with it.");
+        disconnect();
+    }
+
+    /**
+     * Convenience read() wrapper that take a String key argument.
+     */
+    public Object
+    read(long tableId, String key)
+    {
+        return read(tableId, key.getBytes());
+    }
+
+    /**
+     * Convenience read() wrapper that take a String key argument.
+     */
+    public Object
+    read(long tableId, String key, RejectRules rules)
+    {
+        return read(tableId, key.getBytes(), rules);
+    }
+    
+    /**
+     * Convenience remove() wrapper that take a String key argument.
+     */
+    public long
+    remove(long tableId, String key)
+    {
+        return remove(tableId, key.getBytes());
+    }
+
+    /**
+     * Convenience remove() wrapper that take a String key argument.
+     */
+    public long
+    remove(long tableId, String key, RejectRules rules)
+    {
+        return remove(tableId, key.getBytes(), rules);
+    }
+
+    /**
+     * Convenience write() wrapper that take String key and value arguments.
+     */
+    public long
+    write(long tableId, String key, String value)
+    {
+        return write(tableId, key.getBytes(), value.getBytes());
+    }
+
+    /**
+     * Convenience write() wrapper that take String key and value arguments.
+     */
+    public long
+    write(long tableId, String key, String value, RejectRules rules)
+    {
+        return write(tableId, key.getBytes(), value.getBytes(), rules);
+    }
+
+    /**
+     * Convenience write() wrapper that takes a String key and a byte[] value
+     * argument.
+     */
+    public long
+    write(long tableId, String key, byte[] value)
+    {
+        return write(tableId, key.getBytes(), value);
+    }
+
+    /**
+     * Convenience write() wrapper that takes a String key and a byte[] value
+     * argument.
+     */
+    public long
+    write(long tableId, String key, byte[] value, RejectRules rules)
+    {
+        return write(tableId, key.getBytes(), value, rules);
+    }
+    
+    private static native long connect(String coordinatorLocator);
+    private static native void disconnect(long ramcloudObjectPointer);
+
+    public native long createTable(String name);
+    public native long createTable(String name, int serverSpan);
+    public native void dropTable(String name);
+    public native long getTableId(String name);
+    public native Object read(long tableId, byte[] key);
+    public native Object read(long tableId, byte[] key, RejectRules rules);
+    public native Object[] multiRead(multiReadObject[] mread);
+    public native long remove(long tableId, byte[] key);
+    public native long remove(long tableId, byte[] key, RejectRules rules);
+    public native long write(long tableId, byte[] key, byte[] value);
+    public native long write(long tableId, byte[] key, byte[] value, RejectRules rules);
+    public native long writeRule(long tableId, byte[] key, byte[] value, RejectRules rules);
+    public native MultiWriteRspObject[] multiWrite(MultiWriteObject[] mwrite);
+
+    /*
+     * The following exceptions may be thrown by the JNI functions:
+     */
+
+    public class TableDoesntExistException extends Exception {
+        public TableDoesntExistException(String message)
+        {
+            super(message);
+        }
+    }
+
+    public class ObjectDoesntExistException extends Exception {
+        public ObjectDoesntExistException(String message)
+        {
+            super(message);
+        }
+    }
+
+    public class ObjectExistsException extends Exception {
+        public ObjectExistsException(String message)
+        {
+            super(message);
+        }
+    }
+
+    public class WrongVersionException extends Exception {
+        public WrongVersionException(String message)
+        {
+            super(message);
+        }
+    }
+    
+    public class InvalidObjectException extends Exception {
+        public InvalidObjectException(String message) {
+            super(message);
+        }
+    }
+    
+    public class RejectRulesException extends Exception {
+        public RejectRulesException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * A simple end-to-end test of the java bindings.
+     */
+    public static void
+    main(String argv[])
+    {
+        JRamCloud ramcloud = new JRamCloud(argv[0]);
+        long tableId = ramcloud.createTable("hi");
+        System.out.println("created table, id = " + tableId);
+        long tableId2 = ramcloud.getTableId("hi");
+        System.out.println("getTableId says tableId = " + tableId2);
+
+        System.out.println("wrote obj version = " +
+            ramcloud.write(tableId, "thisIsTheKey", "thisIsTheValue"));
+
+        JRamCloud.Object o = ramcloud.read(tableId, "thisIsTheKey");
+        System.out.println("read object: key = [" + o.getKey() + "], value = ["
+            + o.getValue() + "], version = " + o.version);
+
+        ramcloud.remove(tableId, "thisIsTheKey");
+
+        try {
+            ramcloud.read(tableId, "thisIsTheKey");
+            System.out.println("Error: shouldn't have read successfully!");
+        } catch (Exception e) {
+            // OK
+        }
+
+        ramcloud.write(tableId, "thisIsTheKey", "thisIsTheValue");
+        
+        long before = System.nanoTime();
+        for (int i = 0; i < 1000; i++) {
+            JRamCloud.Object unused = ramcloud.read(tableId, "thisIsTheKey");
+        }
+        long after = System.nanoTime();
+        System.out.println("Avg read latency: " +
+            ((double)(after - before) / 1000 / 1000) + " usec");
+        
+        // multiRead test
+        long tableId4 = ramcloud.createTable("table4");
+        System.out.println("table4 id " + tableId4);
+        ramcloud.write(tableId4, "object1-1", "value:1-1");
+        ramcloud.write(tableId4, "object1-2", "value:1-2");
+        ramcloud.write(tableId4, "object1-3", "value:1-3");
+        long tableId5 = ramcloud.createTable("table5");
+        System.out.println("table5 id " + tableId5);
+        ramcloud.write(tableId5, "object2-1", "value:2-1");
+        long tableId6 = ramcloud.createTable("table6");
+        ramcloud.write(tableId6, "object3-1", "value:3-1");
+        ramcloud.write(tableId6, "object3-2", "value:3-2");
+
+        multiReadObject mread[] = new multiReadObject[2];
+        //for (int k = 0; k < 2000; k++) {
+        mread[0] = new multiReadObject(tableId4, "object1-1".getBytes());
+        mread[1] = new multiReadObject(tableId5, "object2-1".getBytes());
+        JRamCloud.Object out[] = ramcloud.multiRead(mread);
+        for (int i = 0 ; i < 2 ; i++){
+            System.out.println("multi read object: key = [" + out[i].getKey() + "], value = ["
+                    + out[i].getValue() + "]");
+        //}
+        }
+        MultiWriteObject mwrite[] = new MultiWriteObject[2];
+        for (int i = 0; i < 1000; i++) {
+            String key1 = "key1" + new Integer(i).toString();
+            String key2 = "key2" + new Integer(i).toString();
+      
+            mwrite[0] = new MultiWriteObject(tableId4, key1.getBytes(), "v0-value".getBytes(), null);
+            mwrite[1] = new MultiWriteObject(tableId5, key2.getBytes(), "v1".getBytes(), null);
+            MultiWriteRspObject[] rsp = ramcloud.multiWrite(mwrite);
+            if (rsp != null) {
+                for (int j = 0; j < rsp.length; j++) {
+                    System.out.println("multi write rsp(" + j + ") status:version " + rsp[j].getStatus() + ":" + rsp[j].getVersion());
+                }
+            }
+        }
+        for (int i = 0; i < 1000; i++) {
+            String key1 = "key1" + new Integer(i).toString();
+            String key2 = "key2" + new Integer(i).toString();
+            mread[0] = new multiReadObject(tableId4, key1.getBytes());
+            mread[1] = new multiReadObject(tableId5, key2.getBytes());
+            out = ramcloud.multiRead(mread);
+            for (int j = 0; j < 2; j++) {
+                System.out.println("multi read object: key = [" + out[j].getKey() + "], value = [" + out[j].getValue() + "]");
+            }
+        }
+        ramcloud.dropTable("table4");
+        ramcloud.dropTable("table5");
+        ramcloud.dropTable("table6");
+        ramcloud.disconnect();
+    }
+}
diff --git a/src/main/protobuf/ramcloudgraph.proto b/src/main/protobuf/ramcloudgraph.proto
new file mode 100644
index 0000000..abd270d
--- /dev/null
+++ b/src/main/protobuf/ramcloudgraph.proto
@@ -0,0 +1,37 @@
+package RamCloudGraph;
+
+option java_package = "com.tinkerpop.blueprints.impls.ramcloud";
+option java_outer_classname = "RamCloudGraphProtos";
+
+message EdgeListProtoBuf {
+  repeated EdgeProtoBuf edge = 1;
+}
+
+message EdgeProtoBuf {
+  required uint64 neighborId = 1;
+  required bool outgoing = 2;
+  required string label = 3;
+}
+
+message PropertyListProtoBuf {
+  repeated PropertyProtoBuf property = 1;
+}
+
+message PropertyProtoBuf {
+  enum Type { STRING = 1; INT32 = 2; INT64 = 3; DOUBLE = 4; FLOAT = 5; BOOL = 6; }
+
+  required string key = 1;
+  
+  required Type value_type = 2;
+
+  optional string string_value = 3;
+  optional int32 int32_value = 4;
+  optional int64 int64_value = 5;
+  optional double double_value = 6;
+  optional float float_value = 7;
+  optional bool bool_value = 8;
+}
+
+message IndexBlob {
+  repeated int64 vertexId = 1;
+}
diff --git a/start-ramcloud-coordinator.sh b/start-ramcloud-coordinator.sh
new file mode 100755
index 0000000..bba962a
--- /dev/null
+++ b/start-ramcloud-coordinator.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${HOME}/ramcloud/bindings/java/edu/stanford/ramcloud:${HOME}/ramcloud/obj.blueprint-java
+
+function host2ip (){
+   ip=`egrep "$1\$" /etc/hosts |grep -v "ip6"|  awk '{print $1}'`
+   echo $ip
+}
+
+# Set paths
+ONOS_HOME=`dirname $0`
+RAMCLOUD_DIR=${HOME}/ramcloud
+LOGDIR=${ONOS_HOME}/onos-logs
+RAMCLOUD_LOG=${LOGDIR}/ramcloudcoordinator.`hostname`.log
+thishost=`hostname`
+thisip=`host2ip $thishost`
+RAMCLOUD_COORDINATOR="fast+udp:host=$thisip,port=12242"
+
+function lotate {
+    logfile=$1
+    nr_max=${2:-10}
+    if [ -f $logfile ]; then
+	for i in `seq $(expr $nr_max - 1) -1 1`; do
+	    if [ -f ${logfile}.${i} ]; then
+		mv -f ${logfile}.${i} ${logfile}.`expr $i + 1`
+	    fi
+	done
+	mv $logfile $logfile.1
+    fi
+}
+
+function start {
+  if [ ! -d ${LOGDIR} ]; then
+    mkdir -p ${LOGDIR}
+  fi
+  echo "rotate log: $log"
+  if [ -f $RAMCLOUD_LOG ]; then
+    lotate $RAMCLOUD_LOG
+  fi
+
+  # Run ramcloud 
+  echo "Starting ramcloud coordinator"
+  $RAMCLOUD_DIR/obj.blueprint-java/coordinator  -L $RAMCLOUD_COORDINATOR > $RAMCLOUD_LOG 2>&1 &
+}
+
+function stop {
+  # Kill the existing processes
+  capid=`pgrep coordinator | awk '{print $1}'`
+  pids="$capid"
+  for p in ${pids}; do
+    if [ x$p != "x" ]; then
+      kill -KILL $p
+      echo "Killed existing prosess (pid: $p)"
+    fi
+  done
+}
+
+function deldb {
+#   # Delete the berkeley db database
+   if [ -d "/tmp/ramcloud.conf" ]; then
+      echo "deleting berkeley db dir"
+      sudo rm -rf /tmp/ramcloud.conf
+   fi
+}
+
+case "$1" in
+  start)
+    deldb
+    cp $ONOS_HOME/conf/ramcloud.conf /tmp
+    stop
+    start 
+    ;;
+  stop)
+    stop
+    ;;
+#  deldb)
+#    deldb
+#    ;;
+  status)
+    n=`pgrep -f obj.blueprint-java/coordinator | wc -l`
+    echo "$n ramcloud coordinator is running"
+    ;;
+  *)
+    echo "Usage: $0 {start|stop|restart|status}"
+    exit 1
+esac
