
com.tinkerpop.blueprints.TransactionalGraphTestSuite Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of blueprints-test Show documentation
Show all versions of blueprints-test Show documentation
Reusable test suites for Blueprints
The newest version!
package com.tinkerpop.blueprints;
import com.tinkerpop.blueprints.impls.GraphTest;
import com.tinkerpop.blueprints.util.TransactionRetryHelper;
import com.tinkerpop.blueprints.util.TransactionRetryStrategy;
import com.tinkerpop.blueprints.util.TransactionWork;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONMode;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONUtility;
import org.codehaus.jettison.json.JSONObject;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
public class TransactionalGraphTestSuite extends TestSuite {
public TransactionalGraphTestSuite() {
}
public TransactionalGraphTestSuite(final GraphTest graphTest) {
super(graphTest);
}
public void testTrue() {
assertTrue(true);
}
public void testRepeatedTransactionStopException() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
graph.commit();
graph.rollback();
graph.commit();
graph.shutdown();
}
public void testAutoStartTransaction() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
Vertex v1 = graph.addVertex(null);
vertexCount(graph, 1);
assertEquals(v1.getId(), graph.getVertex(v1.getId()).getId());
graph.commit();
vertexCount(graph, 1);
assertEquals(v1.getId(), graph.getVertex(v1.getId()).getId());
graph.shutdown();
}
public void testTransactionsForVertices() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
List vin = new ArrayList();
List vout = new ArrayList();
vin.add(graph.addVertex(null));
graph.commit();
vertexCount(graph, 1);
containsVertices(graph, vin);
this.stopWatch();
vout.add(graph.addVertex(null));
vertexCount(graph, 2);
containsVertices(graph, vin);
containsVertices(graph, vout);
graph.rollback();
containsVertices(graph, vin);
vertexCount(graph, 1);
printPerformance(graph.toString(), 1, "vertex not added in failed transaction", this.stopWatch());
this.stopWatch();
vin.add(graph.addVertex(null));
vertexCount(graph, 2);
containsVertices(graph, vin);
graph.commit();
printPerformance(graph.toString(), 1, "vertex added in successful transaction", this.stopWatch());
vertexCount(graph, 2);
containsVertices(graph, vin);
graph.shutdown();
}
public void testBasicVertexEdgeTransactions() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
Vertex v = graph.addVertex(null);
graph.addEdge(null, v, v, graphTest.convertLabel("self"));
assertEquals(count(v.getEdges(Direction.IN)), 1);
assertEquals(count(v.getEdges(Direction.OUT)), 1);
assertEquals(v.getEdges(Direction.IN).iterator().next(), v.getEdges(Direction.OUT).iterator().next());
graph.commit();
v = graph.getVertex(v.getId());
assertEquals(count(v.getEdges(Direction.IN)), 1);
assertEquals(count(v.getEdges(Direction.OUT)), 1);
assertEquals(v.getEdges(Direction.IN).iterator().next(), v.getEdges(Direction.OUT).iterator().next());
graph.commit();
v = graph.getVertex(v.getId());
assertEquals(count(v.getVertices(Direction.IN)), 1);
assertEquals(count(v.getVertices(Direction.OUT)), 1);
assertEquals(v.getVertices(Direction.IN).iterator().next(), v.getVertices(Direction.OUT).iterator().next());
graph.commit();
graph.shutdown();
}
public void testBruteVertexTransactions() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
List vin = new ArrayList(), vout = new ArrayList();
this.stopWatch();
for (int i = 0; i < 100; i++) {
vin.add(graph.addVertex(null));
graph.commit();
}
printPerformance(graph.toString(), 100, "vertices added in 100 successful transactions", this.stopWatch());
vertexCount(graph, 100);
containsVertices(graph, vin);
this.stopWatch();
for (int i = 0; i < 100; i++) {
vout.add(graph.addVertex(null));
graph.rollback();
}
printPerformance(graph.toString(), 100, "vertices not added in 100 failed transactions", this.stopWatch());
vertexCount(graph, 100);
containsVertices(graph, vin);
graph.rollback();
vertexCount(graph, 100);
containsVertices(graph, vin);
this.stopWatch();
for (int i = 0; i < 100; i++) {
vin.add(graph.addVertex(null));
}
vertexCount(graph, 200);
containsVertices(graph, vin);
graph.commit();
printPerformance(graph.toString(), 100, "vertices added in 1 successful transactions", this.stopWatch());
vertexCount(graph, 200);
containsVertices(graph, vin);
this.stopWatch();
for (int i = 0; i < 100; i++) {
vout.add(graph.addVertex(null));
}
vertexCount(graph, 300);
containsVertices(graph, vin);
containsVertices(graph, vout.subList(100, 200));
graph.rollback();
printPerformance(graph.toString(), 100, "vertices not added in 1 failed transactions", this.stopWatch());
vertexCount(graph, 200);
containsVertices(graph, vin);
graph.shutdown();
}
public void testTransactionsForEdges() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
Vertex v = graph.addVertex(null);
Vertex u = graph.addVertex(null);
graph.commit();
this.stopWatch();
Edge e = graph.addEdge(null, graph.getVertex(v.getId()), graph.getVertex(u.getId()), graphTest.convertLabel("test"));
assertEquals(graph.getVertex(v.getId()), v);
assertEquals(graph.getVertex(u.getId()), u);
if (graph.getFeatures().supportsEdgeRetrieval)
assertEquals(graph.getEdge(e.getId()), e);
vertexCount(graph, 2);
edgeCount(graph, 1);
graph.rollback();
printPerformance(graph.toString(), 1, "edge not added in failed transaction (w/ iteration)", this.stopWatch());
assertEquals(graph.getVertex(v.getId()), v);
assertEquals(graph.getVertex(u.getId()), u);
if (graph.getFeatures().supportsEdgeRetrieval)
assertNull(graph.getEdge(e.getId()));
if (graph.getFeatures().supportsVertexIteration)
assertEquals(count(graph.getVertices()), 2);
if (graph.getFeatures().supportsEdgeIteration)
assertEquals(count(graph.getEdges()), 0);
this.stopWatch();
e = graph.addEdge(null, graph.getVertex(u.getId()), graph.getVertex(v.getId()), graphTest.convertLabel("test"));
assertEquals(graph.getVertex(v.getId()), v);
assertEquals(graph.getVertex(u.getId()), u);
if (graph.getFeatures().supportsEdgeRetrieval)
assertEquals(graph.getEdge(e.getId()), e);
if (graph.getFeatures().supportsVertexIteration)
assertEquals(count(graph.getVertices()), 2);
if (graph.getFeatures().supportsEdgeIteration)
assertEquals(count(graph.getEdges()), 1);
assertEquals(e, getOnlyElement(graph.getVertex(u.getId()).getEdges(Direction.OUT)));
graph.commit();
printPerformance(graph.toString(), 1, "edge added in successful transaction (w/ iteration)", this.stopWatch());
if (graph.getFeatures().supportsVertexIteration)
assertEquals(count(graph.getVertices()), 2);
if (graph.getFeatures().supportsEdgeIteration)
assertEquals(count(graph.getEdges()), 1);
assertEquals(graph.getVertex(v.getId()), v);
assertEquals(graph.getVertex(u.getId()), u);
if (graph.getFeatures().supportsEdgeRetrieval)
assertEquals(graph.getEdge(e.getId()), e);
assertEquals(e, getOnlyElement(graph.getVertex(u.getId()).getEdges(Direction.OUT)));
graph.shutdown();
}
public void testBruteEdgeTransactions() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
this.stopWatch();
for (int i = 0; i < 100; i++) {
Vertex v = graph.addVertex(null);
Vertex u = graph.addVertex(null);
graph.addEdge(null, v, u, graphTest.convertLabel("test"));
graph.commit();
}
printPerformance(graph.toString(), 100, "edges added in 100 successful transactions (2 vertices added for each edge)", this.stopWatch());
vertexCount(graph, 200);
edgeCount(graph, 100);
this.stopWatch();
for (int i = 0; i < 100; i++) {
Vertex v = graph.addVertex(null);
Vertex u = graph.addVertex(null);
graph.addEdge(null, v, u, graphTest.convertLabel("test"));
graph.rollback();
}
printPerformance(graph.toString(), 100, "edges not added in 100 failed transactions (2 vertices added for each edge)", this.stopWatch());
vertexCount(graph, 200);
edgeCount(graph, 100);
this.stopWatch();
for (int i = 0; i < 100; i++) {
Vertex v = graph.addVertex(null);
Vertex u = graph.addVertex(null);
graph.addEdge(null, v, u, graphTest.convertLabel("test"));
}
vertexCount(graph, 400);
edgeCount(graph, 200);
graph.commit();
printPerformance(graph.toString(), 100, "edges added in 1 successful transactions (2 vertices added for each edge)", this.stopWatch());
vertexCount(graph, 400);
edgeCount(graph, 200);
this.stopWatch();
for (int i = 0; i < 100; i++) {
Vertex v = graph.addVertex(null);
Vertex u = graph.addVertex(null);
graph.addEdge(null, v, u, graphTest.convertLabel("test"));
}
vertexCount(graph, 600);
edgeCount(graph, 300);
graph.rollback();
printPerformance(graph.toString(), 100, "edges not added in 1 failed transactions (2 vertices added for each edge)", this.stopWatch());
vertexCount(graph, 400);
edgeCount(graph, 200);
graph.shutdown();
}
public void testPropertyTransactions() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsElementProperties()) {
this.stopWatch();
Vertex v = graph.addVertex(null);
Object id = v.getId();
v.setProperty("name", "marko");
graph.commit();
printPerformance(graph.toString(), 1, "vertex added with string property in a successful transaction", this.stopWatch());
this.stopWatch();
v = graph.getVertex(id);
assertNotNull(v);
assertEquals(v.getProperty("name"), "marko");
v.setProperty("age", 30);
assertEquals(v.getProperty("age"), 30);
graph.rollback();
printPerformance(graph.toString(), 1, "integer property not added in a failed transaction", this.stopWatch());
this.stopWatch();
v = graph.getVertex(id);
assertNotNull(v);
assertEquals(v.getProperty("name"), "marko");
assertNull(v.getProperty("age"));
printPerformance(graph.toString(), 2, "vertex properties checked in a successful transaction", this.stopWatch());
Edge edge = graph.addEdge(null, v, graph.addVertex(null), "test");
edgeCount(graph, 1);
graph.commit();
edgeCount(graph, 1);
edge = getOnlyElement(graph.getVertex(v.getId()).getEdges(Direction.OUT));
assertNotNull(edge);
this.stopWatch();
edge.setProperty("transaction-1", "success");
assertEquals(edge.getProperty("transaction-1"), "success");
graph.commit();
printPerformance(graph.toString(), 1, "edge property added and checked in a successful transaction", this.stopWatch());
edge = getOnlyElement(graph.getVertex(v.getId()).getEdges(Direction.OUT));
assertEquals(edge.getProperty("transaction-1"), "success");
this.stopWatch();
edge.setProperty("transaction-2", "failure");
assertEquals(edge.getProperty("transaction-1"), "success");
assertEquals(edge.getProperty("transaction-2"), "failure");
graph.rollback();
printPerformance(graph.toString(), 1, "edge property added and checked in a failed transaction", this.stopWatch());
edge = getOnlyElement(graph.getVertex(v.getId()).getEdges(Direction.OUT));
assertEquals(edge.getProperty("transaction-1"), "success");
assertNull(edge.getProperty("transaction-2"));
}
graph.shutdown();
}
public void testIndexTransactions() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsVertexIndex) {
this.stopWatch();
Index index = ((IndexableGraph) graph).createIndex("txIdx", Vertex.class);
Vertex v = graph.addVertex(null);
Object id = v.getId();
v.setProperty("name", "marko");
index.put("name", "marko", v);
vertexCount(graph, 1);
v = getOnlyElement(((IndexableGraph) graph).getIndex("txIdx", Vertex.class).get("name", "marko"));
assertEquals(v.getId(), id);
assertEquals(v.getProperty("name"), "marko");
graph.commit();
printPerformance(graph.toString(), 1, "vertex added and retrieved from index in a successful transaction", this.stopWatch());
this.stopWatch();
vertexCount(graph, 1);
v = getOnlyElement(((IndexableGraph) graph).getIndex("txIdx", Vertex.class).get("name", "marko"));
assertEquals(v.getId(), id);
assertEquals(v.getProperty("name"), "marko");
printPerformance(graph.toString(), 1, "vertex retrieved from index outside successful transaction", this.stopWatch());
this.stopWatch();
v = graph.addVertex(null);
v.setProperty("name", "pavel");
index.put("name", "pavel", v);
vertexCount(graph, 2);
v = getOnlyElement(((IndexableGraph) graph).getIndex("txIdx", Vertex.class).get("name", "marko"));
assertEquals(v.getProperty("name"), "marko");
v = getOnlyElement(((IndexableGraph) graph).getIndex("txIdx", Vertex.class).get("name", "pavel"));
assertEquals(v.getProperty("name"), "pavel");
graph.rollback();
printPerformance(graph.toString(), 1, "vertex not added in a failed transaction", this.stopWatch());
this.stopWatch();
vertexCount(graph, 1);
assertEquals(count(((IndexableGraph) graph).getIndex("txIdx", Vertex.class).get("name", "pavel")), 0);
printPerformance(graph.toString(), 1, "vertex not retrieved in a successful transaction", this.stopWatch());
v = getOnlyElement(((IndexableGraph) graph).getIndex("txIdx", Vertex.class).get("name", "marko"));
assertEquals(v.getProperty("name"), "marko");
}
graph.shutdown();
}
public void testAutomaticSuccessfulTransactionOnShutdown() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().isPersistent && graph.getFeatures().supportsVertexProperties) {
Vertex v = graph.addVertex(null);
Object id = v.getId();
v.setProperty("count", "1");
v.setProperty("count", "2");
graph.shutdown();
graph = (TransactionalGraph) graphTest.generateGraph();
Vertex reloadedV = graph.getVertex(id);
assertEquals("2", reloadedV.getProperty("count"));
}
graph.shutdown();
}
public void testVertexCountOnPreTransactionCommit() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
Vertex v1 = graph.addVertex(null);
graph.commit();
vertexCount(graph, 1);
Vertex v2 = graph.addVertex(null);
v1 = graph.getVertex(v1.getId());
graph.addEdge(null, v1, v2, graphTest.convertLabel("friend"));
vertexCount(graph, 2);
graph.commit();
vertexCount(graph, 2);
graph.shutdown();
}
public void testVertexPropertiesOnPreTransactionCommit() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsVertexProperties) {
Vertex v1 = graph.addVertex(null);
v1.setProperty("name", "marko");
assertEquals(1, v1.getPropertyKeys().size());
assertTrue(v1.getPropertyKeys().contains("name"));
assertEquals("marko", v1.getProperty("name"));
graph.commit();
assertEquals("marko", v1.getProperty("name"));
}
graph.shutdown();
}
public void testBulkTransactionsOnEdges() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
for (int i = 0; i < 5; i++) {
graph.addEdge(null, graph.addVertex(null), graph.addVertex(null), graphTest.convertLabel("test"));
}
edgeCount(graph, 5);
graph.rollback();
edgeCount(graph, 0);
for (int i = 0; i < 4; i++) {
graph.addEdge(null, graph.addVertex(null), graph.addVertex(null), graphTest.convertLabel("test"));
}
edgeCount(graph, 4);
graph.rollback();
edgeCount(graph, 0);
for (int i = 0; i < 3; i++) {
graph.addEdge(null, graph.addVertex(null), graph.addVertex(null), graphTest.convertLabel("test"));
}
edgeCount(graph, 3);
graph.commit();
edgeCount(graph, 3);
graph.shutdown();
}
public void testCompetingThreads() {
final TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsThreadIsolatedTransactions) {
int totalThreads = 250;
final AtomicInteger vertices = new AtomicInteger(0);
final AtomicInteger edges = new AtomicInteger(0);
final AtomicInteger completedThreads = new AtomicInteger(0);
for (int i = 0; i < totalThreads; i++) {
new Thread() {
public void run() {
Random random = new Random();
if (random.nextBoolean()) {
Vertex a = graph.addVertex(null);
Vertex b = graph.addVertex(null);
Edge e = graph.addEdge(null, a, b, graphTest.convertLabel("friend"));
if (graph.getFeatures().supportsElementProperties()) {
a.setProperty("test", this.getId());
b.setProperty("blah", random.nextFloat());
e.setProperty("bloop", random.nextInt());
}
vertices.getAndAdd(2);
edges.getAndAdd(1);
graph.commit();
} else {
Vertex a = graph.addVertex(null);
Vertex b = graph.addVertex(null);
Edge e = graph.addEdge(null, a, b, graphTest.convertLabel("friend"));
if (graph.getFeatures().supportsElementProperties()) {
a.setProperty("test", this.getId());
b.setProperty("blah", random.nextFloat());
e.setProperty("bloop", random.nextInt());
}
if (random.nextBoolean()) {
graph.commit();
vertices.getAndAdd(2);
edges.getAndAdd(1);
} else {
graph.rollback();
}
}
completedThreads.getAndAdd(1);
}
}.start();
}
while (completedThreads.get() < totalThreads) {
}
assertEquals(completedThreads.get(), 250);
edgeCount(graph, edges.get());
vertexCount(graph, vertices.get());
}
graph.shutdown();
}
public void testCompetingThreadsOnMultipleDbInstances() throws Exception {
// the idea behind this test is to simulate a rexster environment where two graphs of the same type
// are being mutated by multiple threads. the test itself surfaced issues with OrientDB in such
// an environment and remains relevant for any graph that might be exposed through rexster.
graphTest.dropGraph("first");
graphTest.dropGraph("second");
final TransactionalGraph graph1 = (TransactionalGraph) graphTest.generateGraph("first");
final TransactionalGraph graph2 = (TransactionalGraph) graphTest.generateGraph("second");
final Thread threadModFirstGraph = new Thread() {
public void run() {
final Vertex v = graph1.addVertex(null);
// v.setProperty("name", "stephen");
graph1.commit();
}
};
threadModFirstGraph.start();
threadModFirstGraph.join();
final Thread threadReadBothGraphs = new Thread() {
public void run() {
int counter = 0;
for (Vertex v : graph1.getVertices()) {
counter++;
}
assertEquals(1, counter);
counter = 0;
for (Vertex v : graph2.getVertices()) {
counter++;
}
assertEquals(0, counter);
}
};
threadReadBothGraphs.start();
threadReadBothGraphs.join();
graph1.shutdown();
graphTest.dropGraph("first");
graph2.shutdown();
graphTest.dropGraph("second");
}
public void testTransactionIsolationCommitCheck() throws Exception {
// the purpose of this test is to simulate rexster access to a graph instance, where one thread modifies
// the graph and a separate thread cannot affect the transaction of the first
final TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsThreadIsolatedTransactions) {
final CountDownLatch latchCommittedInOtherThread = new CountDownLatch(1);
final CountDownLatch latchCommitInOtherThread = new CountDownLatch(1);
// this thread starts a transaction then waits while the second thread tries to commit it.
final Thread threadTxStarter = new Thread() {
public void run() {
final Vertex v = graph.addVertex(null);
// System.out.println("added vertex");
latchCommitInOtherThread.countDown();
try {
latchCommittedInOtherThread.await();
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
graph.rollback();
// there should be no vertices here
// System.out.println("reading vertex before tx");
assertFalse(graph.getVertices().iterator().hasNext());
// System.out.println("read vertex before tx");
}
};
threadTxStarter.start();
// this thread tries to commit the transaction started in the first thread above.
final Thread threadTryCommitTx = new Thread() {
public void run() {
try {
latchCommitInOtherThread.await();
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
// try to commit the other transaction
graph.commit();
latchCommittedInOtherThread.countDown();
}
};
threadTryCommitTx.start();
threadTxStarter.join();
threadTryCommitTx.join();
}
graph.shutdown();
}
public void testRemoveInTransaction() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
edgeCount(graph, 0);
Vertex v1 = graph.addVertex(null);
Object v1id = v1.getId();
Vertex v2 = graph.addVertex(null);
graph.addEdge(null, v1, v2, graphTest.convertLabel("test-edge"));
graph.commit();
edgeCount(graph, 1);
Edge e1 = getOnlyElement(graph.getVertex(v1id).getEdges(Direction.OUT));
assertNotNull(e1);
graph.removeEdge(e1);
edgeCount(graph, 0);
assertNull(getOnlyElement(graph.getVertex(v1id).getEdges(Direction.OUT)));
graph.rollback();
edgeCount(graph, 1);
e1 = getOnlyElement(graph.getVertex(v1id).getEdges(Direction.OUT));
assertNotNull(e1);
graph.removeEdge(e1);
graph.commit();
edgeCount(graph, 0);
assertNull(getOnlyElement(graph.getVertex(v1id).getEdges(Direction.OUT)));
graph.shutdown();
}
public void testTransactionGraphHelperFireAndForget() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
// first fail the tx
new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
graph.addVertex(null);
throw new Exception("fail");
}
}).build().fireAndForget();
vertexCount(graph, 0);
// this tx will work
List vin = new ArrayList();
TransactionRetryHelper trh = new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
return graph.addVertex(null);
}
}).build();
vin.add(trh.fireAndForget());
vertexCount(graph, 1);
containsVertices(graph, vin);
graph.shutdown();
}
public void testTransactionGraphHelperOneAndDone() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
// first fail the tx
try {
new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
graph.addVertex(null);
throw new Exception("fail");
}
}).build().oneAndDone();
} catch (Exception ex) {
assertEquals("fail", ex.getCause().getMessage());
}
vertexCount(graph, 0);
// this tx will work
List vin = new ArrayList();
vin.add(new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
return graph.addVertex(null);
}
}).build().oneAndDone());
vertexCount(graph, 1);
containsVertices(graph, vin);
graph.shutdown();
}
public void testTransactionGraphHelperExponentialBackoff() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
// first fail the tx
final AtomicInteger attempts = new AtomicInteger(0);
try {
new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
graph.addVertex(null);
attempts.incrementAndGet();
throw new Exception("fail");
}
}).build().exponentialBackoff();
} catch (Exception ex) {
assertEquals("fail", ex.getCause().getMessage());
}
assertEquals(TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES, attempts.get());
vertexCount(graph, 0);
// this tx will work after several tries
final AtomicInteger tries = new AtomicInteger(0);
List vin = new ArrayList();
vin.add(new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
final int tryNumber = tries.incrementAndGet();
if (tryNumber == TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES - 2)
return graph.addVertex(null);
else
throw new Exception("fail");
}
}).build().exponentialBackoff());
vertexCount(graph, 1);
containsVertices(graph, vin);
graph.shutdown();
}
public void testTransactionGraphHelperExponentialBackoffWithExceptionChecks() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
Set exceptions = new HashSet() {{
add(IllegalStateException.class);
}};
// immediately fail the tx
final AtomicInteger attempts = new AtomicInteger(0);
try {
new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
graph.addVertex(null);
attempts.incrementAndGet();
throw new Exception("fail");
}
}).build().exponentialBackoff(TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES, 20, exceptions);
} catch (Exception ex) {
assertEquals("fail", ex.getCause().getMessage());
}
assertEquals(1, attempts.get());
vertexCount(graph, 0);
// this tx will fail after a few tries due to exception raised not in set
final AtomicInteger setOfTries = new AtomicInteger(0);
try {
new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
final int tryNumber = setOfTries.incrementAndGet();
if (tryNumber == TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES - 2)
throw new Exception("fail");
else
throw new IllegalStateException("fail");
}
}).build().exponentialBackoff(TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES, 20, exceptions);
} catch (Exception ex) {
assertEquals("fail", ex.getCause().getMessage());
}
assertEquals(TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES - 2, setOfTries.get());
vertexCount(graph, 0);
// this tx will work after several tries
final AtomicInteger tries = new AtomicInteger(0);
List vin = new ArrayList();
vin.add(new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
final int tryNumber = tries.incrementAndGet();
if (tryNumber == TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES - 2)
return graph.addVertex(null);
else
throw new IllegalStateException("fail");
}
}).build().exponentialBackoff(TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES, 20, exceptions));
vertexCount(graph, 1);
containsVertices(graph, vin);
graph.shutdown();
}
public void testTransactionGraphHelperRetry() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
// first fail the tx
final AtomicInteger attempts = new AtomicInteger(0);
try {
new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
graph.addVertex(null);
attempts.incrementAndGet();
throw new Exception("fail");
}
}).build().retry();
} catch (Exception ex) {
assertEquals("fail", ex.getCause().getMessage());
}
assertEquals(TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES, attempts.get());
vertexCount(graph, 0);
// this tx will work after several tries
final AtomicInteger tries = new AtomicInteger(0);
List vin = new ArrayList();
vin.add(new TransactionRetryHelper.Builder(graph).perform(new TransactionWork() {
@Override
public Vertex execute(final TransactionalGraph graph) throws Exception {
final int tryNumber = tries.incrementAndGet();
if (tryNumber == TransactionRetryStrategy.DelayedRetry.DEFAULT_TRIES - 2)
return graph.addVertex(null);
else
throw new Exception("fail");
}
}).build().retry());
vertexCount(graph, 1);
containsVertices(graph, vin);
graph.shutdown();
}
public void testRemovedElementsInvisibleInTransaction() {
TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
try {
boolean supportsVertexIteration = graph.getFeatures().supportsVertexIteration;
boolean supportsEdgeIteration = graph.getFeatures().supportsEdgeIteration;
if (supportsEdgeIteration) {
assertEquals(0, count(graph.getEdges()));
}
Vertex v1 = graph.addVertex(null);
Vertex v2 = graph.addVertex(null);
Edge e1 = graph.addEdge(null, v1, v2, graphTest.convertLabel("link"));
if (supportsVertexIteration) {
assertEquals(2, count(graph.getVertices()));
}
if (supportsEdgeIteration) {
assertEquals(1, count(graph.getEdges()));
}
graph.commit();
if (supportsVertexIteration) {
assertEquals(2, count(graph.getVertices()));
}
if (supportsEdgeIteration) {
assertEquals(1, count(graph.getEdges()));
}
graph.removeEdge(e1);
// We have removed an edge and not yet committed the change.
// However, the edge should appear to be removed until the end of the transaction.
if (supportsVertexIteration) {
assertEquals(2, count(graph.getVertices()));
}
if (supportsEdgeIteration) {
assertEquals(0, count(graph.getEdges()));
}
graph.removeVertex(v1);
if (supportsVertexIteration) {
assertEquals(1, count(graph.getVertices()));
}
graph.rollback();
if (supportsVertexIteration) {
assertEquals(2, count(graph.getVertices()));
}
if (supportsEdgeIteration) {
assertEquals(1, count(graph.getEdges()));
}
} finally {
graph.shutdown();
}
}
public void untestSimulateRexsterIntegrationTests() throws Exception {
// this test simulates the flow of rexster integration test. integration tests requests are generally not made
// in parallel, but it is expected each request they may be processed by different threads from a thread pool
// for each request. this test fails for orientdb given it's optimnisitc locking strategy.
final TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsKeyIndices) {
final String id = "_ID";
((KeyIndexableGraph) graph).createKeyIndex(id, Vertex.class);
final int numberOfVerticesToCreate = 100;
final Random rand = new Random(12356);
final List graphAssignedIds = new ArrayList();
final ExecutorService executorService = Executors.newFixedThreadPool(4);
for (int ix = 0; ix < numberOfVerticesToCreate; ix++) {
final int id1 = ix;
final int id2 = ix + numberOfVerticesToCreate + rand.nextInt();
// add a vertex and block for the thread to complete
executorService.submit(new Runnable() {
@Override
public void run() {
final Vertex v = graph.addVertex(null);
v.setProperty(id, id1);
graph.commit();
graphAssignedIds.add(v.getId().toString());
}
}).get();
if (ix > 0) {
// add a vertex and block for the thread to complete
executorService.submit(new Runnable() {
@Override
public void run() {
final Vertex v = graph.addVertex(null);
v.setProperty(id, id2);
graph.commit();
graphAssignedIds.add(v.getId().toString());
}
}).get();
// add an edge to two randomly selected vertices and block for the thread to complete. integration
// tests tend to fail here, so the code is replicated pretty closely to what is in rexster
// (i.e. serialization to JSON) even though that may have nothing to do with failures.
executorService.submit(new Runnable() {
@Override
public void run() {
final Vertex vActual1 = graph.getVertex(graphAssignedIds.get(rand.nextInt(graphAssignedIds.size())));
final Vertex vActual2 = graph.getVertex(graphAssignedIds.get(rand.nextInt(graphAssignedIds.size())));
final Edge e = graph.addEdge(null, vActual1, vActual2, "knows");
e.setProperty("weight", rand.nextFloat());
JSONObject elementJson = null;
try {
// just replicating rexster
elementJson = GraphSONUtility.jsonFromElement(e, null, GraphSONMode.NORMAL);
} catch (Exception ex) {
fail();
}
graph.commit();
try {
if (elementJson != null) {
// just replicating rexster
elementJson.put("_ID", e.getId());
}
} catch (Exception ex) {
fail();
}
}
}).get();
}
}
final Set ids = new HashSet();
for (final Vertex v : graph.getVertices()) {
ids.add(v.getId().toString());
}
for (final String idToRemove : ids) {
executorService.submit(new Runnable() {
@Override
public void run() {
final Vertex toRemove = graph.getVertex(idToRemove);
graph.removeVertex(toRemove);
graph.commit();
}
});
}
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
}
graph.shutdown();
}
public void untestSimulateRexsterIntegrationTestsWithRetries() throws Exception {
// this test simulates the flow of rexster integration test. integration tests requests are generally not made
// in parallel, but it is expected each request they may be processed by different threads from a thread pool
// for each request...this test is similar to the previous one but includes retries. in this case,
// orientdb passes, but this isn't currently how Rexster integration tests work.
final TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsKeyIndices && graph.getFeatures().supportsThreadIsolatedTransactions) {
final String id = "_ID";
((KeyIndexableGraph) graph).createKeyIndex(id, Vertex.class);
final int maxRetries = 10;
final int numberOfVerticesToCreate = 100;
final Random rand = new Random(12356);
final List graphAssignedIds = new ArrayList();
final ExecutorService executorService = Executors.newFixedThreadPool(4);
for (int ix = 0; ix < numberOfVerticesToCreate; ix++) {
final int id1 = ix;
final int id2 = ix + numberOfVerticesToCreate + rand.nextInt();
// add a vertex and block for the thread to complete
executorService.submit(new Runnable() {
@Override
public void run() {
final Vertex v = graph.addVertex(null);
v.setProperty(id, id1);
graph.commit();
graphAssignedIds.add(v.getId().toString());
}
}).get();
if (ix > 0) {
// add a vertex and block for the thread to complete
executorService.submit(new Runnable() {
@Override
public void run() {
final Vertex v = graph.addVertex(null);
v.setProperty(id, id2);
graph.commit();
graphAssignedIds.add(v.getId().toString());
}
}).get();
// add an edge to two randomly selected vertices and block for the thread to complete. integration
// tests tend to fail here, so the code is replicated pretty closely to what is in rexster
// (i.e. serialization to JSON) even though that may have nothing to do with failures.
executorService.submit(new Runnable() {
@Override
public void run() {
int v1 = rand.nextInt(graphAssignedIds.size());
int v2 = rand.nextInt(graphAssignedIds.size());
for (int retry = 0; retry < maxRetries; ++retry) {
try {
final Vertex vActual1 = graph.getVertex(graphAssignedIds.get(v1));
final Vertex vActual2 = graph.getVertex(graphAssignedIds.get(v2));
final Edge e = graph.addEdge(null, vActual1, vActual2, "knows");
e.setProperty("weight", rand.nextFloat());
// just replicating rexster
final JSONObject elementJson = GraphSONUtility.jsonFromElement(e, null, GraphSONMode.NORMAL);
graph.commit();
if (elementJson != null) {
// just replicating rexster
elementJson.put("_ID", e.getId());
}
break;
} catch (Exception ex) {
if (!ex.getClass().getSimpleName().equals("OConcurrentModificationException"))
fail(ex.getMessage());
}
}
}
}).get();
}
}
final Set ids = new HashSet();
for (final Vertex v : graph.getVertices()) {
ids.add(v.getId().toString());
}
for (final String idToRemove : ids) {
executorService.submit(new Runnable() {
@Override
public void run() {
final Vertex toRemove = graph.getVertex(idToRemove);
graph.removeVertex(toRemove);
graph.commit();
}
});
}
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
}
graph.shutdown();
}
public void untestTransactionVertexPropertiesAcrossThreads() throws Exception {
// the purpose of this test is to ensure that properties of a element are available prior to commit()
// across threads
final TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsThreadIsolatedTransactions) {
final AtomicReference v = new AtomicReference();
final Thread thread = new Thread() {
public void run() {
final Vertex vertex = graph.addVertex(null);
vertex.setProperty("name", "stephen");
v.set(vertex);
}
};
thread.start();
thread.join();
Set k = v.get().getPropertyKeys();
assertTrue(k.contains("name"));
assertEquals("stephen", v.get().getProperty("name"));
}
graph.shutdown();
}
public void untestTransactionIsolationWithSeparateThreads() throws Exception {
// the purpose of this test is to simulate rexster access to a graph instance, where one thread modifies
// the graph and a separate thread reads before the transaction is committed. the expectation is that
// the changes in the transaction are isolated to the thread that made the change and the second thread
// should not see the change until commit() in the first thread.
final TransactionalGraph graph = (TransactionalGraph) graphTest.generateGraph();
if (graph.getFeatures().supportsThreadIsolatedTransactions) {
final CountDownLatch latchCommit = new CountDownLatch(1);
final CountDownLatch latchFirstRead = new CountDownLatch(1);
final CountDownLatch latchSecondRead = new CountDownLatch(1);
final Thread threadMod = new Thread() {
public void run() {
final Vertex v = graph.addVertex(null);
//v.setProperty("name", "stephen");
// System.out.println("added vertex");
latchFirstRead.countDown();
try {
latchCommit.await();
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
graph.commit();
// System.out.println("committed vertex");
latchSecondRead.countDown();
}
};
threadMod.start();
final Thread threadRead = new Thread() {
public void run() {
try {
latchFirstRead.await();
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
// System.out.println("reading vertex before tx");
assertFalse(graph.getVertices().iterator().hasNext());
// System.out.println("read vertex before tx");
latchCommit.countDown();
try {
latchSecondRead.await();
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
// System.out.println("reading vertex after tx");
assertTrue(graph.getVertices().iterator().hasNext());
// System.out.println("read vertex after tx");
}
};
threadRead.start();
threadMod.join();
threadRead.join();
}
graph.shutdown();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy