Merge lp:~pbeaman/akiban-persistit/fix-1023549-traverse-wrong into lp:akiban-persistit

Proposed by Peter Beaman
Status: Merged
Approved by: Peter Beaman
Approved revision: 382
Merged at revision: 382
Proposed branch: lp:~pbeaman/akiban-persistit/fix-1023549-traverse-wrong
Merge into: lp:akiban-persistit
Diff against target: 95 lines (+28/-7)
2 files modified
src/main/java/com/persistit/Exchange.java (+16/-7)
src/test/java/com/persistit/unit/ExchangeTest.java (+12/-0)
To merge this branch: bzr merge lp:~pbeaman/akiban-persistit/fix-1023549-traverse-wrong
Reviewer Review Type Date Requested Status
Nathan Williams Approve
Review via email: mp+129744@code.launchpad.net

Description of the change

Fix bug 1023549: traverse(LTEQ, false, 0) incorrectly returns true.

The bug resulted from some failure to handle a couple of cases in the Exchange#traverse method. Proposed code sets the "matches" variable on each applicable code path. Also fixes an infinite loop in code path for travers(EQ, false, 0) where the key provided is for an MVV that has no visible versions.

Currently Akiban Server works around this problem: see

   com.akiban.server.store.PersistitStore#keyExistsInIndexcom.akiban.server.store

With this proposed branch I have successfully tested a version of Akiban Server in which the deep flag is set to false as originally intended.

Since the changes are subtle and Akiban Server currently works around this problem I recommend holding this proposal out of 3.2.0.

To post a comment you must log in.
Revision history for this message
Nathan Williams (nwilliams) wrote :

Looks good.

Holding off big-A until version bump gets through.

review: Approve
Revision history for this message
Peter Beaman (pbeaman) wrote :

Pushing this through since 3.2.1 update is now merged.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/main/java/com/persistit/Exchange.java'
--- src/main/java/com/persistit/Exchange.java 2012-10-08 19:48:22 +0000
+++ src/main/java/com/persistit/Exchange.java 2012-10-15 19:30:28 +0000
@@ -2053,7 +2053,7 @@
2053 for (;;) {2053 for (;;) {
2054 ++_keysVisitedDuringTraverse;2054 ++_keysVisitedDuringTraverse;
2055 final LevelCache lc = _levelCache[0];2055 final LevelCache lc = _levelCache[0];
2056 boolean matches = false;2056 boolean matches;
2057 //2057 //
2058 // Optimal path - pick up the buffer and location left2058 // Optimal path - pick up the buffer and location left
2059 // by previous operation.2059 // by previous operation.
@@ -2103,9 +2103,9 @@
2103 if (edge && (foundAt & EXACT_MASK) != 0) {2103 if (edge && (foundAt & EXACT_MASK) != 0) {
2104 matches = true;2104 matches = true;
2105 } else if (edge && !deep && Buffer.decodeDepth(foundAt) == index) {2105 } else if (edge && !deep && Buffer.decodeDepth(foundAt) == index) {
2106 // None2106 matches = true;
2107 } else if (direction == EQ) {2107 } else if (direction == EQ) {
2108 // None2108 matches = false;
2109 } else {2109 } else {
2110 edge = false;2110 edge = false;
2111 foundAt = buffer.traverse(_key, direction, foundAt);2111 foundAt = buffer.traverse(_key, direction, foundAt);
@@ -2123,7 +2123,12 @@
2123 buffer = rightSibling;2123 buffer = rightSibling;
2124 checkPageType(buffer, PAGE_TYPE_DATA, false);2124 checkPageType(buffer, PAGE_TYPE_DATA, false);
2125 foundAt = buffer.traverse(_key, direction, buffer.toKeyBlock(0));2125 foundAt = buffer.traverse(_key, direction, buffer.toKeyBlock(0));
2126 matches = !buffer.isAfterRightEdge(foundAt);
2127 } else {
2128 matches = false;
2126 }2129 }
2130 } else {
2131 matches = true;
2127 }2132 }
21282133
2129 //2134 //
@@ -2164,7 +2169,7 @@
2164 // finishing2169 // finishing
21652170
2166 if (reverse && _key.isLeftEdge() || !reverse && _key.isRightEdge() || stopDueToKeyDepth) {2171 if (reverse && _key.isLeftEdge() || !reverse && _key.isRightEdge() || stopDueToKeyDepth) {
2167 // None2172 matches = false;
2168 } else {2173 } else {
2169 if (deep) {2174 if (deep) {
2170 matches |= direction != EQ;2175 matches |= direction != EQ;
@@ -2186,7 +2191,7 @@
2186 parentIndex = 0;2191 parentIndex = 0;
2187 }2192 }
21882193
2189 matches = (spareKey.compareKeyFragment(_key, 0, parentIndex) == 0);2194 matches &= (spareKey.compareKeyFragment(_key, 0, parentIndex) == 0);
21902195
2191 if (matches) {2196 if (matches) {
2192 index = _key.nextElementIndex(parentIndex);2197 index = _key.nextElementIndex(parentIndex);
@@ -2201,10 +2206,14 @@
2201 //2206 //
2202 if (!isVisibleMatch) {2207 if (!isVisibleMatch) {
2203 nudged = false;2208 nudged = false;
2204 nudgeForMVCC = (direction == GTEQ || direction == LTEQ);
2205 buffer.release();2209 buffer.release();
2206 buffer = null;2210 buffer = null;
2207 continue;2211 if (direction == EQ) {
2212 matches = false;
2213 } else {
2214 nudgeForMVCC = (direction == GTEQ || direction == LTEQ);
2215 continue;
2216 }
2208 }2217 }
2209 //2218 //
2210 // It was a niece or nephew, record non-exact2219 // It was a niece or nephew, record non-exact
22112220
=== modified file 'src/test/java/com/persistit/unit/ExchangeTest.java'
--- src/test/java/com/persistit/unit/ExchangeTest.java 2012-10-08 17:59:29 +0000
+++ src/test/java/com/persistit/unit/ExchangeTest.java 2012-10-15 19:30:28 +0000
@@ -424,6 +424,18 @@
424 assertEquals("Should be false", false, ex.traverse(Key.LT, deep, -1));424 assertEquals("Should be false", false, ex.traverse(Key.LT, deep, -1));
425 ex.clear();425 ex.clear();
426426
427 ex.append(1);
428 assertEquals("Should be false", false, ex.traverse(Key.EQ, deep, -1));
429 ex.clear().append(1);
430 assertEquals("Should be false", false, ex.traverse(Key.GTEQ, deep, -1));
431 ex.clear().append(1);
432 assertEquals("Should be false", false, ex.traverse(Key.GT, deep, -1));
433 ex.clear().append(1);
434 assertEquals("Should be false", false, ex.traverse(Key.LTEQ, deep, -1));
435 ex.clear().append(1);
436 assertEquals("Should be false", false, ex.traverse(Key.LT, deep, -1));
437 ex.clear().append(1);
438
427 ex.append(1).append(2).store();439 ex.append(1).append(2).store();
428 ex.clear().append(Key.BEFORE);440 ex.clear().append(Key.BEFORE);
429 assertEquals("Should be false", false, ex.traverse(Key.EQ, deep, -1));441 assertEquals("Should be false", false, ex.traverse(Key.EQ, deep, -1));

Subscribers

People subscribed via source and target branches