You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2014/04/12 00:21:29 UTC

[3/7] git commit: Refactored cache and shard allocation to seperate concerns

Refactored cache and shard allocation to seperate concerns


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/ed2e63be
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/ed2e63be
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/ed2e63be

Branch: refs/heads/asyncqueue
Commit: ed2e63beea3f3b0726e9f892b7038efe52a5bd12
Parents: c9975aa
Author: Todd Nine <tn...@apigee.com>
Authored: Fri Apr 4 11:41:30 2014 -0700
Committer: Todd Nine <tn...@apigee.com>
Committed: Fri Apr 4 11:41:30 2014 -0700

----------------------------------------------------------------------
 .../graph/impl/cache/NodeShardAllocation.java   |  81 +++++++++
 .../graph/impl/cache/NodeShardCacheImpl.java    |  64 +++----
 .../graph/impl/cache/NodeShardCacheTest.java    | 173 +++++++++++++++----
 3 files changed, 246 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ed2e63be/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardAllocation.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardAllocation.java b/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardAllocation.java
new file mode 100644
index 0000000..8bc4f6c
--- /dev/null
+++ b/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardAllocation.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.usergrid.persistence.graph.impl.cache;
+
+
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.usergrid.persistence.collection.OrganizationScope;
+import org.apache.usergrid.persistence.model.entity.Id;
+
+
+
+public interface NodeShardAllocation {
+
+    public static final UUID MIN_UUID =  new UUID( 0, 1 );
+
+    /**
+     * Get all shards for the given info.  If none exist, a default shard should be allocated
+     * @param scope
+     * @param nodeId
+     * @param edgeTypes
+     * @return A list of all shards <= the current shard.  This will always return MIN_UUID if no shards are allocated
+     */
+    public List<UUID> getShards(final OrganizationScope scope, final Id nodeId, final String... edgeTypes);
+
+
+    /**
+     * Audit our highest shard for it's maximum capacity.  If it has reached the max capacity <=, it will allocate a new shard
+     *
+     * @param scope The organization scope
+     * @param nodeId The node id
+     * @param edgeType The edge types
+     * @return True if a new shard was allocated
+     */
+    public boolean auditMaxShard(final OrganizationScope scope, final Id nodeId, final String... edgeType);
+
+    /**
+        * The minimum uuid we allocate
+        */
+//       private static final UUID MIN_UUID =  new UUID( 0, 1 );
+//
+
+    /**
+     *
+              * There are no shards allocated, allocate the minimum shard
+              */
+    /**
+     *
+     *
+             if(shards == null || shards.size() == 0){
+
+                 try {
+                     edgeSeriesSerialization.writeEdgeMeta( scope, nodeId, MIN_UUID, edgeType ).execute();
+                 }
+                 catch ( ConnectionException e ) {
+                     throw new RuntimeException("Unable to write edge meta data", e);
+                 }
+
+                 return MIN_UUID;
+              }
+
+     (**/
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ed2e63be/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheImpl.java b/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheImpl.java
index b75cd19..1c373af 100644
--- a/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheImpl.java
+++ b/stack/corepersistence/graph/src/main/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheImpl.java
@@ -33,6 +33,7 @@ import org.apache.usergrid.persistence.collection.OrganizationScope;
 import org.apache.usergrid.persistence.graph.GraphFig;
 import org.apache.usergrid.persistence.graph.serialization.EdgeSeriesSerialization;
 import org.apache.usergrid.persistence.model.entity.Id;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
 
 import com.fasterxml.uuid.UUIDComparator;
 import com.google.common.cache.CacheBuilder;
@@ -48,12 +49,9 @@ import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
  */
 public class NodeShardCacheImpl implements NodeShardCache {
 
-    /**
-     * The minimum uuid we allocate
-     */
-    private static final UUID MIN_UUID =  new UUID( 0, 1 );
 
-    private final EdgeSeriesSerialization edgeSeriesSerialization;
+
+    private final NodeShardAllocation nodeShardAllocation;
     private final GraphFig graphFig;
 
     private LoadingCache<CacheKey, CacheEntry> graphs;
@@ -61,12 +59,12 @@ public class NodeShardCacheImpl implements NodeShardCache {
 
     /**
      *
-     * @param edgeSeriesSerialization
+     * @param nodeShardAllocation
      * @param graphFig
      */
     @Inject
-    public NodeShardCacheImpl( final EdgeSeriesSerialization edgeSeriesSerialization, final GraphFig graphFig ) {
-        this.edgeSeriesSerialization = edgeSeriesSerialization;
+    public NodeShardCacheImpl( final  NodeShardAllocation nodeShardAllocation, final GraphFig graphFig ) {
+        this.nodeShardAllocation = nodeShardAllocation;
         this.graphFig = graphFig;
 
         /**
@@ -104,27 +102,13 @@ public class NodeShardCacheImpl implements NodeShardCache {
             throw new RuntimeException( "Unable to load cache key for graph", e );
         }
 
-        List<UUID> shards = entry.getShardId(time, 1 );
-
-        if(shards == null || shards.size() == 0){
-
-            try {
-                edgeSeriesSerialization.writeEdgeMeta( scope, nodeId, MIN_UUID, edgeType ).execute();
-            }
-            catch ( ConnectionException e ) {
-                throw new RuntimeException("Unable to write edge meta data", e);
-            }
-
-            return MIN_UUID;
-         }
-
-        final UUID shardId = entry.getShardId(time, 1).get( 0 );
+        final UUID shardId = entry.getShardId(time);
 
         if(shardId != null){
             return shardId;
         }
 
-        //if we get here, something went wrong, our cache should always have a min time UUID.
+        //if we get here, something went wrong, our cache should always have a time UUID to return to us
         throw new RuntimeException( "No time UUID shard was found and could not allocate one" );
 
     }
@@ -144,8 +128,14 @@ public class NodeShardCacheImpl implements NodeShardCache {
 
                                       @Override
                                       public CacheEntry load( final CacheKey key ) throws Exception {
-                                          final List<UUID> edges = edgeSeriesSerialization
-                                                  .getEdgeMetaData( key.scope, key.id, key.types );
+                                          final List<UUID> edges = nodeShardAllocation.getShards( key.scope,
+                                                  key.id, key.types );
+
+
+                                          /**
+                                           * Perform an async audit
+                                           */
+                                          nodeShardAllocation.auditMaxShard( key.scope, key.id, key.types );
 
                                           return new CacheEntry( edges );
                                       }
@@ -218,44 +208,34 @@ public class NodeShardCacheImpl implements NodeShardCache {
 
         /**
          * Get the shard's UUID for the uuid we're attempting to seek from
+         *
          * @param seek
          * @return
          */
-        public List<UUID> getShardId( final UUID seek, final int size) {
+        public UUID getShardId( final UUID seek) {
             int index = Collections.binarySearch( this.shards, seek, MetaComparator.INSTANCE );
 
             /**
              * We have an exact match, return it
              */
             if(index > -1){
-               return getShards(index, size);
+               return shards.get( index );
             }
 
 
             //update the index to represent the index we should insert to and read it.  This will be <= the UUID we were passed
-            index = index*-1+1;
+            //we subtract 2 to get the index < this one
+            index = (index*-1) -2;
 
 
             if(index < shards.size()){
-                return getShards( index, size );
+                return shards.get( index );
             }
 
 
             return null;
         }
 
-        /**
-          * Get the ordered list of shards from high to low
-          * @param index
-          * @param size
-          * @return
-          */
-         private List<UUID> getShards(final int index, final int size){
-             int toIndex = Math.min( shards.size(), index+size );
-             return shards.subList(index,  toIndex );
-         }
-
-
     }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ed2e63be/stack/corepersistence/graph/src/test/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/graph/src/test/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheTest.java b/stack/corepersistence/graph/src/test/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheTest.java
index 96787be..9ea684e 100644
--- a/stack/corepersistence/graph/src/test/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheTest.java
+++ b/stack/corepersistence/graph/src/test/java/org/apache/usergrid/persistence/graph/impl/cache/NodeShardCacheTest.java
@@ -19,6 +19,7 @@
 package org.apache.usergrid.persistence.graph.impl.cache;
 
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.UUID;
 
@@ -27,8 +28,6 @@ import org.junit.Test;
 
 import org.apache.usergrid.persistence.collection.OrganizationScope;
 import org.apache.usergrid.persistence.graph.GraphFig;
-import org.apache.usergrid.persistence.graph.serialization.EdgeSerialization;
-import org.apache.usergrid.persistence.graph.serialization.EdgeSeriesSerialization;
 import org.apache.usergrid.persistence.model.entity.Id;
 import org.apache.usergrid.persistence.model.util.UUIDGenerator;
 
@@ -37,8 +36,6 @@ import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
 
 import static org.apache.usergrid.persistence.graph.test.util.EdgeTestUtils.createId;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.same;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -51,7 +48,6 @@ import static org.mockito.Mockito.when;
 public class NodeShardCacheTest {
 
 
-
     protected OrganizationScope scope;
 
 
@@ -73,72 +69,189 @@ public class NodeShardCacheTest {
 
         final GraphFig graphFig = getFigMock();
 
-        final EdgeSeriesSerialization serialization = mock( EdgeSeriesSerialization.class );
+        final NodeShardAllocation allocation = mock( NodeShardAllocation.class );
 
-        final Id id = createId("test");
+        final Id id = createId( "test" );
 
         final String edgeType = "edge";
 
         final String otherIdType = "type";
 
 
+        UUID newTime = UUIDGenerator.newTimeUUID();
 
 
+        NodeShardCache cache = new NodeShardCacheImpl( allocation, graphFig );
 
 
-        UUID newTime = UUIDGenerator.newTimeUUID();
+        /**
+         * Simulate returning no shards at all.
+         */
+        when( allocation.getShards( same( scope ), same( id ), same( edgeType ), same( otherIdType ) ) )
+                .thenReturn( Collections.singletonList( NodeShardAllocation.MIN_UUID ) );
 
 
+        UUID slice = cache.getSlice( scope, id, newTime, edgeType, otherIdType );
+
 
-        NodeShardCache cache = new NodeShardCacheImpl(serialization, graphFig  );
+        //we return the min UUID possible, all edges should start by writing to this edge
+        assertEquals( NodeShardAllocation.MIN_UUID, slice );
 
 
         /**
-         * Simulate returning no shards at all.
+         * Verify that we fired the audit
          */
-        when(serialization.getEdgeMetaData( same(scope), same(id), same(edgeType), same(otherIdType)  )).thenReturn(
-                Collections.<UUID>emptyList() );
+        verify( allocation ).auditMaxShard( scope, id, edgeType, otherIdType );
+    }
 
 
-        final MutationBatch batch = mock(MutationBatch.class);
+    @Test
+    public void testSingleExistingShard() {
+
+        final GraphFig graphFig = getFigMock();
 
-        //mock up returning the mutation batch
-        when(serialization.writeEdgeMeta(  same( scope ), same( id ), any( UUID.class ), same(edgeType), same(otherIdType))).thenReturn( batch );
+        final NodeShardAllocation allocation = mock( NodeShardAllocation.class );
+
+
+        final Id id = createId( "test" );
+
+        final String edgeType = "edge";
+
+        final String otherIdType = "type";
+
+
+        UUID newTime = UUIDGenerator.newTimeUUID();
+
+        final UUID min = new UUID( 0, 1 );
+
+
+        NodeShardCache cache = new NodeShardCacheImpl( allocation, graphFig );
+
+
+        /**
+         * Simulate returning single shard
+         */
+        when( allocation.getShards( same( scope ), same( id ), same( edgeType ), same( otherIdType ) ) )
+                .thenReturn( Collections.singletonList( min ) );
 
-        final UUID min = new UUID(0, 1);
 
         UUID slice = cache.getSlice( scope, id, newTime, edgeType, otherIdType );
 
 
         //we return the min UUID possible, all edges should start by writing to this edge
-        assertEquals(min, slice);
+        assertEquals( min, slice );
+
+        /**
+         * Verify that we fired the audit
+         */
+        verify( allocation ).auditMaxShard( scope, id, edgeType, otherIdType );
+    }
+
+
+    @Test
+    public void testRangeShard() {
+
+        final GraphFig graphFig = getFigMock();
+
+        final NodeShardAllocation allocation = mock( NodeShardAllocation.class );
+
+        final Id id = createId( "test" );
+
+        final String edgeType = "edge";
+
+        final String otherIdType = "type";
+
 
         /**
-         * Verify that we
+         * Set our min mid and max
          */
-        verify( serialization).writeEdgeMeta( scope, id, slice, edgeType, otherIdType);
+        final UUID min = new UUID( 0, 1 );
+
+
+        final UUID mid = new UUID( 0, 100 );
+
+
+        final UUID max = new UUID( 0, 200 );
+
+
+        NodeShardCache cache = new NodeShardCacheImpl( allocation, graphFig );
+
 
         /**
-         * Verify that execute was invoked
+         * Simulate returning all shards
          */
-        verify(batch).execute();
+        when( allocation.getShards( same( scope ), same( id ), same( edgeType ), same( otherIdType ) ) )
+                .thenReturn( Arrays.asList( min, mid, max ) );
 
 
-    }
+        //check getting equal to our min, mid and max
 
+        UUID slice = cache.getSlice( scope, id, new UUID( min.getMostSignificantBits(), min.getLeastSignificantBits() ),
+                edgeType, otherIdType );
+
+
+        //we return the min UUID possible, all edges should start by writing to this edge
+        assertEquals( min, slice );
+
+        slice = cache.getSlice( scope, id, new UUID( mid.getMostSignificantBits(), mid.getLeastSignificantBits() ),
+                edgeType, otherIdType );
+
+
+        //we return the mid UUID possible, all edges should start by writing to this edge
+        assertEquals( mid, slice );
+
+        slice = cache.getSlice( scope, id, new UUID( max.getMostSignificantBits(), max.getLeastSignificantBits() ),
+                edgeType, otherIdType );
+
+
+        //we return the mid UUID possible, all edges should start by writing to this edge
+        assertEquals( max, slice );
+
+        //now test in between
+        slice = cache.getSlice( scope, id, new UUID( 0, 1 ), edgeType, otherIdType );
 
-    @Test
-    public void testExistingShard(){
 
-        fail("TODO");
+        //we return the min UUID possible, all edges should start by writing to this edge
+        assertEquals( min, slice );
+
+        slice = cache.getSlice( scope, id, new UUID( 0, 99 ), edgeType, otherIdType );
+
+
+        //we return the min UUID possible, all edges should start by writing to this edge
+        assertEquals( min, slice );
+
+
+        slice = cache.getSlice( scope, id, new UUID( 0, 101 ), edgeType, otherIdType );
+
+
+        //we return the mid UUID possible, all edges should start by writing to this edge
+        assertEquals( mid, slice );
+
+        slice = cache.getSlice( scope, id, new UUID( 0, 199 ), edgeType, otherIdType );
+
+
+        //we return the mid UUID possible, all edges should start by writing to this edge
+        assertEquals( mid, slice );
+
+
+        slice = cache.getSlice( scope, id, new UUID( 0, 201 ), edgeType, otherIdType );
+
+
+        //we return the mid UUID possible, all edges should start by writing to this edge
+        assertEquals( max, slice );
+
+        /**
+         * Verify that we fired the audit
+         */
+        verify( allocation ).auditMaxShard( scope, id, edgeType, otherIdType );
     }
 
-    private GraphFig getFigMock(){
-        final GraphFig graphFig = mock( GraphFig.class);
-        when(graphFig.getCacheSize()).thenReturn( 1000 );
-        when(graphFig.getCacheTimeout()).thenReturn( 30000l );
+
+    private GraphFig getFigMock() {
+        final GraphFig graphFig = mock( GraphFig.class );
+        when( graphFig.getCacheSize() ).thenReturn( 1000 );
+        when( graphFig.getCacheTimeout() ).thenReturn( 30000l );
 
         return graphFig;
     }
-
 }