[ 
https://issues.apache.org/jira/browse/OAK-1274?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13845462#comment-13845462
 ] 

Thomas Mueller commented on OAK-1274:
-------------------------------------

I have a patch, but one of the tests fails now for me, and I am not sure why 
(the org.apache.jackrabbit.oak.plugins.mongomk.RandomizedClusterTest):

{noformat}
Index: src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Revision.java
===================================================================
--- src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Revision.java       
(revision 1550150)
+++ src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Revision.java       
(working copy)
@@ -72,10 +72,19 @@
     /**
      * Compare the time part of two revisions. If they contain the same time,
      * the counter is compared.
+     * <p>
+     * This method requires that both revisions are from the same cluster node.
      * 
+     * @param other the other revision
      * @return -1 if this revision occurred earlier, 1 if later, 0 if equal
+     * @throws IllegalArgumentException if the cluster ids don't match
      */
     int compareRevisionTime(Revision other) {
+        if (clusterId != other.clusterId) {
+            throw new IllegalArgumentException(
+                    "Trying to compare revisions of different cluster ids: " + 
+                            this + " and " + other);
+        }
         int comp = timestamp < other.timestamp ? -1 : timestamp > 
other.timestamp ? 1 : 0;
         if (comp == 0) {
             comp = counter < other.counter ? -1 : counter > other.counter ? 1 
: 0;
@@ -84,6 +93,35 @@
     }
     
     /**
+     * Compare the time part of two revisions. If they contain the same time,
+     * the counter is compared. If the counter is the same, the cluster ids are
+     * compared.
+     * 
+     * @param other the other revision
+     * @return -1 if this revision occurred earlier, 1 if later, 0 if equal
+     */    
+    int compareRevisionTimeThenClusterId(Revision other) {
+        int comp = timestamp < other.timestamp ? -1 : timestamp > 
other.timestamp ? 1 : 0;
+        if (comp == 0) {
+            comp = counter < other.counter ? -1 : counter > other.counter ? 1 
: 0;
+        }
+        if (comp == 0) {
+            comp = compareClusterId(other);
+        }
+        return comp;
+    }
+    
+    /**
+     * Compare the cluster node ids of both revisions.
+     * 
+     * @param other the other revision
+     * @return -1 if this revision occurred earlier, 1 if later, 0 if equal
+     */
+    int compareClusterId(Revision other) {
+        return clusterId < other.clusterId ? -1 : clusterId > other.clusterId 
? 1 : 0;
+    }
+    
+    /**
      * Create a simple revision id. The format is similar to MongoDB ObjectId.
      * 
      * @param clusterId the unique machineId + processId
@@ -427,12 +465,12 @@
             Revision range1 = getRevisionSeen(o1);
             Revision range2 = getRevisionSeen(o2);
             if (range1 == FUTURE && range2 == FUTURE) {
-                return o1.compareRevisionTime(o2);
+                return o1.compareRevisionTimeThenClusterId(o2);
             }
             if (range1 == null || range2 == null) {
-                return o1.compareRevisionTime(o2);
+                return o1.compareRevisionTimeThenClusterId(o2);
             }
-            int comp = range1.compareRevisionTime(range2);
+            int comp = range1.compareRevisionTimeThenClusterId(range2);
             if (comp != 0) {
                 return comp;
             }
@@ -464,11 +502,12 @@
             // search from latest backward
             // (binary search could be used, but we expect most queries
             // at the end of the list)
-            Revision result = null;
             for (int i = list.size() - 1; i >= 0; i--) {
                 RevisionRange range = list.get(i);
                 int compare = r.compareRevisionTime(range.revision);
-                if (compare > 0) {
+                if (compare == 0) {
+                    return range.seenAt;
+                } else if (compare > 0) {
                     if (i == list.size() - 1) {
                         // newer than the newest range
                         if (r.getClusterId() == currentClusterNodeId) {
@@ -478,11 +517,10 @@
                         // happenes in the future (not visible yet)
                         return FUTURE;
                     }
-                    break;
+                    return range.seenAt;
                 }
-                result = range.seenAt;
             }
-            return result;
+            return null;
         }
         
         @Override
Index: 
src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/StableRevisionComparator.java
===================================================================
--- 
src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/StableRevisionComparator.java
       (revision 1550150)
+++ 
src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/StableRevisionComparator.java
       (working copy)
@@ -34,10 +34,6 @@
 
     @Override
     public int compare(Revision o1, Revision o2) {
-        int comp = o1.compareRevisionTime(o2);
-        if (comp != 0) {
-            return comp;
-        }
-        return Integer.signum(o1.getClusterId() - o2.getClusterId());
+        return o1.compareRevisionTimeThenClusterId(o2);
     }
 }
Index: 
src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/DocumentSplitTest.java
===================================================================
--- 
src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/DocumentSplitTest.java  
    (revision 1550150)
+++ 
src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/DocumentSplitTest.java  
    (working copy)
@@ -200,7 +200,7 @@
         Revision previous = null;
         for (Map.Entry<Revision, String> entry : revs.entrySet()) {
             if (previous != null) {
-                assertTrue(previous.compareRevisionTime(entry.getKey()) > 0);
+                
assertTrue(previous.compareRevisionTimeThenClusterId(entry.getKey()) > 0);
             }
             previous = entry.getKey();
         }
Index: src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/RevisionTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/RevisionTest.java   
(revision 1550150)
+++ src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/RevisionTest.java   
(working copy)
@@ -122,6 +122,9 @@
 
         RevisionComparator comp = new RevisionComparator(0);
 
+        Revision r0c1 = new Revision(0x010, 0, 1);
+        Revision r0c2 = new Revision(0x010, 0, 2);
+        
         Revision r1c1 = new Revision(0x110, 0, 1);
         Revision r2c1 = new Revision(0x120, 0, 1);
         Revision r3c1 = new Revision(0x130, 0, 1);
@@ -142,6 +145,8 @@
                 "1:\n r120-0-1:r20-0-0\n" +
                 "2:\n r200-0-2:r10-0-0\n", comp.toString());
 
+        assertEquals(-1, comp.compare(r0c1, r0c2));
+
         assertEquals(1, comp.compare(r1c1, r1c2));
         assertEquals(1, comp.compare(r2c1, r2c2));
         // both r3cx are still "in the future"
@@ -186,10 +191,6 @@
 
     }
 
-    /**
-     * OAK-1274
-     */
-    @Ignore
     @Test
     public void clusterCompare() {
         RevisionComparator comp = new RevisionComparator(1);
@@ -198,12 +199,21 @@
         Revision r1c1 = new Revision(0x10, 0, 1);
         Revision r1c2 = new Revision(0x20, 0, 2);
         Revision r2c1 = new Revision(0x30, 0, 1);
-
+        Revision r2c2 = new Revision(0x40, 0, 2);
+        
         comp.add(r1c1, new Revision(0x10, 0, 0));
         comp.add(r2c1, new Revision(0x20, 0, 0));
 
-        // there's no range for r1c2 and must
-        // be considered in the past
+        // there's no range for c2, and therefore this
+        // revision must be considered to be in the future
+        assertTrue(comp.compare(r1c2, r2c1) > 0);
+        
+        // add a range for r2r2
+        comp.add(r2c2, new Revision(0x30, 0, 0));
+
+        // now there is a range for c2, but the revision is old,
+        // so it must be considered to be in the past
         assertTrue(comp.compare(r1c2, r2c1) < 0);
     }
+    
 }

{noformat}

> Wrong comparison for old Revisions
> ----------------------------------
>
>                 Key: OAK-1274
>                 URL: https://issues.apache.org/jira/browse/OAK-1274
>             Project: Jackrabbit Oak
>          Issue Type: Bug
>          Components: core, mongomk
>    Affects Versions: 0.13
>            Reporter: Marcel Reutegger
>            Priority: Minor
>
> Comparing revisions may return wrong results when one of the revision is 
> older than the oldest revision range kept in the RevisionComparator.
> There are multiple reasons why there is no revision range for a revision.
> - The revision was created more than an hour ago and the associated range was 
> purged from the RevisionComparator. This happens in the background thread of 
> MongoNodeStore with a threshold of one hour.
> - The revision isn't actually that old, but still included in a range of the 
> RevisionComparator because the MongoNodeStore instance was just initialized 
> and only has ranges for recent revisions but not for those before the init.



--
This message was sent by Atlassian JIRA
(v6.1.4#6159)

Reply via email to