diff --git a/store-implementation/federated-store/pom.xml b/store-implementation/federated-store/pom.xml
index bf27d431dca..e1d3af14b49 100644
--- a/store-implementation/federated-store/pom.xml
+++ b/store-implementation/federated-store/pom.xml
@@ -44,7 +44,6 @@
uk.gov.gchq.gaffer
accumulo-store
${project.parent.version}
- test
uk.gov.gchq.gaffer
diff --git a/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedGraphStorage.java b/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedGraphStorage.java
index e3ff1944f18..278c9d7aef2 100644
--- a/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedGraphStorage.java
+++ b/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedGraphStorage.java
@@ -17,9 +17,13 @@
package uk.gov.gchq.gaffer.federatedstore;
import com.google.common.collect.Sets;
+import org.apache.accumulo.core.client.Connector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import uk.gov.gchq.gaffer.accumulostore.AccumuloProperties;
+import uk.gov.gchq.gaffer.accumulostore.AccumuloStore;
+import uk.gov.gchq.gaffer.accumulostore.utils.TableUtils;
import uk.gov.gchq.gaffer.cache.CacheServiceLoader;
import uk.gov.gchq.gaffer.cache.exception.CacheOperationException;
import uk.gov.gchq.gaffer.commonutil.JsonUtil;
@@ -227,7 +231,7 @@ private boolean remove(final String graphId, final Predicate accessPredicate) throws StorageException {
boolean rtn;
- Graph graphToMove = getGraphToMove(graphId, accessPredicate);
+ final Graph graphToMove = getGraphToMove(graphId, accessPredicate);
if (nonNull(graphToMove)) {
//remove graph to be moved
+ FederatedAccess oldAccess = null;
for (final Entry> entry : storage.entrySet()) {
entry.getValue().removeIf(graph -> graph.getGraphId().equals(graphId));
+ oldAccess = entry.getKey();
}
//add the graph being moved.
this.put(new GraphSerialisable.Builder().graph(graphToMove).build(), newFederatedAccess);
+
+ if (isCacheEnabled()) {
+ //Update cache
+ try {
+ federatedStoreCache.addGraphToCache(graphToMove, newFederatedAccess, true/*true because graphLibrary should have throw error*/);
+ } catch (final CacheOperationException e) {
+ //TODO FS recovery
+ String s = "Error occurred updating graphAccess. GraphStorage=updated, Cache=outdated. graphId:" + graphId;
+ LOGGER.error(s + " graphStorage access:{} cache access:{}", newFederatedAccess, oldAccess);
+ throw new StorageException(s, e);
+ }
+ }
+
rtn = true;
} else {
rtn = false;
@@ -568,28 +587,20 @@ private boolean changeGraphAccess(final String graphId, final FederatedAccess ne
}
public boolean changeGraphId(final String graphId, final String newGraphId, final User requestingUser) throws StorageException {
- final Graph graphToMove = getGraphToMove(graphId, access -> access.hasWriteAccess(requestingUser));
- return changeGraphId(graphId, newGraphId, graphToMove);
+ return changeGraphId(graphId, newGraphId, access -> access.hasWriteAccess(requestingUser));
}
public boolean changeGraphId(final String graphId, final String newGraphId, final User requestingUser, final String adminAuth) throws StorageException {
- final Graph graphToMove = getGraphToMove(graphId, access -> access.hasWriteAccess(requestingUser, adminAuth));
- return changeGraphId(graphId, newGraphId, graphToMove);
- }
-
-
- @Deprecated
- public boolean changeGraphIdAsAdmin(final String graphId, final String newGraphId) throws StorageException {
- final Graph graphToMove = getGraphToMove(graphId, access -> true);
- return changeGraphId(graphId, newGraphId, graphToMove);
+ return changeGraphId(graphId, newGraphId, access -> access.hasWriteAccess(requestingUser, adminAuth));
}
- private boolean changeGraphId(final String graphId, final String newGraphId, final Graph graphToMove) throws StorageException {
+ private boolean changeGraphId(final String graphId, final String newGraphId, final Predicate accessPredicate) throws StorageException {
boolean rtn;
+ final Graph graphToMove = getGraphToMove(graphId, accessPredicate);
if (nonNull(graphToMove)) {
FederatedAccess key = null;
- //remove graph to be moved
+ //remove graph to be moved from storage
for (final Entry> entry : storage.entrySet()) {
final boolean removed = entry.getValue().removeIf(graph -> graph.getGraphId().equals(graphId));
if (removed) {
@@ -598,16 +609,54 @@ private boolean changeGraphId(final String graphId, final String newGraphId, fin
}
}
- final GraphConfig configWithNewGraphId = new GraphConfig.Builder()
- .json(new GraphSerialisable.Builder().graph(graphToMove).build().getConfig())
- .graphId(newGraphId)
- .build();
+ //Update Tables
+ String storeClass = graphToMove.getStoreProperties().getStoreClass();
+ if (nonNull(storeClass) && storeClass.startsWith(AccumuloStore.class.getPackage().getName())) {
+ /*
+ * uk.gov.gchq.gaffer.accumulostore.[AccumuloStore, SingleUseAccumuloStore,
+ * SingleUseMockAccumuloStore, MockAccumuloStore, MiniAccumuloStore]
+ */
+ try {
+ AccumuloProperties tmpAccumuloProps = (AccumuloProperties) graphToMove.getStoreProperties();
+ Connector connection = TableUtils.getConnector(tmpAccumuloProps.getInstance(),
+ tmpAccumuloProps.getZookeepers(),
+ tmpAccumuloProps.getUser(),
+ tmpAccumuloProps.getPassword());
+
+ if (connection.tableOperations().exists(graphId)) {
+ connection.tableOperations().offline(graphId);
+ connection.tableOperations().clone(graphId, newGraphId, true, null, null);
+ connection.tableOperations().online(newGraphId);
+ connection.tableOperations().delete(graphId);
+ }
+ } catch (final Exception e) {
+ LOGGER.warn("Error trying to update tables for graphID:{} graphToMove:{}", graphId, graphToMove);
+ LOGGER.warn("Error trying to update tables.", e);
+ }
+ }
+
+ final GraphConfig configWithNewGraphId = cloneGraphConfigWithNewGraphId(newGraphId, graphToMove);
//add the graph being renamed.
- this.put(new GraphSerialisable.Builder()
+ GraphSerialisable newGraphSerialisable = new GraphSerialisable.Builder()
.graph(graphToMove)
.config(configWithNewGraphId)
- .build(), key);
+ .build();
+ this.put(newGraphSerialisable, key);
+
+ //Update cache
+ if (isCacheEnabled()) {
+ try {
+ federatedStoreCache.addGraphToCache(newGraphSerialisable, key, true/*true because graphLibrary should have throw error*/);
+ } catch (final CacheOperationException e) {
+ //TODO FS recovery
+ String s = "Error occurred updating graphId. GraphStorage=updated, Cache=outdated graphId.";
+ LOGGER.error(s + " graphStorage graphId:{} cache graphId:{}", newGraphId, graphId);
+ throw new StorageException(s, e);
+ }
+ federatedStoreCache.deleteGraphFromCache(graphId);
+ }
+
rtn = true;
} else {
rtn = false;
@@ -615,6 +664,13 @@ private boolean changeGraphId(final String graphId, final String newGraphId, fin
return rtn;
}
+ private GraphConfig cloneGraphConfigWithNewGraphId(final String newGraphId, final Graph graphToMove) {
+ return new GraphConfig.Builder()
+ .json(new GraphSerialisable.Builder().graph(graphToMove).build().getConfig())
+ .graphId(newGraphId)
+ .build();
+ }
+
private Graph getGraphToMove(final String graphId, final Predicate accessPredicate) {
Graph graphToMove = null;
for (final Entry> entry : storage.entrySet()) {
diff --git a/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedStoreCache.java b/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedStoreCache.java
index f9e919c39ef..ecc2d979e02 100644
--- a/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedStoreCache.java
+++ b/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedStoreCache.java
@@ -55,8 +55,20 @@ public Set getAllGraphIds() {
* @throws CacheOperationException if there was an error trying to add to the cache
*/
public void addGraphToCache(final Graph graph, final FederatedAccess access, final boolean overwrite) throws CacheOperationException {
- String graphId = graph.getGraphId();
- Pair pair = new Pair<>(new GraphSerialisable.Builder().graph(graph).build(), access);
+ addGraphToCache(new GraphSerialisable.Builder().graph(graph).build(), access, overwrite);
+ }
+
+ /**
+ * Add the specified {@link Graph} to the cache.
+ *
+ * @param graphSerialisable the serialised {@link Graph} to be added
+ * @param access Access for the graph being stored.
+ * @param overwrite if true, overwrite any graphs already in the cache with the same ID
+ * @throws CacheOperationException if there was an error trying to add to the cache
+ */
+ public void addGraphToCache(final GraphSerialisable graphSerialisable, final FederatedAccess access, final boolean overwrite) throws CacheOperationException {
+ String graphId = graphSerialisable.getDeserialisedConfig().getGraphId();
+ Pair pair = new Pair<>(graphSerialisable, access);
try {
addToCache(graphId, pair, overwrite);
} catch (final CacheOperationException e) {
@@ -64,6 +76,10 @@ public void addGraphToCache(final Graph graph, final FederatedAccess access, fin
}
}
+ public void deleteGraphFromCache(final String graphId) {
+ super.deleteFromCache(graphId);
+ }
+
/**
* Retrieve the {@link Graph} with the specified ID from the cache.
*
@@ -88,6 +104,6 @@ public GraphSerialisable getGraphSerialisableFromCache(final String graphId) {
public FederatedAccess getAccessFromCache(final String graphId) {
final Pair fromCache = getFromCache(graphId);
- return fromCache.getSecond();
+ return (isNull(fromCache)) ? null : fromCache.getSecond();
}
}
diff --git a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/FederatedStoreCacheTest.java b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/FederatedStoreCacheTest.java
index dd14ee6142d..1cc4e4c185b 100644
--- a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/FederatedStoreCacheTest.java
+++ b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/FederatedStoreCacheTest.java
@@ -92,7 +92,7 @@ public void shouldDeleteFromCache() throws CacheOperationException {
assertEquals(1, cachedGraphIds.size());
assertTrue(cachedGraphIds.contains(testGraph.getGraphId()));
- federatedStoreCache.deleteFromCache(testGraph.getGraphId());
+ federatedStoreCache.deleteGraphFromCache(testGraph.getGraphId());
Set cachedGraphIdsAfterDelete = federatedStoreCache.getAllGraphIds();
assertEquals(0, cachedGraphIdsAfterDelete.size());
}
@@ -111,7 +111,7 @@ public void shouldThrowExceptionIfGraphAlreadyExistsInCache() throws CacheOperat
@Test
public void shouldThrowExceptionIfGraphIdToBeRemovedIsNull() throws CacheOperationException {
federatedStoreCache.addGraphToCache(testGraph, null, false);
- federatedStoreCache.deleteFromCache(null);
+ federatedStoreCache.deleteGraphFromCache(null);
assertEquals(1, federatedStoreCache.getAllGraphIds().size());
}
diff --git a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/AbstractStandaloneFederatedStoreIT.java b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/AbstractStandaloneFederatedStoreIT.java
index ce64d9b7adb..d95f65b12ae 100644
--- a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/AbstractStandaloneFederatedStoreIT.java
+++ b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/AbstractStandaloneFederatedStoreIT.java
@@ -16,8 +16,10 @@
package uk.gov.gchq.gaffer.federatedstore.integration;
+import org.junit.AfterClass;
import org.junit.jupiter.api.BeforeEach;
+import uk.gov.gchq.gaffer.cache.CacheServiceLoader;
import uk.gov.gchq.gaffer.commonutil.StreamUtil;
import uk.gov.gchq.gaffer.federatedstore.FederatedStoreProperties;
import uk.gov.gchq.gaffer.graph.Graph;
@@ -36,6 +38,16 @@ public void setUp() throws Exception {
_setUp();
}
+ @AfterClass
+ public void tearDown() throws Exception {
+ CacheServiceLoader.shutdown();
+ _tearDown();
+ }
+
+ private void _tearDown() throws Exception {
+ }
+
+
protected void _setUp() throws Exception {
// Override if required;
}
diff --git a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/FederatedAdminIT.java b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/FederatedAdminIT.java
index af0df80323f..96ce161d629 100644
--- a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/FederatedAdminIT.java
+++ b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/FederatedAdminIT.java
@@ -17,11 +17,14 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import org.apache.accumulo.core.client.Connector;
import org.junit.jupiter.api.Test;
import uk.gov.gchq.gaffer.accumulostore.AccumuloProperties;
+import uk.gov.gchq.gaffer.accumulostore.utils.TableUtils;
import uk.gov.gchq.gaffer.commonutil.StreamUtil;
import uk.gov.gchq.gaffer.federatedstore.FederatedAccess;
+import uk.gov.gchq.gaffer.federatedstore.FederatedStoreCache;
import uk.gov.gchq.gaffer.federatedstore.FederatedStoreConstants;
import uk.gov.gchq.gaffer.federatedstore.PublicAccessPredefinedFederatedStore;
import uk.gov.gchq.gaffer.federatedstore.operation.AddGraph;
@@ -30,16 +33,23 @@
import uk.gov.gchq.gaffer.federatedstore.operation.GetAllGraphIds;
import uk.gov.gchq.gaffer.federatedstore.operation.GetAllGraphInfo;
import uk.gov.gchq.gaffer.federatedstore.operation.RemoveGraph;
+import uk.gov.gchq.gaffer.graph.GraphSerialisable;
import uk.gov.gchq.gaffer.integration.AbstractStoreIT;
+import uk.gov.gchq.gaffer.jsonserialisation.JSONSerialiser;
import uk.gov.gchq.gaffer.store.schema.Schema;
import uk.gov.gchq.gaffer.user.User;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
+import java.util.Set;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static uk.gov.gchq.gaffer.federatedstore.FederatedStoreConstants.KEY_OPERATION_OPTIONS_GRAPH_IDS;
@@ -48,7 +58,8 @@ public class FederatedAdminIT extends AbstractStandaloneFederatedStoreIT {
public static final User ADMIN_USER = new User("admin", Collections.EMPTY_SET, Sets.newHashSet("AdminAuth"));
public static final User NOT_ADMIN_USER = new User("admin", Collections.EMPTY_SET, Sets.newHashSet("NotAdminAuth"));
- private static Class currentClass = new Object() { }.getClass().getEnclosingClass();
+ private static Class currentClass = new Object() {
+ }.getClass().getEnclosingClass();
private static final AccumuloProperties ACCUMULO_PROPERTIES = AccumuloProperties.loadStoreProperties(
StreamUtil.openStream(currentClass, "properties/singleUseAccumuloStore.properties"));
@@ -70,6 +81,53 @@ public void _setUp() throws Exception {
.build(), user);
}
+ @Test
+ public void shouldRemoveGraphFromStorage() throws Exception {
+ //given
+ final String graphA = "graphA";
+ graph.execute(new AddGraph.Builder()
+ .graphId(graphA)
+ .schema(new Schema())
+ .storeProperties(ACCUMULO_PROPERTIES)
+ .build(), user);
+ assertTrue(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphA));
+
+ //when
+ final Boolean removed = graph.execute(new RemoveGraph.Builder()
+ .graphId(graphA)
+ .build(), user);
+
+ //then
+ assertTrue(removed);
+ assertEquals(0, Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).size());
+
+ }
+
+ @Test
+ public void shouldRemoveGraphFromCache() throws Exception {
+ //given
+ FederatedStoreCache federatedStoreCache = new FederatedStoreCache();
+ final String graphA = "graphA";
+ graph.execute(new AddGraph.Builder()
+ .graphId(graphA)
+ .schema(new Schema())
+ .storeProperties(ACCUMULO_PROPERTIES)
+ .build(), user);
+ assertTrue(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphA));
+
+ //when
+ assertNotNull(federatedStoreCache.getGraphSerialisableFromCache(graphA));
+ final Boolean removed = graph.execute(new RemoveGraph.Builder()
+ .graphId(graphA)
+ .build(), user);
+
+ //then
+ assertTrue(removed);
+ GraphSerialisable graphSerialisableFromCache = federatedStoreCache.getGraphSerialisableFromCache(graphA);
+ assertNull(new String(JSONSerialiser.serialise(graphSerialisableFromCache, true)), graphSerialisableFromCache);
+ assertEquals(0, federatedStoreCache.getAllGraphIds().size());
+ }
+
@Test
public void shouldRemoveGraphForAdmin() throws Exception {
//given
@@ -384,8 +442,13 @@ public void shouldNotChangeGraphUserFromSomeoneElseToReplacementUserAsNonAdminWh
@Test
public void shouldChangeGraphIdForOwnGraph() throws Exception {
//given
- final String graphA = "graphA";
- final String graphB = "graphB";
+ final String graphA = "graphTableA";
+ final String graphB = "graphTableB";
+ Connector connector = TableUtils.getConnector(ACCUMULO_PROPERTIES.getInstance(),
+ ACCUMULO_PROPERTIES.getZookeepers(),
+ ACCUMULO_PROPERTIES.getUser(),
+ ACCUMULO_PROPERTIES.getPassword());
+
graph.execute(new AddGraph.Builder()
.graphId(graphA)
.schema(new Schema())
@@ -395,15 +458,25 @@ public void shouldChangeGraphIdForOwnGraph() throws Exception {
assertTrue(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphA));
//when
+ boolean tableGraphABefore = connector.tableOperations().exists(graphA);
+ boolean tableGraphBBefore = connector.tableOperations().exists(graphB);
+
final Boolean changed = graph.execute(new ChangeGraphId.Builder()
.graphId(graphA)
.newGraphId(graphB)
.build(), user);
+ boolean tableGraphAfter = connector.tableOperations().exists(graphA);
+ boolean tableGraphBAfter = connector.tableOperations().exists(graphB);
+
//then
assertTrue(changed);
assertFalse(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphA));
assertTrue(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphB));
+ assertTrue(tableGraphABefore);
+ assertFalse(tableGraphBBefore);
+ assertFalse(tableGraphAfter);
+ assertTrue(tableGraphBAfter);
}
@@ -489,4 +562,120 @@ public void shouldNotChangeGraphIdForNonOwnedGraphAsNonAdminWhenRequestingAdminA
assertFalse(Lists.newArrayList(graph.execute(new GetAllGraphIds(), otherUser)).contains(graphA));
assertFalse(Lists.newArrayList(graph.execute(new GetAllGraphIds(), otherUser)).contains(graphB));
}
+
+ @Test
+ public void shouldStartWithEmptyCache() throws Exception {
+ //given
+ FederatedStoreCache federatedStoreCache = new FederatedStoreCache();
+
+ //then
+ assertEquals(0, federatedStoreCache.getAllGraphIds().size());
+ }
+
+ @Test
+ public void shouldChangeGraphIdInStorage() throws Exception {
+ //given
+ String newName = "newName";
+ final String graphA = "graphA";
+ graph.execute(new AddGraph.Builder()
+ .graphId(graphA)
+ .schema(new Schema())
+ .storeProperties(ACCUMULO_PROPERTIES)
+ .build(), user);
+ assertTrue(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphA));
+
+ //when
+ final Boolean changed = graph.execute(new ChangeGraphId.Builder()
+ .graphId(graphA)
+ .newGraphId(newName)
+ .build(), user);
+
+ //then
+ ArrayList graphIds = Lists.newArrayList(graph.execute(new GetAllGraphIds(), user));
+
+ assertTrue(changed);
+ assertEquals(1, graphIds.size());
+ assertArrayEquals(new String[]{newName}, graphIds.toArray());
+ }
+
+ @Test
+ public void shouldChangeGraphIdInCache() throws Exception {
+ //given
+ String newName = "newName";
+ FederatedStoreCache federatedStoreCache = new FederatedStoreCache();
+ final String graphA = "graphA";
+ graph.execute(new AddGraph.Builder()
+ .graphId(graphA)
+ .schema(new Schema())
+ .storeProperties(ACCUMULO_PROPERTIES)
+ .build(), user);
+ assertTrue(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphA));
+
+ //when
+ final Boolean changed = graph.execute(new ChangeGraphId.Builder()
+ .graphId(graphA)
+ .newGraphId(newName)
+ .build(), user);
+
+ //then
+ Set graphIds = federatedStoreCache.getAllGraphIds();
+
+ assertTrue(changed);
+ assertArrayEquals(graphIds.toString(), new String[]{newName}, graphIds.toArray());
+ }
+
+ @Test
+ public void shouldChangeGraphAccessIdInStorage() throws Exception {
+ //given
+ final String graphA = "graphA";
+ graph.execute(new AddGraph.Builder()
+ .graphId(graphA)
+ .schema(new Schema())
+ .storeProperties(ACCUMULO_PROPERTIES)
+ .build(), user);
+ assertTrue(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphA));
+
+ //when
+ final Boolean changed = graph.execute(new ChangeGraphAccess.Builder()
+ .graphId(graphA)
+ .ownerUserId(NOT_ADMIN_USER.getUserId())
+ .build(), user);
+
+ //then
+ ArrayList userGraphIds = Lists.newArrayList(graph.execute(new GetAllGraphIds(), user));
+ ArrayList otherUserGraphIds = Lists.newArrayList(graph.execute(new GetAllGraphIds(), NOT_ADMIN_USER));
+
+ assertTrue(changed);
+ assertEquals(0, userGraphIds.size());
+ assertEquals(1, otherUserGraphIds.size());
+ assertArrayEquals(new String[]{graphA}, otherUserGraphIds.toArray());
+ }
+
+ @Test
+ public void shouldChangeGraphAccessIdInCache() throws Exception {
+ //given
+ FederatedStoreCache federatedStoreCache = new FederatedStoreCache();
+ final String graphA = "graphA";
+ graph.execute(new AddGraph.Builder()
+ .graphId(graphA)
+ .schema(new Schema())
+ .storeProperties(ACCUMULO_PROPERTIES)
+ .build(), user);
+ assertTrue(Lists.newArrayList(graph.execute(new GetAllGraphIds(), user)).contains(graphA));
+
+ //when
+ FederatedAccess before = federatedStoreCache.getAccessFromCache(graphA);
+ final Boolean changed = graph.execute(new ChangeGraphAccess.Builder()
+ .graphId(graphA)
+ .ownerUserId(ADMIN_USER.getUserId())
+ .build(), user);
+ FederatedAccess after = federatedStoreCache.getAccessFromCache(graphA);
+
+ //then
+ assertTrue(changed);
+ assertNotEquals(before, after);
+ assertEquals(user.getUserId(), before.getAddingUserId());
+ assertEquals(ADMIN_USER.getUserId(), after.getAddingUserId());
+ }
+
}
diff --git a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/FederatedStoreRecursionIT.java b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/FederatedStoreRecursionIT.java
index b11ba18e3e5..3dd87a925b4 100644
--- a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/FederatedStoreRecursionIT.java
+++ b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/integration/FederatedStoreRecursionIT.java
@@ -64,7 +64,7 @@ public class FederatedStoreRecursionIT {
private User user = new User();
@Test
- @Timeout(value = 60)
+ @Timeout(value = 20000)
public void shouldNotInfinityLoopWhenAddingElements() throws Exception {
/*
* Structure: