Search in sources :

Example 1 with InternalRelationType

use of com.thinkaurelius.titan.graphdb.internal.InternalRelationType in project titan by thinkaurelius.

the class TitanOperationCountingTest method testReadOperations.

public void testReadOperations(boolean cache) {
    metricsPrefix = "testReadOperations" + cache;
    resetEdgeCacheCounts();
    makeVertexIndexedUniqueKey("uid", Integer.class);
    mgmt.setConsistency(mgmt.getGraphIndex("uid"), ConsistencyModifier.LOCK);
    finishSchema();
    if (cache)
        clopen(option(DB_CACHE), true, option(DB_CACHE_CLEAN_WAIT), 0, option(DB_CACHE_TIME), 0);
    else
        clopen();
    TitanTransaction tx = graph.buildTransaction().groupName(metricsPrefix).start();
    tx.makePropertyKey("name").dataType(String.class).make();
    tx.makeEdgeLabel("knows").make();
    tx.makeVertexLabel("person").make();
    tx.commit();
    verifyStoreMetrics(EDGESTORE_NAME);
    verifyLockingOverwrite(INDEXSTORE_NAME, 3);
    verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 1l));
    resetMetrics();
    metricsPrefix = GraphDatabaseConfiguration.METRICS_SCHEMA_PREFIX_DEFAULT;
    resetMetrics();
    //Test schema caching
    for (int t = 0; t < 10; t++) {
        tx = graph.buildTransaction().groupName(metricsPrefix).start();
        //Retrieve name by index (one backend call each)
        assertTrue(tx.containsRelationType("name"));
        assertTrue(tx.containsRelationType("knows"));
        assertTrue(tx.containsVertexLabel("person"));
        PropertyKey name = tx.getPropertyKey("name");
        EdgeLabel knows = tx.getEdgeLabel("knows");
        VertexLabel person = tx.getVertexLabel("person");
        PropertyKey uid = tx.getPropertyKey("uid");
        //Retrieve name as property (one backend call each)
        assertEquals("name", name.name());
        assertEquals("knows", knows.name());
        assertEquals("person", person.name());
        assertEquals("uid", uid.name());
        //Looking up the definition (one backend call each)
        assertEquals(Cardinality.SINGLE, name.cardinality());
        assertEquals(Multiplicity.MULTI, knows.multiplicity());
        assertFalse(person.isPartitioned());
        assertEquals(Integer.class, uid.dataType());
        //Retrieving in and out relations for the relation types...
        InternalRelationType namei = (InternalRelationType) name;
        InternalRelationType knowsi = (InternalRelationType) knows;
        InternalRelationType uidi = (InternalRelationType) uid;
        assertNull(namei.getBaseType());
        assertNull(knowsi.getBaseType());
        IndexType index = Iterables.getOnlyElement(uidi.getKeyIndexes());
        assertEquals(1, index.getFieldKeys().length);
        assertEquals(ElementCategory.VERTEX, index.getElement());
        assertEquals(ConsistencyModifier.LOCK, ((CompositeIndexType) index).getConsistencyModifier());
        assertEquals(1, Iterables.size(uidi.getRelationIndexes()));
        assertEquals(1, Iterables.size(namei.getRelationIndexes()));
        assertEquals(namei, Iterables.getOnlyElement(namei.getRelationIndexes()));
        assertEquals(knowsi, Iterables.getOnlyElement(knowsi.getRelationIndexes()));
        //.. and vertex labels
        assertEquals(0, ((InternalVertexLabel) person).getTTL());
        tx.commit();
        //Needs to read on first iteration, after that it doesn't change anymore
        verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 19l));
        verifyStoreMetrics(INDEXSTORE_NAME, ImmutableMap.of(M_GET_SLICE, 4l, /* name, knows, person, uid */
        M_ACQUIRE_LOCK, 0l));
    }
    //Create some graph data
    metricsPrefix = "add" + cache;
    tx = graph.buildTransaction().groupName(metricsPrefix).start();
    TitanVertex v = tx.addVertex(), u = tx.addVertex("person");
    v.property(VertexProperty.Cardinality.single, "uid", 1);
    u.property(VertexProperty.Cardinality.single, "name", "juju");
    Edge e = v.addEdge("knows", u);
    e.property("name", "edge");
    tx.commit();
    verifyStoreMetrics(EDGESTORE_NAME);
    verifyLockingOverwrite(INDEXSTORE_NAME, 1);
    for (int i = 1; i <= 30; i++) {
        metricsPrefix = "op" + i + cache;
        tx = graph.buildTransaction().groupName(metricsPrefix).start();
        v = getOnlyElement(tx.query().has("uid", 1).vertices());
        assertEquals(1, v.<Integer>value("uid").intValue());
        u = getOnlyElement(v.query().direction(Direction.BOTH).labels("knows").vertices());
        e = getOnlyElement(u.query().direction(Direction.IN).labels("knows").edges());
        assertEquals("juju", u.value("name"));
        assertEquals("edge", e.value("name"));
        tx.commit();
        if (!cache || i == 0) {
            verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 4l));
            verifyStoreMetrics(INDEXSTORE_NAME, ImmutableMap.of(M_GET_SLICE, 1l));
        } else if (cache && i > 20) {
            //Needs a couple of iterations for cache to be cleaned
            verifyStoreMetrics(EDGESTORE_NAME);
            verifyStoreMetrics(INDEXSTORE_NAME);
        }
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) InternalVertexLabel(com.thinkaurelius.titan.graphdb.internal.InternalVertexLabel) InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType) CompositeIndexType(com.thinkaurelius.titan.graphdb.types.CompositeIndexType) IndexType(com.thinkaurelius.titan.graphdb.types.IndexType) Edge(org.apache.tinkerpop.gremlin.structure.Edge)

