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();
}
}
}
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);
}
}
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;
}
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);
}
Aggregations