diff --git a/ChangeLog.md b/ChangeLog.md index 463a3b6e9..af9831534 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] +### Added + +- added minReplicationAttribute for collections and graphs + ## [5.0.7] - 2019-07-19 ### Fixed diff --git a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java index 84000d9e3..8092edec6 100644 --- a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java @@ -38,6 +38,7 @@ public class CollectionPropertiesEntity extends CollectionEntity { private Integer numberOfShards; private Collection shardKeys; private final ReplicationFactor replicationFactor; + private final MinReplicationFactor minReplicationFactor; private String shardingStrategy; // cluster option private String smartJoinAttribute; // enterprise option @@ -45,6 +46,7 @@ public class CollectionPropertiesEntity extends CollectionEntity { public CollectionPropertiesEntity() { super(); replicationFactor = new ReplicationFactor(); + minReplicationFactor = new MinReplicationFactor(); } public Boolean getDoCompact() { @@ -118,6 +120,14 @@ public void setReplicationFactor(final Integer replicationFactor) { this.replicationFactor.setReplicationFactor(replicationFactor); } + public Integer getMinReplicationFactor() { + return minReplicationFactor.getMinReplicationFactor(); + } + + public void setMinReplicationFactor(final Integer minReplicationFactor) { + this.minReplicationFactor.setMinReplicationFactor(minReplicationFactor); + } + /** * @return whether the collection is a satellite collection. Only in an enterprise cluster setup (else returning null). */ diff --git a/src/main/java/com/arangodb/entity/GraphEntity.java b/src/main/java/com/arangodb/entity/GraphEntity.java index 19a7518f3..50af41d86 100644 --- a/src/main/java/com/arangodb/entity/GraphEntity.java +++ b/src/main/java/com/arangodb/entity/GraphEntity.java @@ -39,6 +39,8 @@ public class GraphEntity implements Entity { private Boolean isSmart; private Integer numberOfShards; private String smartGraphAttribute; + private Integer replicationFactor; + private Integer minReplicationFactor; public String getName() { return name != null ? name : _key; @@ -60,6 +62,13 @@ public Integer getNumberOfShards() { return numberOfShards; } + public Integer getReplicationFactor() { + return replicationFactor; + } + public Integer getMinReplicationFactor() { + return minReplicationFactor; + } + public String getSmartGraphAttribute() { return smartGraphAttribute; } diff --git a/src/main/java/com/arangodb/entity/MinReplicationFactor.java b/src/main/java/com/arangodb/entity/MinReplicationFactor.java new file mode 100644 index 000000000..3fc5ff7fc --- /dev/null +++ b/src/main/java/com/arangodb/entity/MinReplicationFactor.java @@ -0,0 +1,43 @@ +/* + * DISCLAIMER + * + * Copyright 2019 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Heiko Kernbach + * + */ +public class MinReplicationFactor { + + private Integer minReplicationFactor; + + public MinReplicationFactor() { + super(); + } + + public Integer getMinReplicationFactor() { + return minReplicationFactor; + } + + public void setMinReplicationFactor(final Integer minReplicationFactor) { + this.minReplicationFactor = minReplicationFactor; + } + +} \ No newline at end of file diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index f7d0e13ad..fde352d8b 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -27,21 +27,10 @@ import java.util.Map; import java.util.Map.Entry; +import com.arangodb.entity.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.CollectionStatus; -import com.arangodb.entity.CollectionType; -import com.arangodb.entity.License; -import com.arangodb.entity.LogLevel; -import com.arangodb.entity.Permissions; -import com.arangodb.entity.QueryExecutionState; -import com.arangodb.entity.ReplicationFactor; -import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; import com.arangodb.entity.arangosearch.CollectionLink; @@ -200,6 +189,18 @@ public ReplicationFactor deserialize( } }; + public static final VPackDeserializer MIN_REPLICATION_FACTOR = new VPackDeserializer() { + @Override + public MinReplicationFactor deserialize( + final VPackSlice parent, + final VPackSlice vpack, + final VPackDeserializationContext context) throws VPackException { + final MinReplicationFactor minReplicationFactor = new MinReplicationFactor(); + minReplicationFactor.setMinReplicationFactor(vpack.getAsInt()); + return minReplicationFactor; + } + }; + public static final VPackDeserializer VIEW_TYPE = new VPackDeserializer() { @Override public ViewType deserialize( diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java index 7ec963f74..d94693c5e 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java @@ -34,6 +34,7 @@ import com.arangodb.entity.QueryEntity; import com.arangodb.entity.QueryExecutionState; import com.arangodb.entity.ReplicationFactor; +import com.arangodb.entity.MinReplicationFactor; import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; @@ -77,6 +78,7 @@ public String translateName(final Field field) { context.registerSerializer(LogLevel.class, VPackSerializers.LOG_LEVEL); context.registerSerializer(Permissions.class, VPackSerializers.PERMISSIONS); context.registerSerializer(ReplicationFactor.class, VPackSerializers.REPLICATION_FACTOR); + context.registerSerializer(MinReplicationFactor.class, VPackSerializers.MIN_REPLICATION_FACTOR); context.registerSerializer(ViewType.class, VPackSerializers.VIEW_TYPE); context.registerSerializer(ArangoSearchPropertiesOptions.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES_OPTIONS); context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES); diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java index 53f71e3f5..ffa896e6c 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java @@ -25,14 +25,7 @@ import java.util.Map; import java.util.Map.Entry; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.CollectionType; -import com.arangodb.entity.DocumentField; -import com.arangodb.entity.LogLevel; -import com.arangodb.entity.Permissions; -import com.arangodb.entity.ReplicationFactor; -import com.arangodb.entity.ViewType; +import com.arangodb.entity.*; import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.ConsolidationType; @@ -197,6 +190,17 @@ public void serialize( } }; + public static final VPackSerializer MIN_REPLICATION_FACTOR = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final MinReplicationFactor value, + final VPackSerializationContext context) throws VPackException { + builder.add(attribute, value.getMinReplicationFactor()); + } + }; + public static final VPackSerializer VIEW_TYPE = new VPackSerializer() { @Override public void serialize( diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 4984efb47..e1c705972 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -24,6 +24,7 @@ import com.arangodb.entity.KeyOptions; import com.arangodb.entity.KeyType; import com.arangodb.entity.ReplicationFactor; +import com.arangodb.entity.MinReplicationFactor; /** * @author Mark Vollmary @@ -36,6 +37,7 @@ public class CollectionCreateOptions { private String name; private Long journalSize; private final ReplicationFactor replicationFactor; + private final MinReplicationFactor minReplicationFactor; private KeyOptions keyOptions; private Boolean waitForSync; private Boolean doCompact; @@ -53,6 +55,7 @@ public class CollectionCreateOptions { public CollectionCreateOptions() { super(); replicationFactor = new ReplicationFactor(); + minReplicationFactor = new MinReplicationFactor(); } protected String getName() { @@ -87,6 +90,10 @@ public Integer getReplicationFactor() { return replicationFactor.getReplicationFactor(); } + public Integer getMinReplicationFactor() { + return minReplicationFactor.getMinReplicationFactor(); + } + /** * @param replicationFactor * (The default is 1): in a cluster, this attribute determines how many copies of each shard are kept on @@ -103,6 +110,24 @@ public CollectionCreateOptions replicationFactor(final Integer replicationFactor return this; } + /** + * @param minReplicationFactor + * (optional, default is 1): in a cluster, this attribute determines how many desired copies of each + * shard are kept on different DBServers. The value 1 means that only one copy (no synchronous + * replication) is kept. A value of k means that desired k-1 replicas are kept. If in a failover scenario + * a shard of a collection has less than minReplicationFactor many insync followers it will go into + * "read-only" mode and will reject writes until enough followers are insync again. In more detail: + * Having `minReplicationFactor == 1` means as soon as a "master-copy" is available of the data writes + * are allowed. Having `minReplicationFactor > 1` requires additional insync copies on follower servers + * to allow writes. + * + * @return options + */ + public CollectionCreateOptions minReplicationFactor(final Integer minReplicationFactor) { + this.minReplicationFactor.setMinReplicationFactor(minReplicationFactor); + return this; + } + public Boolean getSatellite() { return replicationFactor.getSatellite(); } diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index 63778d833..b19307d58 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -119,6 +119,28 @@ public GraphCreateOptions replicationFactor(final Integer replicationFactor) { return this; } + public Integer getMinReplicationFactor() { + return getOptions().getMinReplicationFactor(); + } + + /** + * @param minReplicationFactor + * (optional, default is 1): in a cluster, this attribute determines how many desired copies of each + * shard are kept on different DBServers. The value 1 means that only one copy (no synchronous + * replication) is kept. A value of k means that desired k-1 replicas are kept. If in a failover scenario + * a shard of a collection has less than minReplicationFactor many insync followers it will go into + * "read-only" mode and will reject writes until enough followers are insync again. In more detail: + * Having `minReplicationFactor == 1` means as soon as a "master-copy" is available of the data writes + * are allowed. Having `minReplicationFactor > 1` requires additional insync copies on follower servers + * to allow writes. + * + * @return options + */ + public GraphCreateOptions minReplicationFactor(final Integer minReplicationFactor) { + getOptions().setMinReplicationFactor(minReplicationFactor); + return this; + } + public Integer getNumberOfShards() { return getOptions().getNumberOfShards(); } @@ -157,6 +179,7 @@ private SmartOptions getOptions() { public static class SmartOptions { private Integer replicationFactor; + private Integer minReplicationFactor; private Integer numberOfShards; private String smartGraphAttribute; @@ -172,6 +195,14 @@ public void setReplicationFactor(final Integer replicationFactor) { this.replicationFactor = replicationFactor; } + public Integer getMinReplicationFactor() { + return minReplicationFactor; + } + + public void setMinReplicationFactor(final Integer minReplicationFactor) { + this.minReplicationFactor = minReplicationFactor; + } + public Integer getNumberOfShards() { return numberOfShards; } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 911f3b1d9..75f498231 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -212,6 +212,37 @@ public void createCollectionWithReplicationFactor() { } + @Test + public void createCollectionWithMinReplicationFactor() { + + // if we do not have version at least 3.5+ => exit + if (!requireVersion(3, 5)) { + LOG.info("Skip Test 'createCollectionWithMinReplicationFactor' because feature not implemented yet."); + return; + } + + // if we do not have a cluster => exit + if (arangoDB.getRole() == ServerRole.SINGLE) { + return; + } + + try { + final CollectionEntity result = db.createCollection(COLLECTION_NAME, + new CollectionCreateOptions().replicationFactor(2).minReplicationFactor(2)); + assertThat(result, is(notNullValue())); + assertThat(result.getId(), is(notNullValue())); + assertThat(db.collection(COLLECTION_NAME).getProperties().getReplicationFactor(), is(2)); + assertThat(db.collection(COLLECTION_NAME).getProperties().getMinReplicationFactor(), is(2)); + assertThat(db.collection(COLLECTION_NAME).getProperties().getSatellite(), is(nullValue())); + } catch (final ArangoDBException e) { + e.printStackTrace(); + } finally { + db.collection(COLLECTION_NAME).drop(); + } + + } + + @Test public void createSatelliteCollection() { if (arangoDB.getVersion().getLicense() == License.COMMUNITY) { diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index 6b5c0a5d4..658eb6156 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -49,248 +49,261 @@ /** * @author Mark Vollmary - * */ @RunWith(Parameterized.class) public class ArangoGraphTest extends BaseTest { - private static final String GRAPH_NAME = "db_collection_test"; - private static final String EDGE_COL_1 = "db_edge1_collection_test"; - private static final String EDGE_COL_2 = "db_edge2_collection_test"; - private static final String EDGE_COL_3 = "db_edge3_collection_test"; - private static final String VERTEX_COL_1 = "db_vertex1_collection_test"; - private static final String VERTEX_COL_2 = "db_vertex2_collection_test"; - private static final String VERTEX_COL_3 = "db_vertex3_collection_test"; - private static final String VERTEX_COL_4 = "db_vertex4_collection_test"; - private static final Integer REPLICATION_FACTOR = 2; - private static final Integer NUMBER_OF_SHARDS = 2; - - public ArangoGraphTest(final Builder builder) { - super(builder); - } - - @Before - public void setup() { - try { - db.graph(GRAPH_NAME).drop(true); - } catch (final ArangoDBException e1) { - } - final Collection edgeDefinitions = new ArrayList(); - edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); - edgeDefinitions - .add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); - final GraphCreateOptions options = new GraphCreateOptions(); - if (arangoDB.getRole() != ServerRole.SINGLE) { - options.replicationFactor(REPLICATION_FACTOR).numberOfShards(NUMBER_OF_SHARDS); - } - db.createGraph(GRAPH_NAME, edgeDefinitions, options); - } - - @After - public void teardown() { - for (final String collection : new String[] { EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, - VERTEX_COL_4 }) { - final ArangoCollection c = db.collection(collection); - if (c.exists()) { - c.truncate(); - } - } - } - - @Test - public void exists() { - assertThat(db.graph(GRAPH_NAME).exists(), is(true)); - assertThat(db.graph(GRAPH_NAME + "no").exists(), is(false)); - } - - @Test - public void create() { - try { - final GraphEntity result = db.graph(GRAPH_NAME + "_1").create(null); - assertThat(result, is(notNullValue())); - assertThat(result.getName(), is(GRAPH_NAME + "_1")); - } finally { - db.graph(GRAPH_NAME + "_1").drop(); - } - } - - @Test - public void getGraphs() { - final Collection graphs = db.getGraphs(); - assertThat(graphs, is(notNullValue())); - assertThat(graphs.size(), is(1)); - assertThat(graphs.iterator().next().getName(), is(GRAPH_NAME)); - } - - @Test - public void getInfo() { - final GraphEntity info = db.graph(GRAPH_NAME).getInfo(); - assertThat(info, is(notNullValue())); - assertThat(info.getName(), is(GRAPH_NAME)); - assertThat(info.getEdgeDefinitions().size(), is(2)); - final Iterator iterator = info.getEdgeDefinitions().iterator(); - final EdgeDefinition e1 = iterator.next(); - assertThat(e1.getCollection(), is(EDGE_COL_1)); - assertThat(e1.getFrom(), hasItem(VERTEX_COL_1)); - assertThat(e1.getTo(), hasItem(VERTEX_COL_2)); - final EdgeDefinition e2 = iterator.next(); - assertThat(e2.getCollection(), is(EDGE_COL_2)); - assertThat(e2.getFrom(), hasItem(VERTEX_COL_2)); - assertThat(e2.getTo(), hasItems(VERTEX_COL_1, VERTEX_COL_3)); - assertThat(info.getOrphanCollections(), is(empty())); - - if (arangoDB.getRole() != ServerRole.SINGLE) { - for (final String collection : new String[] { EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2 }) { - final CollectionPropertiesEntity properties = db.collection(collection).getProperties(); - assertThat(properties.getReplicationFactor(), is(REPLICATION_FACTOR)); - assertThat(properties.getNumberOfShards(), is(NUMBER_OF_SHARDS)); - } - } - } - - @Test - public void getVertexCollections() { - final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections(); - assertThat(vertexCollections, is(notNullValue())); - assertThat(vertexCollections.size(), is(3)); - assertThat(vertexCollections, hasItems(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3)); - } - - @Test - public void addVertexCollection() { - final GraphEntity graph = db.graph(GRAPH_NAME).addVertexCollection(VERTEX_COL_4); - assertThat(graph, is(notNullValue())); - final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections(); - assertThat(vertexCollections, hasItems(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4)); - setup(); - } - - @Test - public void getEdgeCollections() { - final Collection edgeCollections = db.graph(GRAPH_NAME).getEdgeDefinitions(); - assertThat(edgeCollections, is(notNullValue())); - assertThat(edgeCollections.size(), is(2)); - assertThat(edgeCollections, hasItems(EDGE_COL_1, EDGE_COL_2)); - } - - @Test - public void addEdgeDefinition() { - final GraphEntity graph = db.graph(GRAPH_NAME) - .addEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_3).from(VERTEX_COL_1).to(VERTEX_COL_2)); - assertThat(graph, is(notNullValue())); - final Collection edgeDefinitions = graph.getEdgeDefinitions(); - assertThat(edgeDefinitions.size(), is(3)); - int count = 0; - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_3)) { - count++; - } - } - assertThat(count, is(1)); - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_3)) { - assertThat(e.getFrom(), hasItem(VERTEX_COL_1)); - assertThat(e.getTo(), hasItem(VERTEX_COL_2)); - } - } - if (arangoDB.getRole() != ServerRole.SINGLE) { - final CollectionPropertiesEntity properties = db.collection(EDGE_COL_3).getProperties(); - assertThat(properties.getReplicationFactor(), is(REPLICATION_FACTOR)); - assertThat(properties.getNumberOfShards(), is(NUMBER_OF_SHARDS)); - } - setup(); - } - - @Test - public void replaceEdgeDefinition() { - final GraphEntity graph = db.graph(GRAPH_NAME) - .replaceEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_3).to(VERTEX_COL_4)); - final Collection edgeDefinitions = graph.getEdgeDefinitions(); - assertThat(edgeDefinitions.size(), is(2)); - int count = 0; - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_1)) { - count++; - } - } - assertThat(count, is(1)); - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_1)) { - assertThat(e.getFrom(), hasItem(VERTEX_COL_3)); - assertThat(e.getTo(), hasItem(VERTEX_COL_4)); - } - } - setup(); - } - - @Test - public void removeEdgeDefinition() { - final GraphEntity graph = db.graph(GRAPH_NAME).removeEdgeDefinition(EDGE_COL_1); - final Collection edgeDefinitions = graph.getEdgeDefinitions(); - assertThat(edgeDefinitions.size(), is(1)); - assertThat(edgeDefinitions.iterator().next().getCollection(), is(EDGE_COL_2)); - setup(); - } - - @Test - public void smartGraph() { - - if (arangoDB.getVersion().getLicense() == License.ENTERPRISE) { - - for (final String collection : new String[] { EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4 }) { - try { - db.collection(collection).drop(); - } catch (final ArangoDBException e) { - - } - } - try { - db.graph(GRAPH_NAME).drop(); - } catch (final ArangoDBException e) { - } - - final Collection edgeDefinitions = new ArrayList(); - - edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); - edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); - - final GraphEntity graph = db.createGraph(GRAPH_NAME, edgeDefinitions, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); - - assertThat(graph, is(notNullValue())); - assertThat(graph.getIsSmart(), is(true)); - assertThat(graph.getSmartGraphAttribute(), is("test")); - assertThat(graph.getNumberOfShards(), is(2)); - } - } - - @Test - public void drop() { - final String edgeCollection = "edge_drop"; - final String vertexCollection = "vertex_drop"; - final String graph = GRAPH_NAME + "_drop"; - final GraphEntity result = db.graph(graph).create(Collections - .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))); - assertThat(result, is(notNullValue())); - db.graph(graph).drop(); - assertThat(db.collection(edgeCollection).exists(), is(true)); - assertThat(db.collection(vertexCollection).exists(), is(true)); - } - - @Test - public void dropPlusDropCollections() { - final String edgeCollection = "edge_dropC"; - final String vertexCollection = "vertex_dropC"; - final String graph = GRAPH_NAME + "_dropC"; - final GraphEntity result = db.graph(graph).create(Collections - .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))); - assertThat(result, is(notNullValue())); - db.graph(graph).drop(true); - assertThat(db.collection(edgeCollection).exists(), is(false)); - assertThat(db.collection(vertexCollection).exists(), is(false)); - } - - @AfterClass - public static void shutdown() { - db.drop(); - } + private static final String GRAPH_NAME = "db_collection_test"; + private static final String EDGE_COL_1 = "db_edge1_collection_test"; + private static final String EDGE_COL_2 = "db_edge2_collection_test"; + private static final String EDGE_COL_3 = "db_edge3_collection_test"; + private static final String VERTEX_COL_1 = "db_vertex1_collection_test"; + private static final String VERTEX_COL_2 = "db_vertex2_collection_test"; + private static final String VERTEX_COL_3 = "db_vertex3_collection_test"; + private static final String VERTEX_COL_4 = "db_vertex4_collection_test"; + private static final Integer REPLICATION_FACTOR = 2; + private static final Integer NUMBER_OF_SHARDS = 2; + + public ArangoGraphTest(final Builder builder) { + super(builder); + } + + @Before + public void setup() { + try { + db.graph(GRAPH_NAME).drop(true); + } catch (final ArangoDBException e1) { + } + final Collection edgeDefinitions = new ArrayList(); + edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); + edgeDefinitions + .add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); + final GraphCreateOptions options = new GraphCreateOptions(); + if (arangoDB.getRole() != ServerRole.SINGLE) { + options.replicationFactor(REPLICATION_FACTOR).numberOfShards(NUMBER_OF_SHARDS); + } + db.createGraph(GRAPH_NAME, edgeDefinitions, options); + } + + @After + public void teardown() { + for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, + VERTEX_COL_4}) { + final ArangoCollection c = db.collection(collection); + if (c.exists()) { + c.truncate(); + } + } + } + + @Test + public void exists() { + assertThat(db.graph(GRAPH_NAME).exists(), is(true)); + assertThat(db.graph(GRAPH_NAME + "no").exists(), is(false)); + } + + @Test + public void create() { + try { + final GraphEntity result = db.graph(GRAPH_NAME + "_1").create(null); + assertThat(result, is(notNullValue())); + assertThat(result.getName(), is(GRAPH_NAME + "_1")); + } finally { + db.graph(GRAPH_NAME + "_1").drop(); + } + } + + @Test + public void createWithReplicationAndMinReplicationFactor() { + try { + final Collection edgeDefinitions = new ArrayList(); + final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, new GraphCreateOptions().isSmart(true).replicationFactor(2).minReplicationFactor(2)); + assertThat(graph, is(notNullValue())); + assertThat(graph.getName(), is(GRAPH_NAME + "_1")); + assertThat(graph.getMinReplicationFactor(), is(2)); + assertThat(graph.getReplicationFactor(), is(2)); + } finally { + db.graph(GRAPH_NAME + "_1").drop(); + } + } + + @Test + public void getGraphs() { + final Collection graphs = db.getGraphs(); + assertThat(graphs, is(notNullValue())); + assertThat(graphs.size(), is(1)); + assertThat(graphs.iterator().next().getName(), is(GRAPH_NAME)); + } + + @Test + public void getInfo() { + final GraphEntity info = db.graph(GRAPH_NAME).getInfo(); + assertThat(info, is(notNullValue())); + assertThat(info.getName(), is(GRAPH_NAME)); + assertThat(info.getEdgeDefinitions().size(), is(2)); + final Iterator iterator = info.getEdgeDefinitions().iterator(); + final EdgeDefinition e1 = iterator.next(); + assertThat(e1.getCollection(), is(EDGE_COL_1)); + assertThat(e1.getFrom(), hasItem(VERTEX_COL_1)); + assertThat(e1.getTo(), hasItem(VERTEX_COL_2)); + final EdgeDefinition e2 = iterator.next(); + assertThat(e2.getCollection(), is(EDGE_COL_2)); + assertThat(e2.getFrom(), hasItem(VERTEX_COL_2)); + assertThat(e2.getTo(), hasItems(VERTEX_COL_1, VERTEX_COL_3)); + assertThat(info.getOrphanCollections(), is(empty())); + + if (arangoDB.getRole() != ServerRole.SINGLE) { + for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2}) { + final CollectionPropertiesEntity properties = db.collection(collection).getProperties(); + assertThat(properties.getReplicationFactor(), is(REPLICATION_FACTOR)); + assertThat(properties.getNumberOfShards(), is(NUMBER_OF_SHARDS)); + } + } + } + + @Test + public void getVertexCollections() { + final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections(); + assertThat(vertexCollections, is(notNullValue())); + assertThat(vertexCollections.size(), is(3)); + assertThat(vertexCollections, hasItems(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3)); + } + + @Test + public void addVertexCollection() { + final GraphEntity graph = db.graph(GRAPH_NAME).addVertexCollection(VERTEX_COL_4); + assertThat(graph, is(notNullValue())); + final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections(); + assertThat(vertexCollections, hasItems(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4)); + setup(); + } + + @Test + public void getEdgeCollections() { + final Collection edgeCollections = db.graph(GRAPH_NAME).getEdgeDefinitions(); + assertThat(edgeCollections, is(notNullValue())); + assertThat(edgeCollections.size(), is(2)); + assertThat(edgeCollections, hasItems(EDGE_COL_1, EDGE_COL_2)); + } + + @Test + public void addEdgeDefinition() { + final GraphEntity graph = db.graph(GRAPH_NAME) + .addEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_3).from(VERTEX_COL_1).to(VERTEX_COL_2)); + assertThat(graph, is(notNullValue())); + final Collection edgeDefinitions = graph.getEdgeDefinitions(); + assertThat(edgeDefinitions.size(), is(3)); + int count = 0; + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_3)) { + count++; + } + } + assertThat(count, is(1)); + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_3)) { + assertThat(e.getFrom(), hasItem(VERTEX_COL_1)); + assertThat(e.getTo(), hasItem(VERTEX_COL_2)); + } + } + if (arangoDB.getRole() != ServerRole.SINGLE) { + final CollectionPropertiesEntity properties = db.collection(EDGE_COL_3).getProperties(); + assertThat(properties.getReplicationFactor(), is(REPLICATION_FACTOR)); + assertThat(properties.getNumberOfShards(), is(NUMBER_OF_SHARDS)); + } + setup(); + } + + @Test + public void replaceEdgeDefinition() { + final GraphEntity graph = db.graph(GRAPH_NAME) + .replaceEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_3).to(VERTEX_COL_4)); + final Collection edgeDefinitions = graph.getEdgeDefinitions(); + assertThat(edgeDefinitions.size(), is(2)); + int count = 0; + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_1)) { + count++; + } + } + assertThat(count, is(1)); + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_1)) { + assertThat(e.getFrom(), hasItem(VERTEX_COL_3)); + assertThat(e.getTo(), hasItem(VERTEX_COL_4)); + } + } + setup(); + } + + @Test + public void removeEdgeDefinition() { + final GraphEntity graph = db.graph(GRAPH_NAME).removeEdgeDefinition(EDGE_COL_1); + final Collection edgeDefinitions = graph.getEdgeDefinitions(); + assertThat(edgeDefinitions.size(), is(1)); + assertThat(edgeDefinitions.iterator().next().getCollection(), is(EDGE_COL_2)); + setup(); + } + + @Test + public void smartGraph() { + + if (arangoDB.getVersion().getLicense() == License.ENTERPRISE) { + + for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4}) { + try { + db.collection(collection).drop(); + } catch (final ArangoDBException e) { + + } + } + try { + db.graph(GRAPH_NAME).drop(); + } catch (final ArangoDBException e) { + } + + final Collection edgeDefinitions = new ArrayList(); + + edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); + edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); + + final GraphEntity graph = db.createGraph(GRAPH_NAME, edgeDefinitions, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); + + assertThat(graph, is(notNullValue())); + assertThat(graph.getIsSmart(), is(true)); + assertThat(graph.getSmartGraphAttribute(), is("test")); + assertThat(graph.getNumberOfShards(), is(2)); + } + } + + @Test + public void drop() { + final String edgeCollection = "edge_drop"; + final String vertexCollection = "vertex_drop"; + final String graph = GRAPH_NAME + "_drop"; + final GraphEntity result = db.graph(graph).create(Collections + .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))); + assertThat(result, is(notNullValue())); + db.graph(graph).drop(); + assertThat(db.collection(edgeCollection).exists(), is(true)); + assertThat(db.collection(vertexCollection).exists(), is(true)); + } + + @Test + public void dropPlusDropCollections() { + final String edgeCollection = "edge_dropC"; + final String vertexCollection = "vertex_dropC"; + final String graph = GRAPH_NAME + "_dropC"; + final GraphEntity result = db.graph(graph).create(Collections + .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))); + assertThat(result, is(notNullValue())); + db.graph(graph).drop(true); + assertThat(db.collection(edgeCollection).exists(), is(false)); + assertThat(db.collection(vertexCollection).exists(), is(false)); + } + + @AfterClass + public static void shutdown() { + db.drop(); + } }