Search in sources :

Example 1 with InternalVertex

use of com.thinkaurelius.titan.graphdb.internal.InternalVertex in project titan by thinkaurelius.

the class StandardTitanGraph method prepareCommit.

public ModificationSummary prepareCommit(final Collection<InternalRelation> addedRelations, final Collection<InternalRelation> deletedRelations, final Predicate<InternalRelation> filter, final BackendTransaction mutator, final StandardTitanTx tx, final boolean acquireLocks) throws BackendException {
    ListMultimap<Long, InternalRelation> mutations = ArrayListMultimap.create();
    ListMultimap<InternalVertex, InternalRelation> mutatedProperties = ArrayListMultimap.create();
    List<IndexSerializer.IndexUpdate> indexUpdates = Lists.newArrayList();
    //1) Collect deleted edges and their index updates and acquire edge locks
    for (InternalRelation del : Iterables.filter(deletedRelations, filter)) {
        Preconditions.checkArgument(del.isRemoved());
        for (int pos = 0; pos < del.getLen(); pos++) {
            InternalVertex vertex = del.getVertex(pos);
            if (pos == 0 || !del.isLoop()) {
                if (del.isProperty())
                    mutatedProperties.put(vertex, del);
                mutations.put(vertex.longId(), del);
            }
            if (acquireLock(del, pos, acquireLocks)) {
                Entry entry = edgeSerializer.writeRelation(del, pos, tx);
                mutator.acquireEdgeLock(idManager.getKey(vertex.longId()), entry);
            }
        }
        indexUpdates.addAll(indexSerializer.getIndexUpdates(del));
    }
    //2) Collect added edges and their index updates and acquire edge locks
    for (InternalRelation add : Iterables.filter(addedRelations, filter)) {
        Preconditions.checkArgument(add.isNew());
        for (int pos = 0; pos < add.getLen(); pos++) {
            InternalVertex vertex = add.getVertex(pos);
            if (pos == 0 || !add.isLoop()) {
                if (add.isProperty())
                    mutatedProperties.put(vertex, add);
                mutations.put(vertex.longId(), add);
            }
            if (!vertex.isNew() && acquireLock(add, pos, acquireLocks)) {
                Entry entry = edgeSerializer.writeRelation(add, pos, tx);
                mutator.acquireEdgeLock(idManager.getKey(vertex.longId()), entry.getColumn());
            }
        }
        indexUpdates.addAll(indexSerializer.getIndexUpdates(add));
    }
    //3) Collect all index update for vertices
    for (InternalVertex v : mutatedProperties.keySet()) {
        indexUpdates.addAll(indexSerializer.getIndexUpdates(v, mutatedProperties.get(v)));
    }
    //4) Acquire index locks (deletions first)
    for (IndexSerializer.IndexUpdate update : indexUpdates) {
        if (!update.isCompositeIndex() || !update.isDeletion())
            continue;
        CompositeIndexType iIndex = (CompositeIndexType) update.getIndex();
        if (acquireLock(iIndex, acquireLocks)) {
            mutator.acquireIndexLock((StaticBuffer) update.getKey(), (Entry) update.getEntry());
        }
    }
    for (IndexSerializer.IndexUpdate update : indexUpdates) {
        if (!update.isCompositeIndex() || !update.isAddition())
            continue;
        CompositeIndexType iIndex = (CompositeIndexType) update.getIndex();
        if (acquireLock(iIndex, acquireLocks)) {
            mutator.acquireIndexLock((StaticBuffer) update.getKey(), ((Entry) update.getEntry()).getColumn());
        }
    }
    //5) Add relation mutations
    for (Long vertexid : mutations.keySet()) {
        Preconditions.checkArgument(vertexid > 0, "Vertex has no id: %s", vertexid);
        List<InternalRelation> edges = mutations.get(vertexid);
        List<Entry> additions = new ArrayList<Entry>(edges.size());
        List<Entry> deletions = new ArrayList<Entry>(Math.max(10, edges.size() / 10));
        for (InternalRelation edge : edges) {
            InternalRelationType baseType = (InternalRelationType) edge.getType();
            assert baseType.getBaseType() == null;
            for (InternalRelationType type : baseType.getRelationIndexes()) {
                if (type.getStatus() == SchemaStatus.DISABLED)
                    continue;
                for (int pos = 0; pos < edge.getArity(); pos++) {
                    if (!type.isUnidirected(Direction.BOTH) && !type.isUnidirected(EdgeDirection.fromPosition(pos)))
                        //Directionality is not covered
                        continue;
                    if (edge.getVertex(pos).longId() == vertexid) {
                        StaticArrayEntry entry = edgeSerializer.writeRelation(edge, type, pos, tx);
                        if (edge.isRemoved()) {
                            deletions.add(entry);
                        } else {
                            Preconditions.checkArgument(edge.isNew());
                            int ttl = getTTL(edge);
                            if (ttl > 0) {
                                entry.setMetaData(EntryMetaData.TTL, ttl);
                            }
                            additions.add(entry);
                        }
                    }
                }
            }
        }
        StaticBuffer vertexKey = idManager.getKey(vertexid);
        mutator.mutateEdges(vertexKey, additions, deletions);
    }
    //6) Add index updates
    boolean has2iMods = false;
    for (IndexSerializer.IndexUpdate indexUpdate : indexUpdates) {
        assert indexUpdate.isAddition() || indexUpdate.isDeletion();
        if (indexUpdate.isCompositeIndex()) {
            IndexSerializer.IndexUpdate<StaticBuffer, Entry> update = indexUpdate;
            if (update.isAddition())
                mutator.mutateIndex(update.getKey(), Lists.newArrayList(update.getEntry()), KCVSCache.NO_DELETIONS);
            else
                mutator.mutateIndex(update.getKey(), KeyColumnValueStore.NO_ADDITIONS, Lists.newArrayList(update.getEntry()));
        } else {
            IndexSerializer.IndexUpdate<String, IndexEntry> update = indexUpdate;
            has2iMods = true;
            IndexTransaction itx = mutator.getIndexTransaction(update.getIndex().getBackingIndexName());
            String indexStore = ((MixedIndexType) update.getIndex()).getStoreName();
            if (update.isAddition())
                itx.add(indexStore, update.getKey(), update.getEntry(), update.getElement().isNew());
            else
                itx.delete(indexStore, update.getKey(), update.getEntry().field, update.getEntry().value, update.getElement().isRemoved());
        }
    }
    return new ModificationSummary(!mutations.isEmpty(), has2iMods);
}
Also used : LongArrayList(com.carrotsearch.hppc.LongArrayList) IndexTransaction(com.thinkaurelius.titan.diskstorage.indexing.IndexTransaction) IndexEntry(com.thinkaurelius.titan.diskstorage.indexing.IndexEntry) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation) StaticArrayEntry(com.thinkaurelius.titan.diskstorage.util.StaticArrayEntry) StaticArrayEntry(com.thinkaurelius.titan.diskstorage.util.StaticArrayEntry) IndexEntry(com.thinkaurelius.titan.diskstorage.indexing.IndexEntry) MixedIndexType(com.thinkaurelius.titan.graphdb.types.MixedIndexType) AtomicLong(java.util.concurrent.atomic.AtomicLong) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex) CompositeIndexType(com.thinkaurelius.titan.graphdb.types.CompositeIndexType) InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType)

