use of org.janusgraph.core.JanusGraphElement 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.janusgraph.core.JanusGraphElement 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.core.JanusGraphElement in project janusgraph by JanusGraph.
the class JanusGraphTest method evaluateQuery.
public static void evaluateQuery(JanusGraphQuery query, ElementCategory resultType, int expectedResults, boolean[] subQuerySpecs, Map<PropertyKey, Order> orderMap, String... intersectingIndexes) {
if (intersectingIndexes == null)
intersectingIndexes = new String[0];
SimpleQueryProfiler profiler = new SimpleQueryProfiler();
((GraphCentricQueryBuilder) query).profiler(profiler);
Iterable<? extends JanusGraphElement> result;
switch(resultType) {
case PROPERTY:
result = query.properties();
break;
case EDGE:
result = query.edges();
break;
case VERTEX:
result = query.vertices();
break;
default:
throw new AssertionError();
}
OrderList orders = profiler.getAnnotation(QueryProfiler.ORDERS_ANNOTATION);
// Check elements and that they are returned in the correct order
int no = 0;
JanusGraphElement previous = null;
for (JanusGraphElement e : result) {
assertNotNull(e);
no++;
if (previous != null && !orders.isEmpty()) {
assertTrue(orders.compare(previous, e) <= 0);
}
previous = e;
}
assertEquals(expectedResults, no);
// Check OrderList of query
assertNotNull(orders);
assertEquals(orderMap.size(), orders.size());
for (int i = 0; i < orders.size(); i++) {
assertEquals(orderMap.get(orders.getKey(i)), orders.getOrder(i));
}
for (PropertyKey key : orderMap.keySet()) assertTrue(orders.containsKey(key));
// Check subqueries
SimpleQueryProfiler simpleQueryProfiler = Iterables.getOnlyElement(StreamSupport.stream(profiler.spliterator(), false).filter(p -> !p.getGroupName().equals(QueryProfiler.OPTIMIZATION)).collect(Collectors.toList()));
if (subQuerySpecs.length == 2) {
// 0=>fitted, 1=>ordered
assertEquals(subQuerySpecs[0], simpleQueryProfiler.getAnnotation(QueryProfiler.FITTED_ANNOTATION));
assertEquals(subQuerySpecs[1], simpleQueryProfiler.getAnnotation(QueryProfiler.ORDERED_ANNOTATION));
}
Set<String> indexNames = new HashSet<>();
int indexQueries = 0;
boolean fullScan = false;
for (SimpleQueryProfiler indexProfiler : simpleQueryProfiler) {
if (indexProfiler.getAnnotation(QueryProfiler.FULLSCAN_ANNOTATION) != null) {
fullScan = true;
} else {
indexNames.add(indexProfiler.getAnnotation(QueryProfiler.INDEX_ANNOTATION));
indexQueries++;
}
}
if (indexQueries > 0)
assertFalse(fullScan);
if (fullScan)
assertEquals(0, intersectingIndexes.length);
assertEquals(intersectingIndexes.length, indexQueries);
assertEquals(Sets.newHashSet(intersectingIndexes), indexNames);
}
use of org.janusgraph.core.JanusGraphElement in project janusgraph by JanusGraph.
the class JanusGraphTest method evaluateQuery.
public static void evaluateQuery(JanusGraphVertexQuery query, RelationCategory resultType, int expectedResults, int numSubQueries, boolean[] subQuerySpecs, Map<PropertyKey, Order> orderMap) {
SimpleQueryProfiler profiler = new SimpleQueryProfiler();
((BasicVertexCentricQueryBuilder) query).profiler(profiler);
Iterable<? extends JanusGraphElement> result;
switch(resultType) {
case PROPERTY:
result = query.properties();
break;
case EDGE:
result = query.edges();
break;
case RELATION:
result = query.relations();
break;
default:
throw new AssertionError();
}
OrderList orders = profiler.getAnnotation(QueryProfiler.ORDERS_ANNOTATION);
// Check elements and that they are returned in the correct order
int no = 0;
JanusGraphElement previous = null;
for (JanusGraphElement e : result) {
assertNotNull(e);
no++;
if (previous != null && !orders.isEmpty()) {
assertTrue(orders.compare(previous, e) <= 0);
}
previous = e;
}
assertEquals(expectedResults, no);
// Check OrderList of query
assertNotNull(orders);
assertEquals(orderMap.size(), orders.size());
for (int i = 0; i < orders.size(); i++) {
assertEquals(orderMap.get(orders.getKey(i)), orders.getOrder(i));
}
for (PropertyKey key : orderMap.keySet()) assertTrue(orders.containsKey(key));
// Check subqueries
assertEquals(Integer.valueOf(1), profiler.getAnnotation(QueryProfiler.NUMVERTICES_ANNOTATION));
int subQueryCounter = 0;
for (SimpleQueryProfiler subProfiler : profiler) {
assertNotNull(subProfiler);
if (subProfiler.getGroupName().equals(QueryProfiler.OPTIMIZATION))
continue;
if (subQuerySpecs.length == 2) {
// 0=>fitted, 1=>ordered
assertEquals(subQuerySpecs[0], subProfiler.getAnnotation(QueryProfiler.FITTED_ANNOTATION));
assertEquals(subQuerySpecs[1], subProfiler.getAnnotation(QueryProfiler.ORDERED_ANNOTATION));
}
// assertEquals(1,Iterables.size(subProfiler)); This only applies if a disk call is necessary
subQueryCounter++;
}
assertEquals(numSubQueries, subQueryCounter);
}
use of org.janusgraph.core.JanusGraphElement in project janusgraph by JanusGraph.
the class IndexSerializerTest method mockIndexAppliesTo.
private JanusGraphElement mockIndexAppliesTo(MixedIndexType mit, boolean indexable) {
String key = "foo";
String value = "bar";
JanusGraphElement indexableElement = mockIndexableElement(key, value, indexable);
ElementCategory ec = ElementCategory.VERTEX;
doReturn(ec).when(mit).getElement();
doReturn(false).when(mit).hasSchemaTypeConstraint();
PropertyKey pk = mock(PropertyKey.class);
doReturn(1L).when(pk).longId();
doReturn(key).when(pk).name();
ParameterIndexField pif = mock(ParameterIndexField.class);
Parameter[] parameter = { new Parameter(key, value) };
doReturn(parameter).when(pif).getParameters();
doReturn(SchemaStatus.REGISTERED).when(pif).getStatus();
doReturn(pk).when(pif).getFieldKey();
ParameterIndexField[] ifField = { pif };
doReturn(ifField).when(mit).getFieldKeys();
return indexableElement;
}
Aggregations