Search in sources :

Example 6 with InternalRelation

use of com.thinkaurelius.titan.graphdb.internal.InternalRelation 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 7 with InternalRelation

use of com.thinkaurelius.titan.graphdb.internal.InternalRelation 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, getVertexIDType(vertex));
                }
            }
            assignID(relation);
        }
    } else {
        //2) only assign ids to (user) vertices
        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()) {
                    //Those are assigned ids immediately in the transaction
                    assert !(vertex instanceof TitanSchemaVertex);
                    if (vertex.vertexLabel().isPartitioned())
                        //Assign partitioned vertex ids immediately
                        assignID(vertex, getVertexIDType(vertex));
                    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(), getVertexIDType(entry.getKey()));
                    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");
        //3) assign ids to relations
        for (InternalRelation relation : addedRelations) {
            assignID(relation);
        }
    }
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) TitanSchemaVertex(com.thinkaurelius.titan.graphdb.types.vertices.TitanSchemaVertex) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex) ConcurrentMap(java.util.concurrent.ConcurrentMap) ImmutableMap(com.google.common.collect.ImmutableMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 8 with InternalRelation

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

the class StandardTransactionLogProcessor method fixSecondaryFailure.

private void fixSecondaryFailure(final StandardTransactionId txId, final TxEntry entry) {
    logRecoveryMsg("Attempting to repair partially failed transaction [%s]", txId);
    if (entry.entry == null) {
        logRecoveryMsg("Trying to repair expired or unpersisted transaction [%s] (Ignore in startup)", txId);
        return;
    }
    boolean userLogFailure = true;
    boolean secIndexFailure = true;
    final Predicate<String> isFailedIndex;
    final TransactionLogHeader.Entry commitEntry = entry.entry;
    final TransactionLogHeader.SecondaryFailures secFail = entry.failures;
    if (secFail != null) {
        userLogFailure = secFail.userLogFailure;
        secIndexFailure = !secFail.failedIndexes.isEmpty();
        isFailedIndex = new Predicate<String>() {

            @Override
            public boolean apply(@Nullable String s) {
                return secFail.failedIndexes.contains(s);
            }
        };
    } else {
        isFailedIndex = Predicates.alwaysTrue();
    }
    // I) Restore external indexes
    if (secIndexFailure) {
        //1) Collect all elements (vertices and relations) and the indexes for which they need to be restored
        final SetMultimap<String, IndexRestore> indexRestores = HashMultimap.create();
        BackendOperation.execute(new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                StandardTitanTx tx = (StandardTitanTx) graph.newTransaction();
                try {
                    for (TransactionLogHeader.Modification modification : commitEntry.getContentAsModifications(serializer)) {
                        InternalRelation rel = ModificationDeserializer.parseRelation(modification, tx);
                        //Collect affected vertex indexes
                        for (MixedIndexType index : getMixedIndexes(rel.getType())) {
                            if (index.getElement() == ElementCategory.VERTEX && isFailedIndex.apply(index.getBackingIndexName())) {
                                assert rel.isProperty();
                                indexRestores.put(index.getBackingIndexName(), new IndexRestore(rel.getVertex(0).longId(), ElementCategory.VERTEX, getIndexId(index)));
                            }
                        }
                        //See if relation itself is affected
                        for (RelationType relType : rel.getPropertyKeysDirect()) {
                            for (MixedIndexType index : getMixedIndexes(relType)) {
                                if (index.getElement().isInstance(rel) && isFailedIndex.apply(index.getBackingIndexName())) {
                                    assert rel.id() instanceof RelationIdentifier;
                                    indexRestores.put(index.getBackingIndexName(), new IndexRestore(rel.id(), ElementCategory.getByClazz(rel.getClass()), getIndexId(index)));
                                }
                            }
                        }
                    }
                } finally {
                    if (tx.isOpen())
                        tx.rollback();
                }
                return true;
            }
        }, readTime);
        //2) Restore elements per backing index
        for (final String indexName : indexRestores.keySet()) {
            final StandardTitanTx tx = (StandardTitanTx) graph.newTransaction();
            try {
                BackendTransaction btx = tx.getTxHandle();
                final IndexTransaction indexTx = btx.getIndexTransaction(indexName);
                BackendOperation.execute(new Callable<Boolean>() {

                    @Override
                    public Boolean call() throws Exception {
                        Map<String, Map<String, List<IndexEntry>>> restoredDocs = Maps.newHashMap();
                        for (IndexRestore restore : indexRestores.get(indexName)) {
                            TitanSchemaVertex indexV = (TitanSchemaVertex) tx.getVertex(restore.indexId);
                            MixedIndexType index = (MixedIndexType) indexV.asIndexType();
                            TitanElement element = restore.retrieve(tx);
                            if (element != null) {
                                graph.getIndexSerializer().reindexElement(element, index, restoredDocs);
                            } else {
                                //Element is deleted
                                graph.getIndexSerializer().removeElement(restore.elementId, index, restoredDocs);
                            }
                        }
                        indexTx.restore(restoredDocs);
                        indexTx.commit();
                        return true;
                    }

                    @Override
                    public String toString() {
                        return "IndexMutation";
                    }
                }, persistenceTime);
            } finally {
                if (tx.isOpen())
                    tx.rollback();
            }
        }
    }
    // II) Restore log messages
    final String logTxIdentifier = (String) commitEntry.getMetadata().get(LogTxMeta.LOG_ID);
    if (userLogFailure && logTxIdentifier != null) {
        TransactionLogHeader txHeader = new TransactionLogHeader(txCounter.incrementAndGet(), times.getTime(), times);
        final StaticBuffer userLogContent = txHeader.serializeUserLog(serializer, commitEntry, txId);
        BackendOperation.execute(new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                final Log userLog = graph.getBackend().getUserLog(logTxIdentifier);
                Future<Message> env = userLog.add(userLogContent);
                if (env.isDone()) {
                    env.get();
                }
                return true;
            }
        }, persistenceTime);
    }
}
Also used : IndexTransaction(com.thinkaurelius.titan.diskstorage.indexing.IndexTransaction) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation) InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType) RelationType(com.thinkaurelius.titan.core.RelationType) TitanElement(com.thinkaurelius.titan.core.TitanElement) List(java.util.List) TransactionLogHeader(com.thinkaurelius.titan.graphdb.database.log.TransactionLogHeader) MixedIndexType(com.thinkaurelius.titan.graphdb.types.MixedIndexType) TitanSchemaVertex(com.thinkaurelius.titan.graphdb.types.vertices.TitanSchemaVertex) RelationIdentifier(com.thinkaurelius.titan.graphdb.relations.RelationIdentifier) StandardTitanTx(com.thinkaurelius.titan.graphdb.transaction.StandardTitanTx) TitanException(com.thinkaurelius.titan.core.TitanException) ExecutionException(java.util.concurrent.ExecutionException) Future(java.util.concurrent.Future) Map(java.util.Map)

