/************************************************************************
* Copyright (c) 2015-2016 IoT-Solutions e.U.
*
* 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.
************************************************************************/
package test.concurrency;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import iot.jcypher.concurrency.Locking;
import iot.jcypher.database.DBAccessFactory;
import iot.jcypher.database.DBProperties;
import iot.jcypher.database.DBType;
import iot.jcypher.database.IDBAccess;
import iot.jcypher.domain.DomainAccessFactory;
import iot.jcypher.domain.IDomainAccess;
import iot.jcypher.graph.GrNode;
import iot.jcypher.graph.GrProperty;
import iot.jcypher.graph.GrRelation;
import iot.jcypher.graph.Graph;
import iot.jcypher.query.JcQuery;
import iot.jcypher.query.JcQueryResult;
import iot.jcypher.query.api.IClause;
import iot.jcypher.query.factories.clause.MATCH;
import iot.jcypher.query.factories.clause.OPTIONAL_MATCH;
import iot.jcypher.query.factories.clause.RETURN;
import iot.jcypher.query.factories.clause.START;
import iot.jcypher.query.factories.clause.WHERE;
import iot.jcypher.query.result.JcError;
import iot.jcypher.query.result.JcResultException;
import iot.jcypher.query.values.JcNode;
import iot.jcypher.query.values.JcRelation;
import iot.jcypher.util.QueriesPrintObserver;
import iot.jcypher.util.QueriesPrintObserver.ContentToObserve;
import iot.jcypher.util.QueriesPrintObserver.QueryToObserve;
import java.util.List;
import java.util.Properties;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import test.AbstractTestSuite;
import test.DBAccessSettings;
import test.domainquery.Population;
import test.domainquery.model.Person;
import test.domainquery.model.PointOfContact;
public class ConcurrencyGraphTest extends AbstractTestSuite {
public static IDBAccess dbAccess;
public static String domainName;
private static List<Object> storedDomainObjects;
@Test
public void testGraphRelConcurrency_08() {
// second client deletes relation
// first client tries to delete same relation
Locking lockingStrategy = Locking.OPTIMISTIC;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult res = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, res, 0,0,0,0);
/******* second client loading j_smith ******/
QResult res2 = queryResult2(j_smithId, lockingStrategy, dbAccess);
long relId = res2.relations.get(0).getId();
/******* second client modifying relation ******/
res2.relations.get(0).remove();
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeletedRelation(relId, dbAccess);
assertTrue(del);
/******* first client deleting relation ******/
assertEquals(relId, res.relations.get(0).getId());
res.relations.get(0).remove();
errors = res.graph.store();
assertTrue(!errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
JcError error = errors.get(0);
assertEquals("Optimistic locking failed (an element was deleted by another client)", error.getMessage());
//throw new JcResultException(errors);
}
del = testDeletedRelation(relId, dbAccess);
assertTrue(del);
return;
}
@Test
public void testGraphRelConcurrency_07() {
// second client deletes relation
// first client tries to delete same relation
Locking lockingStrategy = Locking.NONE;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult res = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, res, 0,0,0,0);
/******* second client loading j_smith ******/
QResult res2 = queryResult2(j_smithId, lockingStrategy, dbAccess);
long relId = res2.relations.get(0).getId();
/******* second client modifying relation ******/
res2.relations.get(0).remove();
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeletedRelation(relId, dbAccess);
assertTrue(del);
/******* first client deleting relation ******/
assertEquals(relId, res.relations.get(0).getId());
res.relations.get(0).remove();
errors = res.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
del = testDeletedRelation(relId, dbAccess);
assertTrue(del);
return;
}
@Test
public void testGraphRelConcurrency_06() {
// second client changes relation
// first client tries to delete same relation
Locking lockingStrategy = Locking.OPTIMISTIC;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult res = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, res, 0,0,0,0);
/******* second client loading j_smith ******/
QResult res2 = queryResult2(j_smithId, lockingStrategy, dbAccess);
long relId = res2.relations.get(0).getId();
/******* second client modifying relation ******/
GrProperty prop2 = res2.relations.get(0).getProperty("key");
prop2.setValue(100);
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 1,0,0,0);
assertEquals(100, ((Number)pocRes.relations.get(0).getProperty("key").getValue()).intValue());
/******* first client deleting relation ******/
assertEquals(relId, res.relations.get(0).getId());
res.relations.get(0).remove();
errors = res.graph.store();
assertTrue(!errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
JcError error = errors.get(0);
assertEquals("Optimistic locking failed (an element was changed by another client)", error.getMessage());
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 1,0,0,0);
assertEquals(100, ((Number)pocRes.relations.get(0).getProperty("key").getValue()).intValue());
return;
}
@Test
public void testGraphRelConcurrency_05() {
// second client changes relation
// first client tries to delete same relation
Locking lockingStrategy = Locking.NONE;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult res = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, res, 0,0,0,0);
/******* second client loading j_smith ******/
QResult res2 = queryResult2(j_smithId, lockingStrategy, dbAccess);
long relId = res2.relations.get(0).getId();
/******* second client modifying relation ******/
GrProperty prop2 = res2.relations.get(0).getProperty("key");
prop2.setValue(100);
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 1,0,0,0);
assertEquals(100, ((Number)pocRes.relations.get(0).getProperty("key").getValue()).intValue());
/******* first client deleting relation ******/
assertEquals(relId, res.relations.get(0).getId());
res.relations.get(0).remove();
errors = res.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeletedRelation(res.relations.get(0).getId(), dbAccess);
assertTrue(del);
return;
}
@Test
public void testGraphRelConcurrency_04() {
// second client deletes relation
// first client tries to change same relation
Locking lockingStrategy = Locking.OPTIMISTIC;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult res = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, res, 0,0,0,0);
/******* second client loading j_smith ******/
QResult res2 = queryResult2(j_smithId, lockingStrategy, dbAccess);
/******* second client deleting relation ******/
long relId = res2.relations.get(0).getId();
res2.relations.get(0).remove();
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeletedRelation(relId, dbAccess);
assertTrue(del);
/******* first client modifying relation ******/
assertEquals(relId, res.relations.get(0).getId());
GrProperty prop = res.relations.get(0).getProperty("key");
prop.setValue(101);
errors = res.graph.store();
assertTrue(!errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
JcError error = errors.get(0);
assertEquals("Optimistic locking failed (an element was deleted by another client)", error.getMessage());
assertEquals("element id: " + res.relations.get(0).getId(), error.getAdditionalInfo());
//throw new JcResultException(errors);
}
del = testDeletedRelation(res.relations.get(0).getId(), dbAccess);
assertTrue(del);
return;
}
/**
* Note: Locking.NONE: changes to a changed relation will be applied,
* changes to a deleted relation will be ignored, the relation is still deleted
*/
@Test
public void testGraphRelConcurrency_03() {
// second client deletes relation
// first client tries to change same relation
Locking lockingStrategy = Locking.NONE;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult res = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, res, 0,0,0,0);
/******* second client loading j_smith ******/
QResult res2 = queryResult2(j_smithId, lockingStrategy, dbAccess);
long relId = res2.relations.get(0).getId();
/******* second client deleting relation ******/
res2.relations.get(0).remove();
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeletedRelation(relId, dbAccess);
assertTrue(del);
/******* first client modifying relation ******/
assertEquals(relId, res.relations.get(0).getId());
GrProperty prop = res.relations.get(0).getProperty("key");
prop.setValue(101);
errors = res.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
del = testDeletedRelation(res.relations.get(0).getId(), dbAccess);
assertTrue(del);
return;
}
@Test
public void testGraphRelConcurrency_02() {
// second client changes relation
// first client tries to change same relation
Locking lockingStrategy = Locking.OPTIMISTIC;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult res = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, res, 0,0,0,0);
/******* second client loading j_smith ******/
QResult res2 = queryResult2(j_smithId, lockingStrategy, dbAccess);
long relId = res2.relations.get(0).getId();
/******* second client modifying relation ******/
GrProperty prop2 = res2.relations.get(0).getProperty("key");
prop2.setValue(100);
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 1,0,0,0);
assertEquals(100, ((Number)pocRes.relations.get(0).getProperty("key").getValue()).intValue());
/******* first client modifying relation ******/
assertEquals(relId, res.relations.get(0).getId());
GrProperty prop = res.relations.get(0).getProperty("key");
prop.setValue(101);
errors = res.graph.store();
assertTrue(!errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
JcError error = errors.get(0);
assertEquals("Optimistic locking failed (an element was changed by another client)", error.getMessage());
assertEquals("element id: " + res.relations.get(0).getId(), error.getAdditionalInfo());
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 1,0,0,0);
assertEquals(100, ((Number)pocRes.relations.get(0).getProperty("key").getValue()).intValue());
return;
}
@Test
public void testGraphRelConcurrency_01() {
// second client changes relation
// first client tries to change same relation
Locking lockingStrategy = Locking.NONE;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult res = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, res, 0,0,0,0);
/******* second client loading j_smith ******/
QResult res2 = queryResult2(j_smithId, lockingStrategy, dbAccess);
long relId = res2.relations.get(0).getId();
/******* second client modifying relation ******/
GrProperty prop2 = res2.relations.get(0).getProperty("key");
prop2.setValue(100);
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 1,0,0,0);
assertEquals(100, ((Number)pocRes.relations.get(0).getProperty("key").getValue()).intValue());
/******* first client modifying relation ******/
assertEquals(relId, res.relations.get(0).getId());
GrProperty prop = res.relations.get(0).getProperty("key");
prop.setValue(101);
errors = res.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 2,0,0,0);
assertEquals(101, ((Number)pocRes.relations.get(0).getProperty("key").getValue()).intValue());
return;
}
@Test
public void testGraphConcurrency_08() {
// second client deletes node
// first client tries to delete same node
Locking lockingStrategy = Locking.OPTIMISTIC;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 0,0,0,0);
QResult res = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client loading j_smith ******/
QResult res2 = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client deletes j_smith ******/
for (GrRelation relat : res2.relations) {
relat.remove();
}
res2.node.remove();
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
/******* first client trying to delete j_smith ******/
for (GrRelation relat : res.relations) {
relat.remove();
}
res.node.remove();
errors = res.graph.store();
assertTrue(!errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
JcError error = errors.get(0);
assertEquals("Optimistic locking failed (an element was deleted by another client)", error.getMessage());
//throw new JcResultException(errors);
}
del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
return;
}
@Test
public void testGraphConcurrency_07() {
// second client deletes node
// first client tries to delete same node
Locking lockingStrategy = Locking.NONE;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 0,0,0,0);
QResult res = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client loading j_smith ******/
QResult res2 = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client deletes j_smith ******/
for (GrRelation relat : res2.relations) {
relat.remove();
}
res2.node.remove();
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
/******* first client trying to delete j_smith ******/
for (GrRelation relat : res.relations) {
relat.remove();
}
res.node.remove();
errors = res.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
return;
}
@Test
public void testGraphConcurrency_06() {
// second client changes node
// first client tries to delete same node
Locking lockingStrategy = Locking.OPTIMISTIC;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 0,0,0,0);
QResult res = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client loading j_smith ******/
QResult res2 = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client modifying j_smith ******/
GrProperty prop2 = res2.node.getProperty("firstName");
prop2.setValue("Johnny");
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(1, pocRes, 0,0,0,0);
assertEquals("Johnny", pocRes.node.getProperty("firstName").getValue().toString());
/******* first client trying to delete j_smith ******/
for (GrRelation relat : res.relations) {
relat.remove();
}
res.node.remove();
errors = res.graph.store();
assertTrue(!errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
JcError error = errors.get(0);
assertEquals("Optimistic locking failed (an element was changed by another client)", error.getMessage());
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(1, pocRes, 0,0,0,0);
assertEquals("Johnny", pocRes.node.getProperty("firstName").getValue().toString());
return;
}
@Test
public void testGraphConcurrency_05() {
// second client changes node
// first client tries to delete same node
Locking lockingStrategy = Locking.NONE;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 0,0,0,0);
QResult res = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client loading j_smith ******/
QResult res2 = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client modifying j_smith ******/
GrProperty prop2 = res2.node.getProperty("firstName");
prop2.setValue("Johnny");
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(1, pocRes, 0,0,0,0);
assertEquals("Johnny", pocRes.node.getProperty("firstName").getValue().toString());
/******* first client trying to delete j_smith ******/
for (GrRelation relat : res.relations) {
relat.remove();
}
res.node.remove();
errors = res.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
return;
}
@Test
public void testGraphConcurrency_04() {
// second client deletes node (+ adjacent relations)
// first client tries to change same node
Locking lockingStrategy = Locking.OPTIMISTIC;
initDB(lockingStrategy);
/******* modifying j_smith to increment version ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 0,0,0,0);
List<PointOfContact> pocs = j_smith.getPointsOfContact();
PointOfContact poc = pocs.remove(0);
pocs.add(poc);
j_smith.setFirstName("Johnny");
List<JcError> errors = da1.store(j_smith);
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(1, pocRes, 1,1,1,1);
/******* first client loading j_smith ******/
QResult res = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client loading j_smith ******/
QResult res2 = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client deleting j_smith ******/
for (GrRelation relat : res2.relations) {
relat.remove();
}
res2.node.remove();
errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
/******* first client modifying j_smith ******/
GrProperty prop = res.node.getProperty("firstName");
prop.setValue("Johnny Boy");
errors = res.graph.store();
assertTrue(!errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
JcError error = errors.get(0);
assertEquals("Optimistic locking failed (an element was deleted by another client)", error.getMessage());
assertEquals("element id: " + j_smithId, error.getAdditionalInfo());
//throw new JcResultException(errors);
}
del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
return;
}
/**
* Note: Locking.NONE: changes to a changed node will be applied,
* changes to a deleted node will be ignored, the node is still deleted
*/
@Test
public void testGraphConcurrency_03() {
// second client deletes node (+ adjacent relations)
// first client tries to change same node
Locking lockingStrategy = Locking.NONE;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 0,0,0,0);
QResult res = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client loading j_smith ******/
QResult res2 = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client deleting j_smith ******/
for (GrRelation relat : res2.relations) {
relat.remove();
}
res2.node.remove();
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
boolean del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
/******* first client modifying j_smith ******/
GrProperty prop = res.node.getProperty("firstName");
prop.setValue("Johnny Boy");
errors = res.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
del = testDeleted(j_smithId, dbAccess);
assertTrue(del);
return;
}
@Test
public void testGraphConcurrency_02() {
// second client changes node
// first client tries to change same node
Locking lockingStrategy = Locking.OPTIMISTIC;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 0,0,0,0);
QResult res = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client loading j_smith ******/
QResult res2 = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client modifying j_smith ******/
GrProperty prop2 = res2.node.getProperty("firstName");
prop2.setValue("Johnny");
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(1, pocRes, 0,0,0,0);
assertEquals("Johnny", pocRes.node.getProperty("firstName").getValue().toString());
/******* first client modifying j_smith ******/
GrProperty prop = res.node.getProperty("firstName");
prop.setValue("Johnny Boy");
errors = res.graph.store();
assertTrue(!errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
JcError error = errors.get(0);
assertEquals("Optimistic locking failed (an element was changed by another client)", error.getMessage());
assertEquals("element id: " + j_smithId, error.getAdditionalInfo());
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(1, pocRes, 0,0,0,0);
assertEquals("Johnny", pocRes.node.getProperty("firstName").getValue().toString());
return;
}
@Test
public void testGraphConcurrency_01() {
// second client changes node
// first client tries to change same node
Locking lockingStrategy = Locking.NONE;
initDB(lockingStrategy);
/******* first client loading j_smith ******/
IDomainAccess da1 = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
Person j_smith = ConcurrencyTest.findPerson(da1, "Smith", "John");
long j_smithId = da1.getSyncInfo(j_smith).getId();
QResult pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(0, pocRes, 0,0,0,0);
QResult res = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client loading j_smith ******/
QResult res2 = queryResult(j_smithId, lockingStrategy, dbAccess);
/******* second client modifying j_smith ******/
GrProperty prop2 = res2.node.getProperty("firstName");
prop2.setValue("Johnny");
List<JcError> errors = res2.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(1, pocRes, 0,0,0,0);
assertEquals("Johnny", pocRes.node.getProperty("firstName").getValue().toString());
/******* first client modifying j_smith ******/
GrProperty prop = res.node.getProperty("firstName");
prop.setValue("Johnny Boy");
errors = res.graph.store();
assertTrue(errors.isEmpty());
if (errors.size() > 0) {
printErrors(errors);
//throw new JcResultException(errors);
}
pocRes = queryResult2(j_smithId, lockingStrategy, dbAccess);
assertVersions(2, pocRes, 0,0,0,0);
assertEquals("Johnny Boy", pocRes.node.getProperty("firstName").getValue().toString());
return;
}
@BeforeClass
public static void before() {
domainName = "QTEST-DOMAIN";
dbAccess = DBAccessSettings.createDBAccess();
// init db
Population population = new Population();
storedDomainObjects = population.createPopulation();
QueriesPrintObserver.addOutputStream(System.out);
QueriesPrintObserver.addToEnabledQueries(QueryToObserve.COUNT_QUERY, ContentToObserve.CYPHER);
QueriesPrintObserver.addToEnabledQueries(QueryToObserve.DOM_QUERY, ContentToObserve.CYPHER);
QueriesPrintObserver.addToEnabledQueries(QueryToObserve.UPDATE_QUERY, ContentToObserve.CYPHER);
QueriesPrintObserver.addToEnabledQueries(QueryToObserve.CLOSURE_QUERY, ContentToObserve.CYPHER);
}
@AfterClass
public static void after() {
if (dbAccess != null) {
dbAccess.close();
dbAccess = null;
}
storedDomainObjects = null;
QueriesPrintObserver.removeAllEnabledQueries();
QueriesPrintObserver.removeAllOutputStreams();
}
private static void initDB(Locking lockingStrategy) {
List<JcError> errors = dbAccess.clearDatabase();
if (errors.size() > 0) {
printErrors(errors);
throw new JcResultException(errors);
}
IDomainAccess da = DomainAccessFactory.createDomainAccess(dbAccess, domainName)
.setLockingStrategy(lockingStrategy);
errors = da.store(storedDomainObjects);
if (errors.size() > 0) {
printErrors(errors);
throw new JcResultException(errors);
}
}
/**
* return a node, the node's relations, and the node's adjacent nodes.
* @param personId
* @param lockingStrategy
* @return
*/
static QResult queryResult(long personId, Locking lockingStrategy, IDBAccess dba) {
QResult res = new QResult();
JcNode persN = new JcNode("a");
JcRelation pocsR = new JcRelation("r");
JcNode pocsN = new JcNode("b");
IClause[] clauses = new IClause[] {
MATCH.node(persN).relation(pocsR).node(pocsN),
WHERE.valueOf(persN.id()).EQUALS(personId),
RETURN.ALL()
};
JcQuery query = new JcQuery();
query.setClauses(clauses);
//String qStr = print(query, Format.PRETTY_1);
JcQueryResult result = dba.execute(query);
res.node = result.resultOf(persN).get(0);
res.relations = result.resultOf(pocsR);
res.relatedNodes = result.resultOf(pocsN);
res.graph = result.getGraph().setLockingStrategy(lockingStrategy);
return res;
}
/**
* return a node, the node's pointOfContact relations, and the node's PointsOfContact.
* @param personId
* @param lockingStrategy
* @return
*/
static QResult queryResult2(long personId, Locking lockingStrategy, IDBAccess dba) {
QResult res = new QResult();
JcNode persN = new JcNode("a");
JcRelation pocsR = new JcRelation("r");
JcNode pocsN = new JcNode("b");
IClause[] clauses = new IClause[] {
MATCH.node(persN).relation().type("pointsOfContact").out().node()
.relation(pocsR).out().node(pocsN),
WHERE.valueOf(persN.id()).EQUALS(personId),
RETURN.ALL()
};
JcQuery query = new JcQuery();
query.setClauses(clauses);
//String qStr = print(query, Format.PRETTY_1);
JcQueryResult result = dba.execute(query);
res.node = result.resultOf(persN).get(0);
res.relations = result.resultOf(pocsR);
res.relatedNodes = result.resultOf(pocsN);
res.graph = result.getGraph().setLockingStrategy(lockingStrategy);
return res;
}
static boolean testDeleted(long nodeId, IDBAccess dba) {
JcNode a = new JcNode("a");
IClause[] clauses = new IClause[] {
OPTIONAL_MATCH.node(a),
WHERE.valueOf(a.id()).EQUALS(nodeId),
RETURN.ALL()
};
JcQuery query = new JcQuery();
query.setClauses(clauses);
//String qStr = print(query, Format.PRETTY_1);
JcQueryResult result = dba.execute(query);
List<GrNode> ares = result.resultOf(a);
return (ares.size() == 0) || (ares.size() == 1 && ares.get(0) == null);
}
static boolean testDeletedRelation(long relId, IDBAccess dba) {
JcRelation a = new JcRelation("a");
IClause[] clauses = new IClause[] {
START.relation(a).byId(relId),
RETURN.ALL()
};
JcQuery query = new JcQuery();
query.setClauses(clauses);
//String qStr = print(query, Format.PRETTY_1);
JcQueryResult result = dba.execute(query);
try {
List<GrRelation> ares = result.resultOf(a);
return ares.size() == 0 || (ares.size() == 1 && ares.get(0) == null);
} catch (IndexOutOfBoundsException e) {
return true;
}
}
static void assertVersions(int nodeVersion, QResult qResult, int... relationVersions) {
assertEquals(relationVersions.length, qResult.relations.size());
assertEquals(nodeVersion, ((Number)qResult.node.getProperty("_c_version_").getValue()).intValue());
for (int i = 0; i < relationVersions.length; i++) {
assertEquals("at index: " + i, relationVersions[i], ((Number)qResult.relations.get(i).getProperty("_c_version_").getValue()).intValue());
}
}
/*********************************/
static class QResult {
GrNode node;
List<GrRelation> relations;
private List<GrNode> relatedNodes;
Graph graph;
}
}