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();
+    }
+}
