use of org.janusgraph.core.Cardinality in project janusgraph by JanusGraph.
the class JanusGraphTest method testConcurrentConsistencyEnforcement.
/**
* Execute multiple identical transactions concurrently. Note that since these transactions are running in the same process,
* {@link org.janusgraph.diskstorage.locking.LocalLockMediator} is used to resolve lock contentions. If there is only
* one lock needed in the whole transaction, exactly one transaction shall succeed and others shall fail due to local
* lock contention. If there is more than one lock needed in the transaction, at most one transaction shall succeed
* and others shall fail due to local lock contention.
* @throws Exception
*/
@Test
public void testConcurrentConsistencyEnforcement() throws Exception {
PropertyKey name = mgmt.makePropertyKey("name").dataType(String.class).cardinality(Cardinality.SINGLE).make();
JanusGraphIndex nameIndex = mgmt.buildIndex("name", Vertex.class).addKey(name).unique().buildCompositeIndex();
mgmt.setConsistency(nameIndex, ConsistencyModifier.LOCK);
EdgeLabel married = mgmt.makeEdgeLabel("married").multiplicity(Multiplicity.ONE2ONE).make();
mgmt.setConsistency(married, ConsistencyModifier.LOCK);
mgmt.makeEdgeLabel("friend").multiplicity(Multiplicity.MULTI).make();
finishSchema();
JanusGraphVertex baseV = tx.addVertex("name", "base");
newTx();
final long baseVid = getId(baseV);
final String nameA = "a", nameB = "b";
final int parallelThreads = 4;
// Only one lock is needed
int[] results = executeParallelTransactions(tx -> {
final JanusGraphVertex a = tx.addVertex();
final JanusGraphVertex base = getV(tx, baseVid);
base.addEdge("married", a);
}, parallelThreads);
int numOfSuccess = results[0];
int numOfLockContentions = results[1];
assertEquals(1, numOfSuccess);
assertEquals(parallelThreads - 1, numOfLockContentions);
// Two locks are needed. Note that the order of adding/modifying/deleting elements might not be consistent with
// the order of real mutations during commit. Thus, it can be the case that one thread gets one lock and another
// thread gets another, and both fail because they are unable to get the other lock.
results = executeParallelTransactions(tx -> {
tx.addVertex("name", nameA);
final JanusGraphVertex b = tx.addVertex("name", nameB);
b.addEdge("friend", b);
}, parallelThreads);
numOfSuccess = results[0];
numOfLockContentions = results[1];
assertTrue(numOfSuccess <= 1);
assertEquals(parallelThreads - numOfSuccess, numOfLockContentions);
newTx();
final long numA = Iterables.size(tx.query().has("name", nameA).vertices());
final long numB = Iterables.size(tx.query().has("name", nameB).vertices());
assertTrue(numA <= 1);
assertTrue(numB <= 1);
}
use of org.janusgraph.core.Cardinality in project janusgraph by JanusGraph.
the class ElasticSearchIndex method getParameters.
private List<Map<String, Object>> getParameters(KeyInformation.StoreRetriever storeRetriever, List<IndexEntry> entries, boolean deletion, Cardinality... cardinalitiesToSkip) {
Set<Cardinality> cardinalityToSkipSet = Sets.newHashSet(cardinalitiesToSkip);
List<Map<String, Object>> result = new ArrayList<>();
for (IndexEntry entry : entries) {
KeyInformation info = storeRetriever.get(entry.field);
if (cardinalityToSkipSet.contains(info.getCardinality())) {
continue;
}
Object jsValue = deletion && info.getCardinality() == Cardinality.SINGLE ? "" : convertToEsType(entry.value, Mapping.getMapping(info));
result.add(ImmutableMap.of("name", entry.field, "value", jsValue, "cardinality", info.getCardinality().name()));
if (hasDualStringMapping(info)) {
result.add(ImmutableMap.of("name", getDualMappingName(entry.field), "value", jsValue, "cardinality", info.getCardinality().name()));
}
}
return result;
}
use of org.janusgraph.core.Cardinality in project janusgraph by JanusGraph.
the class StandardJanusGraphTx method addProperty.
public JanusGraphVertexProperty addProperty(VertexProperty.Cardinality cardinality, JanusGraphVertex vertex, PropertyKey key, Object value, Long id) {
if (key.cardinality().convert() != cardinality && cardinality != VertexProperty.Cardinality.single)
throw new SchemaViolationException("Key is defined for %s cardinality which conflicts with specified: %s", key.cardinality(), cardinality);
verifyWriteAccess(vertex);
Preconditions.checkArgument(!(key instanceof ImplicitKey), "Cannot create a property of implicit type: %s", key.name());
vertex = ((InternalVertex) vertex).it();
Preconditions.checkNotNull(key);
checkPropertyConstraintForVertexOrCreatePropertyConstraint(vertex, key);
final Object normalizedValue = verifyAttribute(key, value);
Cardinality keyCardinality = key.cardinality();
// Determine unique indexes
final List<IndexLockTuple> uniqueIndexTuples = new ArrayList<>();
for (CompositeIndexType index : TypeUtil.getUniqueIndexes(key)) {
IndexSerializer.IndexRecords matches = IndexSerializer.indexMatches(vertex, index, key, normalizedValue);
for (Object[] match : matches.getRecordValues()) uniqueIndexTuples.add(new IndexLockTuple(index, match));
}
TransactionLock uniqueLock = getUniquenessLock(vertex, (InternalRelationType) key, normalizedValue);
// Add locks for unique indexes
for (IndexLockTuple lockTuple : uniqueIndexTuples) uniqueLock = new CombinerLock(uniqueLock, getLock(lockTuple), times);
uniqueLock.lock(LOCK_TIMEOUT);
try {
// //Check vertex-centric uniqueness -> this doesn't really make sense to check
// if (config.hasVerifyUniqueness()) {
// if (cardinality == Cardinality.SINGLE) {
// if (!Iterables.isEmpty(query(vertex).type(key).properties()))
// throw new SchemaViolationException("A property with the given key [%s] already exists on the vertex [%s] and the property key is defined as single-valued", key.name(), vertex);
// }
// if (cardinality == Cardinality.SET) {
// if (!Iterables.isEmpty(Iterables.filter(query(vertex).type(key).properties(), new Predicate<JanusGraphVertexProperty>() {
// @Override
// public boolean apply(@Nullable JanusGraphVertexProperty janusgraphProperty) {
// return normalizedValue.equals(janusgraphProperty.value());
// }
// })))
// throw new SchemaViolationException("A property with the given key [%s] and value [%s] already exists on the vertex and the property key is defined as set-valued", key.name(), normalizedValue);
// }
// }
long propId = id == null ? IDManager.getTemporaryRelationID(temporaryIds.nextID()) : id;
StandardVertexProperty prop = new StandardVertexProperty(propId, key, (InternalVertex) vertex, normalizedValue, ElementLifeCycle.New);
if (config.hasAssignIDsImmediately() && id == null)
graph.assignID(prop);
// Delete properties if the cardinality is restricted
if (cardinality == VertexProperty.Cardinality.single || cardinality == VertexProperty.Cardinality.set) {
Consumer<JanusGraphVertexProperty> propertyRemover = JanusGraphVertexProperty.getRemover(cardinality, normalizedValue);
if ((!config.hasVerifyUniqueness() || ((InternalRelationType) key).getConsistencyModifier() != ConsistencyModifier.LOCK) && !TypeUtil.hasAnyIndex(key) && cardinality == keyCardinality.convert()) {
// Only delete in-memory so as to not trigger a read from the database which isn't necessary because we will overwrite blindly
// We need to label the new property as "upsert", so that in case property deletion happens, we not only delete this new
// in-memory property, but also read from database to delete the old value (if exists)
((InternalVertex) vertex).getAddedRelations(p -> p.getType().equals(key)).forEach(p -> propertyRemover.accept((JanusGraphVertexProperty) p));
prop.setUpsert(true);
} else {
((InternalVertex) vertex).query().types(key).properties().forEach(propertyRemover);
}
}
// Check index uniqueness
if (config.hasVerifyUniqueness()) {
// Check all unique indexes
for (IndexLockTuple lockTuple : uniqueIndexTuples) {
if (!Iterables.isEmpty(IndexHelper.getQueryResults(lockTuple.getIndex(), lockTuple.getAll(), this)))
throw new SchemaViolationException("Adding this property for key [%s] and value [%s] violates a uniqueness constraint [%s]", key.name(), normalizedValue, lockTuple.getIndex());
}
}
connectRelation(prop);
return prop;
} finally {
uniqueLock.unlock();
}
}
use of org.janusgraph.core.Cardinality in project atlas by apache.
the class AtlasJanusGraphManagement method makePropertyKey.
@Override
public AtlasPropertyKey makePropertyKey(String propertyName, Class propertyClass, AtlasCardinality cardinality) {
if (cardinality.isMany()) {
newMultProperties.add(propertyName);
}
PropertyKeyMaker propertyKeyBuilder = management.makePropertyKey(propertyName).dataType(propertyClass);
if (cardinality != null) {
Cardinality janusCardinality = AtlasJanusObjectFactory.createCardinality(cardinality);
propertyKeyBuilder.cardinality(janusCardinality);
}
PropertyKey propertyKey = propertyKeyBuilder.make();
return GraphDbObjectFactory.createPropertyKey(propertyKey);
}
use of org.janusgraph.core.Cardinality in project janusgraph by JanusGraph.
the class ManagementSystem method createCompositeIndex.
private JanusGraphIndex createCompositeIndex(String indexName, ElementCategory elementCategory, boolean unique, JanusGraphSchemaType constraint, PropertyKey... keys) {
checkIndexName(indexName);
Preconditions.checkArgument(keys != null && keys.length > 0, "Need to provide keys to index [%s]", indexName);
Preconditions.checkArgument(!unique || elementCategory == ElementCategory.VERTEX, "Unique indexes can only be created on vertices [%s]", indexName);
boolean allSingleKeys = true;
boolean oneNewKey = false;
for (PropertyKey key : keys) {
Preconditions.checkArgument(key != null && key instanceof PropertyKeyVertex, "Need to provide valid keys: %s", key);
if (key.cardinality() != Cardinality.SINGLE)
allSingleKeys = false;
if (key.isNew())
oneNewKey = true;
else
updatedTypes.add((PropertyKeyVertex) key);
}
Cardinality indexCardinality;
if (unique)
indexCardinality = Cardinality.SINGLE;
else
indexCardinality = (allSingleKeys ? Cardinality.SET : Cardinality.LIST);
boolean canIndexBeEnabled = oneNewKey || (constraint != null && constraint.isNew());
TypeDefinitionMap def = new TypeDefinitionMap();
def.setValue(TypeDefinitionCategory.INTERNAL_INDEX, true);
def.setValue(TypeDefinitionCategory.ELEMENT_CATEGORY, elementCategory);
def.setValue(TypeDefinitionCategory.BACKING_INDEX, Token.INTERNAL_INDEX_NAME);
def.setValue(TypeDefinitionCategory.INDEXSTORE_NAME, indexName);
def.setValue(TypeDefinitionCategory.INDEX_CARDINALITY, indexCardinality);
def.setValue(TypeDefinitionCategory.STATUS, canIndexBeEnabled ? SchemaStatus.ENABLED : SchemaStatus.INSTALLED);
JanusGraphSchemaVertex indexVertex = transaction.makeSchemaVertex(JanusGraphSchemaCategory.GRAPHINDEX, indexName, def);
for (int i = 0; i < keys.length; i++) {
Parameter[] paras = { ParameterType.INDEX_POSITION.getParameter(i) };
addSchemaEdge(indexVertex, keys[i], TypeDefinitionCategory.INDEX_FIELD, paras);
}
Preconditions.checkArgument(constraint == null || (elementCategory.isValidConstraint(constraint) && constraint instanceof JanusGraphSchemaVertex));
if (constraint != null) {
addSchemaEdge(indexVertex, (JanusGraphSchemaVertex) constraint, TypeDefinitionCategory.INDEX_SCHEMA_CONSTRAINT, null);
}
updateSchemaVertex(indexVertex);
JanusGraphIndexWrapper index = new JanusGraphIndexWrapper(indexVertex.asIndexType());
if (!canIndexBeEnabled)
updateIndex(index, SchemaAction.REGISTER_INDEX);
return index;
}
Aggregations