Example 2 with InternalRelationType

use of com.thinkaurelius.titan.graphdb.internal.InternalRelationType in project titan by thinkaurelius.

the class PredicateCondition method evaluate.

@Override
public boolean evaluate(E element) {
    RelationType type;
    if (key instanceof String) {
        type = ((InternalElement) element).tx().getRelationType((String) key);
        if (type == null)
            return satisfiesCondition(null);
    } else {
        type = (RelationType) key;
    }
    Preconditions.checkNotNull(type);
    if (type.isPropertyKey()) {
        Iterator<Object> iter = ElementHelper.getValues(element, (PropertyKey) type).iterator();
        if (iter.hasNext()) {
            while (iter.hasNext()) {
                if (satisfiesCondition(iter.next()))
                    return true;
            }
            return false;
        }
        return satisfiesCondition(null);
    } else {
        assert ((InternalRelationType) type).multiplicity().isUnique(Direction.OUT);
        return satisfiesCondition((TitanVertex) element.value(type.name()));
    }
}
Also used : InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType) InternalElement(com.thinkaurelius.titan.graphdb.internal.InternalElement)

Example 3 with InternalRelationType

use of com.thinkaurelius.titan.graphdb.internal.InternalRelationType in project titan by thinkaurelius.

the class GraphCentricQueryBuilder method constructQueryWithoutProfile.