Example 2 with InternalVertex

use of com.thinkaurelius.titan.graphdb.internal.InternalVertex in project titan by thinkaurelius.

the class VertexIDAssigner method assignID.

private void assignID(InternalElement element, IDManager.VertexIDType vertexIDType) {
    for (int attempt = 0; attempt < MAX_PARTITION_RENEW_ATTEMPTS; attempt++) {
        long partitionID = -1;
        if (element instanceof TitanSchemaVertex) {
            partitionID = IDManager.SCHEMA_PARTITION;
        } else if (element instanceof TitanVertex) {
            if (vertexIDType == IDManager.VertexIDType.PartitionedVertex)
                partitionID = IDManager.PARTITIONED_VERTEX_PARTITION;
            else
                partitionID = placementStrategy.getPartition(element);
        } else if (element instanceof InternalRelation) {
            InternalRelation relation = (InternalRelation) element;
            if (attempt < relation.getLen()) {
                //On the first attempts, try to use partition of incident vertices
                InternalVertex incident = relation.getVertex(attempt);
                Preconditions.checkArgument(incident.hasId());
                if (!IDManager.VertexIDType.PartitionedVertex.is(incident.longId()) || relation.isProperty()) {
                    partitionID = getPartitionID(incident);
                } else {
                    continue;
                }
            } else {
                partitionID = placementStrategy.getPartition(element);
            }
        }
        try {
            assignID(element, partitionID, vertexIDType);
        } catch (IDPoolExhaustedException e) {
            //try again on a different partition
            continue;
        }
        assert element.hasId();
        //Check if we should assign a different representative of a potential partitioned vertex
        if (element instanceof InternalRelation) {
            InternalRelation relation = (InternalRelation) element;
            if (relation.isProperty() && isPartitionedAt(relation, 0)) {
                //Always assign properties to the canonical representative of a partitioned vertex
                InternalVertex vertex = relation.getVertex(0);
                ((ReassignableRelation) relation).setVertexAt(0, vertex.tx().getInternalVertex(idManager.getCanonicalVertexId(vertex.longId())));
            } else if (relation.isEdge()) {
                for (int pos = 0; pos < relation.getArity(); pos++) {
                    if (isPartitionedAt(relation, pos)) {
                        InternalVertex incident = relation.getVertex(pos);
                        long newPartition;
                        int otherpos = (pos + 1) % 2;
                        if (((InternalRelationType) relation.getType()).multiplicity().isUnique(EdgeDirection.fromPosition(pos))) {
                            //If the relation is unique in the direction, we assign it to the canonical vertex...
                            newPartition = idManager.getPartitionId(idManager.getCanonicalVertexId(incident.longId()));
                        } else if (!isPartitionedAt(relation, otherpos)) {
                            //...else, we assign it to the partition of the non-partitioned vertex...
                            newPartition = getPartitionID(relation.getVertex(otherpos));
                        } else {
                            //...and if such does not exists (i.e. both end vertices are partitioned) we use the hash of the relation id
                            newPartition = idManager.getPartitionHashForId(relation.longId());
                        }
                        if (idManager.getPartitionId(incident.longId()) != newPartition) {
                            ((ReassignableRelation) relation).setVertexAt(pos, incident.tx().getOtherPartitionVertex(incident, newPartition));
                        }
                    }
                }
            }
        }
        return;
    }
    throw new IDPoolExhaustedException("Could not find non-exhausted partition ID Pool after " + MAX_PARTITION_RENEW_ATTEMPTS + " attempts");
}
Also used : ReassignableRelation(com.thinkaurelius.titan.graphdb.relations.ReassignableRelation) TitanSchemaVertex(com.thinkaurelius.titan.graphdb.types.vertices.TitanSchemaVertex) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex) InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation)

