Skip to content

Commit

Permalink
Merge pull request #4754 from ntisseyre/management_api
Browse files Browse the repository at this point in the history
Schema Management APIs for Enhanced Debugging in JanusGraph
  • Loading branch information
ntisseyre authored Jan 23, 2025
2 parents 53a5332 + 167758d commit 613996f
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import com.google.common.base.Preconditions;
import io.github.artsok.RepeatedIfExceptionsTest;
import org.apache.commons.codec.DecoderException;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.T;
Expand Down Expand Up @@ -582,6 +583,38 @@ public void testWriteAndReadWithJanusGraphIoRegistryWithGraphson(@TempDir Path t
testWritingAndReading(file.toFile());
}

@Test
public void testGetVertexId() throws DecoderException {

open(true, true);

mgmt.makeVertexLabel("cat").make();
makeKey("id", Integer.class);
makeKey("name", String.class);

mgmt.commit();

Vertex v1 = tx.addVertex(T.id, 1000L, T.label, "cat");
v1.property("id", 1);
v1.property("name", "cat_1");
Object vertexId1 = v1.id();

Vertex v2 = tx.addVertex(T.id, "id_cat2", T.label, "cat");
v2.property("id", 2);
v2.property("name", "cat_2");
Object vertexId2 = v2.id();

tx.commit();

mgmt = graph.openManagement();

String hex1 = mgmt.getVertexKey(vertexId1);
String hex2 = mgmt.getVertexKey(vertexId2);

assertEquals(vertexId1, mgmt.getVertexId(hex1));
assertEquals(vertexId2, mgmt.getVertexId(hex2));
}

private void testWritingAndReading(File f) {
GraphTraversalSource g = graph.traversal();
Vertex fromV = g.addV().property("name", f.getName()).property(T.id, "custom_id").next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import io.github.artsok.RepeatedIfExceptionsTest;
import org.apache.commons.codec.DecoderException;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
Expand Down Expand Up @@ -96,6 +97,8 @@
import org.janusgraph.graphdb.tinkerpop.optimize.step.JanusGraphStep;
import org.janusgraph.graphdb.tinkerpop.optimize.strategy.JanusGraphMixedIndexCountStrategy;
import org.janusgraph.graphdb.transaction.StandardJanusGraphTx;
import org.janusgraph.graphdb.types.CompositeIndexType;
import org.janusgraph.graphdb.types.IndexField;
import org.janusgraph.graphdb.types.MixedIndexType;
import org.janusgraph.graphdb.types.ParameterType;
import org.janusgraph.graphdb.types.StandardEdgeLabelMaker;
Expand Down Expand Up @@ -4346,4 +4349,37 @@ public void testMixedIndexAggregatedCountReturnsCorrectResult() {
);
}
}

