Search in sources :

Example 1 with ModificationStamp

use of org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp in project jackrabbit-oak by apache.

the class RDBDocumentStore method internalQuery.

private <T extends Document> List<T> internalQuery(Collection<T> collection, String fromKey, String toKey, List<String> excludeKeyPatterns, List<QueryCondition> conditions, int limit) {
    Connection connection = null;
    RDBTableMetaData tmd = getTable(collection);
    for (QueryCondition cond : conditions) {
        if (!INDEXEDPROPERTIES.contains(cond.getPropertyName())) {
            String message = "indexed property " + cond.getPropertyName() + " not supported, query was '" + cond + "'; supported properties are " + INDEXEDPROPERTIES;
            LOG.info(message);
            throw new DocumentStoreException(message);
        }
    }
    final Stopwatch watch = startWatch();
    int resultSize = 0;
    try (CacheChangesTracker tracker = obtainTracker(collection, fromKey, toKey)) {
        long now = System.currentTimeMillis();
        connection = this.ch.getROConnection();
        String from = collection == Collection.NODES && NodeDocument.MIN_ID_VALUE.equals(fromKey) ? null : fromKey;
        String to = collection == Collection.NODES && NodeDocument.MAX_ID_VALUE.equals(toKey) ? null : toKey;
        // OAK-6839: only populate the cache with *new* entries if the query
        // isn't open-ended (something done by GC processes)
        boolean populateCache = to != null;
        List<RDBRow> dbresult = db.query(connection, tmd, from, to, excludeKeyPatterns, conditions, limit);
        connection.commit();
        int size = dbresult.size();
        List<T> result = new ArrayList<T>(size);
        for (int i = 0; i < size; i++) {
            // free RDBRow as early as possible
            RDBRow row = dbresult.set(i, null);
            T doc = getIfCached(collection, row.getId(), row.getModcount());
            if (doc == null) {
                // parse DB contents into document if and only if it's not
                // already in the cache
                doc = convertFromDBObject(collection, row);
            } else {
                // we got a document from the cache, thus collection is NODES
                // and a tracker is present
                long lastmodified = modifiedOf(doc);
                if (lastmodified == row.getModified() && lastmodified >= 1) {
                    try (CacheLock lock = acquireLockFor(row.getId())) {
                        if (!tracker.mightBeenAffected(row.getId())) {
                            // otherwise mark it as fresh
                            ((NodeDocument) doc).markUpToDate(now);
                        }
                    }
                } else {
                    // we need a fresh document instance
                    doc = convertFromDBObject(collection, row);
                }
            }
            result.add(doc);
        }
        if (collection == Collection.NODES) {
            if (populateCache) {
                nodesCache.putNonConflictingDocs(tracker, castAsNodeDocumentList(result));
            } else {
                Map<String, ModificationStamp> invMap = Maps.newHashMap();
                for (Document doc : result) {
                    invMap.put(doc.getId(), new ModificationStamp(modcountOf(doc), modifiedOf(doc)));
                }
                nodesCache.invalidateOutdated(invMap);
            }
        }
        resultSize = result.size();
        return result;
    } catch (Exception ex) {
        LOG.error("SQL exception on query", ex);
        throw asDocumentStoreException(ex, "SQL exception on query");
    } finally {
        this.ch.closeConnection(connection);
        stats.doneQuery(watch.elapsed(TimeUnit.NANOSECONDS), collection, fromKey, toKey, !conditions.isEmpty(), resultSize, -1, false);
    }
}
Also used : DocumentStoreException(org.apache.jackrabbit.oak.plugins.document.DocumentStoreException) RDBJDBCTools.asDocumentStoreException(org.apache.jackrabbit.oak.plugins.document.rdb.RDBJDBCTools.asDocumentStoreException) Connection(java.sql.Connection) Stopwatch(com.google.common.base.Stopwatch) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) ArrayList(java.util.ArrayList) NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument) NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument) Document(org.apache.jackrabbit.oak.plugins.document.Document) UnsupportedEncodingException(java.io.UnsupportedEncodingException) DocumentStoreException(org.apache.jackrabbit.oak.plugins.document.DocumentStoreException) SQLException(java.sql.SQLException) IOException(java.io.IOException) RDBJDBCTools.asDocumentStoreException(org.apache.jackrabbit.oak.plugins.document.rdb.RDBJDBCTools.asDocumentStoreException) ExecutionException(java.util.concurrent.ExecutionException) ModificationStamp(org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp) CacheChangesTracker(org.apache.jackrabbit.oak.plugins.document.cache.CacheChangesTracker)

