use of com.thinkaurelius.titan.diskstorage.BackendTransaction 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);
}
use of com.thinkaurelius.titan.diskstorage.BackendTransaction in project titan by thinkaurelius.
the class IndexRemoveJob method process.
@Override
public void process(StaticBuffer key, Map<SliceQuery, EntryList> entries, ScanMetrics metrics) {
//The queries are already tailored enough => everything should be removed
try {
BackendTransaction mutator = writeTx.getTxHandle();
final List<Entry> deletions;
if (entries.size() == 1)
deletions = Iterables.getOnlyElement(entries.values());
else {
int size = IteratorUtils.stream(entries.values().iterator()).map(e -> e.size()).reduce(0, (x, y) -> x + y);
deletions = new ArrayList<>(size);
entries.values().forEach(e -> deletions.addAll(e));
}
metrics.incrementCustom(DELETED_RECORDS_COUNT, deletions.size());
if (isRelationTypeIndex()) {
mutator.mutateEdges(key, KCVSCache.NO_ADDITIONS, deletions);
} else {
mutator.mutateIndex(key, KCVSCache.NO_ADDITIONS, deletions);
}
} catch (final Exception e) {
mgmt.rollback();
writeTx.rollback();
metrics.incrementCustom(FAILED_TX);
throw new TitanException(e.getMessage(), e);
}
}
use of com.thinkaurelius.titan.diskstorage.BackendTransaction in project titan by thinkaurelius.
the class IndexRepairJob method process.
@Override
public void process(TitanVertex vertex, ScanMetrics metrics) {
try {
BackendTransaction mutator = writeTx.getTxHandle();
if (index instanceof RelationTypeIndex) {
RelationTypeIndexWrapper wrapper = (RelationTypeIndexWrapper) index;
InternalRelationType wrappedType = wrapper.getWrappedType();
EdgeSerializer edgeSerializer = writeTx.getEdgeSerializer();
List<Entry> additions = new ArrayList<>();
for (TitanRelation relation : vertex.query().types(indexRelationTypeName).direction(Direction.OUT).relations()) {
InternalRelation titanRelation = (InternalRelation) relation;
for (int pos = 0; pos < titanRelation.getArity(); pos++) {
if (!wrappedType.isUnidirected(Direction.BOTH) && !wrappedType.isUnidirected(EdgeDirection.fromPosition(pos)))
//Directionality is not covered
continue;
Entry entry = edgeSerializer.writeRelation(titanRelation, wrappedType, pos, writeTx);
additions.add(entry);
}
}
StaticBuffer vertexKey = writeTx.getIdInspector().getKey(vertex.longId());
mutator.mutateEdges(vertexKey, additions, KCVSCache.NO_DELETIONS);
metrics.incrementCustom(ADDED_RECORDS_COUNT, additions.size());
} else if (index instanceof TitanGraphIndex) {
IndexType indexType = mgmt.getSchemaVertex(index).asIndexType();
assert indexType != null;
IndexSerializer indexSerializer = graph.getIndexSerializer();
//Gather elements to index
List<TitanElement> elements;
switch(indexType.getElement()) {
case VERTEX:
elements = ImmutableList.of(vertex);
break;
case PROPERTY:
elements = Lists.newArrayList();
for (TitanVertexProperty p : addIndexSchemaConstraint(vertex.query(), indexType).properties()) {
elements.add(p);
}
break;
case EDGE:
elements = Lists.newArrayList();
for (TitanEdge e : addIndexSchemaConstraint(vertex.query().direction(Direction.OUT), indexType).edges()) {
elements.add(e);
}
break;
default:
throw new AssertionError("Unexpected category: " + indexType.getElement());
}
if (indexType.isCompositeIndex()) {
for (TitanElement element : elements) {
Set<IndexSerializer.IndexUpdate<StaticBuffer, Entry>> updates = indexSerializer.reindexElement(element, (CompositeIndexType) indexType);
for (IndexSerializer.IndexUpdate<StaticBuffer, Entry> update : updates) {
log.debug("Mutating index {}: {}", indexType, update.getEntry());
mutator.mutateIndex(update.getKey(), Lists.newArrayList(update.getEntry()), KCVSCache.NO_DELETIONS);
metrics.incrementCustom(ADDED_RECORDS_COUNT);
}
}
} else {
assert indexType.isMixedIndex();
Map<String, Map<String, List<IndexEntry>>> documentsPerStore = new HashMap<>();
for (TitanElement element : elements) {
indexSerializer.reindexElement(element, (MixedIndexType) indexType, documentsPerStore);
metrics.incrementCustom(DOCUMENT_UPDATES_COUNT);
}
mutator.getIndexTransaction(indexType.getBackingIndexName()).restore(documentsPerStore);
}
} else
throw new UnsupportedOperationException("Unsupported index found: " + index);
} catch (final Exception e) {
mgmt.rollback();
writeTx.rollback();
metrics.incrementCustom(FAILED_TX);
throw new TitanException(e.getMessage(), e);
}
}
use of com.thinkaurelius.titan.diskstorage.BackendTransaction in project titan by thinkaurelius.
the class StandardTitanGraph method persist.
private <V extends InternalVertex> List<StaticBuffer> persist(ListMultimap<V, InternalRelation> mutatedEdges, StandardTitanTx tx) throws StorageException {
assert mutatedEdges != null && !mutatedEdges.isEmpty();
Collection<V> vertices = mutatedEdges.keySet();
BackendTransaction mutator = tx.getTxHandle();
List<StaticBuffer> mutatedKeys = new ArrayList<StaticBuffer>(vertices.size());
for (V vertex : vertices) {
Preconditions.checkArgument(vertex.getID() > 0, "Vertex has no id: %s", vertex.getID());
List<InternalRelation> edges = mutatedEdges.get(vertex);
List<Entry> additions = new ArrayList<Entry>(edges.size());
List<StaticBuffer> deletions = new ArrayList<StaticBuffer>(Math.max(10, edges.size() / 10));
for (InternalRelation edge : edges) {
for (int pos = 0; pos < edge.getLen(); pos++) {
if (edge.getVertex(pos).equals(vertex)) {
if (edge.isRemoved()) {
deletions.add(edgeSerializer.writeRelation(edge, pos, tx).getColumn());
} else {
Preconditions.checkArgument(edge.isNew());
additions.add(edgeSerializer.writeRelation(edge, pos, tx));
}
}
}
}
StaticBuffer vertexKey = IDHandler.getKey(vertex.getID());
mutator.mutateEdges(vertexKey, additions, deletions);
if (!vertex.isNew())
mutatedKeys.add(vertexKey);
// Index Updates
for (InternalRelation relation : edges) {
if (relation.getVertex(0).equals(vertex)) {
if (relation.isRemoved()) {
if (relation.isProperty()) {
indexSerializer.removeProperty((TitanProperty) relation, mutator);
} else if (relation.isEdge()) {
indexSerializer.removeEdge(relation, mutator);
}
} else {
Preconditions.checkArgument(relation.isNew());
if (relation.isProperty()) {
indexSerializer.addProperty((TitanProperty) relation, mutator);
} else {
indexSerializer.addEdge(relation, mutator);
}
}
}
}
}
return mutatedKeys;
}
Aggregations