> entry : futureMap.entrySet()){
128 | resultMap.put(entry.getKey(), entry.getValue().get());
129 | }
130 | } catch (InterruptedException | ExecutionException e) {
131 | throw new RuntimeException(e);
132 | }
133 | return resultMap;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/aerospike-storage-backend/src/main/java/com/playtika/janusgraph/aerospike/util/NamedThreadFactory.java:
--------------------------------------------------------------------------------
1 | package com.playtika.janusgraph.aerospike.util;
2 |
3 | import java.util.concurrent.ThreadFactory;
4 | import java.util.concurrent.atomic.AtomicInteger;
5 |
6 | /**
7 | * ThreadFactory with the ability to set the thread name prefix.
8 | * This class is exactly similar to
9 | * {@link java.util.concurrent.Executors#defaultThreadFactory()}
10 | * from JDK8, except for the thread naming feature.
11 | *
12 | *
13 | * The factory creates threads that have names on the form
14 | * prefix-N-thread-M, where prefix
15 | * is a string provided in the constructor, N is the sequence number of
16 | * this factory, and M is the sequence number of the thread created
17 | * by this factory.
18 | */
19 | public class NamedThreadFactory implements ThreadFactory {
20 |
21 | // Note: The source code for this class was based entirely on
22 | // Executors.DefaultThreadFactory class from the JDK8 source.
23 | // The only change made is the ability to configure the thread
24 | // name prefix.
25 |
26 | private final ThreadGroup group;
27 | private final AtomicInteger threadNumber = new AtomicInteger(1);
28 | private final String namePrefix;
29 |
30 | /**
31 | * Creates a new ThreadFactory where threads are created with a name prefix
32 | * of prefix
.
33 | *
34 | * @param prefix Thread name prefix. Never use a value of "pool" as in that
35 | * case you might as well have used
36 | * {@link java.util.concurrent.Executors#defaultThreadFactory()}.
37 | */
38 | public NamedThreadFactory(String groupName, String prefix) {
39 | SecurityManager s = System.getSecurityManager();
40 | ThreadGroup parent = (s != null) ? s.getThreadGroup()
41 | : Thread.currentThread().getThreadGroup();
42 | this.group = new ThreadGroup(parent, groupName);
43 | this.namePrefix = groupName+"-"+prefix+"-";
44 | }
45 |
46 |
47 | @Override
48 | public Thread newThread(Runnable r) {
49 | Thread t = new Thread(group, r,
50 | namePrefix + threadNumber.getAndIncrement(),
51 | 0);
52 | if (t.isDaemon()) {
53 | t.setDaemon(false);
54 | }
55 | if (t.getPriority() != Thread.NORM_PRIORITY) {
56 | t.setPriority(Thread.NORM_PRIORITY);
57 | }
58 | return t;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/aerospike-storage-backend/src/main/java/com/playtika/janusgraph/utility/GhostVertexRemover.java:
--------------------------------------------------------------------------------
1 | package com.playtika.janusgraph.utility;
2 |
3 | import com.google.common.base.Preconditions;
4 | import org.janusgraph.core.JanusGraphRelation;
5 | import org.janusgraph.core.JanusGraphVertex;
6 | import org.janusgraph.diskstorage.BackendException;
7 | import org.janusgraph.diskstorage.BaseTransactionConfig;
8 | import org.janusgraph.diskstorage.EntryList;
9 | import org.janusgraph.diskstorage.StaticBuffer;
10 | import org.janusgraph.diskstorage.keycolumnvalue.KeyColumnValueStore;
11 | import org.janusgraph.diskstorage.keycolumnvalue.KeyColumnValueStoreManager;
12 | import org.janusgraph.diskstorage.keycolumnvalue.KeySliceQuery;
13 | import org.janusgraph.diskstorage.keycolumnvalue.SliceQuery;
14 | import org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction;
15 | import org.janusgraph.diskstorage.util.BufferUtil;
16 | import org.janusgraph.graphdb.database.StandardJanusGraph;
17 | import org.janusgraph.graphdb.idmanagement.IDManager;
18 | import org.janusgraph.graphdb.transaction.StandardJanusGraphTx;
19 | import org.janusgraph.graphdb.vertices.CacheVertex;
20 |
21 | import java.util.Collections;
22 | import java.util.Iterator;
23 | import java.util.Map;
24 |
25 | import static org.janusgraph.diskstorage.Backend.EDGESTORE_NAME;
26 | import static org.janusgraph.graphdb.olap.VertexJobConverter.startTransaction;
27 |
28 | public class GhostVertexRemover {
29 |
30 | private static final SliceQuery EVERYTHING_QUERY = new SliceQuery(BufferUtil.zeroBuffer(1),BufferUtil.oneBuffer(4));
31 | private static final int RELATION_COUNT_LIMIT = 20000;
32 | private static final SliceQuery EVERYTHING_QUERY_LIMIT = EVERYTHING_QUERY.updateLimit(RELATION_COUNT_LIMIT);
33 |
34 | private final IDManager idManager;
35 | private final KeyColumnValueStore edgeStore;
36 | private final StandardJanusGraphTx tx;
37 |
38 | public GhostVertexRemover(StandardJanusGraph standardJanusGraph) throws BackendException {
39 | idManager = standardJanusGraph.getIDManager();
40 | KeyColumnValueStoreManager storeManager = (KeyColumnValueStoreManager)standardJanusGraph.getBackend().getStoreManager();
41 | edgeStore = storeManager.openDatabase(EDGESTORE_NAME);
42 | tx = startTransaction(standardJanusGraph);
43 | }
44 |
45 | public void removeGhostVertex(long vertexId) throws BackendException {
46 | StaticBuffer key = idManager.getKey(vertexId);
47 | EntryList entryList = edgeStore.getSlice(new KeySliceQuery(key, EVERYTHING_QUERY), new FakeStoreTransaction());
48 | Map entries = Collections.singletonMap(EVERYTHING_QUERY, entryList);
49 |
50 | assert entries.get(EVERYTHING_QUERY_LIMIT)!=null;
51 | final EntryList everything = entries.get(EVERYTHING_QUERY_LIMIT);
52 |
53 | JanusGraphVertex vertex = tx.getInternalVertex(vertexId);
54 | Preconditions.checkArgument(vertex instanceof CacheVertex,
55 | "The bounding transaction is not configured correctly");
56 | CacheVertex v = (CacheVertex)vertex;
57 | v.loadRelations(EVERYTHING_QUERY, input -> everything);
58 |
59 | int removedRelations = 0;
60 | Iterator iterator = v.query().noPartitionRestriction().relations().iterator();
61 | while (iterator.hasNext()) {
62 | iterator.next();
63 | iterator.remove();
64 | removedRelations++;
65 | }
66 | v.remove();
67 |
68 | tx.commit();
69 |
70 | }
71 |
72 | private static class FakeStoreTransaction implements StoreTransaction {
73 | @Override
74 | public void commit() {
75 | }
76 |
77 | @Override
78 | public void rollback() {
79 | }
80 |
81 | @Override
82 | public BaseTransactionConfig getConfiguration() {
83 | return null;
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/aerospike-storage-backend/src/main/java/com/playtika/janusgraph/utility/KeyExtractor.java:
--------------------------------------------------------------------------------
1 | package com.playtika.janusgraph.utility;
2 |
3 | import org.janusgraph.diskstorage.StaticBuffer;
4 | import org.janusgraph.graphdb.idmanagement.IDManager;
5 |
6 | import static com.playtika.janusgraph.aerospike.operations.batch.BatchUpdates.EDGE_STORE_NAME;
7 |
8 | public class KeyExtractor {
9 |
10 | private final IDManager idManager;
11 |
12 | public KeyExtractor(IDManager idManager) {
13 | this.idManager = idManager;
14 | }
15 |
16 | public long getVertexId(String storeName, StaticBuffer key) {
17 | long keyID;
18 | if(storeName.equals(EDGE_STORE_NAME)){
19 | keyID = idManager.getKeyID(key);
20 | } else {
21 | keyID = -1;
22 | }
23 | return keyID;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/aerospike-storage-backend/src/test/java/com/playtika/janusgraph/aerospike/AerospikeIDAuthorityCleanupTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 JanusGraph Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.playtika.janusgraph.aerospike;
16 |
17 | import com.aerospike.client.AerospikeClient;
18 | import com.aerospike.client.async.NioEventLoops;
19 | import com.playtika.janusgraph.aerospike.operations.AerospikeOperations;
20 | import com.playtika.janusgraph.aerospike.operations.ReadOperations;
21 | import org.janusgraph.diskstorage.EntryList;
22 | import org.janusgraph.diskstorage.IDAuthorityTest;
23 | import org.janusgraph.diskstorage.StaticBuffer;
24 | import org.janusgraph.diskstorage.configuration.WriteConfiguration;
25 | import org.janusgraph.diskstorage.keycolumnvalue.KeySliceQuery;
26 | import org.janusgraph.diskstorage.util.StaticArrayBuffer;
27 | import org.junit.ClassRule;
28 | import org.junit.Ignore;
29 | import org.junit.jupiter.api.Test;
30 | import org.junit.jupiter.params.ParameterizedTest;
31 | import org.junit.jupiter.params.provider.MethodSource;
32 | import org.testcontainers.containers.GenericContainer;
33 |
34 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.AEROSPIKE_PROPERTIES;
35 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeClient;
36 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeConfiguration;
37 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeContainer;
38 | import static com.playtika.janusgraph.aerospike.ConfigOptions.IDS_BLOCK_TTL;
39 | import static com.playtika.janusgraph.aerospike.operations.BasicOperations.AEROSPIKE_PREFIX;
40 | import static com.playtika.janusgraph.aerospike.operations.BasicOperations.BATCH_PREFIX;
41 | import static com.playtika.janusgraph.aerospike.operations.BasicOperations.executorService;
42 | import static com.playtika.janusgraph.aerospike.operations.IdsCleanupOperations.LOWER_SLICE;
43 | import static com.playtika.janusgraph.aerospike.operations.IdsCleanupOperations.PROTECTED_BLOCKS_AMOUNT;
44 | import static com.playtika.janusgraph.aerospike.operations.IdsCleanupOperations.UPPER_SLICE;
45 | import static org.assertj.core.api.Assertions.assertThat;
46 | import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.IDS_STORE_NAME;
47 | import static org.janusgraph.graphdb.configuration.JanusGraphConstants.JANUSGRAPH_ID_STORE_NAME;
48 |
49 |
50 | public class AerospikeIDAuthorityCleanupTest extends IDAuthorityTest {
51 | @ClassRule
52 | public static final GenericContainer container = getAerospikeContainer();
53 | public static final String IDS_STORE = "ids";
54 |
55 | @Test
56 | public void testSimpleIDAcquisition() throws Exception {
57 | super.testSimpleIDAcquisition((WriteConfiguration) configs().findFirst().get().get()[0]);
58 |
59 | ReadOperations readOperations = getReadOperations();
60 |
61 | StaticBuffer partitionKey = new StaticArrayBuffer(new byte[]{0, 0, 0, 0, 0, 0, 0, 0});
62 | EntryList entries = readOperations.getSlice(IDS_STORE, new KeySliceQuery(partitionKey, LOWER_SLICE, UPPER_SLICE));
63 | assertThat(entries).hasSize(PROTECTED_BLOCKS_AMOUNT);
64 | }
65 |
66 | @Override
67 | public AerospikeStoreManager openStorageManager() {
68 | return new AerospikeStoreManager(
69 | getAerospikeConfiguration(container)
70 | .set(IDS_STORE_NAME, IDS_STORE)
71 | .set(IDS_BLOCK_TTL, 1L));
72 | }
73 |
74 | public ReadOperations getReadOperations() {
75 | NioEventLoops eventLoops = new NioEventLoops();
76 | AerospikeClient client = getAerospikeClient(container, eventLoops);
77 | return new ReadOperations(
78 | new AerospikeOperations("test",
79 | AEROSPIKE_PROPERTIES.getNamespace(), AEROSPIKE_PROPERTIES.getNamespace(),
80 | JANUSGRAPH_ID_STORE_NAME,
81 | client,
82 | new AerospikePolicyProvider(getAerospikeConfiguration(container)),
83 | executorService(4, AEROSPIKE_PREFIX),
84 | executorService(4, 4, BATCH_PREFIX)),
85 | 1);
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/aerospike-storage-backend/src/test/java/com/playtika/janusgraph/aerospike/AerospikePolicyProviderTest.java:
--------------------------------------------------------------------------------
1 | package com.playtika.janusgraph.aerospike;
2 |
3 | import com.aerospike.client.policy.ClientPolicy;
4 | import org.junit.ClassRule;
5 | import org.junit.Test;
6 | import org.testcontainers.containers.GenericContainer;
7 |
8 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeConfiguration;
9 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeContainer;
10 | import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
11 |
12 | public class AerospikePolicyProviderTest {
13 |
14 | @ClassRule
15 | public static GenericContainer> container = getAerospikeContainer();
16 |
17 | @Test
18 | public void shouldReturnDefaultClientPolicyMaxSocketIdle() {
19 | var aerospikePolicyProvider = new AerospikePolicyProvider(
20 | getAerospikeConfiguration(container)
21 | );
22 |
23 | var clientPolicy = aerospikePolicyProvider.clientPolicy();
24 |
25 | assertThat(clientPolicy.maxSocketIdle)
26 | .isEqualTo(new ClientPolicy().maxSocketIdle);
27 | }
28 |
29 | @Test
30 | public void shouldOverrideClientPolicyMaxSocketIdle() {
31 | var clientMaxSocketIdle = 55;
32 | var aerospikePolicyProvider = new AerospikePolicyProvider(
33 | getAerospikeConfiguration(container)
34 | .set(ConfigOptions.AEROSPIKE_CLIENT_MAX_SOCKET_IDLE, clientMaxSocketIdle)
35 | );
36 |
37 | var clientPolicy = aerospikePolicyProvider.clientPolicy();
38 |
39 | assertThat(clientPolicy.maxSocketIdle).isEqualTo(clientMaxSocketIdle);
40 | }
41 | }
--------------------------------------------------------------------------------
/aerospike-storage-backend/src/test/java/com/playtika/janusgraph/aerospike/AerospikeStoreManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.playtika.janusgraph.aerospike;
2 |
3 | import org.janusgraph.diskstorage.BackendException;
4 | import org.junit.ClassRule;
5 | import org.junit.Test;
6 | import org.testcontainers.containers.GenericContainer;
7 |
8 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeConfiguration;
9 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeContainer;
10 |
11 | public class AerospikeStoreManagerTest {
12 |
13 | @ClassRule
14 | public static GenericContainer container = getAerospikeContainer();
15 |
16 | @Test
17 | public void shouldNotFailIfUdfsAlreadyRegistered() throws BackendException {
18 | AerospikeStoreManager manager = new AerospikeStoreManager(getAerospikeConfiguration(container));
19 | manager.close();
20 | manager = new AerospikeStoreManager(getAerospikeConfiguration(container));
21 | manager.close();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/aerospike-storage-backend/src/test/java/com/playtika/janusgraph/aerospike/AerospikeTestUtils.java:
--------------------------------------------------------------------------------
1 | package com.playtika.janusgraph.aerospike;
2 |
3 | import com.aerospike.AerospikeContainerUtils;
4 | import com.aerospike.AerospikeProperties;
5 | import com.aerospike.client.AerospikeClient;
6 | import com.aerospike.client.async.EventLoops;
7 | import com.aerospike.client.policy.ClientPolicy;
8 | import org.janusgraph.diskstorage.configuration.ModifiableConfiguration;
9 | import org.testcontainers.containers.GenericContainer;
10 |
11 | import static com.playtika.janusgraph.aerospike.AerospikeStoreManager.AEROSPIKE_BUFFER_SIZE;
12 | import static com.playtika.janusgraph.aerospike.ConfigOptions.GRAPH_PREFIX;
13 | import static com.playtika.janusgraph.aerospike.ConfigOptions.IDS_NAMESPACE;
14 | import static com.playtika.janusgraph.aerospike.ConfigOptions.NAMESPACE;
15 | import static com.playtika.janusgraph.aerospike.ConfigOptions.SCAN_PARALLELISM;
16 | import static com.playtika.janusgraph.aerospike.ConfigOptions.WAL_NAMESPACE;
17 | import static com.playtika.janusgraph.aerospike.util.AerospikeUtils.isEmptyNamespace;
18 | import static com.playtika.janusgraph.aerospike.util.AerospikeUtils.truncateNamespace;
19 | import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.BUFFER_SIZE;
20 | import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.STORAGE_BACKEND;
21 | import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.STORAGE_HOSTS;
22 | import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.STORAGE_PORT;
23 | import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.buildGraphConfiguration;
24 |
25 | public class AerospikeTestUtils {
26 |
27 | public static AerospikeProperties AEROSPIKE_PROPERTIES = new AerospikeProperties();
28 |
29 | public static GenericContainer getAerospikeContainer() {
30 | return AerospikeContainerUtils.startAerospikeContainer(AEROSPIKE_PROPERTIES);
31 | }
32 |
33 | public static AerospikeClient getAerospikeClient(GenericContainer aerospike, EventLoops eventLoops) {
34 | ClientPolicy clientPolicy = new ClientPolicy();
35 | clientPolicy.eventLoops = eventLoops;
36 | return new AerospikeClient(clientPolicy, aerospike.getContainerIpAddress(),
37 | aerospike.getMappedPort(AEROSPIKE_PROPERTIES.getPort()));
38 | }
39 |
40 | public static ModifiableConfiguration getAerospikeConfiguration(GenericContainer container) {
41 |
42 | ModifiableConfiguration config = buildGraphConfiguration();
43 | config.set(STORAGE_HOSTS, new String[]{container.getContainerIpAddress()});
44 | config.set(STORAGE_PORT, container.getMappedPort(AEROSPIKE_PROPERTIES.getPort()));
45 | config.set(STORAGE_BACKEND, "com.playtika.janusgraph.aerospike.AerospikeStoreManager");
46 | config.set(NAMESPACE, AEROSPIKE_PROPERTIES.getNamespace());
47 | config.set(IDS_NAMESPACE, AEROSPIKE_PROPERTIES.getNamespace());
48 | config.set(WAL_NAMESPACE, AEROSPIKE_PROPERTIES.getNamespace());
49 | config.set(GRAPH_PREFIX, "test");
50 | //!!! need to prevent small batches mutations as we use deferred locking approach !!!
51 | config.set(BUFFER_SIZE, AEROSPIKE_BUFFER_SIZE);
52 | config.set(SCAN_PARALLELISM, 100);
53 | return config;
54 | }
55 |
56 | static void deleteAllRecords(GenericContainer container) throws InterruptedException {
57 | try(AerospikeClient client = new AerospikeClient(container.getContainerIpAddress(),
58 | container.getMappedPort(AEROSPIKE_PROPERTIES.getPort()))) {
59 | while(!isEmptyNamespace(client, AEROSPIKE_PROPERTIES.getNamespace())){
60 | truncateNamespace(client, AEROSPIKE_PROPERTIES.getNamespace());
61 | Thread.sleep(100);
62 | }
63 | }
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/aerospike-storage-backend/src/test/java/com/playtika/janusgraph/aerospike/GraphOfTheGodsTest.java:
--------------------------------------------------------------------------------
1 | package com.playtika.janusgraph.aerospike;
2 |
3 | import com.playtika.janusgraph.trace.DebugJanusGraph;
4 | import org.apache.tinkerpop.gremlin.structure.Vertex;
5 | import org.janusgraph.core.JanusGraph;
6 | import org.janusgraph.core.JanusGraphFactory;
7 | import org.janusgraph.example.GraphOfTheGodsFactory;
8 | import org.junit.After;
9 | import org.junit.Before;
10 | import org.junit.Rule;
11 | import org.junit.Test;
12 | import org.testcontainers.containers.GenericContainer;
13 |
14 | import java.util.ArrayList;
15 | import java.util.Iterator;
16 | import java.util.List;
17 |
18 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeConfiguration;
19 | import static com.playtika.janusgraph.aerospike.AerospikeTestUtils.getAerospikeContainer;
20 | import static org.junit.Assert.assertEquals;
21 | import static org.junit.Assert.assertFalse;
22 | import static org.junit.Assert.assertNotNull;
23 | import static org.junit.Assert.assertTrue;
24 |
25 | public class GraphOfTheGodsTest {
26 |
27 | @Rule
28 | public GenericContainer container = getAerospikeContainer();
29 |
30 | JanusGraph graph;
31 |
32 | @Before
33 | public void buildGraph() {
34 | // graph = JanusGraphFactory.open(getAerospikeConfiguration(container));
35 | graph = DebugJanusGraph.open(getAerospikeConfiguration(container).getConfiguration());
36 |
37 | GraphOfTheGodsFactory.loadWithoutMixedIndex(graph, true);
38 | }
39 |
40 | @After
41 | public void tearDownGraph() {
42 | graph.close();
43 | }
44 |
45 | @Test
46 | public void testQueryByName() {
47 | final Iterator results = graph.traversal().V().has("name", "jupiter");
48 | assertTrue("Query should return a result", results.hasNext());
49 | final Vertex jupiter = results.next();
50 | assertNotNull("Query result should be non null", jupiter);
51 |
52 | jupiter.remove();
53 | graph.tx().commit();
54 |
55 | final Iterator resultsNew = graph.traversal().V().has("name", "jupiter");
56 | assertFalse("Query should not return a result", resultsNew.hasNext());
57 | }
58 |
59 | @Test
60 | public void testQueryAllVertices() {
61 | assertEquals("Expected the correct number of VERTICES",
62 | 12, graph.traversal().V().count().tryNext().get().longValue());
63 | }
64 |
65 | @Test
66 | public void testQueryAllEdges() {
67 | assertEquals("Expected the correct number of EDGES",
68 | 17, graph.traversal().E().count().tryNext().get().longValue());
69 | }
70 |
71 | @Test
72 | public void testRemoveAllVertices() {
73 | List