Example 3 with InternalVertex

use of com.thinkaurelius.titan.graphdb.internal.InternalVertex in project titan by thinkaurelius.

the class StandardTitanGraph method commit.

public void commit(final Collection<InternalRelation> addedRelations, final Collection<InternalRelation> deletedRelations, final StandardTitanTx tx) {
    // Setup
    log.debug("Saving transaction. Added {}, removed {}", addedRelations.size(), deletedRelations.size());
    final BackendTransaction mutator = tx.getTxHandle();
    final boolean acquireLocks = tx.getConfiguration().hasAcquireLocks();
    // 1. Assign TitanVertex IDs
    if (!tx.getConfiguration().hasAssignIDsImmediately())
        idAssigner.assignIDs(addedRelations);
    Callable<List<StaticBuffer>> persist = new Callable<List<StaticBuffer>>() {

        @Override
        public List<StaticBuffer> call() throws Exception {
            // 2. Collect deleted edges
            ListMultimap<InternalVertex, InternalRelation> mutations = ArrayListMultimap.create();
            if (deletedRelations != null && !deletedRelations.isEmpty()) {
                for (InternalRelation del : deletedRelations) {
                    Preconditions.checkArgument(del.isRemoved());
                    for (int pos = 0; pos < del.getLen(); pos++) {
                        InternalVertex vertex = del.getVertex(pos);
                        if (pos == 0 || !del.isLoop())
                            mutations.put(vertex, del);
                        Direction dir = EdgeDirection.fromPosition(pos);
                        if (acquireLocks && del.getType().isUnique(dir) && ((InternalType) del.getType()).uniqueLock(dir)) {
                            Entry entry = edgeSerializer.writeRelation(del, pos, tx);
                            mutator.acquireEdgeLock(IDHandler.getKey(vertex.getID()), entry.getColumn(), entry.getValue());
                        }
                    }
                    // Update Indexes
                    if (del.isProperty()) {
                        if (acquireLocks)
                            indexSerializer.lockKeyedProperty((TitanProperty) del, mutator);
                    }
                }
            }
            ListMultimap<InternalType, InternalRelation> otherEdgeTypes = ArrayListMultimap.create();
            // 3. Sort Added Edges
            for (InternalRelation relation : addedRelations) {
                Preconditions.checkArgument(relation.isNew());
                TitanType type = relation.getType();
                // Give special treatment to edge type definitions
                if (SystemTypeManager.prepersistedSystemTypes.contains(type)) {
                    InternalType itype = (InternalType) relation.getVertex(0);
                    otherEdgeTypes.put(itype, relation);
                } else {
                    // STANDARD TitanRelation
                    for (int pos = 0; pos < relation.getLen(); pos++) {
                        InternalVertex vertex = relation.getVertex(pos);
                        if (pos == 0 || !relation.isLoop())
                            mutations.put(vertex, relation);
                        Direction dir = EdgeDirection.fromPosition(pos);
                        if (acquireLocks && relation.getType().isUnique(dir) && !vertex.isNew() && ((InternalType) relation.getType()).uniqueLock(dir)) {
                            Entry entry = edgeSerializer.writeRelation(relation, pos, tx);
                            mutator.acquireEdgeLock(IDHandler.getKey(vertex.getID()), entry.getColumn(), null);
                        }
                    }
                }
                // Update Indexes
                if (relation.isProperty()) {
                    if (acquireLocks)
                        indexSerializer.lockKeyedProperty((TitanProperty) relation, mutator);
                }
            }
            // 3. Persist
            List<StaticBuffer> mutatedVertexKeys = new ArrayList<StaticBuffer>();
            if (!otherEdgeTypes.isEmpty()) {
                mutatedVertexKeys.addAll(persist(otherEdgeTypes, tx));
                mutator.flush();
                // Register new keys with indexprovider
                for (InternalType itype : otherEdgeTypes.keySet()) {
                    if (itype.isPropertyKey() && itype.isNew())
                        indexSerializer.newPropertyKey((TitanKey) itype, mutator);
                }
            }
            if (!mutations.isEmpty())
                mutatedVertexKeys.addAll(persist(mutations, tx));
            mutator.commit();
            return mutatedVertexKeys;
        }

        @Override
        public String toString() {
            return "PersistingTransaction";
        }
    };
    List<StaticBuffer> mutatedVertexKeys = BackendOperation.execute(persist, maxWriteRetryAttempts, retryStorageWaitTime);
    for (StaticBuffer vertexKey : mutatedVertexKeys) edgeStoreCache.invalidate(vertexKey);
}
Also used : LongArrayList(com.carrotsearch.hppc.LongArrayList) ArrayList(java.util.ArrayList) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation) EdgeDirection(com.thinkaurelius.titan.graphdb.relations.EdgeDirection) Direction(com.tinkerpop.blueprints.Direction) Callable(java.util.concurrent.Callable) InternalType(com.thinkaurelius.titan.graphdb.internal.InternalType) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex) LongArrayList(com.carrotsearch.hppc.LongArrayList) ArrayList(java.util.ArrayList) List(java.util.List) StaticBuffer(com.thinkaurelius.titan.diskstorage.StaticBuffer) BackendTransaction(com.thinkaurelius.titan.diskstorage.BackendTransaction)

