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(); } }
private static void writeAttribute(DataOutput out, TitanProperty property) { Object attribute = property.getAttribute(); TitanKey key = (TitanKey) property.getType(); assert attribute != null; assert key.getDataType().isInstance(attribute); if (hasGenericDataType(key)) { out.writeClassAndObject(attribute); } else { out.writeObjectNotNull(attribute); } }
private Object readInline(ByteBuffer read, TitanType type) { if (type.isPropertyKey()) { TitanKey proptype = ((TitanKey) type); if (hasGenericDataType(proptype)) return serializer.readClassAndObject(read); else return serializer.readObject(read, proptype.getDataType()); } else { assert type.isEdgeLabel(); Long id = Long.valueOf(VariableLong.readPositive(read)); if (id.longValue() == 0) return null; else return id; } }
private void lockKeyedProperty(TitanProperty prop, StoreMutator mutator) throws StorageException { TitanKey pt = prop.getPropertyKey(); assert pt.isSimple(); if (pt.hasIndex() && pt.isUnique()) { if (prop.isNew()) { mutator.acquireIndexLock(getIndexKey(prop.getAttribute()), getKeyedIndexColumn(pt), null); } else { assert prop.isRemoved(); mutator.acquireIndexLock( getIndexKey(prop.getAttribute()), getKeyedIndexColumn(pt), getIndexValue(prop)); } } }
private void addIndexEntry(TitanProperty prop, StoreMutator mutator) throws StorageException { TitanKey pt = prop.getPropertyKey(); assert pt.isSimple(); if (pt.hasIndex()) { if (pt.isUnique()) { mutator.mutateIndex( getIndexKey(prop.getAttribute()), Lists.newArrayList(new Entry(getKeyedIndexColumn(pt), getIndexValue(prop))), null); } else { mutator.mutateIndex( getIndexKey(prop.getAttribute()), Lists.newArrayList(new Entry(getIndexColumn(pt, prop.getID()), getIndexValue(prop))), null); } } }
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 long[] indexRetrieval(Object key, TitanKey pt, InternalTitanTransaction tx) { Preconditions.checkArgument( pt.isSimple(), "Currently, only simple properties are supported for index retrieval"); Preconditions.checkArgument( pt.hasIndex(), "Cannot retrieve for given property key - it does not have an index"); long[] vertices = null; Preconditions.checkArgument( pt.getDataType().isInstance(key), "Specified object is incompatible with property data type [" + pt.getName() + "]"); for (int readAttempt = 0; readAttempt < maxReadRetryAttempts; readAttempt++) { try { if (pt.isUnique()) { ByteBuffer value = propertyIndex.get(getIndexKey(key), getKeyedIndexColumn(pt), tx.getTxHandle()); if (value != null) { vertices = new long[1]; vertices[0] = VariableLong.readPositive(value); } } else { ByteBuffer startColumn = VariableLong.positiveByteBuffer(pt.getID()); List<Entry> entries = propertyIndex.getSlice( getIndexKey(key), startColumn, ByteBufferUtil.nextBiggerBuffer(startColumn), tx.getTxHandle()); vertices = new long[entries.size()]; int i = 0; for (Entry ent : entries) { vertices[i++] = VariableLong.readPositive(ent.getValue()); } } break; } catch (StorageException e) { if (e instanceof TemporaryStorageException) { if (readAttempt < maxReadRetryAttempts - 1) temporaryStorageException(e); else throw readException(e, maxReadRetryAttempts); } else throw readException(e); } } if (vertices == null) return new long[0]; else return vertices; }
@Override public TitanVertex getVertex(TitanKey key, Object attribute) { Preconditions.checkArgument( key.isUnique(Direction.IN), "Key is not uniquely associated to value [%s]", key.getName()); return Iterables.getOnlyElement(getVertices(key, attribute), null); }
@Override public TitanProperty addProperty(TitanVertex vertex, TitanKey key, Object value) { if (key.isUnique(Direction.OUT)) return setProperty(vertex, key, value); else return addPropertyInternal(vertex, key, value); }
private static final boolean isVertexIndexProperty(TitanKey key) { return key.hasIndex(Titan.Token.STANDARD_INDEX, Vertex.class); }
protected void loadRelations( Iterable<Entry> entries, VertexRelationLoader loader, InternalTitanTransaction tx) { Map<String, TitanType> etCache = new HashMap<String, TitanType>(); TitanType titanType = null; for (Entry entry : entries) { ByteBuffer column = entry.getColumn(); int dirID = IDHandler.getDirectionID(column.get(column.position())); long etid = IDHandler.readEdgeType(column, idManager); if (titanType == null || titanType.getID() != etid) { titanType = getTypeFromID(etid, tx); } Object[] keys = null; if (!titanType.isSimple()) { TypeDefinition def = ((InternalTitanType) titanType).getDefinition(); String[] keysig = def.getKeySignature(); keys = new Object[keysig.length]; for (int i = 0; i < keysig.length; i++) keys[i] = readInline(column, getEdgeType(keysig[i], etCache, tx)); } long edgeid = 0; if (!titanType.isFunctional()) { edgeid = VariableLong.readPositive(column); } ByteBuffer value = entry.getValue(); if (titanType.isEdgeLabel()) { long nodeIDDiff = VariableLong.read(value); if (titanType.isFunctional()) edgeid = VariableLong.readPositive(value); assert edgeid > 0; long otherid = loader.getVertexId() + nodeIDDiff; assert dirID == 3 || dirID == 2; Direction dir = dirID == 3 ? Direction.IN : Direction.OUT; if (!tx.isDeletedRelation(edgeid)) loader.loadEdge(edgeid, (TitanLabel) titanType, dir, otherid); } else { assert titanType.isPropertyKey(); assert dirID == 0; TitanKey propType = ((TitanKey) titanType); Object attribute = null; if (hasGenericDataType(propType)) { attribute = serializer.readClassAndObject(value); } else { attribute = serializer.readObjectNotNull(value, propType.getDataType()); } assert attribute != null; if (titanType.isFunctional()) edgeid = VariableLong.readPositive(value); assert edgeid > 0; if (!tx.isDeletedRelation(edgeid)) loader.loadProperty(edgeid, propType, attribute); } // Read value inline edges if any if (!titanType.isSimple()) { TypeDefinition def = ((InternalTitanType) titanType).getDefinition(); // First create all keys buffered above String[] keysig = def.getKeySignature(); for (int i = 0; i < keysig.length; i++) { createInlineEdge(loader, getEdgeType(keysig[i], etCache, tx), keys[i]); } // value signature for (String str : def.getCompactSignature()) readLabel(loader, value, getEdgeType(str, etCache, tx)); // Third: read rest while (value.hasRemaining()) { TitanType type = (TitanType) tx.getExistingVertex(IDHandler.readInlineEdgeType(value, idManager)); readLabel(loader, value, type); } } } }
private ByteBuffer getIndexColumn(TitanKey type, long propertyID) { assert !type.isUnique(); return VariableLong.positiveByteBuffer(new long[] {type.getID(), propertyID}); }
private ByteBuffer getKeyedIndexColumn(TitanKey type) { assert type.isUnique(); return VariableLong.positiveByteBuffer(type.getID()); }
private static final boolean hasGenericDataType(TitanKey key) { return key.getDataType().equals(Object.class); }