public GraphCentricQuery constructQueryWithoutProfile(final ElementCategory resultType) {
    Preconditions.checkNotNull(resultType);
    if (limit == 0)
        return GraphCentricQuery.emptyQuery(resultType);
    //Prepare constraints
    And<TitanElement> conditions = QueryUtil.constraints2QNF(tx, constraints);
    if (conditions == null)
        return GraphCentricQuery.emptyQuery(resultType);
    //Prepare orders
    orders.makeImmutable();
    if (orders.isEmpty())
        orders = OrderList.NO_ORDER;
    //Compile all indexes that cover at least one of the query conditions
    final Set<IndexType> indexCandidates = new HashSet<IndexType>();
    ConditionUtil.traversal(conditions, new Predicate<Condition<TitanElement>>() {

        @Override
        public boolean apply(@Nullable Condition<TitanElement> condition) {
            if (condition instanceof PredicateCondition) {
                RelationType type = ((PredicateCondition<RelationType, TitanElement>) condition).getKey();
                Preconditions.checkArgument(type != null && type.isPropertyKey());
                Iterables.addAll(indexCandidates, Iterables.filter(((InternalRelationType) type).getKeyIndexes(), new Predicate<IndexType>() {

                    @Override
                    public boolean apply(@Nullable IndexType indexType) {
                        return indexType.getElement() == resultType;
                    }
                }));
            }
            return true;
        }
    });
    /*
        Determine the best join index query to answer this query:
        Iterate over all potential indexes (as compiled above) and compute a score based on how many clauses
        this index covers. The index with the highest score (as long as it covers at least one additional clause)
        is picked and added to the joint query for as long as such exist.
         */
    JointIndexQuery jointQuery = new JointIndexQuery();
    boolean isSorted = orders.isEmpty();
    Set<Condition> coveredClauses = Sets.newHashSet();
    while (true) {
        IndexType bestCandidate = null;
        double candidateScore = 0.0;
        Set<Condition> candidateSubcover = null;
        boolean candidateSupportsSort = false;
        Object candidateSubcondition = null;
        for (IndexType index : indexCandidates) {
            Set<Condition> subcover = Sets.newHashSet();
            Object subcondition;
            boolean supportsSort = orders.isEmpty();
            //Check that this index actually applies in case of a schema constraint
            if (index.hasSchemaTypeConstraint()) {
                TitanSchemaType type = index.getSchemaTypeConstraint();
                Map.Entry<Condition, Collection<Object>> equalCon = getEqualityConditionValues(conditions, ImplicitKey.LABEL);
                if (equalCon == null)
                    continue;
                Collection<Object> labels = equalCon.getValue();
                assert labels.size() >= 1;
                if (labels.size() > 1) {
                    log.warn("The query optimizer currently does not support multiple label constraints in query: {}", this);
                    continue;
                }
                if (!type.name().equals((String) Iterables.getOnlyElement(labels)))
                    continue;
                subcover.add(equalCon.getKey());
            }
            if (index.isCompositeIndex()) {
                subcondition = indexCover((CompositeIndexType) index, conditions, subcover);
            } else {
                subcondition = indexCover((MixedIndexType) index, conditions, serializer, subcover);
                if (coveredClauses.isEmpty() && !supportsSort && indexCoversOrder((MixedIndexType) index, orders))
                    supportsSort = true;
            }
            if (subcondition == null)
                continue;
            assert !subcover.isEmpty();
            double score = 0.0;
            boolean coversAdditionalClause = false;
            for (Condition c : subcover) {
                double s = (c instanceof PredicateCondition && ((PredicateCondition) c).getPredicate() == Cmp.EQUAL) ? EQUAL_CONDITION_SCORE : OTHER_CONDITION_SCORE;
                if (coveredClauses.contains(c))
                    s = s * ALREADY_MATCHED_ADJUSTOR;
                else
                    coversAdditionalClause = true;
                score += s;
                if (index.isCompositeIndex())
                    score += ((CompositeIndexType) index).getCardinality() == Cardinality.SINGLE ? CARDINALITY_SINGE_SCORE : CARDINALITY_OTHER_SCORE;
            }
            if (supportsSort)
                score += ORDER_MATCH;
            if (coversAdditionalClause && score > candidateScore) {
                candidateScore = score;
                bestCandidate = index;
                candidateSubcover = subcover;
                candidateSubcondition = subcondition;
                candidateSupportsSort = supportsSort;
            }
        }
        if (bestCandidate != null) {
            if (coveredClauses.isEmpty())
                isSorted = candidateSupportsSort;
            coveredClauses.addAll(candidateSubcover);
            if (bestCandidate.isCompositeIndex()) {
                jointQuery.add((CompositeIndexType) bestCandidate, serializer.getQuery((CompositeIndexType) bestCandidate, (List<Object[]>) candidateSubcondition));
            } else {
                jointQuery.add((MixedIndexType) bestCandidate, serializer.getQuery((MixedIndexType) bestCandidate, (Condition) candidateSubcondition, orders));
            }
        } else {
            break;
        }
    /* TODO: smarter optimization:
            - use in-memory histograms to estimate selectivity of PredicateConditions and filter out low-selectivity ones
                    if they would result in an individual index call (better to filter afterwards in memory)
            - move OR's up and extend GraphCentricQuery to allow multiple JointIndexQuery for proper or'ing of queries
            */
    }
    BackendQueryHolder<JointIndexQuery> query;
    if (!coveredClauses.isEmpty()) {
        int indexLimit = limit == Query.NO_LIMIT ? HARD_MAX_LIMIT : limit;
        if (tx.getGraph().getConfiguration().adjustQueryLimit()) {
            indexLimit = limit == Query.NO_LIMIT ? DEFAULT_NO_LIMIT : Math.min(MAX_BASE_LIMIT, limit);
        }
        indexLimit = Math.min(HARD_MAX_LIMIT, QueryUtil.adjustLimitForTxModifications(tx, coveredClauses.size(), indexLimit));
        jointQuery.setLimit(indexLimit);
        query = new BackendQueryHolder<JointIndexQuery>(jointQuery, coveredClauses.size() == conditions.numChildren(), isSorted);
    } else {
        query = new BackendQueryHolder<JointIndexQuery>(new JointIndexQuery(), false, isSorted);
    }
    return new GraphCentricQuery(resultType, conditions, orders, query, limit);
}
Also used : InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType) OrderList(com.thinkaurelius.titan.graphdb.internal.OrderList) ImmutableList(com.google.common.collect.ImmutableList) TitanSchemaType(com.thinkaurelius.titan.core.schema.TitanSchemaType)

