Search in sources :

Example 11 with NodeDocument

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

the class MongoDocumentStore method getMongoReadPreference.

<T extends Document> ReadPreference getMongoReadPreference(@Nonnull Collection<T> collection, @Nullable String parentId, @Nullable String documentId, @Nonnull DocumentReadPreference preference) {
    switch(preference) {
        case PRIMARY:
            return ReadPreference.primary();
        case PREFER_PRIMARY:
            return ReadPreference.primaryPreferred();
        case PREFER_SECONDARY:
            return getConfiguredReadPreference(collection);
        case PREFER_SECONDARY_IF_OLD_ENOUGH:
            if (collection != Collection.NODES) {
                return ReadPreference.primary();
            }
            boolean secondarySafe;
            if (fallbackSecondaryStrategy) {
                // This is not quite accurate, because ancestors
                // are updated in a background thread (_lastRev). We
                // will need to revise this for low maxReplicationLagMillis
                // values
                long replicationSafeLimit = getTime() - maxReplicationLagMillis;
                if (parentId == null) {
                    secondarySafe = false;
                } else {
                    //If parent has been modified loooong time back then there children
                    //would also have not be modified. In that case we can read from secondary
                    NodeDocument cachedDoc = nodesCache.getIfPresent(parentId);
                    secondarySafe = cachedDoc != null && !cachedDoc.hasBeenModifiedSince(replicationSafeLimit);
                }
            } else if (localChanges != null) {
                secondarySafe = true;
                secondarySafe &= collection == Collection.NODES;
                secondarySafe &= documentId == null || !localChanges.mayContain(documentId);
                secondarySafe &= parentId == null || !localChanges.mayContainChildrenOf(parentId);
                secondarySafe &= mostRecentAccessedRevisions == null || replicaInfo.isMoreRecentThan(mostRecentAccessedRevisions);
            } else {
                // localChanges not initialized yet
                secondarySafe = false;
            }
            ReadPreference readPreference;
            if (secondarySafe) {
                readPreference = getConfiguredReadPreference(collection);
            } else {
                readPreference = ReadPreference.primary();
            }
            return readPreference;
        default:
            throw new IllegalArgumentException("Unsupported usage " + preference);
    }
}
Also used : ReadPreference(com.mongodb.ReadPreference) NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument)

Example 12 with NodeDocument

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

the class NodeDocumentCache method putNonConflictingDocs.

/**
     * Updates the cache with all the documents that:
     *
     * (1) currently have their older versions in the cache or
     * (2) have been neither put nor invalidated during the tracker lifetime.
     *
     * We can't cache documents that has been invalidated during the tracker
     * lifetime, as it's possible that the invalidated version was newer than
     * the one passed in the docs parameter.
     *
     * If the document has been added during the tracker lifetime, but it is not
     * present in the cache anymore, it means it may have been evicted, so we
     * can't re-add it for the same reason as above.
     *
     * @param tracker
     *            used to decide whether the docs should be put into cache
     * @param docs
     *            to put into cache
     */
public void putNonConflictingDocs(CacheChangesTracker tracker, Iterable<NodeDocument> docs) {
    for (NodeDocument d : docs) {
        if (d == null || d == NodeDocument.NULL) {
            continue;
        }
        String id = d.getId();
        Lock lock = locks.acquire(id);
        try {
            NodeDocument cachedDoc = getIfPresent(id);
            // if an old document is present in the cache, we can simply update it
            if (cachedDoc != null && isNewer(cachedDoc, d)) {
                putInternal(d);
            // if the document hasn't been invalidated or added during the tracker lifetime,
            // we can put it as well
            } else if (cachedDoc == null && !tracker.mightBeenAffected(id)) {
                putInternal(d);
            }
        } finally {
            lock.unlock();
        }
    }
}
Also used : NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument) Lock(java.util.concurrent.locks.Lock)

Example 13 with NodeDocument

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

the class NodeDocumentCache method putIfNewer.

/**
     * Puts document into cache iff no entry with the given key is cached
     * already or the cached document is older (has smaller {@link Document#MOD_COUNT}).
     *
     * @param doc the document to add to the cache
     * @return either the given <code>doc</code> or the document already present
     *         in the cache if it's newer
     */
@Nonnull
public NodeDocument putIfNewer(@Nonnull final NodeDocument doc) {
    if (doc == NodeDocument.NULL) {
        throw new IllegalArgumentException("doc must not be NULL document");
    }
    doc.seal();
    NodeDocument newerDoc;
    String id = doc.getId();
    Lock lock = locks.acquire(id);
    try {
        NodeDocument cachedDoc = getIfPresent(id);
        if (isNewer(cachedDoc, doc)) {
            newerDoc = doc;
            putInternal(doc);
        } else {
            newerDoc = cachedDoc;
        }
    } finally {
        lock.unlock();
    }
    return newerDoc;
}
Also used : NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument) Lock(java.util.concurrent.locks.Lock) Nonnull(javax.annotation.Nonnull)

Example 14 with NodeDocument

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

the class RDBCacheConsistencyIT method runTest.