Example 4 with InternalVertex

use of com.thinkaurelius.titan.graphdb.internal.InternalVertex in project titan by thinkaurelius.

the class VertexIDAssigner method assignIDs.

public void assignIDs(Iterable<InternalRelation> addedRelations) {
    if (!placementStrategy.supportsBulkPlacement()) {
        for (InternalRelation relation : addedRelations) {
            for (int i = 0; i < relation.getArity(); i++) {
                InternalVertex vertex = relation.getVertex(i);
                if (!vertex.hasId()) {
                    assignID(vertex);
                }
            }
            assignID(relation);
        }
    } else {
        // First, only assign idAuthorities to (real) vertices and types
        Map<InternalVertex, PartitionAssignment> assignments = new HashMap<InternalVertex, PartitionAssignment>();
        for (InternalRelation relation : addedRelations) {
            for (int i = 0; i < relation.getArity(); i++) {
                InternalVertex vertex = relation.getVertex(i);
                if (!vertex.hasId()) {
                    if (vertex instanceof TitanType) {
                        assignID(vertex, DEFAULT_PARTITION);
                    } else {
                        assignments.put(vertex, PartitionAssignment.EMPTY);
                    }
                }
            }
        }
        log.trace("Bulk id assignment for {} vertices", assignments.size());
        for (int attempt = 0; attempt < MAX_PARTITION_RENEW_ATTEMPTS && (assignments != null && !assignments.isEmpty()); attempt++) {
            placementStrategy.getPartitions(assignments);
            Map<InternalVertex, PartitionAssignment> leftOvers = null;
            Iterator<Map.Entry<InternalVertex, PartitionAssignment>> iter = assignments.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry<InternalVertex, PartitionAssignment> entry = iter.next();
                try {
                    assignID(entry.getKey(), entry.getValue().getPartitionID());
                    Preconditions.checkArgument(entry.getKey().hasId());
                } catch (IDPoolExhaustedException e) {
                    if (leftOvers == null)
                        leftOvers = new HashMap<InternalVertex, PartitionAssignment>();
                    leftOvers.put(entry.getKey(), PartitionAssignment.EMPTY);
                    break;
                }
            }
            if (leftOvers != null) {
                while (iter.hasNext()) leftOvers.put(iter.next().getKey(), PartitionAssignment.EMPTY);
                log.debug("Exhausted ID Pool in bulk assignment. Left-over vertices {}", leftOvers.size());
            }
            assignments = leftOvers;
        }
        if (assignments != null && !assignments.isEmpty())
            throw new IDPoolExhaustedException("Could not find non-exhausted partition ID Pool after " + MAX_PARTITION_RENEW_ATTEMPTS + " attempts");
        // Second, assign idAuthorities to relations
        for (InternalRelation relation : addedRelations) {
            for (int pos = 0; pos < relation.getArity(); pos++) {
                try {
                    Preconditions.checkArgument(relation.getVertex(pos).hasId());
                    assignID(relation, getPartitionID(relation.getVertex(pos)));
                    break;
                } catch (IDPoolExhaustedException e) {
                }
            }
            if (!relation.hasId())
                assignID(relation);
        }
    }
}
Also used : HashMap(java.util.HashMap) OpenIntObjectHashMap(cern.colt.map.OpenIntObjectHashMap) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation) PartitionAssignment(com.thinkaurelius.titan.graphdb.database.idassigner.placement.PartitionAssignment) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex) TitanType(com.thinkaurelius.titan.core.TitanType) HashMap(java.util.HashMap) OpenIntObjectHashMap(cern.colt.map.OpenIntObjectHashMap) Map(java.util.Map) AbstractIntObjectMap(cern.colt.map.AbstractIntObjectMap)

