Author: jukka
Date: Thu Dec 12 15:14:53 2013
New Revision: 1550436

URL: http://svn.apache.org/r1550436
Log:
OAK-593: Segment-based MK

Simplify the MapRecord comparison code

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java?rev=1550436&r1=1550435&r2=1550436&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
 Thu Dec 12 15:14:53 2013
@@ -291,39 +291,13 @@ class MapRecord extends Record {
     private static boolean compare(
             MapRecord before, MapRecord after, MapDiff diff) {
         Segment beforeSegment = before.getSegment();
-        Segment afterSegment = after.getSegment();
         int beforeHead = beforeSegment.readInt(before.getOffset(0));
+
+        Segment afterSegment = after.getSegment();
         int afterHead = afterSegment.readInt(after.getOffset(0));
-        if (isBranch(getSize(beforeHead), getLevel(beforeHead))
-                && isBranch(getSize(afterHead), getLevel(afterHead))) {
-            MapRecord[] beforeBuckets = before.getBuckets();
-            MapRecord[] afterBuckets = after.getBuckets();
-            for (int i = 0; i < BUCKETS_PER_LEVEL; i++) {
-                if (Objects.equal(beforeBuckets[i], afterBuckets[i])) {
-                    // do nothing
-                } else if (beforeBuckets[i] == null) {
-                    MapRecord bucket = afterBuckets[i];
-                    for (MapEntry entry : bucket.getEntries()) {
-                        if (!diff.entryAdded(entry)) {
-                            return false;
-                        }
-                    }
-                } else if (afterBuckets[i] == null) {
-                    MapRecord bucket = beforeBuckets[i];
-                    for (MapEntry entry : bucket.getEntries()) {
-                        if (!diff.entryDeleted(entry)) {
-                            return false;
-                        }
-                    }
-                } else {
-                    MapRecord beforeBucket = beforeBuckets[i];
-                    MapRecord afterBucket = afterBuckets[i];
-                    if (!compare(beforeBucket, afterBucket, diff)) {
-                        return false;
-                    }
-                }
-            }
-            return true;
+
+        if (isBranch(beforeHead) && isBranch(afterHead)) {
+            return compareBranch(before, after, diff);
         }
 
         Iterator<MapEntry> beforeEntries = before.getEntries().iterator();
@@ -355,6 +329,46 @@ class MapRecord extends Record {
         return true;
     }
 
+    /**
+     * Compares two map branches. Given the way the comparison algorithm
+     * works, the branches are always guaranteed to be at the same level
+     * with the same hash prefixes.
+     */
+    private static boolean compareBranch(
+            MapRecord before, MapRecord after, MapDiff diff) {
+        MapRecord[] beforeBuckets = before.getBuckets();
+        MapRecord[] afterBuckets = after.getBuckets();
+        for (int i = 0; i < BUCKETS_PER_LEVEL; i++) {
+            if (Objects.equal(beforeBuckets[i], afterBuckets[i])) {
+                // these buckets are equal (or both empty), so no changes
+            } else if (beforeBuckets[i] == null) {
+                // before bucket is empty, so all after entries were added
+                MapRecord bucket = afterBuckets[i];
+                for (MapEntry entry : bucket.getEntries()) {
+                    if (!diff.entryAdded(entry)) {
+                        return false;
+                    }
+                }
+            } else if (afterBuckets[i] == null) {
+                // after bucket is empty, so all before entries were deleted
+                MapRecord bucket = beforeBuckets[i];
+                for (MapEntry entry : bucket.getEntries()) {
+                    if (!diff.entryDeleted(entry)) {
+                        return false;
+                    }
+                }
+            } else {
+                // both before and after buckets exist; compare recursively
+                MapRecord beforeBucket = beforeBuckets[i];
+                MapRecord afterBucket = afterBuckets[i];
+                if (!compare(beforeBucket, afterBucket, diff)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     private static int getSize(int head) {
         return head & ((1 << MapRecord.SIZE_BITS) - 1);
     }
@@ -363,6 +377,10 @@ class MapRecord extends Record {
         return head >>> MapRecord.SIZE_BITS;
     }
 
+    private static boolean isBranch(int head) {
+        return isBranch(getSize(head), getLevel(head));
+    }
+
     private static boolean isBranch(int size, int level) {
         return size > MapRecord.BUCKETS_PER_LEVEL
                 && level < MapRecord.MAX_NUMBER_OF_LEVELS;

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java?rev=1550436&r1=1550435&r2=1550436&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
 Thu Dec 12 15:14:53 2013
@@ -38,7 +38,7 @@ class Record {
     }
 
     static boolean fastEquals(Record a, Record b) {
-        return equal(a.uuid, b.uuid) && a.offset == b.offset;
+        return a.offset == b.offset && equal(a.uuid, b.uuid);
     }
 
     /**
@@ -157,6 +157,23 @@ class Record {
     //------------------------------------------------------------< Object >--
 
     @Override
+    public boolean equals(Object object) {
+        if (object == this) {
+            return true;
+        } else if (object instanceof Record) {
+            Record that = (Record) object;
+            return offset == that.offset && uuid.equals(that.uuid);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return uuid.hashCode() ^ offset;
+    }
+
+    @Override
     public String toString() {
         return getRecordId().toString();
     }


Reply via email to