Search in sources :

Example 1 with EdgeSerializer

use of com.thinkaurelius.titan.graphdb.database.EdgeSerializer in project titan by thinkaurelius.

the class TitanGraphTest method simpleLogTest.

public void simpleLogTest(final boolean withLogFailure) throws InterruptedException {
    final String userlogName = "test";
    final Serializer serializer = graph.getDataSerializer();
    final EdgeSerializer edgeSerializer = graph.getEdgeSerializer();
    final TimestampProvider times = graph.getConfiguration().getTimestampProvider();
    final Instant startTime = times.getTime();
    clopen(option(SYSTEM_LOG_TRANSACTIONS), true, option(LOG_BACKEND, USER_LOG), (withLogFailure ? TestMockLog.class.getName() : LOG_BACKEND.getDefaultValue()), option(TestMockLog.LOG_MOCK_FAILADD, USER_LOG), withLogFailure, option(KCVSLog.LOG_READ_LAG_TIME, USER_LOG), Duration.ofMillis(50), option(LOG_READ_INTERVAL, USER_LOG), Duration.ofMillis(250), option(LOG_SEND_DELAY, USER_LOG), Duration.ofMillis(100), option(KCVSLog.LOG_READ_LAG_TIME, TRANSACTION_LOG), Duration.ofMillis(50), option(LOG_READ_INTERVAL, TRANSACTION_LOG), Duration.ofMillis(250), option(MAX_COMMIT_TIME), Duration.ofSeconds(1));
    final String instanceid = graph.getConfiguration().getUniqueGraphId();
    PropertyKey weight = tx.makePropertyKey("weight").dataType(Float.class).cardinality(Cardinality.SINGLE).make();
    EdgeLabel knows = tx.makeEdgeLabel("knows").make();
    TitanVertex n1 = tx.addVertex("weight", 10.5);
    newTx();
    final Instant[] txTimes = new Instant[4];
    //Transaction with custom userlog name
    txTimes[0] = times.getTime();
    TitanTransaction tx2 = graph.buildTransaction().logIdentifier(userlogName).start();
    TitanVertex v1 = tx2.addVertex("weight", 111.1);
    v1.addEdge("knows", v1);
    tx2.commit();
    final long v1id = getId(v1);
    txTimes[1] = times.getTime();
    tx2 = graph.buildTransaction().logIdentifier(userlogName).start();
    TitanVertex v2 = tx2.addVertex("weight", 222.2);
    v2.addEdge("knows", getV(tx2, v1id));
    tx2.commit();
    final long v2id = getId(v2);
    //Only read tx
    tx2 = graph.buildTransaction().logIdentifier(userlogName).start();
    v1 = getV(tx2, v1id);
    assertEquals(111.1, v1.<Float>value("weight").doubleValue(), 0.01);
    assertEquals(222.2, getV(tx2, v2).<Float>value("weight").doubleValue(), 0.01);
    tx2.commit();
    //Deleting transaction
    txTimes[2] = times.getTime();
    tx2 = graph.buildTransaction().logIdentifier(userlogName).start();
    v2 = getV(tx2, v2id);
    assertEquals(222.2, v2.<Float>value("weight").doubleValue(), 0.01);
    v2.remove();
    tx2.commit();
    //Edge modifying transaction
    txTimes[3] = times.getTime();
    tx2 = graph.buildTransaction().logIdentifier(userlogName).start();
    v1 = getV(tx2, v1id);
    assertEquals(111.1, v1.<Float>value("weight").doubleValue(), 0.01);
    Edge e = getOnlyElement(v1.query().direction(Direction.OUT).labels("knows").edges());
    assertFalse(e.property("weight").isPresent());
    e.property("weight", 44.4);
    tx2.commit();
    close();
    final Instant endTime = times.getTime();
    final ReadMarker startMarker = ReadMarker.fromTime(startTime);
    Log txlog = openTxLog();
    Log userLog = openUserLog(userlogName);
    final EnumMap<LogTxStatus, AtomicInteger> txMsgCounter = new EnumMap<LogTxStatus, AtomicInteger>(LogTxStatus.class);
    for (LogTxStatus status : LogTxStatus.values()) txMsgCounter.put(status, new AtomicInteger(0));
    final AtomicInteger userlogMeta = new AtomicInteger(0);
    txlog.registerReader(startMarker, new MessageReader() {

        @Override
        public void read(Message message) {
            Instant msgTime = message.getTimestamp();
            assertTrue(msgTime.isAfter(startTime) || msgTime.equals(startTime));
            assertNotNull(message.getSenderId());
            TransactionLogHeader.Entry txEntry = TransactionLogHeader.parse(message.getContent(), serializer, times);
            TransactionLogHeader header = txEntry.getHeader();
            //                System.out.println(header.getTimestamp(TimeUnit.MILLISECONDS));
            assertTrue(header.getTimestamp().isAfter(startTime) || header.getTimestamp().equals(startTime));
            assertTrue(header.getTimestamp().isBefore(msgTime) || header.getTimestamp().equals(msgTime));
            assertNotNull(txEntry.getMetadata());
            assertNull(txEntry.getMetadata().get(LogTxMeta.GROUPNAME));
            LogTxStatus status = txEntry.getStatus();
            if (status == LogTxStatus.PRECOMMIT) {
                assertTrue(txEntry.hasContent());
                Object logid = txEntry.getMetadata().get(LogTxMeta.LOG_ID);
                if (logid != null) {
                    assertTrue(logid instanceof String);
                    assertEquals(userlogName, logid);
                    userlogMeta.incrementAndGet();
                }
            } else if (withLogFailure) {
                assertTrue(status.isPrimarySuccess() || status == LogTxStatus.SECONDARY_FAILURE);
                if (status == LogTxStatus.SECONDARY_FAILURE) {
                    TransactionLogHeader.SecondaryFailures secFail = txEntry.getContentAsSecondaryFailures(serializer);
                    assertTrue(secFail.failedIndexes.isEmpty());
                    assertTrue(secFail.userLogFailure);
                }
            } else {
                assertFalse(txEntry.hasContent());
                assertTrue(status.isSuccess());
            }
            txMsgCounter.get(txEntry.getStatus()).incrementAndGet();
        }
    });
    final EnumMap<Change, AtomicInteger> userChangeCounter = new EnumMap<Change, AtomicInteger>(Change.class);
    for (Change change : Change.values()) userChangeCounter.put(change, new AtomicInteger(0));
    final AtomicInteger userLogMsgCounter = new AtomicInteger(0);
    userLog.registerReader(startMarker, new MessageReader() {

        @Override
        public void read(Message message) {
            Instant msgTime = message.getTimestamp();
            assertTrue(msgTime.isAfter(startTime) || msgTime.equals(startTime));
            assertNotNull(message.getSenderId());
            StaticBuffer content = message.getContent();
            assertTrue(content != null && content.length() > 0);
            TransactionLogHeader.Entry txentry = TransactionLogHeader.parse(content, serializer, times);
            Instant txTime = txentry.getHeader().getTimestamp();
            assertTrue(txTime.isBefore(msgTime) || txTime.equals(msgTime));
            assertTrue(txTime.isAfter(startTime) || txTime.equals(msgTime));
            long txid = txentry.getHeader().getId();
            assertTrue(txid > 0);
            for (TransactionLogHeader.Modification modification : txentry.getContentAsModifications(serializer)) {
                assertTrue(modification.state == Change.ADDED || modification.state == Change.REMOVED);
                userChangeCounter.get(modification.state).incrementAndGet();
            }
            userLogMsgCounter.incrementAndGet();
        }
    });
    Thread.sleep(4000);
    assertEquals(5, txMsgCounter.get(LogTxStatus.PRECOMMIT).get());
    assertEquals(4, txMsgCounter.get(LogTxStatus.PRIMARY_SUCCESS).get());
    assertEquals(1, txMsgCounter.get(LogTxStatus.COMPLETE_SUCCESS).get());
    assertEquals(4, userlogMeta.get());
    if (withLogFailure)
        assertEquals(4, txMsgCounter.get(LogTxStatus.SECONDARY_FAILURE).get());
    else
        assertEquals(4, txMsgCounter.get(LogTxStatus.SECONDARY_SUCCESS).get());
    //User-Log
    if (withLogFailure) {
        assertEquals(0, userLogMsgCounter.get());
    } else {
        assertEquals(4, userLogMsgCounter.get());
        assertEquals(7, userChangeCounter.get(Change.ADDED).get());
        assertEquals(4, userChangeCounter.get(Change.REMOVED).get());
    }
    clopen(option(VERBOSE_TX_RECOVERY), true);
    /*
        Transaction Recovery
         */
    TransactionRecovery recovery = TitanFactory.startTransactionRecovery(graph, startTime);
    /*
        Use user log processing framework
         */
    final AtomicInteger userLogCount = new AtomicInteger(0);
    LogProcessorFramework userlogs = TitanFactory.openTransactionLog(graph);
    userlogs.addLogProcessor(userlogName).setStartTime(startTime).setRetryAttempts(1).addProcessor(new ChangeProcessor() {

        @Override
        public void process(TitanTransaction tx, TransactionId txId, ChangeState changes) {
            assertEquals(instanceid, txId.getInstanceId());
            //Just some reasonable upper bound
            assertTrue(txId.getTransactionId() > 0 && txId.getTransactionId() < 100);
            final Instant txTime = txId.getTransactionTime();
            assertTrue(String.format("tx timestamp %s not between start %s and end time %s", txTime, startTime, endTime), //Times should be within a second
            (txTime.isAfter(startTime) || txTime.equals(startTime)) && (txTime.isBefore(endTime) || txTime.equals(endTime)));
            assertTrue(tx.containsRelationType("knows"));
            assertTrue(tx.containsRelationType("weight"));
            EdgeLabel knows = tx.getEdgeLabel("knows");
            PropertyKey weight = tx.getPropertyKey("weight");
            Instant txTimeMicro = txId.getTransactionTime();
            int txNo;
            if (txTimeMicro.isBefore(txTimes[1])) {
                txNo = 1;
                //v1 addition transaction
                assertEquals(1, Iterables.size(changes.getVertices(Change.ADDED)));
                assertEquals(0, Iterables.size(changes.getVertices(Change.REMOVED)));
                assertEquals(1, Iterables.size(changes.getVertices(Change.ANY)));
                assertEquals(2, Iterables.size(changes.getRelations(Change.ADDED)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.ADDED, knows)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.ADDED, weight)));
                assertEquals(2, Iterables.size(changes.getRelations(Change.ANY)));
                assertEquals(0, Iterables.size(changes.getRelations(Change.REMOVED)));
                TitanVertex v = Iterables.getOnlyElement(changes.getVertices(Change.ADDED));
                assertEquals(v1id, getId(v));
                VertexProperty<Float> p = Iterables.getOnlyElement(changes.getProperties(v, Change.ADDED, "weight"));
                assertEquals(111.1, p.value().doubleValue(), 0.01);
                assertEquals(1, Iterables.size(changes.getEdges(v, Change.ADDED, OUT)));
                assertEquals(1, Iterables.size(changes.getEdges(v, Change.ADDED, BOTH)));
            } else if (txTimeMicro.isBefore(txTimes[2])) {
                txNo = 2;
                //v2 addition transaction
                assertEquals(1, Iterables.size(changes.getVertices(Change.ADDED)));
                assertEquals(0, Iterables.size(changes.getVertices(Change.REMOVED)));
                assertEquals(2, Iterables.size(changes.getVertices(Change.ANY)));
                assertEquals(2, Iterables.size(changes.getRelations(Change.ADDED)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.ADDED, knows)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.ADDED, weight)));
                assertEquals(2, Iterables.size(changes.getRelations(Change.ANY)));
                assertEquals(0, Iterables.size(changes.getRelations(Change.REMOVED)));
                TitanVertex v = Iterables.getOnlyElement(changes.getVertices(Change.ADDED));
                assertEquals(v2id, getId(v));
                VertexProperty<Float> p = Iterables.getOnlyElement(changes.getProperties(v, Change.ADDED, "weight"));
                assertEquals(222.2, p.value().doubleValue(), 0.01);
                assertEquals(1, Iterables.size(changes.getEdges(v, Change.ADDED, OUT)));
                assertEquals(1, Iterables.size(changes.getEdges(v, Change.ADDED, BOTH)));
            } else if (txTimeMicro.isBefore(txTimes[3])) {
                txNo = 3;
                //v2 deletion transaction
                assertEquals(0, Iterables.size(changes.getVertices(Change.ADDED)));
                assertEquals(1, Iterables.size(changes.getVertices(Change.REMOVED)));
                assertEquals(2, Iterables.size(changes.getVertices(Change.ANY)));
                assertEquals(0, Iterables.size(changes.getRelations(Change.ADDED)));
                assertEquals(2, Iterables.size(changes.getRelations(Change.REMOVED)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.REMOVED, knows)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.REMOVED, weight)));
                assertEquals(2, Iterables.size(changes.getRelations(Change.ANY)));
                TitanVertex v = Iterables.getOnlyElement(changes.getVertices(Change.REMOVED));
                assertEquals(v2id, getId(v));
                VertexProperty<Float> p = Iterables.getOnlyElement(changes.getProperties(v, Change.REMOVED, "weight"));
                assertEquals(222.2, p.value().doubleValue(), 0.01);
                assertEquals(1, Iterables.size(changes.getEdges(v, Change.REMOVED, OUT)));
                assertEquals(0, Iterables.size(changes.getEdges(v, Change.ADDED, BOTH)));
            } else {
                txNo = 4;
                //v1 edge modification
                assertEquals(0, Iterables.size(changes.getVertices(Change.ADDED)));
                assertEquals(0, Iterables.size(changes.getVertices(Change.REMOVED)));
                assertEquals(1, Iterables.size(changes.getVertices(Change.ANY)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.ADDED)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.REMOVED)));
                assertEquals(1, Iterables.size(changes.getRelations(Change.REMOVED, knows)));
                assertEquals(2, Iterables.size(changes.getRelations(Change.ANY)));
                TitanVertex v = Iterables.getOnlyElement(changes.getVertices(Change.ANY));
                assertEquals(v1id, getId(v));
                TitanEdge e = Iterables.getOnlyElement(changes.getEdges(v, Change.REMOVED, Direction.OUT, "knows"));
                assertFalse(e.property("weight").isPresent());
                assertEquals(v, e.vertex(Direction.IN));
                e = Iterables.getOnlyElement(changes.getEdges(v, Change.ADDED, Direction.OUT, "knows"));
                assertEquals(44.4, e.<Float>value("weight").doubleValue(), 0.01);
                assertEquals(v, e.vertex(Direction.IN));
            }
            //See only current state of graph in transaction
            TitanVertex v1 = getV(tx, v1id);
            assertNotNull(v1);
            assertTrue(v1.isLoaded());
            if (txNo != 2) {
                //In the transaction that adds v2, v2 will be considered "loaded"
                assertMissing(tx, v2id);
            //                    assertTrue(txNo + " - " + v2, v2 == null || v2.isRemoved());
            }
            assertEquals(111.1, v1.<Float>value("weight").doubleValue(), 0.01);
            assertCount(1, v1.query().direction(Direction.OUT).edges());
            userLogCount.incrementAndGet();
        }
    }).build();
    //wait
    Thread.sleep(22000L);
    recovery.shutdown();
    long[] recoveryStats = ((StandardTransactionLogProcessor) recovery).getStatistics();
    if (withLogFailure) {
        assertEquals(1, recoveryStats[0]);
        assertEquals(4, recoveryStats[1]);
    } else {
        assertEquals(5, recoveryStats[0]);
        assertEquals(0, recoveryStats[1]);
    }
    userlogs.removeLogProcessor(userlogName);
    userlogs.shutdown();
    assertEquals(4, userLogCount.get());
}
Also used : TransactionRecovery(com.thinkaurelius.titan.core.log.TransactionRecovery) TitanVertex(com.thinkaurelius.titan.core.TitanVertex) ChangeState(com.thinkaurelius.titan.core.log.ChangeState) Message(com.thinkaurelius.titan.diskstorage.log.Message) MessageReader(com.thinkaurelius.titan.diskstorage.log.MessageReader) TitanTransaction(com.thinkaurelius.titan.core.TitanTransaction) ChangeProcessor(com.thinkaurelius.titan.core.log.ChangeProcessor) EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) StaticBuffer(com.thinkaurelius.titan.diskstorage.StaticBuffer) TransactionLogHeader(com.thinkaurelius.titan.graphdb.database.log.TransactionLogHeader) TitanVertexProperty(com.thinkaurelius.titan.core.TitanVertexProperty) VertexProperty(org.apache.tinkerpop.gremlin.structure.VertexProperty) EnumMap(java.util.EnumMap) LogTxStatus(com.thinkaurelius.titan.graphdb.database.log.LogTxStatus) TitanEdge(com.thinkaurelius.titan.core.TitanEdge) EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) SpecialIntSerializer(com.thinkaurelius.titan.graphdb.serializer.SpecialIntSerializer) Serializer(com.thinkaurelius.titan.graphdb.database.serialize.Serializer) KCVSLog(com.thinkaurelius.titan.diskstorage.log.kcvs.KCVSLog) Log(com.thinkaurelius.titan.diskstorage.log.Log) Instant(java.time.Instant) EdgeLabel(com.thinkaurelius.titan.core.EdgeLabel) ReadMarker(com.thinkaurelius.titan.diskstorage.log.ReadMarker) Change(com.thinkaurelius.titan.core.log.Change) LogProcessorFramework(com.thinkaurelius.titan.core.log.LogProcessorFramework) TransactionId(com.thinkaurelius.titan.core.log.TransactionId) TimestampProvider(com.thinkaurelius.titan.diskstorage.util.time.TimestampProvider) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) StandardTransactionLogProcessor(com.thinkaurelius.titan.graphdb.log.StandardTransactionLogProcessor) TitanEdge(com.thinkaurelius.titan.core.TitanEdge) Edge(org.apache.tinkerpop.gremlin.structure.Edge) PropertyKey(com.thinkaurelius.titan.core.PropertyKey)

Example 2 with EdgeSerializer

use of com.thinkaurelius.titan.graphdb.database.EdgeSerializer in project titan by thinkaurelius.

the class BasicVertexCentricQueryBuilder method constructQueryWithoutProfile.

protected BaseVertexCentricQuery constructQueryWithoutProfile(RelationCategory returnType) {
    assert returnType != null;
    Preconditions.checkArgument(adjacentVertex == null || returnType == RelationCategory.EDGE, "Vertex constraints only apply to edges");
    if (limit <= 0)
        return BaseVertexCentricQuery.emptyQuery();
    //Prepare direction
    if (returnType == RelationCategory.PROPERTY) {
        if (dir == Direction.IN)
            return BaseVertexCentricQuery.emptyQuery();
        dir = Direction.OUT;
    }
    //Prepare order
    orders.makeImmutable();
    assert orders.hasCommonOrder();
    //Prepare constraints
    And<TitanRelation> conditions = QueryUtil.constraints2QNF(tx, constraints);
    if (conditions == null)
        return BaseVertexCentricQuery.emptyQuery();
    //Don't be smart with query limit adjustments - it just messes up the caching layer and penalizes when appropriate limits are set by the user!
    int sliceLimit = limit;
    //Construct (optimal) SliceQueries
    EdgeSerializer serializer = tx.getEdgeSerializer();
    List<BackendQueryHolder<SliceQuery>> queries;
    if (!hasTypes()) {
        BackendQueryHolder<SliceQuery> query = new BackendQueryHolder<SliceQuery>(serializer.getQuery(returnType, querySystem), ((dir == Direction.BOTH || (returnType == RelationCategory.PROPERTY && dir == Direction.OUT)) && !conditions.hasChildren()), orders.isEmpty());
        if (sliceLimit != Query.NO_LIMIT && sliceLimit < Integer.MAX_VALUE / 3) {
            //If only one direction is queried, ask for twice the limit from backend since approximately half will be filtered
            if (dir != Direction.BOTH && (returnType == RelationCategory.EDGE || returnType == RelationCategory.RELATION))
                sliceLimit *= 2;
        }
        query.getBackendQuery().setLimit(computeLimit(conditions.size(), sliceLimit));
        queries = ImmutableList.of(query);
        conditions.add(returnType);
        conditions.add(new //Need this to filter out newly created invisible relations in the transaction
        VisibilityFilterCondition<TitanRelation>(querySystem ? VisibilityFilterCondition.Visibility.SYSTEM : VisibilityFilterCondition.Visibility.NORMAL));
    } else {
        Set<RelationType> ts = new HashSet<RelationType>(types.length);
        queries = new ArrayList<BackendQueryHolder<SliceQuery>>(types.length + 2);
        Map<RelationType, Interval> intervalConstraints = new HashMap<RelationType, Interval>(conditions.size());
        final boolean isIntervalFittedConditions = compileConstraints(conditions, intervalConstraints);
        for (Interval pint : intervalConstraints.values()) {
            //Check if one of the constraints leads to an empty result set
            if (pint.isEmpty())
                return BaseVertexCentricQuery.emptyQuery();
        }
        for (String typeName : types) {
            InternalRelationType type = QueryUtil.getType(tx, typeName);
            if (type == null)
                continue;
            Preconditions.checkArgument(!querySystem || (type instanceof SystemRelationType), "Can only query for system types: %s", type);
            if (type instanceof ImplicitKey)
                throw new UnsupportedOperationException("Implicit types are not supported in complex queries: " + type);
            ts.add(type);
            Direction typeDir = dir;
            if (type.isPropertyKey()) {
                if (returnType == RelationCategory.EDGE)
                    throw new IllegalArgumentException("Querying for edges but including a property key: " + type.name());
                returnType = RelationCategory.PROPERTY;
                typeDir = Direction.OUT;
            }
            if (type.isEdgeLabel()) {
                if (returnType == RelationCategory.PROPERTY)
                    throw new IllegalArgumentException("Querying for properties but including an edge label: " + type.name());
                returnType = RelationCategory.EDGE;
                if (!type.isUnidirected(Direction.BOTH)) {
                    //Make sure unidirectionality lines up
                    if (typeDir == Direction.BOTH) {
                        if (type.isUnidirected(Direction.OUT))
                            typeDir = Direction.OUT;
                        else
                            typeDir = Direction.IN;
                    } else //Directions are incompatible
                    if (!type.isUnidirected(typeDir))
                        continue;
                }
            }
            if (type.isEdgeLabel() && typeDir == Direction.BOTH && intervalConstraints.isEmpty() && orders.isEmpty()) {
                //TODO: This if-condition is a little too restrictive - we also want to include those cases where there
                // ARE intervalConstraints or orders but those cannot be covered by any sort-keys
                SliceQuery q = serializer.getQuery(type, typeDir, null);
                q.setLimit(sliceLimit);
                queries.add(new BackendQueryHolder<SliceQuery>(q, isIntervalFittedConditions, true));
            } else {
                //Optimize for each direction independently
                Direction[] dirs = { typeDir };
                if (typeDir == Direction.BOTH) {
                    if (type.isEdgeLabel())
                        dirs = new Direction[] { Direction.OUT, Direction.IN };
                    else
                        //property key
                        dirs = new Direction[] { Direction.OUT };
                }
                for (Direction direction : dirs) {
                    /*
                        Find best scoring relation type to answer this query with. We score each candidate by the number
                        of conditions that each sort-keys satisfy. Equality conditions score higher than interval conditions
                        since they are more restrictive. We assign additional points if the sort key satisfies the order
                        of this query.
                        */
                    InternalRelationType bestCandidate = null;
                    double bestScore = Double.NEGATIVE_INFINITY;
                    boolean bestCandidateSupportsOrder = false;
                    for (InternalRelationType candidate : type.getRelationIndexes()) {
                        //Filter out those that don't apply
                        if (!candidate.isUnidirected(Direction.BOTH) && !candidate.isUnidirected(direction))
                            continue;
                        if (!candidate.equals(type) && candidate.getStatus() != SchemaStatus.ENABLED)
                            continue;
                        boolean supportsOrder = orders.isEmpty() ? true : orders.getCommonOrder() == candidate.getSortOrder();
                        int currentOrder = 0;
                        double score = 0.0;
                        PropertyKey[] extendedSortKey = getExtendedSortKey(candidate, direction, tx);
                        for (int i = 0; i < extendedSortKey.length; i++) {
                            PropertyKey keyType = extendedSortKey[i];
                            if (currentOrder < orders.size() && orders.getKey(currentOrder).equals(keyType))
                                currentOrder++;
                            Interval interval = intervalConstraints.get(keyType);
                            if (interval == null || !interval.isPoints()) {
                                if (interval != null)
                                    score += 1;
                                break;
                            } else {
                                assert interval.isPoints();
                                score += 5.0 / interval.getPoints().size();
                            }
                        }
                        if (supportsOrder && currentOrder == orders.size())
                            score += 3;
                        if (score > bestScore) {
                            bestScore = score;
                            bestCandidate = candidate;
                            bestCandidateSupportsOrder = supportsOrder && currentOrder == orders.size();
                        }
                    }
                    Preconditions.checkArgument(bestCandidate != null, "Current graph schema does not support the specified query constraints for type: %s", type.name());
                    //Construct sort key constraints for the best candidate and then serialize into a SliceQuery
                    //that is wrapped into a BackendQueryHolder
                    PropertyKey[] extendedSortKey = getExtendedSortKey(bestCandidate, direction, tx);
                    EdgeSerializer.TypedInterval[] sortKeyConstraints = new EdgeSerializer.TypedInterval[extendedSortKey.length];
                    constructSliceQueries(extendedSortKey, sortKeyConstraints, 0, bestCandidate, direction, intervalConstraints, sliceLimit, isIntervalFittedConditions, bestCandidateSupportsOrder, queries);
                }
            }
        }
        if (queries.isEmpty())
            return BaseVertexCentricQuery.emptyQuery();
        conditions.add(getTypeCondition(ts));
    }
    return new BaseVertexCentricQuery(QueryUtil.simplifyQNF(conditions), dir, queries, orders, limit);
}
Also used : Direction(org.apache.tinkerpop.gremlin.structure.Direction) SystemRelationType(com.thinkaurelius.titan.graphdb.types.system.SystemRelationType) EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) ImplicitKey(com.thinkaurelius.titan.graphdb.types.system.ImplicitKey) SliceQuery(com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery) SystemRelationType(com.thinkaurelius.titan.graphdb.types.system.SystemRelationType) Interval(com.thinkaurelius.titan.util.datastructures.Interval) PointInterval(com.thinkaurelius.titan.util.datastructures.PointInterval) RangeInterval(com.thinkaurelius.titan.util.datastructures.RangeInterval)

Example 3 with EdgeSerializer

use of com.thinkaurelius.titan.graphdb.database.EdgeSerializer in project titan by thinkaurelius.

the class BasicVertexCentricQueryBuilder method constructSliceQueries.

private void constructSliceQueries(PropertyKey[] extendedSortKey, EdgeSerializer.TypedInterval[] sortKeyConstraints, int position, InternalRelationType bestCandidate, Direction direction, Map<RelationType, Interval> intervalConstraints, int sliceLimit, boolean isIntervalFittedConditions, boolean bestCandidateSupportsOrder, List<BackendQueryHolder<SliceQuery>> queries) {
    if (position < extendedSortKey.length) {
        PropertyKey keyType = extendedSortKey[position];
        Interval interval = intervalConstraints.get(keyType);
        if (interval != null) {
            sortKeyConstraints[position] = new EdgeSerializer.TypedInterval(keyType, interval);
            position++;
        }
        if (interval != null && interval.isPoints()) {
            //Keep invoking recursively to see if we can satisfy more constraints...
            for (Object point : interval.getPoints()) {
                EdgeSerializer.TypedInterval[] clonedSKC = Arrays.copyOf(sortKeyConstraints, sortKeyConstraints.length);
                clonedSKC[position - 1] = new EdgeSerializer.TypedInterval(keyType, new PointInterval(point));
                constructSliceQueries(extendedSortKey, clonedSKC, position, bestCandidate, direction, intervalConstraints, sliceLimit, isIntervalFittedConditions, bestCandidateSupportsOrder, queries);
            }
            return;
        }
    }
    //...otherwise this is it and we can construct the slicequery
    boolean isFitted = isIntervalFittedConditions && position == intervalConstraints.size();
    if (isFitted && position > 0) {
        //If the last interval is open ended toward the larger values, then its not fitted because we need to
        //filter out NULL values which are serialized with -1 (largest value) byte up front.
        EdgeSerializer.TypedInterval lastInterval = sortKeyConstraints[position - 1];
        if (!lastInterval.interval.isPoints() && lastInterval.interval.getEnd() == null)
            isFitted = false;
    }
    EdgeSerializer serializer = tx.getEdgeSerializer();
    SliceQuery q = serializer.getQuery(bestCandidate, direction, sortKeyConstraints);
    q.setLimit(computeLimit(intervalConstraints.size() - position, sliceLimit));
    queries.add(new BackendQueryHolder<SliceQuery>(q, isFitted, bestCandidateSupportsOrder));
}
Also used : PointInterval(com.thinkaurelius.titan.util.datastructures.PointInterval) EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) SliceQuery(com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery) Interval(com.thinkaurelius.titan.util.datastructures.Interval) PointInterval(com.thinkaurelius.titan.util.datastructures.PointInterval) RangeInterval(com.thinkaurelius.titan.util.datastructures.RangeInterval)

Example 4 with EdgeSerializer

use of com.thinkaurelius.titan.graphdb.database.EdgeSerializer 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);
    }
}
Also used : InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation) Entry(com.thinkaurelius.titan.diskstorage.Entry) IndexEntry(com.thinkaurelius.titan.diskstorage.indexing.IndexEntry) EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) RelationTypeIndexWrapper(com.thinkaurelius.titan.graphdb.database.management.RelationTypeIndexWrapper) StaticBuffer(com.thinkaurelius.titan.diskstorage.StaticBuffer) ImmutableList(com.google.common.collect.ImmutableList) MixedIndexType(com.thinkaurelius.titan.graphdb.types.MixedIndexType) CompositeIndexType(com.thinkaurelius.titan.graphdb.types.CompositeIndexType) IndexType(com.thinkaurelius.titan.graphdb.types.IndexType) BackendTransaction(com.thinkaurelius.titan.diskstorage.BackendTransaction) MixedIndexType(com.thinkaurelius.titan.graphdb.types.MixedIndexType) IndexSerializer(com.thinkaurelius.titan.graphdb.database.IndexSerializer) CompositeIndexType(com.thinkaurelius.titan.graphdb.types.CompositeIndexType) InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType)

Example 5 with EdgeSerializer

use of com.thinkaurelius.titan.graphdb.database.EdgeSerializer in project titan by thinkaurelius.

