use of com.thinkaurelius.titan.graphdb.internal.InternalRelation 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);
}
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");
}
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);
}
}
}
use of com.thinkaurelius.titan.graphdb.internal.InternalRelation in project titan by thinkaurelius.
the class SimpleBufferAddedRelations method cleanup.
private void cleanup() {
if (deleted == null || deleted.isEmpty())
return;
Set<InternalRelation> deletedSet = new HashSet<InternalRelation>(deleted);
deleted = null;
List<InternalRelation> newadded = new ArrayList<InternalRelation>(added.size() - deletedSet.size() / 2);
for (InternalRelation r : added) {
if (!deletedSet.contains(r))
newadded.add(r);
}
added = newadded;
}
use of com.thinkaurelius.titan.graphdb.internal.InternalRelation in project titan by thinkaurelius.
the class SimpleBufferAddedRelations method getView.
@Override
public List<InternalRelation> getView(Predicate<InternalRelation> filter) {
cleanup();
List<InternalRelation> result = new ArrayList<InternalRelation>();
for (InternalRelation r : added) {
if (filter.apply(r))
result.add(r);
}
return result;
}
Aggregations