private void runTest() throws Throwable {
    addNodes(null, "/test", "/test/foo");
    final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>());
    Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {
            String id = Utils.getIdFromPath("/test/foo");
            List<String> ids = Lists.newArrayList();
            ids.add(id);
            long v = 0;
            while (exceptions.isEmpty()) {
                try {
                    UpdateOp op = new UpdateOp(ids.get(0), false);
                    op.set("p", ++v);
                    op.set("mb", "update");
                    store.update(NODES, ids, op);
                    NodeDocument doc = store.find(NODES, id);
                    Object p = doc.get("p");
                    assertEquals("Unexpected result after update-then-find sequence, last modification of document by '" + doc.get("mb") + "' thread @" + doc.getModCount(), v, ((Long) p).longValue());
                // System.out.println("u @" + doc.getModCount() + " p=" + v + "; q=" + doc.get("q"));
                } catch (Throwable e) {
                    exceptions.add(e);
                }
            }
        }
    }, "update");
    t1.start();
    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {
            String id = Utils.getIdFromPath("/test/foo");
            long v = 0;
            long lastWrittenV = 0;
            while (exceptions.isEmpty()) {
                try {
                    UpdateOp op = new UpdateOp(id, false);
                    op.set("q", ++v);
                    op.set("mb", "findAndUpdate");
                    NodeDocument old = store.findAndUpdate(NODES, op);
                    Object q = old.get("q");
                    if (q != null) {
                        assertEquals("Unexpected result after findAndUpdate, last modification of document by '" + old.get("mb") + "' thread @" + old.getModCount(), lastWrittenV, ((Long) q).longValue());
                    }
                    lastWrittenV = v;
                // System.out.println("f @" + old.getModCount() + " p=" + old.get("p") + "; q=" + q);
                } catch (DocumentStoreException e) {
                // System.err.println("f update of v to " + v + " failed: " + e.getMessage());
                // keep going, RDBDocumentStore might have given up due
                // to race conditions
                } catch (Throwable e) {
                    exceptions.add(e);
                }
            }
        }
    }, "findAndUpdate");
    t2.start();
    Thread t3 = new Thread(new Runnable() {

        @Override
        public void run() {
            String id = Utils.getIdFromPath("/test/foo");
            long p = 0;
            long q = 0;
            long mc = 0;
            while (exceptions.isEmpty()) {
                try {
                    NodeDocument doc = store.find(NODES, id);
                    if (doc != null) {
                        Object value = doc.get("p");
                        if (value != null) {
                            assertTrue("reader thread at @" + doc.getModCount() + ": observed property value for 'p' (incremented by 'update' thread) decreased, last change by '" + doc.get("mb") + "' thread; previous: " + p + " (at @" + mc + "), now: " + value, (Long) value >= p);
                            p = (Long) value;
                        }
                        value = doc.get("q");
                        if (value != null) {
                            assertTrue("reader thread at @" + doc.getModCount() + ": observed property value for 'q' (incremented by 'findAndUpdate' thread) decreased, last change by '" + doc.get("mb") + "' thread; previous: " + q + " (at @" + mc + "), now: " + value, (Long) value >= q);
                            q = (Long) value;
                        }
                    }
                    mc = doc.getModCount();
                } catch (Throwable e) {
                    exceptions.add(e);
                }
            }
        }
    }, "reader");
    t3.start();
    NodeDocumentCache cache = store.getNodeDocumentCache();
    // run for at most five seconds
    long end = System.currentTimeMillis() + 1000;
    String id = Utils.getIdFromPath("/test/foo");
    while (t1.isAlive() && t2.isAlive() && t3.isAlive() && System.currentTimeMillis() < end) {
        if (cache.getIfPresent(id) != null) {
            Thread.sleep(0, (int) (Math.random() * 100));
            // simulate eviction
            cache.invalidate(id);
        }
    }
    for (Throwable e : exceptions) {
        throw e;
    }
    exceptions.add(new Exception("end"));
    t1.join();
    t2.join();
    t3.join();
}
Also used : DocumentStoreException(org.apache.jackrabbit.oak.plugins.document.DocumentStoreException) NodeDocumentCache(org.apache.jackrabbit.oak.plugins.document.cache.NodeDocumentCache) UpdateOp(org.apache.jackrabbit.oak.plugins.document.UpdateOp) NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument) DocumentStoreException(org.apache.jackrabbit.oak.plugins.document.DocumentStoreException) ArrayList(java.util.ArrayList) List(java.util.List)

Example 15 with NodeDocument

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

the class RDBDocumentSerializerTest method testNullModified.

@Test
public void testNullModified() throws UnsupportedEncodingException {
    RDBRow row = new RDBRow("_foo", 1L, true, null, 2l, 3l, "{}", null);
    NodeDocument doc = this.ser.fromRow(Collection.NODES, row);
    assertNull(doc.getModified());
}
Also used : NodeDocument(org.apache.jackrabbit.oak.plugins.document.NodeDocument) Test(org.junit.Test)

Aggregations

NodeDocument (org.apache.jackrabbit.oak.plugins.document.NodeDocument)43 Test (org.junit.Test)14 Lock (java.util.concurrent.locks.Lock)11 UpdateOp (org.apache.jackrabbit.oak.plugins.document.UpdateOp)8 DBObject (com.mongodb.DBObject)6 ArrayList (java.util.ArrayList)6 Nonnull (javax.annotation.Nonnull)6 DocumentStoreException (org.apache.jackrabbit.oak.plugins.document.DocumentStoreException)6 BasicDBObject (com.mongodb.BasicDBObject)5 ExecutionException (java.util.concurrent.ExecutionException)5 Stopwatch (com.google.common.base.Stopwatch)4 DBCollection (com.mongodb.DBCollection)4 Revision (org.apache.jackrabbit.oak.plugins.document.Revision)4 DBCursor (com.mongodb.DBCursor)3 QueryBuilder (com.mongodb.QueryBuilder)3 Callable (java.util.concurrent.Callable)3 AbstractDocumentStoreTest (org.apache.jackrabbit.oak.plugins.document.AbstractDocumentStoreTest)3 UncheckedExecutionException (com.google.common.util.concurrent.UncheckedExecutionException)2 MongoException (com.mongodb.MongoException)2 ReadPreference (com.mongodb.ReadPreference)2