Example 4 with InternalRelationType

use of com.thinkaurelius.titan.graphdb.internal.InternalRelationType in project titan by thinkaurelius.

the class IndexRemoveJob method getQueries.

@Override
public List<SliceQuery> getQueries() {
    if (isGlobalGraphIndex()) {
        //Everything
        return ImmutableList.of(new SliceQuery(BufferUtil.zeroBuffer(1), BufferUtil.oneBuffer(128)));
    } else {
        RelationTypeIndexWrapper wrapper = (RelationTypeIndexWrapper) index;
        InternalRelationType wrappedType = wrapper.getWrappedType();
        Direction direction = null;
        for (Direction dir : Direction.values()) if (wrappedType.isUnidirected(dir))
            direction = dir;
        assert direction != null;
        StandardTitanTx tx = (StandardTitanTx) graph.get().buildTransaction().readOnly().start();
        try {
            QueryContainer qc = new QueryContainer(tx);
            qc.addQuery().type(wrappedType).direction(direction).relations();
            return qc.getSliceQueries();
        } finally {
            tx.rollback();
        }
    }
}
Also used : RelationTypeIndexWrapper(com.thinkaurelius.titan.graphdb.database.management.RelationTypeIndexWrapper) InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType) Direction(org.apache.tinkerpop.gremlin.structure.Direction) StandardTitanTx(com.thinkaurelius.titan.graphdb.transaction.StandardTitanTx) SliceQuery(com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery) QueryContainer(com.thinkaurelius.titan.graphdb.olap.QueryContainer)

Example 5 with InternalRelationType

use of com.thinkaurelius.titan.graphdb.internal.InternalRelationType 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);
}
Also used : LongArrayList(com.carrotsearch.hppc.LongArrayList) IndexTransaction(com.thinkaurelius.titan.diskstorage.indexing.IndexTransaction) IndexEntry(com.thinkaurelius.titan.diskstorage.indexing.IndexEntry) InternalRelation(com.thinkaurelius.titan.graphdb.internal.InternalRelation) StaticArrayEntry(com.thinkaurelius.titan.diskstorage.util.StaticArrayEntry) StaticArrayEntry(com.thinkaurelius.titan.diskstorage.util.StaticArrayEntry) IndexEntry(com.thinkaurelius.titan.diskstorage.indexing.IndexEntry) MixedIndexType(com.thinkaurelius.titan.graphdb.types.MixedIndexType) AtomicLong(java.util.concurrent.atomic.AtomicLong) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex) CompositeIndexType(com.thinkaurelius.titan.graphdb.types.CompositeIndexType) InternalRelationType(com.thinkaurelius.titan.graphdb.internal.InternalRelationType)

Aggregations

InternalRelationType (com.thinkaurelius.titan.graphdb.internal.InternalRelationType)17 InternalRelation (com.thinkaurelius.titan.graphdb.internal.InternalRelation)4 EdgeLabel (com.thinkaurelius.titan.core.EdgeLabel)3 PropertyKey (com.thinkaurelius.titan.core.PropertyKey)3 TitanSchemaType (com.thinkaurelius.titan.core.schema.TitanSchemaType)3 Entry (com.thinkaurelius.titan.diskstorage.Entry)3 InternalVertex (com.thinkaurelius.titan.graphdb.internal.InternalVertex)3 OrderList (com.thinkaurelius.titan.graphdb.internal.OrderList)3 CompositeIndexType (com.thinkaurelius.titan.graphdb.types.CompositeIndexType)3 ImmutableList (com.google.common.collect.ImmutableList)2 RelationType (com.thinkaurelius.titan.core.RelationType)2 TitanVertex (com.thinkaurelius.titan.core.TitanVertex)2 VertexLabel (com.thinkaurelius.titan.core.VertexLabel)2 IndexEntry (com.thinkaurelius.titan.diskstorage.indexing.IndexEntry)2 RelationTypeIndexWrapper (com.thinkaurelius.titan.graphdb.database.management.RelationTypeIndexWrapper)2 InternalElement (com.thinkaurelius.titan.graphdb.internal.InternalElement)2 IndexType (com.thinkaurelius.titan.graphdb.types.IndexType)2 MixedIndexType (com.thinkaurelius.titan.graphdb.types.MixedIndexType)2 StandardEdgeLabelMaker (com.thinkaurelius.titan.graphdb.types.StandardEdgeLabelMaker)2 TitanSchemaVertex (com.thinkaurelius.titan.graphdb.types.vertices.TitanSchemaVertex)2