Example 2 with ModificationStamp

use of org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp in project jackrabbit-oak by apache.

the class MongoDocumentStore method update.

@Override
public <T extends Document> void update(Collection<T> collection, List<String> keys, UpdateOp updateOp) {
    log("update", keys, updateOp);
    UpdateUtils.assertUnconditional(updateOp);
    DBCollection dbCollection = getDBCollection(collection);
    QueryBuilder query = QueryBuilder.start(Document.ID).in(keys);
    // make sure we don't modify the original updateOp
    updateOp = updateOp.copy();
    DBObject update = createUpdate(updateOp, false);
    final Stopwatch watch = startWatch();
    try {
        Map<String, NodeDocument> cachedDocs = Collections.emptyMap();
        if (collection == Collection.NODES) {
            cachedDocs = Maps.newHashMap();
            for (String key : keys) {
                cachedDocs.put(key, nodesCache.getIfPresent(key));
            }
        }
        try {
            dbCollection.update(query.get(), update, false, true);
            if (collection == Collection.NODES) {
                Map<String, ModificationStamp> modCounts = getModStamps(filterValues(cachedDocs, notNull()).keySet());
                // update cache
                for (Entry<String, NodeDocument> entry : cachedDocs.entrySet()) {
                    // the cachedDocs is not empty, so the collection = NODES
                    Lock lock = nodeLocks.acquire(entry.getKey());
                    try {
                        ModificationStamp postUpdateModStamp = modCounts.get(entry.getKey());
                        if (postUpdateModStamp != null && entry.getValue() != null && entry.getValue() != NodeDocument.NULL && Long.valueOf(postUpdateModStamp.modCount - 1).equals(entry.getValue().getModCount())) {
                            // post update modCount is one higher than
                            // what we currently see in the cache. we can
                            // replace the cached document
                            NodeDocument newDoc = applyChanges(Collection.NODES, entry.getValue(), updateOp.shallowCopy(entry.getKey()));
                            nodesCache.replaceCachedDocument(entry.getValue(), newDoc);
                        } else {
                            // make sure concurrently loaded document is
                            // invalidated
                            nodesCache.invalidate(entry.getKey());
                        }
                    } finally {
                        lock.unlock();
                    }
                }
            }
        } catch (MongoException e) {
            throw handleException(e, collection, keys);
        }
    } finally {
        stats.doneUpdate(watch.elapsed(TimeUnit.NANOSECONDS), collection, keys.size());
    }
}
Also used : DBCollection(com.mongodb.DBCollection) MongoException(com.mongodb.MongoException) Stopwatch(com.google.common.base.Stopwatch) QueryBuilder(com.mongodb.QueryBuilder) NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument) DBObject(com.mongodb.DBObject) BasicDBObject(com.mongodb.BasicDBObject) ModificationStamp(org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp) Lock(java.util.concurrent.locks.Lock)

Example 3 with ModificationStamp

use of org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp in project jackrabbit-oak by apache.

the class MongoDocumentStore method getModStamps.

/**
 * Returns the {@link Document#MOD_COUNT} and
 * {@link NodeDocument#MODIFIED_IN_SECS} values of the documents with the
 * given {@code keys}. The returned map will only contain entries for
 * existing documents. The default value is -1 if the document does not have
 * a modCount field. The same applies to the modified field.
 *
 * @param keys the keys of the documents.
 * @return map with key to modification stamp mapping.
 * @throws MongoException if the call fails
 */
