use of org.janusgraph.graphdb.transaction.lock.CombinerLock 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.graphdb.transaction.lock.CombinerLock in project janusgraph by JanusGraph.
the class StandardJanusGraphTx method getUniquenessLock.
private TransactionLock getUniquenessLock(final JanusGraphVertex out, final InternalRelationType type, final Object in) {
Multiplicity multiplicity = type.multiplicity();
TransactionLock uniqueLock = FakeLock.INSTANCE;
if (config.hasVerifyUniqueness() && multiplicity.isConstrained()) {
uniqueLock = null;
if (multiplicity == Multiplicity.SIMPLE) {
uniqueLock = getLock(out, type, in);
} else {
for (Direction dir : Direction.proper) {
if (multiplicity.isUnique(dir)) {
TransactionLock lock = getLock(dir == Direction.OUT ? out : in, type, dir);
if (uniqueLock == null)
uniqueLock = lock;
else
uniqueLock = new CombinerLock(uniqueLock, lock, times);
}
}
}
}
assert uniqueLock != null;
return uniqueLock;
}
Aggregations