Example 5 with InternalVertex

use of com.thinkaurelius.titan.graphdb.internal.InternalVertex in project titan by thinkaurelius.

the class VertexIterable method iterator.

@Override
public Iterator<InternalVertex> iterator() {
    return new Iterator<InternalVertex>() {

        RecordIterator<Long> iterator = graph.getVertexIDs(tx.getTxHandle());

        InternalVertex nextVertex = nextVertex();

        private InternalVertex nextVertex() {
            InternalVertex v = null;
            while (v == null && iterator.hasNext()) {
                long nextId = iterator.next().longValue();
                v = tx.getExistingVertex(nextId);
                // Filter out deleted vertices and types
                if (v.isRemoved() || (v instanceof TitanType))
                    v = null;
            }
            return v;
        }

        @Override
        public boolean hasNext() {
            return nextVertex != null;
        }

        @Override
        public InternalVertex next() {
            if (!hasNext())
                throw new NoSuchElementException();
            InternalVertex returnVertex = nextVertex;
            nextVertex = nextVertex();
            return returnVertex;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    };
}
Also used : RecordIterator(com.thinkaurelius.titan.diskstorage.util.RecordIterator) RecordIterator(com.thinkaurelius.titan.diskstorage.util.RecordIterator) Iterator(java.util.Iterator) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex) TitanType(com.thinkaurelius.titan.core.TitanType) NoSuchElementException(java.util.NoSuchElementException)