@Nonnull
private Map<String, ModificationStamp> getModStamps(Iterable<String> keys) throws MongoException {
    // Fetch only the modCount and id
    final BasicDBObject fields = new BasicDBObject(Document.ID, 1);
    fields.put(Document.MOD_COUNT, 1);
    fields.put(NodeDocument.MODIFIED_IN_SECS, 1);
    Map<String, ModificationStamp> modCounts = Maps.newHashMap();
    nodes.withReadPreference(ReadPreference.primary()).find(Filters.in(Document.ID, keys)).projection(fields).forEach((Block<BasicDBObject>) obj -> {
        String id = (String) obj.get(Document.ID);
        Long modCount = Utils.asLong((Number) obj.get(Document.MOD_COUNT));
        if (modCount == null) {
            modCount = -1L;
        }
        Long modified = Utils.asLong((Number) obj.get(NodeDocument.MODIFIED_IN_SECS));
        if (modified == null) {
            modified = -1L;
        }
        modCounts.put(id, new ModificationStamp(modCount, modified));
    });
    return modCounts;
}
Also used : Arrays(java.util.Arrays) CacheStats(org.apache.jackrabbit.oak.cache.CacheStats) MongoDatabase(com.mongodb.client.MongoDatabase) Predicates.in(com.google.common.base.Predicates.in) Sets.difference(com.google.common.collect.Sets.difference) Key(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key) Predicates.not(com.google.common.base.Predicates.not) UpdateResult(com.mongodb.client.result.UpdateResult) Map(java.util.Map) UpdateOptions(com.mongodb.client.model.UpdateOptions) Revision(org.apache.jackrabbit.oak.plugins.document.Revision) CacheInvalidationStats(org.apache.jackrabbit.oak.plugins.document.cache.CacheInvalidationStats) Set(java.util.Set) Collection(org.apache.jackrabbit.oak.plugins.document.Collection) BulkWriteUpsert(com.mongodb.bulk.BulkWriteUpsert) Clock(org.apache.jackrabbit.oak.stats.Clock) CacheChangesTracker(org.apache.jackrabbit.oak.plugins.document.cache.CacheChangesTracker) Iterables.filter(com.google.common.collect.Iterables.filter) Iterables(com.google.common.collect.Iterables) MongoClientURI(com.mongodb.MongoClientURI) MongoCollection(com.mongodb.client.MongoCollection) BulkWriteOptions(com.mongodb.client.model.BulkWriteOptions) FindOneAndUpdateOptions(com.mongodb.client.model.FindOneAndUpdateOptions) Callable(java.util.concurrent.Callable) SD_MAX_REV_TIME_IN_SECS(org.apache.jackrabbit.oak.plugins.document.NodeDocument.SD_MAX_REV_TIME_IN_SECS) ArrayList(java.util.ArrayList) UpdateUtils(org.apache.jackrabbit.oak.plugins.document.UpdateUtils) LinkedHashMap(java.util.LinkedHashMap) Bson(org.bson.conversions.Bson) Filters(com.mongodb.client.model.Filters) Lists(com.google.common.collect.Lists) SD_TYPE(org.apache.jackrabbit.oak.plugins.document.NodeDocument.SD_TYPE) ReplicaSetInfo(org.apache.jackrabbit.oak.plugins.document.mongo.replica.ReplicaSetInfo) Nullable(javax.annotation.Nullable) DELETED_ONCE(org.apache.jackrabbit.oak.plugins.document.NodeDocument.DELETED_ONCE) Maps.filterKeys(com.google.common.collect.Maps.filterKeys) LocalChanges(org.apache.jackrabbit.oak.plugins.document.mongo.replica.LocalChanges) UpdateOneModel(com.mongodb.client.model.UpdateOneModel) BasicDBObject(com.mongodb.BasicDBObject) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) DocumentStoreStatsCollector(org.apache.jackrabbit.oak.plugins.document.DocumentStoreStatsCollector) Lock(java.util.concurrent.locks.Lock) TreeMap(java.util.TreeMap) StripedNodeDocumentLocks(org.apache.jackrabbit.oak.plugins.document.locks.StripedNodeDocumentLocks) RevisionListener(org.apache.jackrabbit.oak.plugins.document.RevisionListener) Condition.newEqualsCondition(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Condition.newEqualsCondition) Date(java.util.Date) LoggerFactory(org.slf4j.LoggerFactory) MongoBulkWriteException(com.mongodb.MongoBulkWriteException) WriteModel(com.mongodb.client.model.WriteModel) Utils(org.apache.jackrabbit.oak.plugins.document.util.Utils) MongoUtils.createPartialIndex(org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.createPartialIndex) DBObject(com.mongodb.DBObject) RevisionVector(org.apache.jackrabbit.oak.plugins.document.RevisionVector) MongoUtils.createIndex(org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.createIndex) Function(com.google.common.base.Function) ImmutableMap(com.google.common.collect.ImmutableMap) MongoException(com.mongodb.MongoException) ReturnDocument(com.mongodb.client.model.ReturnDocument) PerfLogger(org.apache.jackrabbit.oak.commons.PerfLogger) NodeDocumentLocks(org.apache.jackrabbit.oak.plugins.document.locks.NodeDocumentLocks) List(java.util.List) DocumentStoreException.asDocumentStoreException(org.apache.jackrabbit.oak.plugins.document.DocumentStoreException.asDocumentStoreException) Block(com.mongodb.Block) JournalEntry(org.apache.jackrabbit.oak.plugins.document.JournalEntry) FindIterable(com.mongodb.client.FindIterable) MongoUtils.hasIndex(org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.hasIndex) Entry(java.util.Map.Entry) NodeDocumentCache(org.apache.jackrabbit.oak.plugins.document.cache.NodeDocumentCache) Condition(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Condition) ModificationStamp(org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp) ReadPreference(com.mongodb.ReadPreference) DocumentStoreException(org.apache.jackrabbit.oak.plugins.document.DocumentStoreException) Stopwatch(com.google.common.base.Stopwatch) MongoUtils.getDocumentStoreExceptionTypeFor(org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.getDocumentStoreExceptionTypeFor) UpdateOp(org.apache.jackrabbit.oak.plugins.document.UpdateOp) HashMap(java.util.HashMap) Iterators(com.google.common.collect.Iterators) MODIFIED_IN_SECS(org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS) HashSet(java.util.HashSet) BulkWriteError(com.mongodb.bulk.BulkWriteError) ImmutableList(com.google.common.collect.ImmutableList) MongoCursor(com.mongodb.client.MongoCursor) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument) Nonnull(javax.annotation.Nonnull) DocumentStore(org.apache.jackrabbit.oak.plugins.document.DocumentStore) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) Maps(com.google.common.collect.Maps) CacheValue(org.apache.jackrabbit.oak.cache.CacheValue) TimeUnit(java.util.concurrent.TimeUnit) StableRevisionComparator(org.apache.jackrabbit.oak.plugins.document.StableRevisionComparator) BulkWriteResult(com.mongodb.bulk.BulkWriteResult) MongoClient(com.mongodb.MongoClient) Document(org.apache.jackrabbit.oak.plugins.document.Document) Operation(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation) WriteConcern(com.mongodb.WriteConcern) Collections(java.util.Collections) CheckForNull(javax.annotation.CheckForNull) BasicDBObject(com.mongodb.BasicDBObject) ModificationStamp(org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp) Nonnull(javax.annotation.Nonnull)

Aggregations

Stopwatch (com.google.common.base.Stopwatch)3 NodeDocument (org.apache.jackrabbit.oak.plugins.document.NodeDocument)3 ModificationStamp (org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp)3 BasicDBObject (com.mongodb.BasicDBObject)2 DBObject (com.mongodb.DBObject)2 MongoException (com.mongodb.MongoException)2 Lock (java.util.concurrent.locks.Lock)2 Function (com.google.common.base.Function)1 Predicates.in (com.google.common.base.Predicates.in)1 Predicates.not (com.google.common.base.Predicates.not)1 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 Iterables (com.google.common.collect.Iterables)1 Iterables.filter (com.google.common.collect.Iterables.filter)1 Iterators (com.google.common.collect.Iterators)1 Lists (com.google.common.collect.Lists)1 Lists.newArrayList (com.google.common.collect.Lists.newArrayList)1 Maps (com.google.common.collect.Maps)1 Maps.filterKeys (com.google.common.collect.Maps.filterKeys)1 Sets.difference (com.google.common.collect.Sets.difference)1