Search in sources :

Example 1 with IndexTransaction

use of org.janusgraph.diskstorage.indexing.IndexTransaction in project janusgraph by JanusGraph.

the class StandardTransactionLogProcessor method restoreExternalIndexes.

private void restoreExternalIndexes(Predicate<String> isFailedIndex, TransactionLogHeader.Entry entry) {
    // 1) Collect all elements (vertices and relations) and the indexes for which they need to be restored
    SetMultimap<String, IndexRestore> indexRestores = HashMultimap.create();
    BackendOperation.execute(() -> {
        final StandardJanusGraphTx tx = (StandardJanusGraphTx) graph.newTransaction();
        try {
            entry.getContentAsModifications(serializer).stream().map(m -> ModificationDeserializer.parseRelation(m, tx)).forEach(rel -> {
                // Collect affected vertex indexes
                for (final 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 (final RelationType relType : rel.getPropertyKeysDirect()) {
                    for (final 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 StandardJanusGraphTx tx = (StandardJanusGraphTx) 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();
                    indexRestores.get(indexName).forEach(restore -> {
                        JanusGraphSchemaVertex indexV = (JanusGraphSchemaVertex) tx.getVertex(restore.indexId);
                        MixedIndexType index = (MixedIndexType) indexV.asIndexType();
                        JanusGraphElement 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();
        }
    }
}
Also used : SchemaSource(org.janusgraph.graphdb.types.SchemaSource) org.janusgraph.diskstorage.log(org.janusgraph.diskstorage.log) StandardJanusGraphTx(org.janusgraph.graphdb.transaction.StandardJanusGraphTx) BackgroundThread(org.janusgraph.util.system.BackgroundThread) BackendOperation(org.janusgraph.diskstorage.util.BackendOperation) LoggerFactory(org.slf4j.LoggerFactory) IndexTransaction(org.janusgraph.diskstorage.indexing.IndexTransaction) HashCodeBuilder(org.apache.commons.lang.builder.HashCodeBuilder) Callable(java.util.concurrent.Callable) IndexTypeWrapper(org.janusgraph.graphdb.types.indextype.IndexTypeWrapper) JanusGraphTransaction(org.janusgraph.core.JanusGraphTransaction) Future(java.util.concurrent.Future) Serializer(org.janusgraph.graphdb.database.serialize.Serializer) IndexEntry(org.janusgraph.diskstorage.indexing.IndexEntry) Duration(java.time.Duration) Map(java.util.Map) Predicates(com.google.common.base.Predicates) MixedIndexType(org.janusgraph.graphdb.types.MixedIndexType) JanusGraphException(org.janusgraph.core.JanusGraphException) IndexType(org.janusgraph.graphdb.types.IndexType) com.google.common.collect(com.google.common.collect) LogTxStatus(org.janusgraph.graphdb.database.log.LogTxStatus) JanusGraphElement(org.janusgraph.core.JanusGraphElement) TransactionLogHeader(org.janusgraph.graphdb.database.log.TransactionLogHeader) TransactionRecovery(org.janusgraph.core.log.TransactionRecovery) RelationType(org.janusgraph.core.RelationType) Logger(org.slf4j.Logger) TimestampProvider(org.janusgraph.diskstorage.util.time.TimestampProvider) StandardJanusGraph(org.janusgraph.graphdb.database.StandardJanusGraph) JanusGraphSchemaVertex(org.janusgraph.graphdb.types.vertices.JanusGraphSchemaVertex) LogTxMeta(org.janusgraph.graphdb.database.log.LogTxMeta) Instant(java.time.Instant) ElementCategory(org.janusgraph.graphdb.internal.ElementCategory) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) com.google.common.cache(com.google.common.cache) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) RelationIdentifier(org.janusgraph.graphdb.relations.RelationIdentifier) Predicate(com.google.common.base.Predicate) GraphDatabaseConfiguration(org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration) Preconditions(com.google.common.base.Preconditions) InternalRelationType(org.janusgraph.graphdb.internal.InternalRelationType) Collections(java.util.Collections) org.janusgraph.diskstorage(org.janusgraph.diskstorage) MixedIndexType(org.janusgraph.graphdb.types.MixedIndexType) IndexTransaction(org.janusgraph.diskstorage.indexing.IndexTransaction) RelationIdentifier(org.janusgraph.graphdb.relations.RelationIdentifier) JanusGraphException(org.janusgraph.core.JanusGraphException) ExecutionException(java.util.concurrent.ExecutionException) JanusGraphElement(org.janusgraph.core.JanusGraphElement) StandardJanusGraphTx(org.janusgraph.graphdb.transaction.StandardJanusGraphTx) RelationType(org.janusgraph.core.RelationType) InternalRelationType(org.janusgraph.graphdb.internal.InternalRelationType) JanusGraphSchemaVertex(org.janusgraph.graphdb.types.vertices.JanusGraphSchemaVertex) List(java.util.List) Map(java.util.Map)

Example 2 with IndexTransaction

use of org.janusgraph.diskstorage.indexing.IndexTransaction in project janusgraph by JanusGraph.

the class BackendTransaction method rollback.

/**
 * Rolls back all transactions and makes sure that this does not get cut short
 * by exceptions. If exceptions occur, the storage exception takes priority on re-throw.
 * @throws BackendException
 */
@Override
public void rollback() throws BackendException {
    Throwable exception = null;
    for (IndexTransaction itx : indexTx.values()) {
        try {
            itx.rollback();
        } catch (Throwable e) {
            exception = e;
        }
    }
    storeTx.rollback();
    if (exception != null) {
        // throw any encountered index transaction rollback exceptions
        if (exception instanceof BackendException)
            throw (BackendException) exception;
        else
            throw new PermanentBackendException("Unexpected exception", exception);
    }
}
Also used : IndexTransaction(org.janusgraph.diskstorage.indexing.IndexTransaction)

Example 3 with IndexTransaction

use of org.janusgraph.diskstorage.indexing.IndexTransaction in project janusgraph by JanusGraph.

the class BackendTransaction method getIndexTransaction.

public IndexTransaction getIndexTransaction(String index) {
    Preconditions.checkArgument(StringUtils.isNotBlank(index));
    IndexTransaction itx = indexTx.get(index);
    Preconditions.checkNotNull(itx, "Unknown index: " + index);
    return itx;
}
Also used : IndexTransaction(org.janusgraph.diskstorage.indexing.IndexTransaction)

Example 4 with IndexTransaction

use of org.janusgraph.diskstorage.indexing.IndexTransaction in project janusgraph by JanusGraph.

the class StandardJanusGraph method prepareCommit.

public ModificationSummary prepareCommit(final Collection<InternalRelation> addedRelations, final Collection<InternalRelation> deletedRelations, final Predicate<InternalRelation> filter, final BackendTransaction mutator, final StandardJanusGraphTx 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);
        final List<InternalRelation> edges = mutations.get(vertexId);
        final List<Entry> additions = new ArrayList<>(edges.size());
        final List<Entry> deletions = new ArrayList<>(Math.max(10, edges.size() / 10));
        for (final InternalRelation edge : edges) {
            final 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()) {
            final 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 {
            final 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(org.janusgraph.diskstorage.indexing.IndexTransaction) IndexEntry(org.janusgraph.diskstorage.indexing.IndexEntry) InternalRelation(org.janusgraph.graphdb.internal.InternalRelation) StaticArrayEntry(org.janusgraph.diskstorage.util.StaticArrayEntry) IndexEntry(org.janusgraph.diskstorage.indexing.IndexEntry) StaticArrayEntry(org.janusgraph.diskstorage.util.StaticArrayEntry) MixedIndexType(org.janusgraph.graphdb.types.MixedIndexType) AtomicLong(java.util.concurrent.atomic.AtomicLong) InternalVertex(org.janusgraph.graphdb.internal.InternalVertex) CompositeIndexType(org.janusgraph.graphdb.types.CompositeIndexType) InternalRelationType(org.janusgraph.graphdb.internal.InternalRelationType)

Aggregations

IndexTransaction (org.janusgraph.diskstorage.indexing.IndexTransaction)4 AtomicLong (java.util.concurrent.atomic.AtomicLong)2 IndexEntry (org.janusgraph.diskstorage.indexing.IndexEntry)2 InternalRelationType (org.janusgraph.graphdb.internal.InternalRelationType)2 MixedIndexType (org.janusgraph.graphdb.types.MixedIndexType)2 LongArrayList (com.carrotsearch.hppc.LongArrayList)1 Preconditions (com.google.common.base.Preconditions)1 Predicate (com.google.common.base.Predicate)1 Predicates (com.google.common.base.Predicates)1 com.google.common.cache (com.google.common.cache)1 com.google.common.collect (com.google.common.collect)1 Duration (java.time.Duration)1 Instant (java.time.Instant)1 Collections (java.util.Collections)1 List (java.util.List)1 Map (java.util.Map)1 Callable (java.util.concurrent.Callable)1 ExecutionException (java.util.concurrent.ExecutionException)1 Future (java.util.concurrent.Future)1 TimeUnit (java.util.concurrent.TimeUnit)1