Example 9 with InternalRelation

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

the class ModificationDeserializer method parseRelation.

public static InternalRelation parseRelation(TransactionLogHeader.Modification modification, StandardTitanTx tx) {
    Change state = modification.state;
    assert state.isProper();
    long outVertexId = modification.outVertexId;
    Entry relEntry = modification.relationEntry;
    InternalVertex outVertex = tx.getInternalVertex(outVertexId);
    //Special relation parsing, compare to {@link RelationConstructor}
    RelationCache relCache = tx.getEdgeSerializer().readRelation(relEntry, false, tx);
    assert relCache.direction == Direction.OUT;
    InternalRelationType type = (InternalRelationType) tx.getExistingRelationType(relCache.typeId);
    assert type.getBaseType() == null;
    InternalRelation rel;
    if (type.isPropertyKey()) {
        if (state == Change.REMOVED) {
            rel = new StandardVertexProperty(relCache.relationId, (PropertyKey) type, outVertex, relCache.getValue(), ElementLifeCycle.Removed);
        } else {
            rel = new CacheVertexProperty(relCache.relationId, (PropertyKey) type, outVertex, relCache.getValue(), relEntry);
        }
    } else {
        assert type.isEdgeLabel();
        InternalVertex otherVertex = tx.getInternalVertex(relCache.getOtherVertexId());
        if (state == Change.REMOVED) {
            rel = new StandardEdge(relCache.relationId, (EdgeLabel) type, outVertex, otherVertex, ElementLifeCycle.Removed);
        } else {
            rel = new CacheEdge(relCache.relationId, (EdgeLabel) type, outVertex, otherVertex, relEntry);
        }
    }
    if (state == Change.REMOVED && relCache.hasProperties()) {
        //copy over properties
        for (LongObjectCursor<Object> entry : relCache) {
            rel.setPropertyDirect(tx.getExistingPropertyKey(entry.key), entry.value);
        }
    }
    return rel;
}
Also used : EdgeLabel(com.thinkaurelius.titan.core.EdgeLabel) Change(com.thinkaurelius.titan.core.log.Change) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation) Entry(com.thinkaurelius.titan.diskstorage.Entry) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex) InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType) PropertyKey(com.thinkaurelius.titan.core.PropertyKey)

Example 10 with InternalRelation

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

the class EdgeSerializerTest method serialize.

private Entry serialize(StandardTitanGraph graph, TitanEdge e, int pos) {
    EdgeSerializer edgeSerializer = graph.getEdgeSerializer();
    InternalRelation r = (InternalRelation) e;
    return edgeSerializer.writeRelation(r, pos, r.tx());
}
Also used : EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation)

Aggregations

InternalRelation (com.thinkaurelius.titan.graphdb.internal.InternalRelation)14 InternalVertex (com.thinkaurelius.titan.graphdb.internal.InternalVertex)7 InternalRelationType (com.thinkaurelius.titan.graphdb.internal.InternalRelationType)5 MixedIndexType (com.thinkaurelius.titan.graphdb.types.MixedIndexType)3 TitanSchemaVertex (com.thinkaurelius.titan.graphdb.types.vertices.TitanSchemaVertex)3 Entry (com.thinkaurelius.titan.diskstorage.Entry)2 IndexEntry (com.thinkaurelius.titan.diskstorage.indexing.IndexEntry)2 IndexTransaction (com.thinkaurelius.titan.diskstorage.indexing.IndexTransaction)2 EdgeSerializer (com.thinkaurelius.titan.graphdb.database.EdgeSerializer)2 CompositeIndexType (com.thinkaurelius.titan.graphdb.types.CompositeIndexType)2 LongArrayList (com.carrotsearch.hppc.LongArrayList)1 LongHashSet (com.carrotsearch.hppc.LongHashSet)1 LongSet (com.carrotsearch.hppc.LongSet)1 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 EdgeLabel (com.thinkaurelius.titan.core.EdgeLabel)1 PropertyKey (com.thinkaurelius.titan.core.PropertyKey)1 RelationType (com.thinkaurelius.titan.core.RelationType)1 TitanElement (com.thinkaurelius.titan.core.TitanElement)1 TitanException (com.thinkaurelius.titan.core.TitanException)1