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();
}