Aggregations

InternalVertex (com.thinkaurelius.titan.graphdb.internal.InternalVertex)14 InternalRelation (com.thinkaurelius.titan.graphdb.internal.InternalRelation)9 InternalRelationType (com.thinkaurelius.titan.graphdb.internal.InternalRelationType)3 LongArrayList (com.carrotsearch.hppc.LongArrayList)2 TitanType (com.thinkaurelius.titan.core.TitanType)2 SliceQuery (com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery)2 HashMap (java.util.HashMap)2 NonBlockingHashMapLong (org.cliffc.high_scale_lib.NonBlockingHashMapLong)2 AbstractIntObjectMap (cern.colt.map.AbstractIntObjectMap)1 OpenIntObjectHashMap (cern.colt.map.OpenIntObjectHashMap)1 EdgeLabel (com.thinkaurelius.titan.core.EdgeLabel)1 PropertyKey (com.thinkaurelius.titan.core.PropertyKey)1 Change (com.thinkaurelius.titan.core.log.Change)1 BackendTransaction (com.thinkaurelius.titan.diskstorage.BackendTransaction)1 Entry (com.thinkaurelius.titan.diskstorage.Entry)1 StaticBuffer (com.thinkaurelius.titan.diskstorage.StaticBuffer)1 IndexEntry (com.thinkaurelius.titan.diskstorage.indexing.IndexEntry)1 IndexTransaction (com.thinkaurelius.titan.diskstorage.indexing.IndexTransaction)1 RecordIterator (com.thinkaurelius.titan.diskstorage.util.RecordIterator)1 StaticArrayEntry (com.thinkaurelius.titan.diskstorage.util.StaticArrayEntry)1