Author: mreutegg Date: Wed Jun 11 12:00:11 2014 New Revision: 1601865 URL: http://svn.apache.org/r1601865 Log: OAK-1822: NodeDocument _modified may go back in time
Merged revisions 1594835,1594888,1601838 from trunk to 1.0 branch. Added: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AmnesiaDiffCache.java - copied unchanged from r1594888, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AmnesiaDiffCache.java jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreIT.java - copied unchanged from r1601838, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreIT.java Modified: jackrabbit/oak/branches/1.0/ (props changed) jackrabbit/oak/branches/1.0/.travis.yml jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentStoreTest.java jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java Propchange: jackrabbit/oak/branches/1.0/ ------------------------------------------------------------------------------ Merged /jackrabbit/oak/trunk:r1594835,1594888,1601838 Modified: jackrabbit/oak/branches/1.0/.travis.yml URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/.travis.yml?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/.travis.yml (original) +++ jackrabbit/oak/branches/1.0/.travis.yml Wed Jun 11 12:00:11 2014 @@ -18,7 +18,12 @@ script: mvn verify -Ppedantic,integrat language: java jdk: - oraclejdk7 -services: mongodb +# OAK-1822: use MongoDB 2.6.1 instead of version provided by travis (2.4.x) +before_install: + - "sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10" + - "echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list" + - "sudo apt-get update" + - "sudo apt-get install mongodb-org=2.6.1 mongodb-org-server=2.6.1 mongodb-org-shell=2.6.1 mongodb-org-mongos=2.6.1 mongodb-org-tools=2.6.1" notifications: email: false webhooks: Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java Wed Jun 11 12:00:11 2014 @@ -23,7 +23,6 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.TimeUnit; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -86,18 +85,6 @@ public class Commit { } /** - * Return time in seconds with 5 second resolution - * - * @param timestamp time in millis to convert - * @return - */ - public static long getModifiedInSecs(long timestamp) { - // 5 second resolution - long timeInSec = TimeUnit.MILLISECONDS.toSeconds(timestamp); - return timeInSec - timeInSec % 5; - } - - /** * The revision for this new commit. That is, the changes within this commit * will be visible with this revision. * Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java Wed Jun 11 12:00:11 2014 @@ -1539,7 +1539,7 @@ public final class DocumentNodeStore private void diffManyChildren(JsopWriter w, String path, Revision fromRev, Revision toRev) { long minTimestamp = Math.min(fromRev.getTimestamp(), toRev.getTimestamp()); - long minValue = Commit.getModifiedInSecs(minTimestamp); + long minValue = NodeDocument.getModifiedInSecs(minTimestamp); String fromKey = Utils.getKeyLowerLimit(path); String toKey = Utils.getKeyUpperLimit(path); Set<String> paths = Sets.newHashSet(); Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java Wed Jun 11 12:00:11 2014 @@ -76,8 +76,8 @@ public class MissingLastRevSeeker { public boolean apply(NodeDocument input) { Long modified = (Long) input.get(NodeDocument.MODIFIED_IN_SECS); return (modified != null - && (modified >= Commit.getModifiedInSecs(startTime)) - && (modified <= Commit.getModifiedInSecs(endTime))); + && (modified >= NodeDocument.getModifiedInSecs(startTime)) + && (modified <= NodeDocument.getModifiedInSecs(endTime))); } }); } Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java Wed Jun 11 12:00:11 2014 @@ -17,7 +17,6 @@ package org.apache.jackrabbit.oak.plugins.document; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -38,6 +37,7 @@ import javax.annotation.Nullable; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.AbstractIterator; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterators; import com.google.common.collect.Queues; @@ -129,6 +129,11 @@ public final class NodeDocument extends */ public static final String MODIFIED_IN_SECS = "_modified"; + /** + * The resolution of the modified time. + */ + static final int MODIFIED_IN_SECS_RESOLUTION = 5; + private static final NavigableMap<Revision, Range> EMPTY_RANGE_MAP = Maps.unmodifiableNavigableMap(new TreeMap<Revision, Range>()); @@ -219,6 +224,18 @@ public final class NodeDocument extends public static final String SD_MAX_REV_TIME_IN_SECS = "_sdMaxRevTime"; /** + * Return time in seconds with 5 second resolution + * + * @param timestamp time in millis to convert + * @return the time in seconds with the given resolution. + */ + public static long getModifiedInSecs(long timestamp) { + // 5 second resolution + long timeInSec = TimeUnit.MILLISECONDS.toSeconds(timestamp); + return timeInSec - timeInSec % MODIFIED_IN_SECS_RESOLUTION; + } + + /** * A document which is created from splitting a main document can be classified * into multiple types depending on the content i.e. weather it contains * REVISIONS, COMMIT_ROOT, property history etc @@ -606,16 +623,14 @@ public final class NodeDocument extends SortedMap<Revision, String> revisions = getLocalRevisions(); SortedMap<Revision, String> commitRoots = getLocalCommitRoot(); Iterator<Revision> it = filter(Iterables.mergeSorted( - Arrays.asList(revisions.keySet(), commitRoots.keySet()), + ImmutableList.of(revisions.keySet(), commitRoots.keySet()), revisions.comparator()), predicate).iterator(); if (it.hasNext()) { newestRev = it.next(); } else { // check full history (only needed in rare cases) it = filter(Iterables.mergeSorted( - Arrays.asList( - getValueMap(REVISIONS).keySet(), - getValueMap(COMMIT_ROOT).keySet()), + ImmutableList.of(getValueMap(REVISIONS).keySet(), getValueMap(COMMIT_ROOT).keySet()), revisions.comparator()), predicate).iterator(); if (it.hasNext()) { newestRev = it.next(); @@ -1186,7 +1201,7 @@ public final class NodeDocument extends public static void setModified(@Nonnull UpdateOp op, @Nonnull Revision revision) { - checkNotNull(op).set(MODIFIED_IN_SECS, Commit.getModifiedInSecs(checkNotNull(revision).getTimestamp())); + checkNotNull(op).max(MODIFIED_IN_SECS, getModifiedInSecs(checkNotNull(revision).getTimestamp())); } public static void setRevision(@Nonnull UpdateOp op, @@ -1291,7 +1306,7 @@ public final class NodeDocument extends private static void setSplitDocMaxRev(@Nonnull UpdateOp op, @Nonnull Revision maxRev) { - checkNotNull(op).set(SD_MAX_REV_TIME_IN_SECS, Commit.getModifiedInSecs(maxRev.getTimestamp())); + checkNotNull(op).set(SD_MAX_REV_TIME_IN_SECS, getModifiedInSecs(maxRev.getTimestamp())); } //----------------------------< internal >---------------------------------- Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java Wed Jun 11 12:00:11 2014 @@ -131,9 +131,7 @@ public final class UpdateOp { * @param value the value */ void setMapEntry(@Nonnull String property, @Nonnull Revision revision, String value) { - Operation op = new Operation(); - op.type = Operation.Type.SET_MAP_ENTRY; - op.value = value; + Operation op = new Operation(Operation.Type.SET_MAP_ENTRY, value); changes.put(new Key(property, checkNotNull(revision)), op); } @@ -145,8 +143,7 @@ public final class UpdateOp { * @param revision the revision */ public void removeMapEntry(@Nonnull String property, @Nonnull Revision revision) { - Operation op = new Operation(); - op.type = Operation.Type.REMOVE_MAP_ENTRY; + Operation op = new Operation(Operation.Type.REMOVE_MAP_ENTRY, null); changes.put(new Key(property, checkNotNull(revision)), op); } @@ -157,9 +154,23 @@ public final class UpdateOp { * @param value the value */ void set(String property, Object value) { - Operation op = new Operation(); - op.type = Operation.Type.SET; - op.value = value; + Operation op = new Operation(Operation.Type.SET, value); + changes.put(new Key(property, null), op); + } + + /** + * Set the property to the given value if the new value is higher than the + * existing value. The property is also set to the given value if the + * property does not yet exist. + * <p> + * The result of a max operation with different types of values is + * undefined. + * + * @param property the name of the property to set. + * @param value the new value for the property. + */ + <T> void max(String property, Comparable<T> value) { + Operation op = new Operation(Operation.Type.MAX, value); changes.put(new Key(property, null), op); } @@ -187,9 +198,7 @@ public final class UpdateOp { if (isNew) { throw new IllegalStateException("Cannot use containsMapEntry() on new document"); } - Operation op = new Operation(); - op.type = Operation.Type.CONTAINS_MAP_ENTRY; - op.value = exists; + Operation op = new Operation(Operation.Type.CONTAINS_MAP_ENTRY, exists); changes.put(new Key(property, checkNotNull(revision)), op); } @@ -200,9 +209,7 @@ public final class UpdateOp { * @param value the increment */ public void increment(@Nonnull String property, long value) { - Operation op = new Operation(); - op.type = Operation.Type.INCREMENT; - op.value = value; + Operation op = new Operation(Operation.Type.INCREMENT, value); changes.put(new Key(property, null), op); } @@ -239,6 +246,14 @@ public final class UpdateOp { SET, /** + * Set the value if the new value is higher than the existing value. + * The new value is also considered higher, when there is no + * existing value. + * The sub-key is not used. + */ + MAX, + + /** * Increment the Long value with the provided Long value. * The sub-key is not used. */ @@ -267,12 +282,17 @@ public final class UpdateOp { /** * The operation type. */ - public Type type; + public final Type type; /** * The value, if any. */ - public Object value; + public final Object value; + + Operation(Type type, Object value) { + this.type = checkNotNull(type); + this.value = value; + } @Override public String toString() { @@ -283,18 +303,16 @@ public final class UpdateOp { Operation reverse = null; switch (type) { case INCREMENT: - reverse = new Operation(); - reverse.type = Type.INCREMENT; - reverse.value = -(Long) value; + reverse = new Operation(Type.INCREMENT, -(Long) value); break; case SET: + case MAX: case REMOVE_MAP_ENTRY: case CONTAINS_MAP_ENTRY: // nothing to do break; case SET_MAP_ENTRY: - reverse = new Operation(); - reverse.type = Type.REMOVE_MAP_ENTRY; + reverse = new Operation(Type.REMOVE_MAP_ENTRY, null); break; } return reverse; Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java Wed Jun 11 12:00:11 2014 @@ -44,7 +44,9 @@ public class UpdateUtils { * @param comparator * the revision comparator. */ - public static void applyChanges(@Nonnull Document doc, @Nonnull UpdateOp update, @Nonnull Comparator<Revision> comparator) { + public static void applyChanges(@Nonnull Document doc, + @Nonnull UpdateOp update, + @Nonnull Comparator<Revision> comparator) { for (Entry<Key, Operation> e : checkNotNull(update).getChanges().entrySet()) { Key k = e.getKey(); Operation op = e.getValue(); @@ -53,6 +55,15 @@ public class UpdateUtils { doc.put(k.toString(), op.value); break; } + case MAX: { + Comparable newValue = (Comparable) op.value; + Object old = doc.get(k.toString()); + //noinspection unchecked + if (old == null || newValue.compareTo(old) > 0) { + doc.put(k.toString(), op.value); + } + break; + } case INCREMENT: { Object old = doc.get(k.toString()); Long x = (Long) op.value; Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java Wed Jun 11 12:00:11 2014 @@ -29,6 +29,8 @@ import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.locks.Lock; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -115,6 +117,7 @@ public class MongoDocumentStore implemen private String lastReadWriteMode; public MongoDocumentStore(DB db, DocumentMK.Builder builder) { + checkVersion(db); nodes = db.getCollection( Collection.NODES.toString()); clusterNodes = db.getCollection( @@ -165,6 +168,24 @@ public class MongoDocumentStore implemen builder.getDocumentCacheSize()); } + private static void checkVersion(DB db) { + String version = db.command("buildInfo").getString("version"); + Matcher m = Pattern.compile("^(\\d+)\\.(\\d+)\\..*").matcher(version); + if (!m.matches()) { + throw new IllegalArgumentException("Malformed MongoDB version: " + version); + } + int major = Integer.parseInt(m.group(1)); + int minor = Integer.parseInt(m.group(2)); + if (major > 2) { + return; + } + if (minor < 6) { + String msg = "MongoDB version 2.6.0 or higher required. " + + "Currently connected to a MongoDB with version: " + version; + throw new RuntimeException(msg); + } + } + private Cache<CacheValue, NodeDocument> createOffHeapCache( DocumentMK.Builder builder) { ForwardingListener<CacheValue, NodeDocument> listener = ForwardingListener.newInstance(); @@ -523,6 +544,7 @@ public class MongoDocumentStore implemen Operation op = entry.getValue(); switch (op.type) { case SET: + case MAX: case INCREMENT: { inserts[i].put(k.toString(), op.value); break; @@ -858,6 +880,7 @@ public class MongoDocumentStore implemen @Nonnull private static DBObject createUpdate(UpdateOp updateOp) { BasicDBObject setUpdates = new BasicDBObject(); + BasicDBObject maxUpdates = new BasicDBObject(); BasicDBObject incUpdates = new BasicDBObject(); BasicDBObject unsetUpdates = new BasicDBObject(); @@ -873,16 +896,17 @@ public class MongoDocumentStore implemen } Operation op = entry.getValue(); switch (op.type) { - case SET: { + case SET: + case SET_MAP_ENTRY: { setUpdates.append(k.toString(), op.value); break; } - case INCREMENT: { - incUpdates.append(k.toString(), op.value); + case MAX: { + maxUpdates.append(k.toString(), op.value); break; } - case SET_MAP_ENTRY: { - setUpdates.append(k.toString(), op.value); + case INCREMENT: { + incUpdates.append(k.toString(), op.value); break; } case REMOVE_MAP_ENTRY: { @@ -896,6 +920,9 @@ public class MongoDocumentStore implemen if (!setUpdates.isEmpty()) { update.append("$set", setUpdates); } + if (!maxUpdates.isEmpty()) { + update.append("$max", maxUpdates); + } if (!incUpdates.isEmpty()) { update.append("$inc", incUpdates); } Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java Wed Jun 11 12:00:11 2014 @@ -33,7 +33,6 @@ import com.mongodb.ReadPreference; import org.apache.jackrabbit.oak.plugins.document.ClusterNodeInfo; import org.apache.jackrabbit.oak.plugins.document.Collection; -import org.apache.jackrabbit.oak.plugins.document.Commit; import org.apache.jackrabbit.oak.plugins.document.Document; import org.apache.jackrabbit.oak.plugins.document.MissingLastRevSeeker; import org.apache.jackrabbit.oak.plugins.document.NodeDocument; @@ -58,9 +57,9 @@ public class MongoMissingLastRevSeeker e final long endTime) { DBObject query = start(NodeDocument.MODIFIED_IN_SECS).lessThanEquals( - Commit.getModifiedInSecs(endTime)) + NodeDocument.getModifiedInSecs(endTime)) .put(NodeDocument.MODIFIED_IN_SECS).greaterThanEquals( - Commit.getModifiedInSecs(startTime)) + NodeDocument.getModifiedInSecs(startTime)) .get(); DBObject sortFields = new BasicDBObject(NodeDocument.MODIFIED_IN_SECS, -1); Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java Wed Jun 11 12:00:11 2014 @@ -38,7 +38,6 @@ import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; import com.mongodb.WriteResult; import org.apache.jackrabbit.oak.plugins.document.Collection; -import org.apache.jackrabbit.oak.plugins.document.Commit; import org.apache.jackrabbit.oak.plugins.document.Document; import org.apache.jackrabbit.oak.plugins.document.NodeDocument; import org.apache.jackrabbit.oak.plugins.document.VersionGCSupport; @@ -71,7 +70,7 @@ public class MongoVersionGCSupport exten //_deletedOnce == true && _modified < lastModifiedTime DBObject query = start(NodeDocument.DELETED_ONCE).is(Boolean.TRUE) - .put(NodeDocument.MODIFIED_IN_SECS).lessThan(Commit.getModifiedInSecs(lastModifiedTime)) + .put(NodeDocument.MODIFIED_IN_SECS).lessThan(NodeDocument.getModifiedInSecs(lastModifiedTime)) .get(); DBCursor cursor = getNodeCollection().find(query).setReadPreference(ReadPreference.secondaryPreferred()); return CloseableIterable.wrap(transform(cursor, new Function<DBObject, NodeDocument>() { @@ -94,7 +93,7 @@ public class MongoVersionGCSupport exten .and( orClause.get(), start(NodeDocument.SD_MAX_REV_TIME_IN_SECS) - .lessThan(Commit.getModifiedInSecs(oldestRevTimeStamp)) + .lessThan(NodeDocument.getModifiedInSecs(oldestRevTimeStamp)) .get() ).get(); Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentStoreTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentStoreTest.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentStoreTest.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentStoreTest.java Wed Jun 11 12:00:11 2014 @@ -31,14 +31,16 @@ public abstract class AbstractDocumentSt protected String dsname; protected DocumentStore ds; protected Set<String> removeMe = new HashSet<String>(); + protected DocumentStoreFixture dsf; public AbstractDocumentStoreTest(DocumentStoreFixture dsf) { this.ds = dsf.createDocumentStore(); + this.dsf = dsf; this.dsname = dsf.getName(); } @After - public void cleanUp() { + public void cleanUp() throws Exception { for (String id : removeMe) { try { ds.remove(org.apache.jackrabbit.oak.plugins.document.Collection.NODES, id); @@ -46,6 +48,7 @@ public abstract class AbstractDocumentSt // best effort } } + dsf.dispose(); } @Parameterized.Parameters Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java Wed Jun 11 12:00:11 2014 @@ -27,10 +27,10 @@ public class CommitTest { @Test public void testModifiedTime(){ - assertEquals(10, Commit.getModifiedInSecs(10000)); - assertEquals(10, Commit.getModifiedInSecs(10003)); - assertEquals(10, Commit.getModifiedInSecs(12000)); - assertEquals(15, Commit.getModifiedInSecs(15000)); - assertEquals(15, Commit.getModifiedInSecs(15006)); + assertEquals(10, NodeDocument.getModifiedInSecs(10000)); + assertEquals(10, NodeDocument.getModifiedInSecs(10003)); + assertEquals(10, NodeDocument.getModifiedInSecs(12000)); + assertEquals(15, NodeDocument.getModifiedInSecs(15000)); + assertEquals(15, NodeDocument.getModifiedInSecs(15006)); } } Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1601865&r1=1601864&r2=1601865&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java Wed Jun 11 12:00:11 2014 @@ -55,8 +55,11 @@ import org.junit.Test; import com.google.common.collect.Iterables; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT; import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES; +import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS; +import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS_RESOLUTION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -391,6 +394,55 @@ public class DocumentNodeStoreTest { nodeStore3.dispose(); } + @Test + public void modifiedReset() throws Exception { + Clock clock = new Clock.Virtual(); + clock.waitUntil(System.currentTimeMillis()); + Revision.setClock(clock); + MemoryDocumentStore docStore = new MemoryDocumentStore(); + DocumentNodeStore ns1 = new DocumentMK.Builder() + .setDocumentStore(docStore).setClusterId(1) + .setAsyncDelay(0).clock(clock).getNodeStore(); + NodeBuilder builder1 = ns1.getRoot().builder(); + builder1.child("node"); + ns1.merge(builder1, EmptyHook.INSTANCE, CommitInfo.EMPTY); + ns1.runBackgroundOperations(); + + DocumentNodeStore ns2 = new DocumentMK.Builder() + .setDocumentStore(docStore).setClusterId(2) + .setAsyncDelay(0).clock(clock).getNodeStore(); + + NodeBuilder builder2 = ns2.getRoot().builder(); + builder2.child("node").child("child-2"); + ns2.merge(builder2, EmptyHook.INSTANCE, CommitInfo.EMPTY); + + // wait at least _modified resolution. in reality the wait may + // not be necessary. e.g. when the clock passes the resolution boundary + // exactly at this time + clock.waitUntil(System.currentTimeMillis() + + SECONDS.toMillis(MODIFIED_IN_SECS_RESOLUTION + 1)); + + builder1 = ns1.getRoot().builder(); + builder1.child("node").child("child-1"); + ns1.merge(builder1, EmptyHook.INSTANCE, CommitInfo.EMPTY); + + ns1.runBackgroundOperations(); + + // get current _modified timestamp on /node + NodeDocument doc = docStore.find(NODES, Utils.getIdFromPath("/node")); + Long mod1 = (Long) doc.get(MODIFIED_IN_SECS); + assertNotNull(mod1); + + ns2.runBackgroundOperations(); + + doc = docStore.find(NODES, Utils.getIdFromPath("/node")); + Long mod2 = (Long) doc.get(MODIFIED_IN_SECS); + assertTrue("" + mod2 + " < " + mod1, mod2 >= mod1); + + ns1.dispose(); + ns2.dispose(); + } + private static class TestHook extends EditorHook { TestHook(final String prefix) {