You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by to...@apache.org on 2013/11/27 23:24:43 UTC

[2/3] Initial import of 2.0 core persistence code.

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/MvccLogEntrySerializationStrategyImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/MvccLogEntrySerializationStrategyImpl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/MvccLogEntrySerializationStrategyImpl.java
new file mode 100644
index 0000000..f6217a2
--- /dev/null
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/MvccLogEntrySerializationStrategyImpl.java
@@ -0,0 +1,219 @@
+package org.apache.usergrid.persistence.collection.serialization;
+
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.cassandra.db.marshal.ReversedType;
+import org.apache.cassandra.db.marshal.UUIDType;
+
+import org.apache.usergrid.persistence.collection.CollectionContext;
+import org.apache.usergrid.persistence.collection.migration.CollectionColumnFamily;
+import org.apache.usergrid.persistence.collection.migration.Migration;
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccLogEntry;
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccLogEntryImpl;
+import org.apache.usergrid.persistence.collection.mvcc.entity.Stage;
+
+import com.google.common.base.Preconditions;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import com.netflix.astyanax.ColumnListMutation;
+import com.netflix.astyanax.Keyspace;
+import com.netflix.astyanax.MutationBatch;
+import com.netflix.astyanax.connectionpool.OperationResult;
+import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+import com.netflix.astyanax.connectionpool.exceptions.NotFoundException;
+import com.netflix.astyanax.model.Column;
+import com.netflix.astyanax.model.ColumnFamily;
+import com.netflix.astyanax.serializers.UUIDSerializer;
+
+
+/**
+ * Simple implementation for reading and writing log entries
+ *
+ * @author tnine
+ */
+@Singleton
+public class MvccLogEntrySerializationStrategyImpl implements MvccLogEntrySerializationStrategy, Migration {
+
+    public static final String TIMEOUT_PROP = "collection.stage.transient.timeout";
+
+    private static final ColumnFamily<UUID, UUID> CF_ENTITY_LOG =
+            new ColumnFamily<UUID, UUID>( "Entity_Log", UUIDSerializer.get(), UUIDSerializer.get() );
+
+    /**
+     * Used for caching the byte => stage mapping
+     */
+    private static final StageCache CACHE = new StageCache();
+
+
+    protected final Keyspace keyspace;
+    protected final int timeout;
+
+
+    @Inject
+    public MvccLogEntrySerializationStrategyImpl( final Keyspace keyspace, @Named( TIMEOUT_PROP ) final int timeout ) {
+        this.keyspace = keyspace;
+        this.timeout = timeout;
+    }
+
+
+    @Override
+    public MutationBatch write( final MvccLogEntry entry ) {
+
+        Preconditions.checkNotNull( entry, "entry is required" );
+
+
+        final Stage stage = entry.getStage();
+        final UUID colName = entry.getVersion();
+        final byte colValue = stage.getId();
+
+        return doWrite( entry.getContext(), entry.getEntityId(), new RowOp() {
+            @Override
+            public void doOp( final ColumnListMutation<UUID> colMutation ) {
+
+                //Write the stage with a timeout, it's set as transient
+                if ( stage.isTransient() ) {
+                    colMutation.putColumn( colName, colValue, timeout );
+                    return;
+                }
+
+                //otherwise it's persistent, write it with no expiration
+                colMutation.putColumn( colName, colValue );
+            }
+        } );
+    }
+
+
+    @Override
+    public MvccLogEntry load( final CollectionContext context, final UUID entityId, final UUID version )
+            throws ConnectionException {
+        Preconditions.checkNotNull( context, "context is required" );
+        Preconditions.checkNotNull( entityId, "entity id is required" );
+        Preconditions.checkNotNull( version, "version is required" );
+
+
+        Column<UUID> result = null;
+
+        try {
+            OperationResult<Column<UUID>>
+                    foo = keyspace.prepareQuery( CF_ENTITY_LOG ).getKey( entityId ).getColumn( version ).execute();
+
+            result = foo.getResult();
+        }
+        catch ( NotFoundException nfe ) {
+            return null;
+        }
+
+        if ( result == null ) {
+            return null;
+        }
+
+        final byte stored = result.getByteValue();
+
+
+        final Stage stage = CACHE.getStage( stored );
+
+        Preconditions.checkNotNull( "No stage was found for byte value " + stored + ".  This is a migration data bug" );
+
+        return new MvccLogEntryImpl( context, entityId, version, stage );
+    }
+
+
+    @Override
+    public List<MvccLogEntry> load( final CollectionContext context, final UUID entityId, final UUID version,
+                                    final int maxSize ) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+
+    @Override
+    public MutationBatch delete( final CollectionContext context, final UUID entityId, final UUID version ) {
+
+        Preconditions.checkNotNull( context, "context is required" );
+        Preconditions.checkNotNull( entityId, "entityId is required" );
+        Preconditions.checkNotNull( version, "version context is required" );
+
+        return doWrite( context, entityId, new RowOp() {
+            @Override
+            public void doOp( final ColumnListMutation<UUID> colMutation ) {
+                colMutation.deleteColumn( version );
+            }
+        } );
+    }
+
+
+    @Override
+    public Collection<CollectionColumnFamily> getColumnFamilies() {
+        //create the CF entity data.  We want it reversed b/c we want the most recent version at the top of the
+        //row for fast seeks
+        CollectionColumnFamily cf = new CollectionColumnFamily( CF_ENTITY_LOG,
+                ReversedType.class.getName() + "(" + UUIDType.class.getName() + ")", true );
+
+
+        return Collections.singleton( cf );
+    }
+
+
+    /**
+     * Simple callback to perform puts and deletes with a common row setup code
+     */
+    private static interface RowOp {
+
+        /**
+         * The operation to perform on the row
+         */
+        void doOp( ColumnListMutation<UUID> colMutation );
+    }
+
+
+    /**
+     * Do the column update or delete for the given column and row key
+     *
+     * @param context We need to use this when getting the keyspace
+     */
+    private MutationBatch doWrite( CollectionContext context, UUID entityId, RowOp op ) {
+
+        final MutationBatch batch = keyspace.prepareMutationBatch();
+
+        op.doOp( batch.withRow( CF_ENTITY_LOG, entityId ) );
+
+        return batch;
+    }
+
+
+    /**
+     * Internal stage cache
+     */
+    private static class StageCache {
+        private Map<Byte, Stage> values = new HashMap<Byte, Stage>( Stage.values().length );
+
+
+        private StageCache() {
+            for ( Stage stage : Stage.values() ) {
+
+                final byte stageValue = stage.getId();
+
+                if ( values.containsKey( stageValue ) ) {
+                    throw new RuntimeException(
+                            "There are two Stages assigned to the byte " + stageValue + ".  This is a bug" );
+                }
+
+                values.put( stageValue, stage );
+            }
+        }
+
+
+        /**
+         * Get the stage with the byte value
+         */
+        private Stage getStage( final byte value ) {
+            return values.get( value );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/CollectionManagerFactoryTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/CollectionManagerFactoryTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/CollectionManagerFactoryTest.java
new file mode 100644
index 0000000..4450efe
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/CollectionManagerFactoryTest.java
@@ -0,0 +1,8 @@
+package org.apache.usergrid.persistence.collection;
+
+
+/**
+ * Basic tests
+ * @author tnine
+ */
+public class CollectionManagerFactoryTest {}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/guice/TestCollectionModule.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/guice/TestCollectionModule.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/guice/TestCollectionModule.java
new file mode 100644
index 0000000..3ea6e62
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/guice/TestCollectionModule.java
@@ -0,0 +1,103 @@
+package org.apache.usergrid.persistence.collection.guice;
+
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.cassandra.locator.SimpleStrategy;
+
+import org.apache.usergrid.persistence.collection.astynax.AstynaxKeyspaceProvider;
+import org.apache.usergrid.persistence.collection.migration.MigrationException;
+import org.apache.usergrid.persistence.collection.migration.MigrationManager;
+import org.apache.usergrid.persistence.collection.migration.MigrationManagerImpl;
+import org.apache.usergrid.persistence.collection.serialization.MvccLogEntrySerializationStrategyImpl;
+import org.apache.usergrid.persistence.test.CassandraRule;
+
+import com.google.guiceberry.GuiceBerryEnvMain;
+import com.google.guiceberry.GuiceBerryModule;
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.name.Names;
+
+
+/**
+ * Simple module for wiring our collection api
+ *
+ * @author tnine
+ */
+public class TestCollectionModule extends AbstractModule {
+
+
+    public TestCollectionModule() {
+    }
+
+
+    @Override
+    protected void configure() {
+
+
+        //import the guice berry module
+        install( new GuiceBerryModule() );
+
+        //now configure our db
+        bind( GuiceBerryEnvMain.class ).to( CassAppMain.class );
+
+        //import the runtime module
+        install( new CollectionModule() );
+
+
+        //configure our integration test properties. This should remain the same across all tests
+
+        Map<String, String> configProperties = new HashMap<String, String>();
+        configProperties.put( AstynaxKeyspaceProvider.CASSANDRA_HOSTS, "localhost" );
+        configProperties.put( AstynaxKeyspaceProvider.CASSANDRA_PORT, "" + CassandraRule.THRIFT_PORT );
+        configProperties.put( AstynaxKeyspaceProvider.CASSANDRA_CONNECTIONS, "10" );
+        configProperties.put( AstynaxKeyspaceProvider.CASSANDRA_CLUSTER_NAME, "Usergrid" );
+        configProperties.put( AstynaxKeyspaceProvider.CASSANDRA_VERSION, "1.2" );
+        configProperties.put( AstynaxKeyspaceProvider.COLLECTIONS_KEYSPACE_NAME, "Usergrid_Collections" );
+
+        configProperties.put( MigrationManagerImpl.REPLICATION_FACTOR, "1" );
+        configProperties.put( MigrationManagerImpl.STRATEGY_CLASS, SimpleStrategy.class.getName() );
+
+        /**
+         * Set the timeout to 60 seconds, no test should take that long for load+delete without a failure
+         */
+        configProperties.put( MvccLogEntrySerializationStrategyImpl.TIMEOUT_PROP, 60+"" );
+
+        Map<String, String> props = getOverrides();
+
+        if(props != null){
+            configProperties.putAll( props );
+        }
+
+        //bind to the props
+        Names.bindProperties( binder(), configProperties );
+    }
+
+
+    /**
+     * Get any overrides we need for system properties
+     */
+    public Map<String, String> getOverrides() {
+        return null;
+    }
+
+
+    static class CassAppMain implements GuiceBerryEnvMain {
+
+        @Inject
+        protected MigrationManager migrationManager;
+
+
+        public void run() {
+            try {
+                //run the injected migration manager to set up cassandra
+                migrationManager.migrate();
+            }
+            catch ( MigrationException e ) {
+                throw new RuntimeException( e );
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/StageTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/StageTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/StageTest.java
new file mode 100644
index 0000000..0090e64
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/StageTest.java
@@ -0,0 +1,91 @@
+package org.apache.usergrid.persistence.collection.mvcc.entity;
+
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * @author tnine
+ */
+public class StageTest {
+
+    @Test
+    public void active() {
+
+        assertTrue( Stage.ACTIVE.isTransient() );
+
+        assertEquals( ( byte ) 0, Stage.ACTIVE.getId() );
+
+        testUnique( Stage.ACTIVE );
+    }
+
+
+    @Test
+    public void rollback() {
+
+        assertTrue( Stage.ROLLBACK.isTransient() );
+
+        assertEquals( ( byte ) 1, Stage.ROLLBACK.getId() );
+
+        testUnique( Stage.ROLLBACK );
+    }
+
+
+    @Test
+    public void comitted() {
+
+        assertFalse( Stage.COMMITTED.isTransient() );
+
+        assertEquals( ( byte ) 2, Stage.COMMITTED.getId() );
+
+        testUnique( Stage.COMMITTED );
+    }
+
+
+
+
+    @Test
+    public void postProcess() {
+
+        assertFalse( Stage.POSTPROCESS.isTransient() );
+
+        assertEquals( ( byte ) 6, Stage.POSTPROCESS.getId() );
+
+        testUnique( Stage.POSTPROCESS );
+    }
+
+
+    @Test
+    public void complete() {
+
+        assertFalse( Stage.COMPLETE.isTransient() );
+
+        assertEquals( ( byte ) 14, Stage.COMPLETE.getId() );
+
+        testUnique( Stage.COMPLETE );
+    }
+
+
+    /**
+     * Test we don't have dups in the byte value
+     * @param test
+     */
+    private void testUnique( Stage test ) {
+
+        for ( Stage stage : Stage.values() ) {
+
+            //skip self
+            if ( stage == test ) {
+                continue;
+            }
+
+            assertFalse( stage.getId() == test.getId() );
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/MvccEntitySerializationStrategyImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/MvccEntitySerializationStrategyImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/MvccEntitySerializationStrategyImplTest.java
new file mode 100644
index 0000000..a3bcead
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/MvccEntitySerializationStrategyImplTest.java
@@ -0,0 +1,343 @@
+package org.apache.usergrid.persistence.collection.serialization;
+
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.cassandra.db.marshal.UUIDType;
+
+import org.apache.usergrid.persistence.collection.CollectionContext;
+import org.apache.usergrid.persistence.collection.CollectionContextImpl;
+import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccEntity;
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccEntityImpl;
+import org.apache.usergrid.persistence.model.entity.Entity;
+import org.apache.usergrid.persistence.model.field.BooleanField;
+import org.apache.usergrid.persistence.model.field.DoubleField;
+import org.apache.usergrid.persistence.model.field.Field;
+import org.apache.usergrid.persistence.model.field.IntegerField;
+import org.apache.usergrid.persistence.model.field.LongField;
+import org.apache.usergrid.persistence.model.field.StringField;
+import org.apache.usergrid.persistence.model.field.UUIDField;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
+import org.apache.usergrid.persistence.test.CassandraRule;
+
+import com.google.common.base.Optional;
+import com.google.guiceberry.junit4.GuiceBerryRule;
+import com.google.inject.Inject;
+import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+import com.netflix.astyanax.serializers.UUIDSerializer;
+import com.netflix.astyanax.util.TimeUUIDUtils;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNull;
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * @author tnine
+ */
+public class MvccEntitySerializationStrategyImplTest {
+
+    @Rule
+    public final GuiceBerryRule guiceBerry = new GuiceBerryRule( TestCollectionModule.class );
+
+    @Rule
+    public final CassandraRule rule = new CassandraRule();
+
+    @Inject
+    private MvccEntitySerializationStrategy serializationStrategy;
+
+
+    @Test
+    public void writeLoadDelete() throws ConnectionException {
+
+        final UUID applicationId = UUIDGenerator.newTimeUUID();
+        final String name = "test";
+
+        CollectionContext context = new CollectionContextImpl( applicationId, applicationId, name );
+
+
+        final UUID entityId = UUIDGenerator.newTimeUUID();
+        final UUID version = UUIDGenerator.newTimeUUID();
+        final String type = "test";
+        final long created = 1l;
+        final long updated = 2l;
+
+        Entity entity = new Entity( entityId, type );
+
+        entity.setVersion( version );
+        entity.setCreated( created );
+        entity.setUpdated( updated );
+
+
+        BooleanField boolField = new BooleanField( "boolean", false );
+        DoubleField doubleField = new DoubleField( "double", 1d );
+        IntegerField intField = new IntegerField( "long", 1 );
+        LongField longField = new LongField( "int", 1l );
+        StringField stringField = new StringField( "name", "test" );
+        UUIDField uuidField = new UUIDField( "uuid", UUIDGenerator.newTimeUUID() );
+
+        entity.setField( boolField );
+        entity.setField( doubleField );
+        entity.setField( intField );
+        entity.setField( longField );
+        entity.setField( stringField );
+        entity.setField( uuidField );
+
+
+        MvccEntity saved = new MvccEntityImpl( context, entityId, version, Optional.of( entity ) );
+
+
+        //persist the entity
+        serializationStrategy.write( saved ).execute();
+
+        //now read it back
+
+        MvccEntity returned = serializationStrategy.load( context, entityId, version );
+
+        assertEquals( "Mvcc entities are the same", saved, returned );
+
+
+        assertEquals( entityId, entity.getUuid() );
+        assertEquals( type, entity.getType() );
+        assertEquals( created, entity.getCreated() );
+        assertEquals( updated, entity.getUpdated() );
+
+
+        Field<Boolean> boolFieldReturned = entity.getField( boolField.getName() );
+
+        assertSame( boolField, boolFieldReturned );
+
+        Field<Double> doubleFieldReturned = entity.getField( doubleField.getName() );
+
+        assertSame( doubleField, doubleFieldReturned );
+
+        Field<Integer> intFieldReturned = entity.getField( intField.getName() );
+
+        assertSame( intField, intFieldReturned );
+
+        Field<Long> longFieldReturned = entity.getField( longField.getName() );
+
+        assertSame( longField, longFieldReturned );
+
+        Field<String> stringFieldReturned = entity.getField( stringField.getName() );
+
+        assertSame( stringField, stringFieldReturned );
+
+        Field<UUID> uuidFieldReturned = entity.getField( uuidField.getName() );
+
+        assertSame( uuidField, uuidFieldReturned );
+
+
+        Set<Field> results = new HashSet<Field>();
+        results.addAll( entity.getFields() );
+
+
+        assertTrue( results.contains( boolField ) );
+        assertTrue( results.contains( doubleField ) );
+        assertTrue( results.contains( intField ) );
+        assertTrue( results.contains( longField ) );
+        assertTrue( results.contains( stringField ) );
+        assertTrue( results.contains( uuidField ) );
+
+        assertEquals( 6, results.size() );
+
+
+        assertEquals( entityId, entity.getUuid() );
+        assertEquals( version, entity.getVersion() );
+
+
+        //now delete it
+        serializationStrategy.delete( context, entityId, version ).execute();
+
+        //now get it, should be gone
+
+        returned = serializationStrategy.load( context, entityId, version );
+
+        assertNull( returned );
+    }
+
+
+    @Test
+    public void writeLoadClearDelete() throws ConnectionException {
+
+        final UUID applicationId = UUIDGenerator.newTimeUUID();
+        final String name = "test";
+
+        CollectionContext context = new CollectionContextImpl( applicationId, applicationId, name );
+
+
+        final UUID entityId = UUIDGenerator.newTimeUUID();
+        final UUID version = UUIDGenerator.newTimeUUID();
+        final String type = "test";
+        final long created = 1l;
+        final long updated = 2l;
+
+        Entity entity = new Entity( entityId, type );
+
+        entity.setVersion( version );
+        entity.setCreated( created );
+        entity.setUpdated( updated );
+
+
+        MvccEntity saved = new MvccEntityImpl( context, entityId, version, Optional.of( entity ) );
+
+
+        //persist the entity
+        serializationStrategy.write( saved ).execute();
+
+        //now read it back
+
+        MvccEntity returned = serializationStrategy.load( context, entityId, version );
+
+        assertEquals( "Mvcc entities are the same", saved, returned );
+
+
+        assertEquals( entityId, entity.getUuid() );
+        assertEquals( type, entity.getType() );
+        assertEquals( created, entity.getCreated() );
+        assertEquals( updated, entity.getUpdated() );
+
+
+        //now clear it
+
+        serializationStrategy.clear( context, entityId, version ).execute();
+
+        returned = serializationStrategy.load( context, entityId, version );
+
+        assertEquals( context, returned.getContext() );
+        assertEquals( entityId, returned.getUuid() );
+        assertEquals( version, returned.getVersion() );
+        assertFalse( returned.getEntity().isPresent() );
+
+        //now delete it
+        serializationStrategy.delete( context, entityId, version ).execute();
+
+        //now get it, should be gone
+
+        returned = serializationStrategy.load( context, entityId, version );
+
+        assertNull( returned );
+    }
+
+
+    @Test
+    public void writeX2ClearDelete() throws ConnectionException {
+
+        final UUID applicationId = UUIDGenerator.newTimeUUID();
+        final String name = "test";
+
+        CollectionContext context = new CollectionContextImpl( applicationId, applicationId, name );
+
+
+        final UUID entityId = UUIDGenerator.newTimeUUID();
+        final UUID version1 = UUIDGenerator.newTimeUUID();
+        final String type = "test";
+
+        Entity entityv1 = new Entity( entityId, type );
+
+        entityv1.setVersion( version1 );
+
+
+        MvccEntity saved = new MvccEntityImpl( context, entityId, version1, Optional.of( entityv1 ) );
+
+
+        //persist the entity
+        serializationStrategy.write( saved ).execute();
+
+        //now read it back
+
+        MvccEntity returnedV1 = serializationStrategy.load( context, entityId, version1 );
+
+        assertEquals( "Mvcc entities are the same", saved, returnedV1 );
+
+
+        assertEquals( entityId, entityv1.getUuid() );
+        assertEquals( type, entityv1.getType() );
+
+
+        //now write a new version of it
+
+
+        Entity entityv2 = new Entity( entityId, type );
+
+        UUID version2 = UUIDGenerator.newTimeUUID();
+        entityv2.setVersion( version2 );
+
+
+        UUIDType comparator = UUIDType.instance;
+
+        int value = comparator.compare( UUIDSerializer.get().toByteBuffer( version1 ), UUIDSerializer.get().toByteBuffer( version2 ) );
+
+        assertTrue(value < 0);
+
+        value = comparator.compare( UUIDSerializer.get().toByteBuffer( version2 ), UUIDSerializer.get().toByteBuffer( version2 ) );
+
+        assertEquals(0, value);
+
+        MvccEntity savedV2 = new MvccEntityImpl( context, entityId, version2, Optional.of( entityv2 ) );
+
+        serializationStrategy.write( savedV2 ).execute();
+
+        MvccEntity returnedV2 = serializationStrategy.load( context, entityId, version2 );
+
+        assertEquals( "Mvcc entities are the same", savedV2, returnedV2 );
+
+
+        //now clear it at v3
+
+        UUID version3 = UUIDGenerator.newTimeUUID();
+
+        serializationStrategy.clear( context, entityId, version3 ).execute();
+
+
+        final Optional<Entity> empty = Optional.absent();
+
+        MvccEntity clearedV3 = new MvccEntityImpl( context, entityId, version3, empty );
+
+        MvccEntity returnedV3 = serializationStrategy.load( context, entityId, version3 );
+
+        assertEquals("entities are the same", clearedV3, returnedV3);
+
+        //now ask for up to 10 versions from the current version, we should get cleared, v2, v1
+        UUID current = UUIDGenerator.newTimeUUID();
+
+        List<MvccEntity> entities = serializationStrategy.load( context, entityId, current, 3 );
+
+        assertEquals( 3, entities.size() );
+
+        assertEquals( clearedV3, entities.get( 0 ) );
+
+        assertEquals( returnedV2, entities.get( 1 ) );
+
+        assertEquals( returnedV1, entities.get( 2 ) );
+
+
+        //now delete v2 and v1, we should still get v3
+        serializationStrategy.delete( context, entityId, version1 ).execute();
+        serializationStrategy.delete( context, entityId, version2 ).execute();
+
+        entities = serializationStrategy.load( context, entityId, current, 3 );
+
+        assertEquals( 1, entities.size() );
+
+        assertEquals( clearedV3, entities.get( 0 ) );
+
+
+        //now get it, should be gone
+        serializationStrategy.delete( context, entityId, version3 ).execute();
+
+
+        entities = serializationStrategy.load( context, entityId, current, 3 );
+
+        assertEquals( 0, entities.size() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/MvccLogEntrySerializationStrategyImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/MvccLogEntrySerializationStrategyImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/MvccLogEntrySerializationStrategyImplTest.java
new file mode 100644
index 0000000..c66fac2
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/MvccLogEntrySerializationStrategyImplTest.java
@@ -0,0 +1,150 @@
+package org.apache.usergrid.persistence.collection.serialization;
+
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.usergrid.persistence.collection.CollectionContext;
+import org.apache.usergrid.persistence.collection.CollectionContextImpl;
+import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccLogEntry;
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccLogEntryImpl;
+import org.apache.usergrid.persistence.collection.mvcc.entity.Stage;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
+import org.apache.usergrid.persistence.test.CassandraRule;
+
+import com.google.guiceberry.GuiceBerryEnvSelector;
+import com.google.guiceberry.TestDescription;
+import com.google.guiceberry.junit4.GuiceBerryRule;
+import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+
+/**
+ * @author tnine
+ */
+public class MvccLogEntrySerializationStrategyImplTest {
+
+
+    /**
+     * Set our timeout to 1 seconds.  If it works for 1 seconds, we'll be good a any value
+     */
+    private static final int TIMEOUT = 1;
+
+
+    @Rule
+    public final GuiceBerryRule guiceBerry = new GuiceBerryRule( new TimeoutModMapper() );
+
+    @Rule
+    public final CassandraRule rule = new CassandraRule();
+
+    @Inject
+    private MvccLogEntrySerializationStrategy logEntryStrategy;
+
+
+    @Test
+    public void createAndDelete() throws ConnectionException {
+
+        final UUID applicationId = UUIDGenerator.newTimeUUID();
+        final String name = "test";
+
+
+        CollectionContext context = new CollectionContextImpl( applicationId, applicationId, name );
+
+
+        final UUID uuid = UUIDGenerator.newTimeUUID();
+        final UUID version = UUIDGenerator.newTimeUUID();
+
+        for ( Stage stage : Stage.values() ) {
+            MvccLogEntry saved = new MvccLogEntryImpl( context, uuid, version, stage );
+            logEntryStrategy.write( saved ).execute();
+
+            //Read it back
+
+            MvccLogEntry returned = logEntryStrategy.load( context, uuid, version );
+
+            assertNotNull( "Returned value should not be null", returned );
+
+            assertEquals( "Returned should equal the saved", saved, returned );
+        }
+    }
+
+
+    @Test
+    public void transientTimeout() throws ConnectionException, InterruptedException {
+
+        final UUID applicationId = UUIDGenerator.newTimeUUID();
+        final String name = "test";
+
+
+        CollectionContext context = new CollectionContextImpl( applicationId, applicationId, name );
+
+
+        final UUID uuid = UUIDGenerator.newTimeUUID();
+        final UUID version = UUIDGenerator.newTimeUUID();
+
+        for ( Stage stage : Stage.values() ) {
+
+            MvccLogEntry saved = new MvccLogEntryImpl( context, uuid, version, stage );
+            logEntryStrategy.write( saved ).execute();
+
+            //Read it back after the timeout
+
+            Thread.sleep( TIMEOUT * 1000 );
+
+            MvccLogEntry returned = logEntryStrategy.load( context, uuid, version );
+
+
+            if ( stage.isTransient() ) {
+
+                assertNull( "Active is transient and should time out", returned );
+            }
+            else {
+                assertNotNull( "Committed is not transient and should be returned", returned );
+
+                assertEquals( "Returned should equal the saved", saved, returned );
+            }
+        }
+    }
+
+
+    /**
+     * Mapper that will change which module we implement based on the test case
+     */
+    public static class TimeoutModMapper implements GuiceBerryEnvSelector {
+
+        @Override
+        public Class<? extends Module> guiceBerryEnvToUse( final TestDescription testDescription ) {
+
+            //in this edge case, we want to truncate the timeout to 1 second for this test, override the env to use
+            //this module setup
+            if ( (MvccLogEntrySerializationStrategyImplTest.class.getName()+".transientTimeout").equals( testDescription.getName() ) ) {
+                return TimeoutEnv.class;
+            }
+
+            //by default, we wnat to run the TestCollectionModule
+            return TestCollectionModule.class;
+        }
+    }
+
+
+    public static class TimeoutEnv extends TestCollectionModule {
+
+        @Override
+        public Map<String, String> getOverrides() {
+            Map<String, String> timeout = new HashMap<String, String>();
+            timeout.put( MvccLogEntrySerializationStrategyImpl.TIMEOUT_PROP, TIMEOUT + "" );
+            return timeout;
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/SerializationComparison.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/SerializationComparison.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/SerializationComparison.java
new file mode 100644
index 0000000..a78293b
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/SerializationComparison.java
@@ -0,0 +1,182 @@
+package org.apache.usergrid.persistence.collection.serialization;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.smile.SmileFactory;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.usergrid.persistence.model.entity.Entity;
+import org.apache.usergrid.persistence.model.field.ArrayField;
+import org.apache.usergrid.persistence.model.field.BooleanField;
+import org.apache.usergrid.persistence.model.field.ByteBufferField;
+import org.apache.usergrid.persistence.model.field.DoubleField;
+import org.apache.usergrid.persistence.model.field.EntityObjectField;
+import org.apache.usergrid.persistence.model.field.IntegerField;
+import org.apache.usergrid.persistence.model.field.ListField;
+import org.apache.usergrid.persistence.model.field.LocationField;
+import org.apache.usergrid.persistence.model.field.LongField;
+import org.apache.usergrid.persistence.model.field.SetField;
+import org.apache.usergrid.persistence.model.field.StringField;
+import org.apache.usergrid.persistence.model.field.UUIDField;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
+import org.apache.usergrid.persistence.model.value.EntityObject;
+import org.apache.usergrid.persistence.model.value.Location;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.ByteBufferInputStream;
+import com.esotericsoftware.kryo.io.ByteBufferOutputStream;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+
+/**
+ * TODO We need to get both of these serialization methods working, and benchmark them for comparison
+ * Neither works out of the box for us without custom work.
+ * @author tnine
+ */
+public class SerializationComparison {
+
+    private static final Logger logger = LoggerFactory.getLogger( SerializationComparison.class );
+
+    private static final int count = 10000;
+
+
+    @Test
+    @Ignore
+    public void smileSerialization() throws IOException {
+        SmileFactory smile = new SmileFactory();
+
+        ObjectMapper smileMapper = new ObjectMapper( smile );
+
+
+        Entity entity = createEntity();
+
+        long writeTime = 0;
+        long readTime = 0;
+
+        for ( int i = 0; i < count; i++ ) {
+
+            //capture time in nannos for write
+            long writeStart = System.nanoTime();
+
+            byte[] smileData = smileMapper.writeValueAsBytes( entity );
+
+            writeTime += System.nanoTime() - writeStart;
+
+            long readStart = System.nanoTime();
+
+            Entity otherValue = smileMapper.readValue( smileData, Entity.class );
+
+            readTime += System.nanoTime() - readStart;
+        }
+
+        logger.info( "Smile took {} nanos for writing {} entities", writeTime, count );
+        logger.info( "Smile took {} nanos for reading {} entities", readTime, count );
+    }
+
+
+    @Test
+    @Ignore
+    public void kyroSerialization() {
+        Kryo kryo = new Kryo();
+
+        //container classes
+        kryo.register( Entity.class );
+
+        kryo.register( EntityObject.class );
+        kryo.register( Location.class );
+
+
+        //field classes
+        kryo.register( ArrayField.class );
+        kryo.register( BooleanField.class );
+        kryo.register( ByteBufferField.class );
+        kryo.register( DoubleField.class );
+        kryo.register( EntityObjectField.class );
+        kryo.register( IntegerField.class );
+        kryo.register( ListField.class );
+        kryo.register( LocationField.class );
+        kryo.register( LongField.class );
+        kryo.register( SetField.class );
+        kryo.register( StringField.class );
+        kryo.register( UUIDField.class, new de.javakaffee.kryoserializers.UUIDSerializer() );
+
+
+        long writeTime = 0;
+        long readTime = 0;
+
+        for ( int i = 0; i < count; i++ ) {
+
+            //capture time in nanos for write
+            long writeStart = System.nanoTime();
+
+            ByteBuffer data = ByteBuffer.allocate( 1024 );
+            ByteBufferOutputStream byteBuffOutputStream = new ByteBufferOutputStream(data);
+            Output output = new Output( byteBuffOutputStream );
+
+            Entity entity = createEntity();
+
+            kryo.writeObject( output, entity );
+            output.close();
+
+            writeTime += System.nanoTime() - writeStart;
+
+            data.rewind();
+
+            long readStart = System.nanoTime();
+
+
+            Input input = new Input( new ByteBufferInputStream( data ) );
+            Entity loaded = kryo.readObject( input, Entity.class );
+            input.close();
+
+            readTime += System.nanoTime() - readStart;
+        }
+
+        logger.info( "Smile took {} nanos for writing {} entities", writeTime, count );
+        logger.info( "Smile took {} nanos for reading {} entities", readTime, count );
+    }
+
+
+    private Entity createEntity() {
+
+        final UUID entityId = UUIDGenerator.newTimeUUID();
+
+        final UUID version = UUIDGenerator.newTimeUUID();
+
+        Entity entity = new Entity( entityId, "test" );
+        entity.setCreated( 1l );
+        entity.setUpdated( 2l );
+        entity.setVersion( version );
+
+
+        BooleanField boolField = new BooleanField( "boolean", false );
+        DoubleField doubleField = new DoubleField( "double", 1d );
+        IntegerField intField = new IntegerField( "long", 1 );
+        LongField longField = new LongField( "int", 1l );
+        StringField stringField = new StringField( "name", "test" );
+        UUIDField uuidField = new UUIDField( "uuid", UUIDGenerator.newTimeUUID() );
+
+        entity.setField( boolField );
+        entity.setField( doubleField );
+        entity.setField( intField );
+        entity.setField( longField );
+        entity.setField( stringField );
+        entity.setField( uuidField );
+
+        return entity;
+    }
+
+
+}
+
+
+
+

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/collection/src/test/resources/cassandra.properties
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/resources/cassandra.properties b/stack/corepersistence/collection/src/test/resources/cassandra.properties
new file mode 100644
index 0000000..a69c771
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/resources/cassandra.properties
@@ -0,0 +1,5 @@
+#Purposefully left empty, we override this in our module code to KISS  The runtime requires this file however
+#Boostrapping should fail fast if it's not present
+
+
+

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/index/pom.xml
----------------------------------------------------------------------
diff --git a/stack/corepersistence/index/pom.xml b/stack/corepersistence/index/pom.xml
new file mode 100644
index 0000000..85c2a0b
--- /dev/null
+++ b/stack/corepersistence/index/pom.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>persistence</artifactId>
+    <groupId>org.apache.usergrid</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>index</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.usergrid</groupId>
+      <artifactId>collection</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/Query.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/Query.java b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/Query.java
new file mode 100644
index 0000000..69fdb3f
--- /dev/null
+++ b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/Query.java
@@ -0,0 +1,6 @@
+package org.apache.usergrid.persistence.index;
+
+
+/** Interface of our query implementation */
+public interface Query
+{}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/QueryEngine.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/QueryEngine.java b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/QueryEngine.java
new file mode 100644
index 0000000..631c027
--- /dev/null
+++ b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/QueryEngine.java
@@ -0,0 +1,22 @@
+package org.apache.usergrid.persistence.index;
+
+
+import org.apache.usergrid.persistence.model.entity.Entity;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public interface QueryEngine
+{
+
+
+    /** Search and return the entities */
+    public Results<Entity> search( Query query );
+
+
+    /** Search the query, but parse the entities into the given class We may not need to implement this at first */
+    public <T> Results<T> search( Query query, Class<T> clazz );
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/QueryEngineFactory.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/QueryEngineFactory.java b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/QueryEngineFactory.java
new file mode 100644
index 0000000..1358a4e
--- /dev/null
+++ b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/QueryEngineFactory.java
@@ -0,0 +1,21 @@
+package org.apache.usergrid.persistence.index;
+
+
+import org.apache.usergrid.persistence.collection.CollectionContext;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public interface QueryEngineFactory
+{
+
+    /**
+     * Create an index manager for the collection context
+     *
+     * @param context The context to use when creating the index manager
+     */
+    public QueryEngineFactory createIndexManager( CollectionContext context );
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/Results.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/Results.java b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/Results.java
new file mode 100644
index 0000000..bc4646e
--- /dev/null
+++ b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/Results.java
@@ -0,0 +1,16 @@
+package org.apache.usergrid.persistence.index;
+
+
+import java.util.Iterator;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public interface Results<Entity> extends Iterable<Entity>, Iterator<Entity>
+{
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Complete.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Complete.java b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Complete.java
new file mode 100644
index 0000000..da051b6
--- /dev/null
+++ b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Complete.java
@@ -0,0 +1,21 @@
+package org.apache.usergrid.persistence.index.stage;
+
+
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccEntity;
+import org.apache.usergrid.persistence.collection.mvcc.stage.WriteStage;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public class Complete implements WriteStage
+{
+
+    @Override
+    public MvccEntity performStage( final MvccEntity entity ) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Start.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Start.java b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Start.java
new file mode 100644
index 0000000..a89e2af
--- /dev/null
+++ b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Start.java
@@ -0,0 +1,16 @@
+package org.apache.usergrid.persistence.index.stage;
+
+
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccEntity;
+import org.apache.usergrid.persistence.collection.mvcc.stage.WriteStage;
+
+
+/** This state should signal an index update has started */
+public class Start implements WriteStage
+{
+
+    @Override
+    public MvccEntity performStage( final MvccEntity entity ) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Write.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Write.java b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Write.java
new file mode 100644
index 0000000..8e75812
--- /dev/null
+++ b/stack/corepersistence/index/src/main/java/org/apache/usergrid/persistence/index/stage/Write.java
@@ -0,0 +1,17 @@
+package org.apache.usergrid.persistence.index.stage;
+
+
+import org.apache.usergrid.persistence.collection.mvcc.entity.MvccEntity;
+import org.apache.usergrid.persistence.collection.mvcc.stage.WriteStage;
+
+
+/** This state should perform an update of the index. */
+public class Write implements WriteStage
+{
+
+    @Override
+    public MvccEntity performStage( final MvccEntity entity ) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/pom.xml
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/pom.xml b/stack/corepersistence/model/pom.xml
new file mode 100644
index 0000000..a79af0b
--- /dev/null
+++ b/stack/corepersistence/model/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>persistence</artifactId>
+    <groupId>org.apache.usergrid</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>model</artifactId>
+
+  <!-- Runtime Dependencies -->
+  <dependencies>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>15.0</version>
+    </dependency>
+
+    <!-- Time UUID library -->
+    <dependency>
+      <groupId>com.fasterxml.uuid</groupId>
+      <artifactId>java-uuid-generator</artifactId>
+      <version>3.1.3</version>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.11</version>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/entity/Entity.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/entity/Entity.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/entity/Entity.java
new file mode 100644
index 0000000..83cca40
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/entity/Entity.java
@@ -0,0 +1,149 @@
+package org.apache.usergrid.persistence.model.entity;
+
+
+import java.util.UUID;
+
+import org.apache.usergrid.persistence.model.value.EntityObject;
+
+import com.google.common.base.Preconditions;
+
+
+/**
+ * Simple entity that is used for persistence.  It has 4 required properties. <p/> uuid: The uuid of the entity type:
+ * The entity name (user, car, restaurant etc) created: The time the entity was created in millis since epoch updated:
+ * The time the entity was updated in millis since epoch;
+ */
+public class Entity extends EntityObject {
+
+
+    /**
+     * The entity type. This must be set
+     */
+    private String type;
+
+    /**
+     * The generated uuid.  This should never be set by a user
+     */
+    private UUID uuid;
+
+    /**
+     * The version of this entity.  Options, since it can be used for optimistic locking
+     */
+    private UUID version;
+
+    /**
+     * The time in milliseconds since epoch the entity was created
+     */
+    private long created;
+
+    /**
+     * The time in milliseconds since epoch the entity was updated
+     */
+    private long updated;
+
+
+    /**
+     * Create an entity with no uuid.  This should be used for creating new entities
+     */
+    public Entity( String type ) {
+        Preconditions.checkNotNull( type, "Type must not be null" );
+        Preconditions.checkArgument( type.length() > 0, "Type must have a length" );
+        this.type = type;
+    }
+
+
+    /**
+     * Create an entity with the given type and uuid.  Should be used for all update operations to an existing entity
+     */
+    public Entity( UUID uuid, String type ) {
+        this( type );
+
+        Preconditions.checkNotNull( uuid, "uuid must not be null" );
+
+        this.uuid = uuid;
+    }
+
+
+    /**
+     * Do not use!  This is only for serialization.
+     */
+    public Entity() {
+
+    }
+
+
+    public UUID getUuid() {
+        return uuid;
+    }
+
+
+    public String getType() {
+        return type;
+    }
+
+
+    public UUID getVersion() {
+        return version;
+    }
+
+
+    public void setVersion( final UUID version ) {
+        this.version = version;
+    }
+
+
+    /**
+     * Should only be invoked by the persistence framework
+     */
+    public void setCreated( long created ) {
+        this.created = created;
+    }
+
+
+    /**
+     * Should only be invoked by the persistence framework
+     */
+    public void setUpdated( long updated ) {
+        this.updated = updated;
+    }
+
+
+    public long getCreated() {
+        return created;
+    }
+
+
+    public long getUpdated() {
+        return updated;
+    }
+
+
+    @Override
+    public boolean equals( Object o ) {
+        if ( this == o ) {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() ) {
+            return false;
+        }
+
+        Entity entity = ( Entity ) o;
+
+        if ( type != null ? !type.equals( entity.type ) : entity.type != null ) {
+            return false;
+        }
+        if ( uuid != null ? !uuid.equals( entity.uuid ) : entity.uuid != null ) {
+            return false;
+        }
+
+        return true;
+    }
+
+
+    @Override
+    public int hashCode() {
+        int result = type != null ? type.hashCode() : 0;
+        result = 31 * result + ( uuid != null ? uuid.hashCode() : 0 );
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/AbstractField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/AbstractField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/AbstractField.java
new file mode 100644
index 0000000..674c7a7
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/AbstractField.java
@@ -0,0 +1,85 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import org.apache.usergrid.persistence.model.value.EntityObject;
+
+
+/** Base class for data information */
+public abstract class AbstractField<T> implements Field<T>
+{
+
+
+    /**
+     * Set the object this field belongs to
+     */
+    protected EntityObject parent;
+    protected String name;
+    protected T value;
+
+
+    /**
+     * Name and value must always be present.
+     *
+     * @param name The name of this field
+     * @param value The value to set.   If value is null, this means that the value should be explicitly removed from
+     * the field storage
+     */
+    protected AbstractField( String name, T value )
+    {
+        this.name = name;
+        this.value = value;
+    }
+
+
+    /**
+     * Default constructor for serialization
+     */
+    protected AbstractField(){
+
+    }
+
+
+
+
+    public String getName()
+    {
+        return name;
+    }
+
+
+    @Override
+    public T getValue()
+    {
+        return value;
+    }
+
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        AbstractField that = ( AbstractField ) o;
+
+        if ( !name.equals( that.name ) )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+
+    @Override
+    public int hashCode()
+    {
+        return name.hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ArrayField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ArrayField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ArrayField.java
new file mode 100644
index 0000000..cb5f45d
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ArrayField.java
@@ -0,0 +1,27 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/** A marker to signal array handling.  Just delegates to list field for easier handling internally */
+public class ArrayField extends ListField
+{
+
+    /** Contructor that intializes with an empty set for adding to later */
+    public ArrayField( String name )
+    {
+        super(name);
+    }
+
+    public ArrayField(){
+        super();
+    }
+
+    /** Add the value to the list */
+    public void add( Field field )
+    {
+        value.add( field );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/BooleanField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/BooleanField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/BooleanField.java
new file mode 100644
index 0000000..3948b27
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/BooleanField.java
@@ -0,0 +1,19 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public class BooleanField extends AbstractField<Boolean> {
+
+    public BooleanField( String name, Boolean value ) {
+        super( name, value );
+    }
+
+
+    public BooleanField() {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ByteBufferField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ByteBufferField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ByteBufferField.java
new file mode 100644
index 0000000..2dbc193
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ByteBufferField.java
@@ -0,0 +1,29 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import java.nio.ByteBuffer;
+
+
+/** A field for storing byte buffers */
+public class ByteBufferField extends AbstractField<ByteBuffer>
+{
+
+
+    /** Creates an immutable copy of the byte buffer */
+    public ByteBufferField( String name, ByteBuffer value )
+    {
+        //always return a duplicate so we don't mess with the markers
+        super( name, value.duplicate() );
+    }
+
+    public ByteBufferField() {
+
+        }
+
+    @Override
+    public ByteBuffer getValue()
+    {
+        //always return a duplicate so we don't mess with the markers
+        return value.duplicate();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/DoubleField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/DoubleField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/DoubleField.java
new file mode 100644
index 0000000..729560c
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/DoubleField.java
@@ -0,0 +1,20 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public class DoubleField extends AbstractField<Double>
+{
+
+    public DoubleField( String name, Double value )
+    {
+        super( name, value );
+    }
+
+    public DoubleField() {
+
+        }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/EntityObjectField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/EntityObjectField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/EntityObjectField.java
new file mode 100644
index 0000000..4031a81
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/EntityObjectField.java
@@ -0,0 +1,20 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import org.apache.usergrid.persistence.model.value.EntityObject;
+
+
+/** An object field */
+public class EntityObjectField extends AbstractField<EntityObject>
+{
+
+
+    public EntityObjectField( String name, EntityObject value )
+    {
+        super( name, value );
+    }
+
+    public EntityObjectField() {
+
+        }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/Field.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/Field.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/Field.java
new file mode 100644
index 0000000..5061d49
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/Field.java
@@ -0,0 +1,28 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import java.io.Serializable;
+
+import org.apache.usergrid.persistence.model.value.EntityObject;
+
+
+/**
+ * Interface for fields.  All fields must implement this method The T is the type of field (in the java runtime) The V
+ * is the value of the field
+ */
+public interface Field<T> extends Serializable {
+
+    /**
+     * Get the name of the field
+     * @return
+     */
+    public String getName();
+
+    /**
+     * Get the value of the field
+     * @return
+     */
+    public T getValue();
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/IntegerField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/IntegerField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/IntegerField.java
new file mode 100644
index 0000000..9c807e0
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/IntegerField.java
@@ -0,0 +1,20 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public class IntegerField extends AbstractField<Integer>
+{
+
+    public IntegerField( String name, Integer value )
+    {
+        super( name, value );
+    }
+
+    public IntegerField() {
+
+        }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ListField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ListField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ListField.java
new file mode 100644
index 0000000..0795201
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/ListField.java
@@ -0,0 +1,28 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/** An object field that represents a list of objects.  This can also be used to represent arrays */
+public class ListField extends AbstractField<List<Field>>
+{
+
+    /** Contructor that intializes with an empty set for adding to later */
+    public ListField( String name )
+    {
+        super( name, new ArrayList<Field>() );
+    }
+
+    public ListField(){
+        super();
+    }
+
+
+    /** Add the value to the list */
+    public void add( Field field )
+    {
+        value.add( field );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/LocationField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/LocationField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/LocationField.java
new file mode 100644
index 0000000..5d9fd57
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/LocationField.java
@@ -0,0 +1,20 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import org.apache.usergrid.persistence.model.value.Location;
+
+
+/** Basic field for storing location data */
+public class LocationField extends AbstractField<Location>
+{
+
+    /** Create a location field with the given point */
+    public LocationField( String name, Location value )
+    {
+        super( name, value );
+    }
+
+    public LocationField() {
+
+        }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/LongField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/LongField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/LongField.java
new file mode 100644
index 0000000..c56b514
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/LongField.java
@@ -0,0 +1,23 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public class LongField extends AbstractField<Long>
+{
+
+    public LongField( String name, Long value )
+    {
+        super( name, value );
+    }
+
+    public LongField() {
+
+        }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/SetField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/SetField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/SetField.java
new file mode 100644
index 0000000..f28b5ec
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/SetField.java
@@ -0,0 +1,28 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+
+/** An object field that represents a set of objects */
+public class SetField extends AbstractField<Set<Field>>
+{
+
+
+    /** Contructor that intializes with an empty set for adding to later */
+    public SetField( String name )
+    {
+        super( name, new LinkedHashSet<Field>() );
+    }
+
+    public SetField() {
+
+        }
+
+    /** Add an entry to the set */
+    public void addEntry( Field field )
+    {
+        value.add( field );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/StringField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/StringField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/StringField.java
new file mode 100644
index 0000000..bcb8b2d
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/StringField.java
@@ -0,0 +1,17 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+/** A String field */
+public class StringField extends AbstractField<String>
+{
+
+
+    public StringField( String name, String value )
+    {
+        super( name, value );
+    }
+
+    public StringField() {
+
+        }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/UUIDField.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/UUIDField.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/UUIDField.java
new file mode 100644
index 0000000..11dfc22
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/field/UUIDField.java
@@ -0,0 +1,20 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import java.util.UUID;
+
+
+/** A String field */
+public class UUIDField extends AbstractField<UUID>
+{
+
+
+    public UUIDField( String name, UUID value )
+    {
+        super( name, value );
+    }
+
+    public UUIDField() {
+
+        }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/util/UUIDGenerator.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/util/UUIDGenerator.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/util/UUIDGenerator.java
new file mode 100644
index 0000000..687e27b
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/util/UUIDGenerator.java
@@ -0,0 +1,106 @@
+package org.apache.usergrid.persistence.model.util;
+
+
+import java.io.IOException;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.fasterxml.uuid.EthernetAddress;
+import com.fasterxml.uuid.TimestampSynchronizer;
+import com.fasterxml.uuid.UUIDTimer;
+import com.fasterxml.uuid.impl.TimeBasedGenerator;
+
+
+/**
+ *
+ * @author: tnine
+ *
+ */
+public class UUIDGenerator
+{
+
+
+    private static final TimestampSynchronizer synchronizer = new TimestampSynchronizer()
+    {
+
+        /**
+         * Pointer to the last value we returned
+         */
+        private long last = 0;
+
+        /**
+         * The number of ticks that can be used in the millisecond.  In a time UUID a tick is divided into 1/10000 of
+         * a millisecond
+         *
+         */
+        private AtomicInteger ticks = new AtomicInteger();
+
+
+        @Override
+        protected long initialize() throws IOException
+        {
+
+            last = System.currentTimeMillis();
+            return last;
+        }
+
+
+        @Override
+        protected void deactivate() throws IOException
+        {
+            //no op
+        }
+
+
+        @Override
+        protected long update( long now ) throws IOException
+        {
+            /**
+             * It's greater
+             */
+            if ( now > last )
+            {
+                last = now;
+                ticks.set( 0 );
+                return last;
+            }
+
+            //we have the same value (since now should always be increasing) increment a tick
+            last = now + ticks.incrementAndGet();
+
+            return last;
+        }
+    };
+
+
+    private static final Random random = new Random();
+    private static final UUIDTimer timer;
+
+
+    /**
+     * Lame, but required
+     */
+    static
+    {
+        try
+        {
+            timer = new UUIDTimer( random, synchronizer );
+        }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( "Couldn't intialize timer", e );
+        }
+    }
+
+
+    private static final TimeBasedGenerator generator =
+            new TimeBasedGenerator( EthernetAddress.fromInterface(), timer );
+
+
+    /** Create a new time uuid */
+    public static UUID newTimeUUID()
+    {
+        return generator.generate();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/value/EntityObject.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/value/EntityObject.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/value/EntityObject.java
new file mode 100644
index 0000000..5f02053
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/value/EntityObject.java
@@ -0,0 +1,40 @@
+package org.apache.usergrid.persistence.model.value;
+
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.usergrid.persistence.model.field.Field;
+
+
+/** Simple wrapper for holding nested objects */
+public class EntityObject implements Serializable
+{
+
+
+    /** Fields the users can set */
+    private Map<String, Field> fields = new HashMap<String, Field>();
+
+
+    /** Add the field, return the old one if it existed */
+    public <T extends java.lang.Object> Field<T> setField( Field<T> value )
+    {
+        return fields.put( value.getName(), value );
+    }
+
+
+    /** Get the field by name the user has set into the entity */
+    public <T extends java.lang.Object> Field<T> getField( String name )
+    {
+        return fields.get( name );
+    }
+
+
+    /** Get all fields in the entity */
+    public Collection<Field> getFields()
+    {
+        return fields.values();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/value/Location.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/value/Location.java b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/value/Location.java
new file mode 100644
index 0000000..4370aa1
--- /dev/null
+++ b/stack/corepersistence/model/src/main/java/org/apache/usergrid/persistence/model/value/Location.java
@@ -0,0 +1,32 @@
+package org.apache.usergrid.persistence.model.value;
+
+
+import java.io.Serializable;
+
+
+/** Geographic point.  Should be used when we want to store geo information */
+public class Location  implements Serializable
+{
+
+    private final double latitude;
+    private final double longtitude;
+
+
+    public Location( double latitude, double longtitude )
+    {
+        this.latitude = latitude;
+        this.longtitude = longtitude;
+    }
+
+
+    public double getLatitude()
+    {
+        return latitude;
+    }
+
+
+    public double getLongtitude()
+    {
+        return longtitude;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/model/src/test/java/org/apache/usergrid/persistence/model/field/EntityTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/model/src/test/java/org/apache/usergrid/persistence/model/field/EntityTest.java b/stack/corepersistence/model/src/test/java/org/apache/usergrid/persistence/model/field/EntityTest.java
new file mode 100644
index 0000000..9f94b18
--- /dev/null
+++ b/stack/corepersistence/model/src/test/java/org/apache/usergrid/persistence/model/field/EntityTest.java
@@ -0,0 +1,117 @@
+package org.apache.usergrid.persistence.model.field;
+
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+import org.junit.Test;
+
+import org.apache.usergrid.persistence.model.entity.Entity;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+
+/** Simple test for validating stored entities */
+public class EntityTest
+{
+
+    @Test
+    public void testPutAndGet()
+    {
+
+
+        final UUID uuid = UUIDGenerator.newTimeUUID();
+        final UUID version = UUIDGenerator.newTimeUUID();
+        final String type = "test";
+        final long created = 1l;
+        final long updated = 2l;
+
+        Entity entity = new Entity( uuid, type );
+
+        entity.setVersion( version );
+        entity.setCreated( created );
+        entity.setUpdated( updated );
+
+        assertEquals( uuid, entity.getUuid() );
+        assertEquals( type, entity.getType() );
+        assertEquals( created, entity.getCreated() );
+        assertEquals( updated, entity.getUpdated() );
+
+
+        BooleanField boolField = new BooleanField( "boolean", false );
+        DoubleField doubleField = new DoubleField( "double", 1d );
+        IntegerField intField = new IntegerField( "long", 1 );
+        LongField longField = new LongField( "int", 1l );
+        StringField stringField = new StringField( "name", "test" );
+        UUIDField uuidField = new UUIDField( "uuid", UUIDGenerator.newTimeUUID() );
+
+        entity.setField( boolField );
+        entity.setField( doubleField );
+        entity.setField( intField );
+        entity.setField( longField );
+        entity.setField( stringField );
+        entity.setField( uuidField );
+
+        Field<Boolean> boolFieldReturned = entity.getField( boolField.getName() );
+
+        assertSame( boolField, boolFieldReturned );
+
+        Field<Double> doubleFieldReturned = entity.getField( doubleField.getName() );
+
+        assertSame( doubleField, doubleFieldReturned );
+
+        Field<Integer> intFieldReturned = entity.getField( intField.getName() );
+
+        assertSame( intField, intFieldReturned );
+
+        Field<Long> longFieldReturned = entity.getField( longField.getName() );
+
+        assertSame( longField, longFieldReturned );
+
+        Field<String> stringFieldReturned = entity.getField( stringField.getName() );
+
+        assertSame( stringField, stringFieldReturned );
+
+        Field<UUID> uuidFieldReturned = entity.getField( uuidField.getName() );
+
+        assertSame( uuidField, uuidFieldReturned );
+
+
+        Set<Field> results = new HashSet<Field>();
+        results.addAll( entity.getFields() );
+
+
+        assertTrue( results.contains( boolField ) );
+        assertTrue( results.contains( doubleField ) );
+        assertTrue( results.contains( intField ) );
+        assertTrue( results.contains( longField ) );
+        assertTrue( results.contains( stringField ) );
+        assertTrue( results.contains( uuidField ) );
+
+        assertEquals( 6, results.size() );
+
+
+        assertEquals( uuid, entity.getUuid() );
+        assertEquals( version, entity.getVersion() );
+    }
+
+
+    @Test( expected = NullPointerException.class )
+    public void uuidRequired()
+    {
+        new Entity( null, "test" );
+    }
+
+
+    @Test( expected = NullPointerException.class )
+    public void versionRequired()
+    {
+        final UUID uuid = UUIDGenerator.newTimeUUID();
+
+        new Entity( uuid, null );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/Readme.md
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/Readme.md b/stack/corepersistence/perftest/Readme.md
new file mode 100644
index 0000000..8061dda
--- /dev/null
+++ b/stack/corepersistence/perftest/Readme.md
@@ -0,0 +1,52 @@
+# A Simple Performance Testing Framework on AWS
+
+This is a simple performance testing framework designed to pound the heck out 
+of a clustered persistence teir. It is designed as a web application that 
+can be run on several tomcat or jetty servers to bombard in unison an in JVM 
+API that operates against a clustered data storage layer like Cassandra.
+
+## Setting up a Perftest
+
+The framework simply executes a number of calls which you specify using a 
+Perftest implementation class. This class specifies all the parameters as 
+methods and is construct by the framework using a TestModule (a guice module)
+which you also provide.
+
+The framework simply loads your TestModule and uses its Guice Injector to 
+create the Perftest instance. It coordinates executing calls against the
+Perftest instance across the set of servers containing the framework. SimpleDB
+is used to communicate presence to all the nodes of the workers so they can
+find each other and coordinate their calls at the same time against the 
+Perftest instance.
+
+The following endpoints are used to control the framework:
+
+ * /perftest/start
+ * /perftest/stop
+ * /perftest/reset
+ * /perftest/stats
+
+The following ascii text shows the states of the framework which one can 
+go through while issuing POSTs to the end points above:
+
+            start           stop
+    +-----+       +-------+     +-------+
+ ---+ready+-------+running+-----+stopped|
+    +--+--+       +-------+     +---+---+
+       |                            |
+       |____________________________|
+                   reset
+
+A post to a single node issues the same POST to all the nodes in the cluster.
+
+## Dependencies
+
+It uses the following libraries to do what it does:
+
+* Jersey - for REST services
+* Jackson - for JSON <--> Java marshalling
+* Guice - for the DI container
+* Archaius - for dynamic properties
+* Blitz4j - for asynchronous logging
+* Slf4j - API for binding to Blitz4j
+

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/pom.xml
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/pom.xml b/stack/corepersistence/perftest/pom.xml
new file mode 100644
index 0000000..b5c70ee
--- /dev/null
+++ b/stack/corepersistence/perftest/pom.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>persistence</artifactId>
+    <groupId>org.apache.usergrid</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>perftest</artifactId>
+  <packaging>war</packaging>
+  <description>Simple Performance Testing Framework</description>
+
+  <properties>
+    <slf4j.version>1.6.1</slf4j.version>
+    <blitz4j.version>1.31</blitz4j.version>
+    <archaius.version>0.4.1</archaius.version>
+    <servo.version>0.4.36</servo.version>
+    <jersey.version>1.9.1</jersey.version>
+    <jackson.version>2.1.5</jackson.version>
+    <fastxml.version>2.3.0-SNAPSHOT</fastxml.version>
+    <jetty.plugin.version>8.1.14.v20131031</jetty.plugin.version>
+    <jetty.version>9.1.0.M0</jetty.version>
+    <log4j.version>1.2.17</log4j.version>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <guice.version>3.0</guice.version>
+  </properties>
+
+  <build>
+    <finalName>${pom.artifactId}</finalName>
+
+    <plugins>
+      <plugin>
+        <groupId>org.mortbay.jetty</groupId>
+        <artifactId>jetty-maven-plugin</artifactId>
+        <version>${jetty.plugin.version}</version>
+        <configuration>
+          <scanIntervalSeconds>5</scanIntervalSeconds>
+          <webApp>
+            <contextPath>/</contextPath>
+          </webApp>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-server</artifactId>
+      <version>${jersey.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.sun.jersey.contribs</groupId>
+      <artifactId>jersey-guice</artifactId>
+      <version>${jersey.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      <artifactId>jackson-jaxrs-json-provider</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.module</groupId>
+      <artifactId>jackson-module-guice</artifactId>
+      <version>${fastxml.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.google.inject</groupId>
+      <artifactId>guice</artifactId>
+      <version>${guice.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.google.inject.extensions</groupId>
+      <artifactId>guice-multibindings</artifactId>
+      <version>${guice.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.google.inject.extensions</groupId>
+      <artifactId>guice-servlet</artifactId>
+      <version>${guice.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-servlet</artifactId>
+      <version>${jetty.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <version>${jetty.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.netflix.archaius</groupId>
+      <artifactId>archaius-core</artifactId>
+      <version>${archaius.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.netflix.blitz4j</groupId>
+      <artifactId>blitz4j</artifactId>
+      <version>${blitz4j.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.netflix.archaius</groupId>
+      <artifactId>archaius-aws</artifactId>
+      <version>${archaius.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>${slf4j.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <version>${slf4j.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>log4j</groupId>
+          <artifactId>log4j</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <!-- Test RelatedDependencies -->
+
+    <dependency>
+      <groupId>com.google.guiceberry</groupId>
+      <artifactId>guiceberry</artifactId>
+      <version>3.3.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
+