the class EdgeSerializerTest method serialize.

private Entry serialize(StandardTitanGraph graph, TitanEdge e, int pos) {
    EdgeSerializer edgeSerializer = graph.getEdgeSerializer();
    InternalRelation r = (InternalRelation) e;
    return edgeSerializer.writeRelation(r, pos, r.tx());
}
Also used : EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation)

Aggregations

EdgeSerializer (com.thinkaurelius.titan.graphdb.database.EdgeSerializer)5 StaticBuffer (com.thinkaurelius.titan.diskstorage.StaticBuffer)2 SliceQuery (com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery)2 InternalRelation (com.thinkaurelius.titan.graphdb.internal.InternalRelation)2 Interval (com.thinkaurelius.titan.util.datastructures.Interval)2 PointInterval (com.thinkaurelius.titan.util.datastructures.PointInterval)2 RangeInterval (com.thinkaurelius.titan.util.datastructures.RangeInterval)2 ImmutableList (com.google.common.collect.ImmutableList)1 EdgeLabel (com.thinkaurelius.titan.core.EdgeLabel)1 PropertyKey (com.thinkaurelius.titan.core.PropertyKey)1 TitanEdge (com.thinkaurelius.titan.core.TitanEdge)1 TitanTransaction (com.thinkaurelius.titan.core.TitanTransaction)1 TitanVertex (com.thinkaurelius.titan.core.TitanVertex)1 TitanVertexProperty (com.thinkaurelius.titan.core.TitanVertexProperty)1 Change (com.thinkaurelius.titan.core.log.Change)1 ChangeProcessor (com.thinkaurelius.titan.core.log.ChangeProcessor)1 ChangeState (com.thinkaurelius.titan.core.log.ChangeState)1 LogProcessorFramework (com.thinkaurelius.titan.core.log.LogProcessorFramework)1 TransactionId (com.thinkaurelius.titan.core.log.TransactionId)1 TransactionRecovery (com.thinkaurelius.titan.core.log.TransactionRecovery)1