@Override public AbstractLongList getRawNeighborhood(AtomicQuery query, InternalTitanTransaction tx) { Preconditions.checkArgument( QueryUtil.queryCoveredByDiskIndexes(query), "Raw retrieval is currently does not support in-memory filtering"); List<Entry> entries = queryForEntries(query, tx.getTxHandle()); InternalTitanVertex node = query.getNode(); TitanType titanType = null; if (query.hasEdgeTypeCondition()) titanType = query.getTypeCondition(); AbstractLongList result = new LongArrayList(); for (Entry entry : entries) { if (!query.hasEdgeTypeCondition()) { long etid = IDHandler.readEdgeType(entry.getColumn(), idManager); if (titanType == null || titanType.getID() != etid) { titanType = getTypeFromID(etid, tx); } } if (titanType.isPropertyKey() || (!titanType.isModifiable() && !query.queryUnmodifiable())) { continue; // Skip since it does not match query } // Get neighboring node id long iddiff = VariableLong.read(entry.getValue()); long nghid = iddiff + node.getID(); result.add(nghid); if (result.size() >= query.getLimit()) break; } return result; }
@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 void save( final Collection<InternalRelation> addedRelations, final Collection<InternalRelation> deletedRelations, final InternalTitanTransaction tx) throws StorageException { // Setup log.debug( "Saving transaction. Added {}, removed {}", addedRelations.size(), deletedRelations.size()); final Map<TitanType, TypeSignature> signatures = new HashMap<TitanType, TypeSignature>(); final TransactionHandle txh = tx.getTxHandle(); final StoreMutator mutator = getStoreMutator(txh); final boolean acquireLocks = tx.getTxConfiguration().hasAcquireLocks(); // 1. Assign TitanVertex IDs assignIDs(addedRelations, tx); for (int saveAttempt = 0; saveAttempt < maxWriteRetryAttempts; saveAttempt++) { // while (true) { //Indefinite loop, broken if no exception occurs, otherwise retried // or failed immediately try { // 2. Collect deleted edges ListMultimap<InternalTitanVertex, InternalRelation> mutations = ArrayListMultimap.create(); if (deletedRelations != null && !deletedRelations.isEmpty()) { for (InternalRelation del : deletedRelations) { assert del.isRemoved(); for (int pos = 0; pos < del.getArity(); pos++) { InternalTitanVertex node = del.getVertex(pos); if (pos == 0 || !del.isUnidirected()) { mutations.put(node, del); } if (pos == 0 && acquireLocks && del.getType().isFunctional() && ((InternalTitanType) del.getType()).isFunctionalLocking()) { Entry entry = getEntry(tx, del, node, signatures); mutator.acquireEdgeLock( IDHandler.getKey(node.getID()), entry.getColumn(), entry.getValue()); } } if (acquireLocks && del.isProperty()) { lockKeyedProperty((TitanProperty) del, mutator); } } } ListMultimap<InternalTitanType, InternalRelation> simpleEdgeTypes = null; ListMultimap<InternalTitanType, InternalRelation> otherEdgeTypes = null; // 3. Sort Added Edges for (InternalRelation edge : addedRelations) { if (edge.isRemoved()) continue; assert edge.isNew(); TitanType et = edge.getType(); // Give special treatment to edge type definitions if (SystemTypeManager.prepersistedSystemTypes.contains(et)) { assert edge.getVertex(0) instanceof InternalTitanType; InternalTitanType node = (InternalTitanType) edge.getVertex(0); assert node.hasID(); if (node.isSimple()) { if (simpleEdgeTypes == null) simpleEdgeTypes = ArrayListMultimap.create(); simpleEdgeTypes.put(node, edge); } else { if (otherEdgeTypes == null) otherEdgeTypes = ArrayListMultimap.create(); otherEdgeTypes.put(node, edge); } } else { // STANDARD TitanRelation assert (edge.getArity() == 1 && edge.isProperty()) || (edge.getArity() == 2 && edge.isEdge()); for (int pos = 0; pos < edge.getArity(); pos++) { InternalTitanVertex node = edge.getVertex(pos); assert node.hasID(); if (pos == 0 || !edge.isUnidirected()) { mutations.put(node, edge); } if (pos == 0 && acquireLocks && edge.getType().isFunctional() && !node.isNew() && ((InternalTitanType) edge.getType()).isFunctionalLocking()) { Entry entry = getEntry(tx, edge, node, signatures, true); mutator.acquireEdgeLock(IDHandler.getKey(node.getID()), entry.getColumn(), null); } } } if (acquireLocks && edge.isProperty()) { lockKeyedProperty((TitanProperty) edge, mutator); } } // 3. Persist if (simpleEdgeTypes != null) persist(simpleEdgeTypes, signatures, tx, mutator); if (otherEdgeTypes != null) persist(otherEdgeTypes, signatures, tx, mutator); mutator.flush(); // Commit saved EdgeTypes to TypeManager if (simpleEdgeTypes != null) commitEdgeTypes(simpleEdgeTypes.keySet()); if (otherEdgeTypes != null) commitEdgeTypes(otherEdgeTypes.keySet()); if (!mutations.isEmpty()) persist(mutations, signatures, tx, mutator); mutator.flush(); // Successfully completed - return to break out of loop break; } catch (Throwable e) { if (e instanceof TemporaryStorageException) { if (saveAttempt < maxWriteRetryAttempts - 1) temporaryStorageException(e); else throw new PermanentStorageException( "Tried committing " + maxWriteRetryAttempts + " times on temporary exception without success", e); } else if (e instanceof StorageException) { throw (StorageException) e; } else { throw new PermanentStorageException( "Unidentified exception occurred during persistence", e); } } } }
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); } } } }