@Test
public void testGetIndexInfo() throws DecoderException {

clopen();

mgmt.makeVertexLabel("cat").make();

makeKey("id", Integer.class);
final PropertyKey nameKey = makeKey("name", String.class);

String indexName = "searchByName";
mgmt.buildIndex(indexName, Vertex.class)
.addKey(nameKey)
.buildCompositeIndex();
mgmt.commit();

mgmt = graph.openManagement();

Map<String, Object> fieldValues = new HashMap<>();
fieldValues.put("name", "someName");

String hexString = mgmt.getIndexKey(indexName, fieldValues);
CompositeIndexType indexType = mgmt.getIndexInfo(hexString);

IndexField[] indexFields = new IndexField[1];
indexFields[0] = IndexField.of(nameKey);

assertEquals(indexName, indexType.getName());
assertEquals(1, indexType.getFieldKeys().length);
assertEquals(nameKey, indexType.getFieldKeys()[0].getFieldKey());
assertEquals(0, indexType.getInlineFieldKeys().length);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.janusgraph.core.schema;

import org.apache.commons.codec.DecoderException;
import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Element;
Expand All @@ -23,9 +24,11 @@
import org.janusgraph.core.RelationType;
import org.janusgraph.core.VertexLabel;
import org.janusgraph.diskstorage.keycolumnvalue.scan.ScanJobFuture;
import org.janusgraph.graphdb.types.CompositeIndexType;

import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
Expand Down Expand Up @@ -469,4 +472,33 @@ interface IndexBuilder {
*/
String printIndexes();

/**
* Get vertexId for the given hex string
* @param hexString
* @return vertex Id
* @throws DecoderException
*/
Object getVertexId(String hexString) throws DecoderException;

/**
* Get a hex string representing vertex id
* @param vertexId vertex id
* @return a hex string representing bytes of vertex id
*/
String getVertexKey(Object vertexId);

/**
* Get a hex string representing index key
* @param indexName schema index name
* @param fieldValues index fields with values
* @return a hex string representing bytes of index key
*/
String getIndexKey(String indexName, Map<String, Object> fieldValues);

/**
* Get index info from given hex string
* @param hexString
* @return composite index info
*/
CompositeIndexType getIndexInfo(String hexString) throws DecoderException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,10 @@ public long getIndexIdFromKey(StaticBuffer key) {
return IndexRecordUtil.getIndexIdFromKey(key, hashKeys, hashLength);
}

public StaticBuffer getIndexKey(CompositeIndexType index, Map<String, Object> fieldValues) {
return IndexRecordUtil.getIndexKey(index, fieldValues, serializer, hashKeys, hashLength);
}

public boolean isHashKeys() {
return hashKeys;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
Expand Down Expand Up @@ -51,6 +53,7 @@
import org.janusgraph.core.schema.SchemaStatus;
import org.janusgraph.core.schema.VertexLabelMaker;
import org.janusgraph.diskstorage.BackendException;
import org.janusgraph.diskstorage.StaticBuffer;
import org.janusgraph.diskstorage.configuration.BasicConfiguration;
import org.janusgraph.diskstorage.configuration.ConfigOption;
import org.janusgraph.diskstorage.configuration.ModifiableConfiguration;
Expand All @@ -62,6 +65,7 @@
import org.janusgraph.diskstorage.keycolumnvalue.scan.ScanMetrics;
import org.janusgraph.diskstorage.keycolumnvalue.scan.StandardScanner;
import org.janusgraph.diskstorage.log.Log;
import org.janusgraph.diskstorage.util.StaticArrayBuffer;
import org.janusgraph.graphdb.database.IndexSerializer;
import org.janusgraph.graphdb.database.StandardJanusGraph;
import org.janusgraph.graphdb.database.cache.SchemaCache;
Expand Down Expand Up @@ -545,6 +549,28 @@ public String printIndexes() {
return this.printIndexes(true);
}

@Override
public Object getVertexId(String hexString) throws DecoderException {
return this.graph.getIDManager().getKeyID(StaticArrayBuffer.of(Hex.decodeHex(hexString)));
}

@Override
public String getVertexKey(Object vertexId) {
return Hex.encodeHexString(graph.getIDManager().getKey(vertexId).asByteBuffer());
}

@Override
public String getIndexKey(String indexName, Map<String, Object> fieldValues) {
StaticBuffer staticBuffer = transaction.getCompositeIndexKey(indexName, fieldValues);
return Hex.encodeHexString(staticBuffer.asByteBuffer());
}

@Override
public CompositeIndexType getIndexInfo(String hexString) throws DecoderException {
StaticArrayBuffer indexKey = StaticArrayBuffer.of(Hex.decodeHex(hexString));
return transaction.getCompositeIndexInfo(indexKey);
}

private String printIndexes(boolean calledDirectly) {
StringBuilder sb = new StringBuilder();
String pattern = "%-30s | %-11s | %-9s | %-14s | %-10s %10s |%n";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import static org.janusgraph.util.encoding.LongEncoding.STRING_ENCODING_MARKER;

Expand Down Expand Up @@ -331,6 +332,19 @@ public static StaticBuffer getIndexKey(CompositeIndexType index, IndexRecordEntr
return getIndexKey(index, IndexRecordUtil.getValues(record), serializer, hashKeys, hashLength);
}

public static StaticBuffer getIndexKey(CompositeIndexType index, Map<String, Object> fieldValues, Serializer serializer, boolean hashKeys, HashingUtil.HashLength hashLength) {
Object[] values = Arrays.stream(index.getFieldKeys()).map(field -> {
String fieldName = field.getFieldKey().name();
if (fieldValues.containsKey(fieldName)) {
return fieldValues.get(fieldName);
} else {
throw new NoSuchElementException("Value for fieldName=" + fieldName + " is not provided for indexName=" + index.getName());
}
}).toArray();

return getIndexKey(index, values, serializer, hashKeys, hashLength);
}

public static StaticBuffer getIndexKey(CompositeIndexType index, Object[] values, Serializer serializer, boolean hashKeys, HashingUtil.HashLength hashLength) {
final DataOutput out = serializer.getDataOutput(8*DEFAULT_OBJECT_BYTELEN + 8);
VariableLong.writePositive(out, index.longId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@
import org.janusgraph.diskstorage.BackendException;
import org.janusgraph.diskstorage.BackendTransaction;
import org.janusgraph.diskstorage.EntryList;
import org.janusgraph.diskstorage.StaticBuffer;
import org.janusgraph.diskstorage.indexing.IndexTransaction;
import org.janusgraph.diskstorage.keycolumnvalue.MultiKeysQueryGroups;
import org.janusgraph.diskstorage.keycolumnvalue.SliceQuery;
import org.janusgraph.diskstorage.util.StaticArrayBuffer;
import org.janusgraph.diskstorage.util.time.TimestampProvider;
import org.janusgraph.graphdb.database.EdgeSerializer;
import org.janusgraph.graphdb.database.IndexSerializer;
Expand Down Expand Up @@ -1243,6 +1245,34 @@ public VertexLabel getOrCreateVertexLabel(String name) {
return vertexLabel;
}

public StaticBuffer getCompositeIndexKey(String indexName, Map<String, Object> fieldValues) {
JanusGraphSchemaVertex schemaVertex = getSchemaVertex(JanusGraphSchemaCategory.GRAPHINDEX.getSchemaName(indexName));
Preconditions.checkNotNull(schemaVertex, "Index with name [" + indexName + "] was not found");
IndexType indexType = schemaVertex.asIndexType();
if (indexType instanceof CompositeIndexType) {
CompositeIndexType compositeIndex = (CompositeIndexType) indexType;
StaticBuffer indexKey = indexSerializer.getIndexKey(compositeIndex, fieldValues);
return indexKey;
} else {
throw new IllegalArgumentException("Index with name [" + indexName + "] is not a composite index");
}
}

public CompositeIndexType getCompositeIndexInfo(StaticArrayBuffer indexKey) {
long schemaVertexId = indexSerializer.getIndexIdFromKey(indexKey);
InternalVertex typeVertex = vertexCache.get(schemaVertexId, existingVertexRetriever);

Preconditions.checkNotNull(typeVertex, "Index with key [" + indexKey + "] was not found");
JanusGraphSchemaVertex schemaVertex = (JanusGraphSchemaVertex) typeVertex;

IndexType indexType = schemaVertex.asIndexType();
if (indexType instanceof CompositeIndexType) {
return (CompositeIndexType) indexType;
} else {
throw new IllegalArgumentException("Index with key [" + indexKey + "] is not a composite index");
}
}

@Override
public VertexLabelMaker makeVertexLabel(String name) {
StandardVertexLabelMaker maker = new StandardVertexLabelMaker(this);
Expand Down

1 comment on commit 613996f

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 613996f Previous: 53a5332 Ratio
org.janusgraph.JanusGraphSpeedBenchmark.basicAddAndDelete 12753.333254140442 ms/op 12606.637936248144 ms/op 1.01
org.janusgraph.GraphCentricQueryBenchmark.getVertices 943.0529720702746 ms/op 933.707013771124 ms/op 1.01
org.janusgraph.MgmtOlapJobBenchmark.runClearIndex 216.80353305942026 ms/op 216.42669925797105 ms/op 1.00
org.janusgraph.MgmtOlapJobBenchmark.runReindex 325.0486575141667 ms/op 325.2034199216667 ms/op 1.00
org.janusgraph.JanusGraphSpeedBenchmark.basicCount 229.37718654643322 ms/op 241.37535189160565 ms/op 0.95
org.janusgraph.CQLMultiQueryMultiSlicesBenchmark.getValuesAllPropertiesWithAllMultiQuerySlicesUnderMaxRequestsPerConnection 4861.000276808747 ms/op 4702.35119956595 ms/op 1.03
org.janusgraph.CQLMultiQueryBenchmark.getElementsWithUsingEmitRepeatSteps 16322.318674389364 ms/op 16231.144626673333 ms/op 1.01
org.janusgraph.CQLMultiQueryMultiSlicesBenchmark.getValuesMultiplePropertiesWithSmallBatch 19340.43921571359 ms/op 18874.23529971717 ms/op 1.02
org.janusgraph.CQLMultiQueryMultiSlicesBenchmark.vertexCentricPropertiesFetching 58571.32120596667 ms/op 57429.257257799996 ms/op 1.02
org.janusgraph.CQLMultiQueryDropBenchmark.dropVertices 1635.7050576543322 ms/op 1568.3338987479272 ms/op 1.04
org.janusgraph.CQLMultiQueryBenchmark.getAllElementsTraversedFromOuterVertex 7830.5603333385725 ms/op 7848.466185459547 ms/op 1.00
org.janusgraph.CQLMultiQueryBenchmark.getVerticesWithDoubleUnion 381.75296376773844 ms/op 381.3076924089574 ms/op 1.00
org.janusgraph.CQLMultiQueryMultiSlicesBenchmark.getValuesAllPropertiesWithUnlimitedBatch 3995.3895422109754 ms/op 3925.9151810796147 ms/op 1.02
org.janusgraph.CQLMultiQueryBenchmark.getNames 7931.8440840538005 ms/op 7999.962392196457 ms/op 0.99
org.janusgraph.CQLMultiQueryMultiSlicesBenchmark.getValuesThreePropertiesWithAllMultiQuerySlicesUnderMaxRequestsPerConnection 5355.785625598493 ms/op 5428.037913477006 ms/op 0.99
org.janusgraph.CQLMultiQueryBenchmark.getLabels 6772.8245748223035 ms/op 6696.0079414739175 ms/op 1.01
org.janusgraph.CQLMultiQueryBenchmark.getVerticesFilteredByAndStep 426.31122717925837 ms/op 448.75009294589086 ms/op 0.95
org.janusgraph.CQLMultiQueryBenchmark.getVerticesFromMultiNestedRepeatStepStartingFromSingleVertex 12729.107438812136 ms/op 12367.791196107844 ms/op 1.03
org.janusgraph.CQLMultiQueryBenchmark.getVerticesWithCoalesceUsage 362.54030692799665 ms/op 367.30972053799104 ms/op 0.99
org.janusgraph.CQLMultiQueryMultiSlicesBenchmark.getValuesMultiplePropertiesWithAllMultiQuerySlicesUnderMaxRequestsPerConnection 13132.65976805517 ms/op 14518.526449692697 ms/op 0.90
org.janusgraph.CQLMultiQueryBenchmark.getIdToOutVerticesProjection 248.22354164552596 ms/op 255.05417396928058 ms/op 0.97
org.janusgraph.CQLMultiQueryMultiSlicesBenchmark.getValuesMultiplePropertiesWithUnlimitedBatch 14411.78975573911 ms/op 14575.609847963999 ms/op 0.99
org.janusgraph.CQLCompositeIndexInlinePropBenchmark.searchVertices 1646.020017087073 ms/op 1552.5877175318828 ms/op 1.06
org.janusgraph.CQLMultiQueryDropBenchmark.dropVerticesGremlinQuery 1666.08106022869 ms/op 1585.1790679378414 ms/op 1.05
org.janusgraph.CQLMultiQueryBenchmark.getNeighborNames 7742.249230307721 ms/op 7881.313643353237 ms/op 0.98
org.janusgraph.CQLMultiQueryBenchmark.getElementsWithUsingRepeatUntilSteps 8837.498024568966 ms/op 8781.835625855028 ms/op 1.01
org.janusgraph.CQLMultiQueryBenchmark.getAdjacentVerticesLocalCounts 8306.772164947897 ms/op 8207.534452278742 ms/op 1.01

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.