use of org.apache.tinkerpop.gremlin.structure.Direction in project janusgraph by JanusGraph.
the class IndexRepairJob method process.
@Override
public void process(JanusGraphVertex 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> outAdditions = new ArrayList<>();
Map<StaticBuffer, List<Entry>> inAdditionsMap = new HashMap<>();
for (Object relation : vertex.query().types(indexRelationTypeName).direction(Direction.OUT).relations()) {
InternalRelation janusgraphRelation = (InternalRelation) relation;
for (int pos = 0; pos < janusgraphRelation.getArity(); pos++) {
if (!wrappedType.isUnidirected(Direction.BOTH) && !wrappedType.isUnidirected(EdgeDirection.fromPosition(pos)))
// Directionality is not covered
continue;
Entry entry = edgeSerializer.writeRelation(janusgraphRelation, wrappedType, pos, writeTx);
if (pos == 0) {
outAdditions.add(entry);
} else {
assert pos == 1;
InternalVertex otherVertex = janusgraphRelation.getVertex(1);
StaticBuffer otherVertexKey = writeTx.getIdInspector().getKey(otherVertex.longId());
inAdditionsMap.computeIfAbsent(otherVertexKey, k -> new ArrayList<>()).add(entry);
}
}
}
// Mutating all OUT relationships for the current vertex
StaticBuffer vertexKey = writeTx.getIdInspector().getKey(vertex.longId());
mutator.mutateEdges(vertexKey, outAdditions, KCVSCache.NO_DELETIONS);
// Mutating all IN relationships for the current vertex
int totalInAdditions = 0;
for (Map.Entry<StaticBuffer, List<Entry>> entry : inAdditionsMap.entrySet()) {
StaticBuffer otherVertexKey = entry.getKey();
List<Entry> inAdditions = entry.getValue();
totalInAdditions += inAdditions.size();
mutator.mutateEdges(otherVertexKey, inAdditions, KCVSCache.NO_DELETIONS);
}
metrics.incrementCustom(ADDED_RECORDS_COUNT, outAdditions.size() + totalInAdditions);
} else if (index instanceof JanusGraphIndex) {
IndexType indexType = managementSystem.getSchemaVertex(index).asIndexType();
assert indexType != null;
IndexSerializer indexSerializer = graph.getIndexSerializer();
// Gather elements to index
List<JanusGraphElement> elements;
switch(indexType.getElement()) {
case VERTEX:
elements = Collections.singletonList(vertex);
break;
case PROPERTY:
elements = new ArrayList<>();
addIndexSchemaConstraint(vertex.query(), indexType).properties().forEach(elements::add);
break;
case EDGE:
elements = new ArrayList<>();
addIndexSchemaConstraint(vertex.query().direction(Direction.OUT), indexType).edges().forEach(elements::add);
break;
default:
throw new AssertionError("Unexpected category: " + indexType.getElement());
}
if (indexType.isCompositeIndex()) {
for (JanusGraphElement 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(), new ArrayList<Entry>(1) {
{
add(update.getEntry());
}
}, KCVSCache.NO_DELETIONS);
metrics.incrementCustom(ADDED_RECORDS_COUNT);
}
}
} else {
assert indexType.isMixedIndex();
for (JanusGraphElement element : elements) {
if (indexSerializer.reindexElement(element, (MixedIndexType) indexType, documentsPerStore)) {
metrics.incrementCustom(DOCUMENT_UPDATES_COUNT);
}
}
}
} else
throw new UnsupportedOperationException("Unsupported index found: " + index);
} catch (final Exception e) {
managementSystem.rollback();
writeTx.rollback();
metrics.incrementCustom(FAILED_TX);
throw new JanusGraphException(e.getMessage(), e);
}
}
use of org.apache.tinkerpop.gremlin.structure.Direction in project janusgraph by JanusGraph.
the class JanusGraphTest method testReindexingForEdgeIndex.
@Test
public void testReindexingForEdgeIndex() throws InterruptedException, ExecutionException {
// Schema creation
String edgeLabelName = "egLabel";
String propertyKeyForIn = "assocKindForIn";
String propertyKeyForOut = "assocKindForOut";
String propertyKeyForBoth = "assocKindForBoth";
EdgeLabel edgeLabel = mgmt.makeEdgeLabel(edgeLabelName).multiplicity(Multiplicity.MULTI).make();
mgmt.makePropertyKey("vtName").dataType(String.class).cardinality(Cardinality.SINGLE).make();
PropertyKey propAssocKindIn = mgmt.makePropertyKey(propertyKeyForIn).dataType(Integer.class).cardinality(Cardinality.SINGLE).make();
PropertyKey propAssocKindOut = mgmt.makePropertyKey(propertyKeyForOut).dataType(Integer.class).cardinality(Cardinality.SINGLE).make();
PropertyKey propAssocKindBoth = mgmt.makePropertyKey(propertyKeyForBoth).dataType(Integer.class).cardinality(Cardinality.SINGLE).make();
finishSchema();
// Create Vertex
JanusGraphVertex a = tx.addVertex();
a.property("vtName", "A");
JanusGraphVertex b = tx.addVertex();
b.property("vtName", "B");
// Add Edges
a.addEdge(edgeLabelName, b, propertyKeyForIn, 1, propertyKeyForOut, 1, propertyKeyForBoth, 1);
b.addEdge(edgeLabelName, a, propertyKeyForIn, 2, propertyKeyForOut, 2, propertyKeyForBoth, 2);
tx.commit();
// Index creation
String indexWithDirectionIn = "edgesByAssocKindIn";
String indexWithDirectionOut = "edgesByAssocKindOut";
String indexWithDirectionBoth = "edgesByAssocKindBoth";
mgmt.buildEdgeIndex(mgmt.getEdgeLabel(edgeLabelName), indexWithDirectionIn, IN, mgmt.getPropertyKey(propertyKeyForIn));
mgmt.buildEdgeIndex(mgmt.getEdgeLabel(edgeLabelName), indexWithDirectionOut, OUT, mgmt.getPropertyKey(propertyKeyForOut));
mgmt.buildEdgeIndex(mgmt.getEdgeLabel(edgeLabelName), indexWithDirectionBoth, BOTH, mgmt.getPropertyKey(propertyKeyForBoth));
mgmt.commit();
ManagementSystem.awaitRelationIndexStatus(graph, indexWithDirectionIn, edgeLabelName).call();
ManagementSystem.awaitRelationIndexStatus(graph, indexWithDirectionOut, edgeLabelName).call();
ManagementSystem.awaitRelationIndexStatus(graph, indexWithDirectionBoth, edgeLabelName).call();
finishSchema();
mgmt.updateIndex(mgmt.getRelationIndex(mgmt.getRelationType(edgeLabelName), indexWithDirectionIn), SchemaAction.ENABLE_INDEX).get();
mgmt.updateIndex(mgmt.getRelationIndex(mgmt.getRelationType(edgeLabelName), indexWithDirectionOut), SchemaAction.ENABLE_INDEX).get();
mgmt.updateIndex(mgmt.getRelationIndex(mgmt.getRelationType(edgeLabelName), indexWithDirectionBoth), SchemaAction.ENABLE_INDEX).get();
finishSchema();
Vertex v1 = tx.traversal().V().has("vtName", "A").next();
Vertex v2 = tx.traversal().V().has("vtName", "B").next();
Vertex[] vertices = new Vertex[] { v1, v1, v1, v1, v1, v1, v2, v2, v2, v2, v2, v2 };
int[] propValues = new int[] { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 };
Direction[] dirs = new Direction[] { IN, IN, OUT, OUT, BOTH, BOTH, IN, IN, OUT, OUT, BOTH, BOTH };
// vertex-centric index is already enabled, but before existing data is reindexed, any query that hits index will return 0
performReindexAndVerifyEdgeCount(indexWithDirectionOut, edgeLabelName, propertyKeyForOut, vertices, propValues, dirs, new int[] { 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0 });
performReindexAndVerifyEdgeCount(indexWithDirectionIn, edgeLabelName, propertyKeyForIn, vertices, propValues, dirs, new int[] { 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1 });
performReindexAndVerifyEdgeCount(indexWithDirectionBoth, edgeLabelName, propertyKeyForBoth, vertices, propValues, dirs, new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
}
use of org.apache.tinkerpop.gremlin.structure.Direction in project janusgraph by JanusGraph.
the class EdgeSerializer method writeRelation.
public StaticArrayEntry writeRelation(InternalRelation relation, InternalRelationType type, int position, TypeInspector tx) {
assert type == relation.getType() || (type.getBaseType() != null && type.getBaseType().equals(relation.getType()));
Direction dir = EdgeDirection.fromPosition(position);
Preconditions.checkArgument(type.isUnidirected(Direction.BOTH) || type.isUnidirected(dir));
long typeId = type.longId();
DirectionID dirID = getDirID(dir, relation.isProperty() ? RelationCategory.PROPERTY : RelationCategory.EDGE);
DataOutput out = serializer.getDataOutput(DEFAULT_CAPACITY);
int valuePosition;
IDHandler.writeRelationType(out, typeId, dirID, type.isInvisibleType());
Multiplicity multiplicity = type.multiplicity();
long[] sortKey = type.getSortKey();
assert !multiplicity.isConstrained() || sortKey.length == 0 : type.name();
int keyStartPos = out.getPosition();
if (!multiplicity.isConstrained()) {
writeInlineTypes(sortKey, relation, out, tx, InlineType.KEY);
}
int keyEndPos = out.getPosition();
long relationId = relation.longId();
// How multiplicity is handled for edges and properties is slightly different
if (relation.isEdge()) {
long otherVertexId = relation.getVertex((position + 1) % 2).longId();
if (multiplicity.isConstrained()) {
if (multiplicity.isUnique(dir)) {
valuePosition = out.getPosition();
VariableLong.writePositive(out, otherVertexId);
} else {
VariableLong.writePositiveBackward(out, otherVertexId);
valuePosition = out.getPosition();
}
VariableLong.writePositive(out, relationId);
} else {
VariableLong.writePositiveBackward(out, otherVertexId);
VariableLong.writePositiveBackward(out, relationId);
valuePosition = out.getPosition();
}
} else {
Preconditions.checkArgument(relation.isProperty(), "Given relation is not property");
Object value = ((JanusGraphVertexProperty) relation).value();
Preconditions.checkNotNull(value);
PropertyKey key = (PropertyKey) type;
assert key.dataType().isInstance(value);
if (multiplicity.isConstrained()) {
if (multiplicity.isUnique(dir)) {
// Cardinality=SINGLE
valuePosition = out.getPosition();
writePropertyValue(out, key, value);
} else {
// Cardinality=SET
writePropertyValue(out, key, value);
valuePosition = out.getPosition();
}
VariableLong.writePositive(out, relationId);
} else {
assert multiplicity.getCardinality() == Cardinality.LIST;
VariableLong.writePositiveBackward(out, relationId);
valuePosition = out.getPosition();
writePropertyValue(out, key, value);
}
}
// Write signature
long[] signature = type.getSignature();
writeInlineTypes(signature, relation, out, tx, InlineType.SIGNATURE);
// Write remaining properties
LongSet writtenTypes = new LongHashSet(sortKey.length + signature.length);
if (sortKey.length > 0 || signature.length > 0) {
for (long id : sortKey) writtenTypes.add(id);
for (long id : signature) writtenTypes.add(id);
}
LongArrayList remainingTypes = new LongArrayList(8);
for (PropertyKey t : relation.getPropertyKeysDirect()) {
if (!(t instanceof ImplicitKey) && !writtenTypes.contains(t.longId())) {
remainingTypes.add(t.longId());
}
}
// Sort types before writing to ensure that value is always written the same way
long[] remaining = remainingTypes.toArray();
Arrays.sort(remaining);
for (long tid : remaining) {
PropertyKey t = tx.getExistingPropertyKey(tid);
writeInline(out, t, relation.getValueDirect(t), InlineType.NORMAL);
}
assert valuePosition > 0;
return new StaticArrayEntry(type.getSortOrder() == Order.DESC ? out.getStaticBufferFlipBytes(keyStartPos, keyEndPos) : out.getStaticBuffer(), valuePosition);
}
use of org.apache.tinkerpop.gremlin.structure.Direction in project janusgraph by JanusGraph.
the class AdjacentVertexFilterOptimizerStrategy method replaceStep.
private void replaceStep(Traversal.Admin<?, ?> traversal, OptimizableQueryType type, TraversalFilterStep originalStep, List<Step> steps) {
// Get the direction in which we filter on the adjacent vertex (or null if not a valid
// adjacency filter)
Direction direction = parseDirection(steps);
P predicate = parsePredicate(type, steps);
// Check that we have a valid direction and a valid vertex filter predicate
if (direction != null && isValidPredicate(type, predicate) && isPreviousStepValid(originalStep, direction)) {
// Now replace the step with a has condition
HasContainer hc = new HasContainer(ImplicitKey.ADJACENT_ID.name(), P.eq(predicate.getValue()));
TraversalHelper.replaceStep(originalStep, new HasStep(traversal, hc), traversal);
}
}
use of org.apache.tinkerpop.gremlin.structure.Direction in project janusgraph by JanusGraph.
the class AdjacentVertexOptimizerStrategy method replaceSequenceV2VthenID.
private void replaceSequenceV2VthenID(T originalStep) {
Traversal.Admin<?, ?> traversal = originalStep.getTraversal();
// remove obsolete NoOpBarrier
if (originalStep.getPreviousStep() instanceof NoOpBarrierStep) {
traversal.removeStep(originalStep.getPreviousStep());
}
// create new V2E step based on old V2V step
VertexStep<?> v2vStep = (VertexStep<?>) originalStep.getPreviousStep();
String[] edgeLabels = v2vStep.getEdgeLabels();
Direction v2vDirection = v2vStep.getDirection();
VertexStep<Edge> v2eStep = new VertexStep<>(traversal, Edge.class, v2vDirection, edgeLabels);
// create new E2V step based on old V2V step
Step<Edge, Vertex> e2vStep;
if (v2vDirection == Direction.BOTH) {
e2vStep = new EdgeOtherVertexStep(traversal);
} else {
e2vStep = new EdgeVertexStep(traversal, v2vDirection.opposite());
}
originalStep.getLabels().forEach(e2vStep::addLabel);
Step<?, Vertex> predecessor = v2vStep.getPreviousStep();
// drop old steps
traversal.removeStep(originalStep);
traversal.removeStep(v2vStep);
// create new has("~adjacent", id_value) step before e2v step
FilterStep<Edge> filterByAdjacentIdStep = makeFilterByAdjacentIdStep(traversal, originalStep);
// insert new steps
TraversalHelper.insertAfterStep(v2eStep, predecessor, traversal);
TraversalHelper.insertAfterStep(filterByAdjacentIdStep, v2eStep, traversal);
TraversalHelper.insertAfterStep(e2vStep, filterByAdjacentIdStep, traversal);
}
Aggregations