Merge lp:~pbeaman/akiban-persistit/fix-1076517-page-in-use2 into lp:akiban-persistit

Proposed by Peter Beaman
Status: Merged
Approved by: Nathan Williams
Approved revision: 402
Merged at revision: 401
Proposed branch: lp:~pbeaman/akiban-persistit/fix-1076517-page-in-use2
Merge into: lp:akiban-persistit
Prerequisite: lp:~pbeaman/akiban-persistit/fix-rebalance-exception2
Diff against target: 118 lines (+17/-11)
3 files modified
src/main/java/com/persistit/Exchange.java (+9/-2)
src/main/java/com/persistit/VolumeStructure.java (+3/-4)
src/test/java/com/persistit/stress/unit/AccumulatorRestart.java (+5/-5)
To merge this branch: bzr merge lp:~pbeaman/akiban-persistit/fix-1076517-page-in-use2
Reviewer Review Type Date Requested Status
Nathan Williams Approve
Review via email: mp+136771@code.launchpad.net

Description of the change

Contains fixes for two observed deadlock scenarios described in https://bugs.launchpad.net/akiban-persistit/+bug/1076517.

1. Avoid calling deallocChain in the quick delete branch because a possible race which is otherwise harmless can lead to a deadlock.

2. In the event of a WWRetryException, the non-exclusive claim on the Tree is released as well as the claim on the buffer.

With these changes stress tests ran successfully 8 x 8 hours.

As mentioned in another merge proposal, the code to avoid a hypothetical livelock has been dropped for now until there is evidence of this actually occurring.

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

Simple enough.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/main/java/com/persistit/Exchange.java'
2--- src/main/java/com/persistit/Exchange.java 2012-11-28 20:04:20 +0000
3+++ src/main/java/com/persistit/Exchange.java 2012-11-28 20:04:21 +0000
4@@ -44,6 +44,7 @@
5 import com.persistit.MVV.PrunedVersion;
6 import com.persistit.ValueHelper.MVVValueWriter;
7 import com.persistit.ValueHelper.RawValueWriter;
8+import com.persistit.VolumeStructure.Chain;
9 import com.persistit.exception.CorruptVolumeException;
10 import com.persistit.exception.InUseException;
11 import com.persistit.exception.PersistitException;
12@@ -1662,10 +1663,14 @@
13 buffer.releaseTouched();
14 buffer = null;
15 }
16+ if (treeClaimAcquired) {
17+ _treeHolder.release();
18+ treeClaimAcquired = false;
19+ }
20 try {
21 sequence(WRITE_WRITE_STORE_A);
22+ final long depends = _persistit.getTransactionIndex().wwDependency(re.getVersionHandle(),
23 // TODO - timeout?
24- final long depends = _persistit.getTransactionIndex().wwDependency(re.getVersionHandle(),
25 _transaction.getTransactionStatus(), SharedResource.DEFAULT_MAX_WAIT_TIME);
26 if (depends != 0 && depends != TransactionStatus.ABORTED) {
27 // version is from concurrent txn that already
28@@ -3260,6 +3265,7 @@
29 // First try for a quick delete from a single data page.
30 //
31 if (tryQuickDelete) {
32+ final List<Chain> chains = new ArrayList<Chain>();
33 Buffer buffer = null;
34 try {
35 final int foundAt1 = search(key1, true) & P_MASK;
36@@ -3290,7 +3296,7 @@
37
38 final long timestamp = timestamp();
39 buffer.writePageOnCheckpoint(timestamp);
40- _volume.getStructure().harvestLongRecords(buffer, foundAt1, foundAt2);
41+ _volume.getStructure().harvestLongRecords(buffer, foundAt1, foundAt2, chains);
42
43 final boolean removed = buffer.removeKeys(foundAt1, foundAt2, _spareKey1);
44 if (removed) {
45@@ -3311,6 +3317,7 @@
46 buffer = null;
47 }
48 }
49+ _volume.getStructure().deallocateGarbageChain(chains);
50 }
51
52 /*
53
54=== modified file 'src/main/java/com/persistit/VolumeStructure.java'
55--- src/main/java/com/persistit/VolumeStructure.java 2012-11-28 20:04:20 +0000
56+++ src/main/java/com/persistit/VolumeStructure.java 2012-11-28 20:04:21 +0000
57@@ -57,7 +57,7 @@
58 private final Map<String, WeakReference<Tree>> _treeNameHashMap = new HashMap<String, WeakReference<Tree>>();
59 private Tree _directoryTree;
60
61- private static class Chain {
62+ static class Chain {
63 final long _left;
64 final long _right;
65
66@@ -526,8 +526,7 @@
67 deallocateGarbageChain(list);
68 }
69
70- private void deallocateGarbageChain(final List<Chain> chains) throws PersistitException {
71-
72+ void deallocateGarbageChain(final List<Chain> chains) throws PersistitException {
73 _volume.getStorage().claimHeadBuffer();
74 try {
75 while (!chains.isEmpty()) {
76@@ -608,7 +607,7 @@
77 deallocateGarbageChain(chains);
78 }
79
80- private void harvestLongRecords(final Buffer buffer, final int start, final int end, final List<Chain> chains)
81+ void harvestLongRecords(final Buffer buffer, final int start, final int end, final List<Chain> chains)
82 throws PersistitException {
83 assert buffer.isOwnedAsWriterByMe() : "Harvesting from page owned by another thread: " + buffer;
84 if (buffer.isDataPage()) {
85
86=== modified file 'src/test/java/com/persistit/stress/unit/AccumulatorRestart.java'
87--- src/test/java/com/persistit/stress/unit/AccumulatorRestart.java 2012-11-27 14:42:49 +0000
88+++ src/test/java/com/persistit/stress/unit/AccumulatorRestart.java 2012-11-28 20:04:21 +0000
89@@ -106,16 +106,16 @@
90 seq.update(1, txn);
91 sum.update(r, txn);
92 seqValue++;
93- long minWas = getLong(_ex.to("min"), Long.MAX_VALUE);
94+ final long minWas = getLong(_ex.to("min"), Long.MAX_VALUE);
95 _ex.getValue().put(Math.min(bsum(minValue, r), minWas));
96 _ex.store();
97- long maxWas = getLong(_ex.to("max"), Long.MIN_VALUE);
98+ final long maxWas = getLong(_ex.to("max"), Long.MIN_VALUE);
99 _ex.getValue().put(Math.max(bsum(maxValue, r), maxWas));
100 _ex.store();
101- long seqWas = getLong(_ex.to("seq"), 0);
102+ final long seqWas = getLong(_ex.to("seq"), 0);
103 _ex.getValue().put(Math.max(seqValue, seqWas));
104 _ex.store();
105- long sumWas = getLong(_ex.to("sum"), 0);
106+ final long sumWas = getLong(_ex.to("sum"), 0);
107 _ex.getValue().put(Math.min(sumValue + r, sumWas));
108 _ex.store();
109 if (!a) {
110@@ -150,7 +150,7 @@
111 } catch (final Exception ex) {
112 handleThrowable(ex);
113 } finally {
114- Persistit db = getPersistit();
115+ final Persistit db = getPersistit();
116 try {
117 db.close();
118 } catch (final PersistitException pe) {

Subscribers

People subscribed via source and target branches