private Lock getUniquenessLock(final TitanVertex start, final TitanType type, final Object end) { if (config.isSingleThreaded()) return FakeLock.INSTANCE; if (uniqueLocks == UNINITIALIZED_LOCKS) { Preconditions.checkArgument(!config.isSingleThreaded()); synchronized (this) { if (uniqueLocks == UNINITIALIZED_LOCKS) uniqueLocks = new ConcurrentHashMap<UniqueLockApplication, Lock>(); } } UniqueLockApplication la = new UniqueLockApplication(start, type, end); Lock lock = new ReentrantLock(); Lock existingLock = uniqueLocks.putIfAbsent(la, lock); if (existingLock == null) return lock; else return existingLock; }
public TitanProperty setProperty(TitanVertex vertex, final TitanKey key, Object value) { Preconditions.checkNotNull(key); Preconditions.checkArgument( key.isUnique(Direction.OUT), "Not an out-unique key: %s", key.getName()); Lock uniqueLock = FakeLock.INSTANCE; try { if (config.hasVerifyUniqueness()) { // Acquire uniqueness lock, remove and add uniqueLock = getUniquenessLock(vertex, key, value); uniqueLock.lock(); vertex.removeProperty(key); } else { // Only delete in-memory InternalVertex v = (InternalVertex) vertex; for (InternalRelation r : v.it() .getAddedRelations( new Predicate<InternalRelation>() { @Override public boolean apply(@Nullable InternalRelation p) { return p.getType().equals(key); } })) { r.remove(); } } return addPropertyInternal(vertex, key, value); } finally { uniqueLock.unlock(); } }
public void removeRelation(InternalRelation relation) { Preconditions.checkArgument(!relation.isRemoved()); relation = relation.it(); // Delete from Vertex for (int i = 0; i < relation.getLen(); i++) { relation.getVertex(i).removeRelation(relation); } // Update transaction data structures if (relation.isNew()) { addedRelations.remove(relation); if (isVertexIndexProperty(relation)) newVertexIndexEntries.remove((TitanProperty) relation); } else { Preconditions.checkArgument(relation.isLoaded()); if (deletedRelations == EMPTY_DELETED_RELATIONS) { if (config.isSingleThreaded()) { deletedRelations = new HashMap<Long, InternalRelation>(); } else { synchronized (this) { if (deletedRelations == EMPTY_DELETED_RELATIONS) deletedRelations = new ConcurrentHashMap<Long, InternalRelation>(); } } } deletedRelations.put(Long.valueOf(relation.getID()), relation); } }
public StandardTitanTx getNextTx() { Preconditions.checkArgument(isClosed()); if (!config.isThreadBound()) throw new IllegalStateException( "Cannot access element because its enclosing transaction is closed and unbound"); else return (StandardTitanTx) graph.getCurrentThreadTx(); }
@Override public TitanEdge addEdge(TitanVertex outVertex, TitanVertex inVertex, TitanLabel label) { verifyWriteAccess(outVertex, inVertex); outVertex = ((InternalVertex) outVertex).it(); inVertex = ((InternalVertex) inVertex).it(); Preconditions.checkNotNull(label); Lock uniqueLock = FakeLock.INSTANCE; if (config.hasVerifyUniqueness() && (label.isUnique(Direction.OUT) || label.isUnique(Direction.IN))) uniqueLock = getUniquenessLock(outVertex, label, inVertex); uniqueLock.lock(); try { // Check uniqueness if (config.hasVerifyUniqueness()) { if (label.isUnique(Direction.OUT)) { Preconditions.checkArgument( Iterables.isEmpty( query(outVertex) .includeHidden() .type(label) .direction(Direction.OUT) .titanEdges()), "An edge with the given type already exists on the out-vertex"); } if (label.isUnique(Direction.IN)) { Preconditions.checkArgument( Iterables.isEmpty( query(inVertex).includeHidden().type(label).direction(Direction.IN).titanEdges()), "An edge with the given type already exists on the in-vertex"); } } StandardEdge edge = new StandardEdge( temporaryID.decrementAndGet(), label, (InternalVertex) outVertex, (InternalVertex) inVertex, ElementLifeCycle.New); if (config.hasAssignIDsImmediately()) graph.assignID(edge); connectRelation(edge); return edge; } finally { uniqueLock.unlock(); } }
@Override public TitanLabel getEdgeLabel(String name) { TitanType et = getType(name); if (et == null) { return config.getAutoEdgeTypeMaker().makeLabel(name, makeType()); } else if (et.isEdgeLabel()) { return (TitanLabel) et; } else throw new IllegalArgumentException("The type of given name is not a label: " + name); }
@Override public TitanKey getPropertyKey(String name) { TitanType et = getType(name); if (et == null) { return config.getAutoEdgeTypeMaker().makeKey(name, makeType()); } else if (et.isPropertyKey()) { return (TitanKey) et; } else throw new IllegalArgumentException("The type of given name is not a key: " + name); }
public StandardTitanTx( StandardTitanGraph graph, TransactionConfig config, BackendTransaction txHandle) { Preconditions.checkNotNull(graph); Preconditions.checkArgument(graph.isOpen()); Preconditions.checkNotNull(config); Preconditions.checkNotNull(txHandle); this.graph = graph; this.config = config; this.idInspector = graph.getIDInspector(); this.txHandle = txHandle; temporaryID = new AtomicLong(-1); Cache<StandardElementQuery, List<Object>> indexCacheBuilder = CacheBuilder.newBuilder() .weigher( new Weigher<StandardElementQuery, List<Object>>() { @Override public int weigh(StandardElementQuery q, List<Object> r) { return 2 + r.size(); } }) .maximumWeight(DEFAULT_CACHE_SIZE) .build(); int concurrencyLevel; if (config.isSingleThreaded()) { vertexCache = new SimpleVertexCache(); addedRelations = new SimpleBufferAddedRelations(); concurrencyLevel = 1; typeCache = new HashMap<String, TitanType>(); newVertexIndexEntries = new SimpleIndexCache(); } else { vertexCache = new ConcurrentVertexCache(); addedRelations = new ConcurrentBufferAddedRelations(); concurrencyLevel = 4; typeCache = new ConcurrentHashMap<String, TitanType>(); newVertexIndexEntries = new ConcurrentIndexCache(); } for (SystemType st : SystemKey.values()) typeCache.put(st.getName(), st); indexCache = CacheBuilder.newBuilder() .weigher( new Weigher<StandardElementQuery, List<Object>>() { @Override public int weigh(StandardElementQuery q, List<Object> r) { return 2 + r.size(); } }) .concurrencyLevel(concurrencyLevel) .maximumWeight(DEFAULT_CACHE_SIZE) .build(); uniqueLocks = UNINITIALIZED_LOCKS; deletedRelations = EMPTY_DELETED_RELATIONS; this.isOpen = true; }
@Override public TitanVertex addVertex() { verifyWriteAccess(); StandardVertex vertex = new StandardVertex(this, temporaryID.decrementAndGet(), ElementLifeCycle.New); vertex.addProperty(SystemKey.VertexState, (byte) 0); if (config.hasAssignIDsImmediately()) graph.assignID(vertex); vertexCache.add(vertex, vertex.getID()); return vertex; }
public TitanProperty addPropertyInternal(TitanVertex vertex, TitanKey key, Object value) { verifyWriteAccess(vertex); vertex = ((InternalVertex) vertex).it(); Preconditions.checkNotNull(key); value = AttributeUtil.verifyAttribute(key, value); Lock uniqueLock = FakeLock.INSTANCE; if (config.hasVerifyUniqueness() && (key.isUnique(Direction.OUT) || key.isUnique(Direction.IN))) uniqueLock = getUniquenessLock(vertex, key, value); uniqueLock.lock(); try { // Check uniqueness if (config.hasVerifyUniqueness()) { if (key.isUnique(Direction.OUT)) { Preconditions.checkArgument( Iterables.isEmpty( query(vertex).includeHidden().type(key).direction(Direction.OUT).properties()), "An property with the given key already exists on the vertex and the property key is defined as out-unique"); } if (key.isUnique(Direction.IN)) { Preconditions.checkArgument( Iterables.isEmpty(getVertices(key, value)), "The given value is already used as a property and the property key is defined as in-unique"); } } StandardProperty prop = new StandardProperty( temporaryID.decrementAndGet(), key, (InternalVertex) vertex, value, ElementLifeCycle.New); if (config.hasAssignIDsImmediately()) graph.assignID(prop); connectRelation(prop); return prop; } finally { uniqueLock.unlock(); } }
@Override public TitanVertex getVertex(final long id) { verifyOpen(); if (config.hasVerifyVertexExistence() && !containsVertex(id)) return null; return getExistingVertex(id); }
private final void verifyWriteAccess(TitanVertex... vertices) { if (config.isReadOnly()) throw new UnsupportedOperationException( "Cannot create new entities in read-only transaction"); verifyAccess(vertices); }