Merge lp:~pbeaman/akiban-persistit/fix_1018526_temp_trees_in_journal into lp:akiban-persistit

Proposed by Peter Beaman
Status: Merged
Approved by: Peter Beaman
Approved revision: 335
Merged at revision: 330
Proposed branch: lp:~pbeaman/akiban-persistit/fix_1018526_temp_trees_in_journal
Merge into: lp:akiban-persistit
Diff against target: 447 lines (+201/-29)
12 files modified
src/main/java/com/persistit/Buffer.java (+3/-1)
src/main/java/com/persistit/Exchange.java (+3/-1)
src/main/java/com/persistit/IntegrityCheck.java (+5/-4)
src/main/java/com/persistit/JournalManager.java (+13/-1)
src/main/java/com/persistit/Persistit.java (+2/-4)
src/main/java/com/persistit/RecoveryManager.java (+18/-6)
src/main/java/com/persistit/Transaction.java (+10/-7)
src/main/java/com/persistit/Tree.java (+11/-0)
src/main/java/com/persistit/Volume.java (+26/-1)
src/main/java/com/persistit/VolumeStructure.java (+6/-1)
src/test/java/com/persistit/Bug1018526Test.java (+104/-0)
src/test/java/com/persistit/Bug932097Test.java (+0/-3)
To merge this branch: bzr merge lp:~pbeaman/akiban-persistit/fix_1018526_temp_trees_in_journal
Reviewer Review Type Date Requested Status
Nathan Williams Needs Fixing
Peter Beaman Needs Resubmitting
Akiban Build User Needs Fixing
Review via email: mp+112454@code.launchpad.net

Description of the change

Fix bug1018526 in which every tree created in a temporary volume has an Identify Tree (IT) record in the journal.

Removes proactive call to JournalManager#handleForTree in VolumeStructure#getTree and instead lets tree handles be created lazily.

Adds a test to verify that no records are written to the journal within a transaction if only temporary volumes are modified.

To post a comment you must log in.
Revision history for this message
Peter Beaman (pbeaman) wrote :

After reconsideration I'm going to add code to remove temporary trees from the _handleToTreeMap on recovery. This will clean up any mess at customer sites related to this bug when we install this update and restart the server.

review: Needs Fixing
Revision history for this message
Nathan Williams (nwilliams) wrote :

What is the intended lifetime of the tree handle now? It looks like it will get created on remove key, remove tree, store key, and accumulator delta inside of a transaction. It looks like _ignoreTransactions hould always mirror isTemporary but it is up to the caller. Maybe an assert inside of JournalManager#handleForTree() would be nice.

A couple of the checks for handle != 0 are also slightly confusing. We shouldn't have MVVs in a temporary tree (txns being ignored) so if we are pruning, we should always have a handle. Similarly, how could we get an index hole if they can't be shared across threads and aren't recovered?

The new test with the "upper bound" to avoid a checkpoint race. We already have a couple intermittent test failures, it would be nice to structure this so it is always deterministic.

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

Added code to detect IT records that refer to temporary volumes during recovery. Such trees are not restored into the handleToTreeMap and treeToHandleMap collections, so that when the journal next rolls over, the recorded tree map will contain only permanent trees and volumes. This logic will fix up existing systems.

Once we have had this version in the field on all sites we can then remove the cleanup code.

Note that from the information in the journal, the detection of a temporary volume is somewhat ad hoc. It is known by the conjunction of two things:

id value is 12345 (for no very good reason temporary volumes have all been marked with that ID number)
name ends with "_temporary_volume"

We feel it is unlikely there are any non-temporary volumes that have these two conditions at this time. However, eventually the detection code should be removed since it is less than perfectly precise.

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

Responses to Nathan:

What is the intended lifetime of the tree handle now? It looks like it will get created on remove key, remove tree, store key, and accumulator delta inside of a transaction. -- Correct

It looks like _ignoreTransactions hould always mirror isTemporary but it is up to the caller. - Not quite: currently the directory tree exchange operates with _ignoreTransactions on non-temporary volumes.

Maybe an assert inside of JournalManager#handleForTree() would be nice. - Added

A couple of the checks for handle != 0 are also slightly confusing. We shouldn't have MVVs in a temporary tree (txns being ignored) so if we are pruning, we should always have a handle. - Correct. Changed to asserts.

Similarly, how could we get an index hole if they can't be shared across threads and aren't recovered? - There's an obscure, gnarly re-balance case in raw_removeKeyRangeInternal that can leave an index hole. A fix for another bug may remove it, but for now since we think it can happen, the condition in walkRight should be retained.

The new test with the "upper bound" to avoid a checkpoint race. We already have a couple intermittent test failures, it would be nice to structure this so it is always deterministic. - Yes. I suggest we should do that comprehensively in a different branch.

Revision history for this message
Nathan Williams (nwilliams) wrote :

Thanks for the changes, looks good.

review: Approve
Revision history for this message
Akiban Build User (build-akiban) wrote :

There were 2 failures during build/test:

* job persistit-build failed at build number 374: http://172.16.20.104:8080/job/persistit-build/374/

* view must-pass failed: persistit-build is yellow

review: Needs Fixing
334. By Peter Beaman

Always allocate tree handles for permanent trees

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

Modified the protocol yet again. Tree handles are now assigned on non-temporary trees as soon as the tree object is created. This permits the Exchange#fetchFromValueInternal to enqueue pages with MVVs before any transaction modifies the tree. (Otherwise the conditional on handle != 0 is required in that code path.) Since this behavior is more similar to what we currently have in trunk, it seemed preferable to restore it.

review: Needs Resubmitting
Revision history for this message
Nathan Williams (nwilliams) wrote :

A static final end for the two magic values (12345 and _temporary_volume) would be nice. Coming across that in the future could be confusing otherwise.

Now that tree handles are always loaded proactively, it might be nice to make JournalManage#handleForTree() private/package, grab the current handle in usages in Transaction, and assert in the various JournalManager#write* methods that the incoming handling is non-0.

I don't mean to harp, but since we are trying to fix a bug about the handle lifetime it seems preferable to check all of our assumptions related to it.

review: Needs Fixing
335. By Peter Beaman

Changes per Nathan's review

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

Modified as requested.

review: Needs Resubmitting
Revision history for this message
Nathan Williams (nwilliams) wrote :

I don't mean to nitpick, but the other source of the constants is in Persistit#createTemporaryVolume(). It is minor, but I know *I* will forget about this soon and it would be easy for one to change and not the other.

Feel free to self-approve after that tiny change.

review: Needs Fixing
336. By Peter Beaman

Use constants when creating temp volume

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

Good suggestion. Delegated createTemporaryVolume to a static method in the Volume class to keep the constants private.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/main/java/com/persistit/Buffer.java'
--- src/main/java/com/persistit/Buffer.java 2012-06-29 20:54:00 +0000
+++ src/main/java/com/persistit/Buffer.java 2012-06-30 15:14:20 +0000
@@ -3712,8 +3712,10 @@
3712 if (p == KEY_BLOCK_START) {3712 if (p == KEY_BLOCK_START) {
3713 if (tree != null) {3713 if (tree != null) {
3714 if (!_enqueuedForAntiValuePruning) {3714 if (!_enqueuedForAntiValuePruning) {
3715 final int treeHandle = tree.getHandle();
3716 assert treeHandle != 0 : "MVV found in a temporary tree " + tree;
3715 if (_persistit.getCleanupManager().offer(3717 if (_persistit.getCleanupManager().offer(
3716 new CleanupAntiValue(tree.getHandle(), getPageAddress()))) {3718 new CleanupAntiValue(treeHandle, getPageAddress()))) {
3717 _enqueuedForAntiValuePruning = true;3719 _enqueuedForAntiValuePruning = true;
3718 }3720 }
3719 }3721 }
37203722
=== modified file 'src/main/java/com/persistit/Exchange.java'
--- src/main/java/com/persistit/Exchange.java 2012-06-29 20:54:00 +0000
+++ src/main/java/com/persistit/Exchange.java 2012-06-30 15:14:20 +0000
@@ -2777,7 +2777,9 @@
2777 fetchFixupForLongRecords(value, Integer.MAX_VALUE);2777 fetchFixupForLongRecords(value, Integer.MAX_VALUE);
2778 if (MVV.isArrayMVV(value.getEncodedBytes(), 0, value.getEncodedSize())) {2778 if (MVV.isArrayMVV(value.getEncodedBytes(), 0, value.getEncodedSize())) {
2779 if (bufferForPruning != null) {2779 if (bufferForPruning != null) {
2780 bufferForPruning.enqueuePruningAction(_tree.getHandle());2780 final int treeHandle = _tree.getHandle();
2781 assert treeHandle != 0 : "MVV found in a temporary tree " + _tree;
2782 bufferForPruning.enqueuePruningAction(treeHandle);
2781 }2783 }
2782 visible = mvccFetch(value, minimumBytes);2784 visible = mvccFetch(value, minimumBytes);
2783 fetchFixupForLongRecords(value, minimumBytes);2785 fetchFixupForLongRecords(value, minimumBytes);
27842786
=== modified file 'src/main/java/com/persistit/IntegrityCheck.java'
--- src/main/java/com/persistit/IntegrityCheck.java 2012-06-28 20:08:30 +0000
+++ src/main/java/com/persistit/IntegrityCheck.java 2012-06-30 15:14:20 +0000
@@ -833,9 +833,9 @@
833 }833 }
834 _currentTree = null;834 _currentTree = null;
835 }835 }
836 if (_holes.size() > 0) {836 if (_counters._indexHoleCount > 0) {
837 postMessage(" Tree " + resourceName(tree) + " has " + plural(_holes.size(), "unindexed page"),837 postMessage(" Tree " + resourceName(tree) + " has "
838 LOG_NORMAL);838 + plural((int) _counters._indexHoleCount, "unindexed page"), LOG_NORMAL);
839 if (_fixHoles) {839 if (_fixHoles) {
840 int offered = 0;840 int offered = 0;
841 for (final CleanupIndexHole hole : _holes) {841 for (final CleanupIndexHole hole : _holes) {
@@ -1082,7 +1082,8 @@
1082 }1082 }
10831083
1084 _counters._indexHoleCount++;1084 _counters._indexHoleCount++;
1085 if (_holes.size() < MAX_HOLES_TO_FIX) {1085 final int treeHandle = _currentTree.getHandle();
1086 if (treeHandle != 0 && _holes.size() < MAX_HOLES_TO_FIX) {
1086 _holes.add(new CleanupIndexHole(_currentTree.getHandle(), page, level));1087 _holes.add(new CleanupIndexHole(_currentTree.getHandle(), page, level));
1087 }1088 }
10881089
10891090
=== modified file 'src/main/java/com/persistit/JournalManager.java'
--- src/main/java/com/persistit/JournalManager.java 2012-06-22 19:07:13 +0000
+++ src/main/java/com/persistit/JournalManager.java 2012-06-30 15:14:20 +0000
@@ -213,6 +213,8 @@
213213
214 private volatile long _earliestAbortedTimestamp = Long.MAX_VALUE;214 private volatile long _earliestAbortedTimestamp = Long.MAX_VALUE;
215215
216 private boolean _allowHandlesForTempVolumesAndTrees;
217
216 /**218 /**
217 * <p>219 * <p>
218 * Initialize the new journal. This method takes its information from the220 * Initialize the new journal. This method takes its information from the
@@ -540,7 +542,10 @@
540 return Math.min(urgency, URGENT);542 return Math.min(urgency, URGENT);
541 }543 }
542544
543 public int handleForVolume(final Volume volume) throws PersistitException {545 int handleForVolume(final Volume volume) throws PersistitException {
546 if (!_allowHandlesForTempVolumesAndTrees && volume.isTemporary()) {
547 throw new IllegalStateException("Creating handle for temporary volume " + volume);
548 }
544 if (volume.getHandle() != 0) {549 if (volume.getHandle() != 0) {
545 return volume.getHandle();550 return volume.getHandle();
546 }551 }
@@ -580,6 +585,9 @@
580 }585 }
581586
582 int handleForTree(final Tree tree) throws PersistitException {587 int handleForTree(final Tree tree) throws PersistitException {
588 if (!_allowHandlesForTempVolumesAndTrees && tree.getVolume().isTemporary()) {
589 throw new IllegalStateException("Creating handle for temporary tree " + tree);
590 }
583 if (tree.getHandle() != 0) {591 if (tree.getHandle() != 0) {
584 return tree.getHandle();592 return tree.getHandle();
585 }593 }
@@ -2835,6 +2843,10 @@
2835 return files;2843 return files;
2836 }2844 }
28372845
2846 void unitTestAllowHandlesForTemporaryVolumesAndTrees() {
2847 _allowHandlesForTempVolumesAndTrees = true;
2848 }
2849
2838 public PageNode queryPageNode(final int volumeHandle, final long pageAddress) {2850 public PageNode queryPageNode(final int volumeHandle, final long pageAddress) {
2839 PageNode pn = _pageMap.get(new PageNode(volumeHandle, pageAddress, -1, -1));2851 PageNode pn = _pageMap.get(new PageNode(volumeHandle, pageAddress, -1, -1));
2840 if (pn != null) {2852 if (pn != null) {
28412853
=== modified file 'src/main/java/com/persistit/Persistit.java'
--- src/main/java/com/persistit/Persistit.java 2012-06-22 19:35:13 +0000
+++ src/main/java/com/persistit/Persistit.java 2012-06-30 15:14:20 +0000
@@ -1108,7 +1108,7 @@
1108 * <p />1108 * <p />
1109 * The backing store file for a temporary volume is created in the directory1109 * The backing store file for a temporary volume is created in the directory
1110 * specified by the configuration property <code>tmpvoldir</code>, or if1110 * specified by the configuration property <code>tmpvoldir</code>, or if
1111 * unspecified, the system temporary directory..1111 * unspecified, the system temporary directory.
1112 * 1112 *
1113 * @param pageSize1113 * @param pageSize
1114 * The page size for the volume. Must be one of 1024, 2048, 4096,1114 * The page size for the volume. Must be one of 1024, 2048, 4096,
@@ -1121,9 +1121,7 @@
1121 if (!Volume.isValidPageSize(pageSize)) {1121 if (!Volume.isValidPageSize(pageSize)) {
1122 throw new IllegalArgumentException("Invalid page size " + pageSize);1122 throw new IllegalArgumentException("Invalid page size " + pageSize);
1123 }1123 }
1124 Volume volume = new Volume(Thread.currentThread().getName() + "_temporary_volume", 12345);1124 return Volume.createTemporaryVolume(this, pageSize);
1125 volume.openTemporary(this, pageSize);
1126 return volume;
1127 }1125 }
11281126
1129 /**1127 /**
11301128
=== modified file 'src/main/java/com/persistit/RecoveryManager.java'
--- src/main/java/com/persistit/RecoveryManager.java 2012-06-14 20:15:48 +0000
+++ src/main/java/com/persistit/RecoveryManager.java 2012-06-30 15:14:20 +0000
@@ -595,8 +595,13 @@
595595
596 void collectRecoveredVolumeMaps(final Map<Integer, Volume> handleToVolumeMap,596 void collectRecoveredVolumeMaps(final Map<Integer, Volume> handleToVolumeMap,
597 final Map<Volume, Integer> volumeToHandleMap) {597 final Map<Volume, Integer> volumeToHandleMap) {
598 volumeToHandleMap.putAll(_volumeToHandleMap);598 for (final Map.Entry<Integer, Volume> entry : _handleToVolumeMap.entrySet()) {
599 handleToVolumeMap.putAll(_handleToVolumeMap);599 final Volume volume = entry.getValue();
600 if (!volume.isTemporary()) {
601 volumeToHandleMap.put(volume, entry.getKey());
602 handleToVolumeMap.put(entry.getKey(), volume);
603 }
604 }
600 }605 }
601606
602 void collectRecoveredTreeMaps(final Map<Integer, TreeDescriptor> handleToTreeMap,607 void collectRecoveredTreeMaps(final Map<Integer, TreeDescriptor> handleToTreeMap,
@@ -994,10 +999,17 @@
994 final Integer handle = Integer.valueOf(IT.getHandle(_readBuffer));999 final Integer handle = Integer.valueOf(IT.getHandle(_readBuffer));
995 final String treeName = IT.getTreeName(_readBuffer);1000 final String treeName = IT.getTreeName(_readBuffer);
996 final Integer volumeHandle = Integer.valueOf(IT.getVolumeHandle(_readBuffer));1001 final Integer volumeHandle = Integer.valueOf(IT.getVolumeHandle(_readBuffer));
997 final TreeDescriptor td = new TreeDescriptor(volumeHandle, treeName);1002 final Volume volume = _handleToVolumeMap.get(volumeHandle);
998 _handleToTreeMap.put(handle, td);1003 if (volume == null) {
999 _treeToHandleMap.put(td, handle);1004 throw new CorruptJournalException("IT JournalRecord refers to unidentified volume handle " + volumeHandle
1000 _persistit.getLogBase().recoveryRecord.log("IT", addressToString(address, timestamp), treeName, timestamp);1005 + " at position " + addressToString(address, timestamp));
1006 }
1007 if (!volume.isTemporary()) {
1008 final TreeDescriptor td = new TreeDescriptor(volumeHandle, treeName);
1009 _handleToTreeMap.put(handle, td);
1010 _treeToHandleMap.put(td, handle);
1011 _persistit.getLogBase().recoveryRecord.log("IT", addressToString(address, timestamp), treeName, timestamp);
1012 }
1001 }1013 }
10021014
1003 /**1015 /**
10041016
=== modified file 'src/main/java/com/persistit/Transaction.java'
--- src/main/java/com/persistit/Transaction.java 2012-05-25 18:50:59 +0000
+++ src/main/java/com/persistit/Transaction.java 2012-06-30 15:14:20 +0000
@@ -1097,8 +1097,7 @@
1097 void store(Exchange exchange, Key key, Value value) throws PersistitException {1097 void store(Exchange exchange, Key key, Value value) throws PersistitException {
1098 if (_nestedDepth > 0) {1098 if (_nestedDepth > 0) {
1099 checkPendingRollback();1099 checkPendingRollback();
1100 final int treeHandle = _persistit.getJournalManager().handleForTree(exchange.getTree());1100 writeStoreRecordToJournal(treeHandle(exchange.getTree()), key, value);
1101 writeStoreRecordToJournal(treeHandle, key, value);
1102 }1101 }
1103 }1102 }
11041103
@@ -1113,8 +1112,7 @@
1113 void remove(Exchange exchange, Key key1, Key key2) throws PersistitException {1112 void remove(Exchange exchange, Key key1, Key key2) throws PersistitException {
1114 if (_nestedDepth > 0) {1113 if (_nestedDepth > 0) {
1115 checkPendingRollback();1114 checkPendingRollback();
1116 final int treeHandle = _persistit.getJournalManager().handleForTree(exchange.getTree());1115 writeDeleteRecordToJournal(treeHandle(exchange.getTree()), key1, key2);
1117 writeDeleteRecordToJournal(treeHandle, key1, key2);
1118 }1116 }
1119 }1117 }
11201118
@@ -1127,8 +1125,7 @@
1127 void removeTree(Exchange exchange) throws PersistitException {1125 void removeTree(Exchange exchange) throws PersistitException {
1128 if (_nestedDepth > 0) {1126 if (_nestedDepth > 0) {
1129 checkPendingRollback();1127 checkPendingRollback();
1130 final int treeHandle = _persistit.getJournalManager().handleForTree(exchange.getTree());1128 writeDeleteTreeToJournal(treeHandle(exchange.getTree()));
1131 writeDeleteTreeToJournal(treeHandle);
1132 }1129 }
1133 }1130 }
11341131
@@ -1203,7 +1200,7 @@
1203 }1200 }
12041201
1205 synchronized void writeDeltaToJournal(final Delta delta) throws PersistitException {1202 synchronized void writeDeltaToJournal(final Delta delta) throws PersistitException {
1206 final int treeHandle = _persistit.getJournalManager().handleForTree(delta.getAccumulator().getTree());1203 final int treeHandle = treeHandle(delta.getAccumulator().getTree());
1207 if (delta.getValue() == 1) {1204 if (delta.getValue() == 1) {
1208 prepare(D0.OVERHEAD);1205 prepare(D0.OVERHEAD);
1209 JournalRecord.putLength(_buffer, D0.OVERHEAD);1206 JournalRecord.putLength(_buffer, D0.OVERHEAD);
@@ -1292,6 +1289,12 @@
1292 + MAXIMUM_STEP);1289 + MAXIMUM_STEP);
1293 }1290 }
1294 }1291 }
1292
1293 private int treeHandle(final Tree tree) {
1294 final int treeHandle = tree.getHandle();
1295 assert treeHandle != 0 : "Undefined tree handle in " + tree;
1296 return treeHandle;
1297 }
12951298
1296 /**1299 /**
1297 * For unit tests only1300 * For unit tests only
12981301
=== modified file 'src/main/java/com/persistit/Tree.java'
--- src/main/java/com/persistit/Tree.java 2012-05-25 18:50:59 +0000
+++ src/main/java/com/persistit/Tree.java 2012-06-30 15:14:20 +0000
@@ -279,6 +279,17 @@
279 }279 }
280280
281 /**281 /**
282 * Assign are set the tree handle. The tree must may not be a member of a
283 * temporary volume.
284 *
285 * @throws PersistitException
286 */
287 void loadHandle() throws PersistitException {
288 assert !_volume.isTemporary() : "Handle allocation for temporary tree " + this;
289 _persistit.getJournalManager().handleForTree(this);
290 }
291
292 /**
282 * Return an <code>Accumulator</code> for this Tree. The caller provides the293 * Return an <code>Accumulator</code> for this Tree. The caller provides the
283 * type (SUM, MAX, MIN or SEQ) of accumulator, and an index value between 0294 * type (SUM, MAX, MIN or SEQ) of accumulator, and an index value between 0
284 * and 63, inclusive. If the <code>Tree</code> does not yet have an295 * and 63, inclusive. If the <code>Tree</code> does not yet have an
285296
=== modified file 'src/main/java/com/persistit/Volume.java'
--- src/main/java/com/persistit/Volume.java 2012-06-15 14:26:11 +0000
+++ src/main/java/com/persistit/Volume.java 2012-06-30 15:14:20 +0000
@@ -62,6 +62,16 @@
62 private volatile VolumeStatistics _statistics;62 private volatile VolumeStatistics _statistics;
63 private volatile VolumeStructure _structure;63 private volatile VolumeStructure _structure;
6464
65 /*
66 * These two constants are used to identify temporary volumes that may have
67 * been identified in existing journal files due to bug 1018526. They are
68 * used in code to detect and remove these records. Once all existing
69 * Persistit volumes sites have been cleaned up, we can remove these
70 * constants and the logic that depends on them.
71 */
72 private final static long TEMP_VOLUME_ID_FOR_FIXUP_DETECTION = 12345;
73 private final static String TEMP_VOLUME_NAME_SUFFIX_FOR_FIXUP_DETECTION = "_temporary_volume";
74
65 public static boolean isValidPageSize(final int pageSize) {75 public static boolean isValidPageSize(final int pageSize) {
66 for (int b = 1024; b <= 16384; b *= 2) {76 for (int b = 1024; b <= 16384; b *= 2) {
67 if (b == pageSize) {77 if (b == pageSize) {
@@ -71,6 +81,13 @@
71 return false;81 return false;
72 }82 }
7383
84 static Volume createTemporaryVolume(final Persistit persistit, final int pageSize) throws PersistitException {
85 Volume volume = new Volume(Thread.currentThread().getName() + TEMP_VOLUME_NAME_SUFFIX_FOR_FIXUP_DETECTION,
86 TEMP_VOLUME_ID_FOR_FIXUP_DETECTION);
87 volume.openTemporary(persistit, pageSize);
88 return volume;
89 }
90
74 /**91 /**
75 * Construct a hollow Volume - used by JournalManager92 * Construct a hollow Volume - used by JournalManager
76 * 93 *
@@ -289,7 +306,15 @@
289 return getStructure().getDirectoryTree();306 return getStructure().getDirectoryTree();
290 }307 }
291308
292 boolean isTemporary() { // TODO309 boolean isTemporary() {
310 if (_storage == null) {
311 /*
312 * TODO - Temporary code to detect temporary volumes on existing
313 * systems to resolve side-effects of bug 1018526.
314 */
315 return _id == TEMP_VOLUME_ID_FOR_FIXUP_DETECTION
316 && _name.endsWith(TEMP_VOLUME_NAME_SUFFIX_FOR_FIXUP_DETECTION);
317 }
293 return getStorage().isTemp();318 return getStorage().isTemp();
294 }319 }
295320
296321
=== modified file 'src/main/java/com/persistit/VolumeStructure.java'
--- src/main/java/com/persistit/VolumeStructure.java 2012-06-22 19:07:13 +0000
+++ src/main/java/com/persistit/VolumeStructure.java 2012-06-30 15:14:20 +0000
@@ -79,6 +79,9 @@
79 _directoryTree.setRootPageAddress(rootPageAddr);79 _directoryTree.setRootPageAddress(rootPageAddr);
80 updateDirectoryTree(_directoryTree);80 updateDirectoryTree(_directoryTree);
81 }81 }
82 if (!_volume.isTemporary()) {
83 _directoryTree.loadHandle();
84 }
82 _directoryTree.setValid();85 _directoryTree.setValid();
83 }86 }
8487
@@ -188,7 +191,9 @@
188 } else {191 } else {
189 return null;192 return null;
190 }193 }
191 _persistit.getJournalManager().handleForTree(tree);194 if (!_volume.isTemporary()) {
195 tree.loadHandle();
196 }
192 _treeNameHashMap.put(name, new WeakReference<Tree>(tree));197 _treeNameHashMap.put(name, new WeakReference<Tree>(tree));
193 return tree;198 return tree;
194 }199 }
195200
=== added file 'src/test/java/com/persistit/Bug1018526Test.java'
--- src/test/java/com/persistit/Bug1018526Test.java 1970-01-01 00:00:00 +0000
+++ src/test/java/com/persistit/Bug1018526Test.java 2012-06-30 15:14:20 +0000
@@ -0,0 +1,104 @@
1/**
2 * Copyright © 2011-2012 Akiban Technologies, Inc. All rights reserved.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation, version 3 (only) of the
7 * License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * This program may also be available under different license terms. For more
18 * information, see www.akiban.com or contact licensing@akiban.com.
19 */
20
21package com.persistit;
22
23import static org.junit.Assert.*;
24import static org.junit.Assert.assertEquals;
25import static org.junit.Assert.assertTrue;
26import static org.junit.Assert.fail;
27
28import java.util.HashSet;
29import java.util.Map;
30import java.util.Set;
31
32import org.junit.Test;
33
34import com.persistit.JournalManager.TreeDescriptor;
35import com.persistit.unit.PersistitUnitTestCase;
36
37public class Bug1018526Test extends PersistitUnitTestCase {
38
39 @Test
40 public void tempVolumesAndTreesDoNotGetHandles() throws Exception {
41 final Volume volume = _persistit.createTemporaryVolume();
42 final Exchange exchange = _persistit.getExchange(volume, "a_temp_tree", true);
43 assertEquals("Handle should be 0", 0, volume.getHandle());
44 assertEquals("Handle should be 0", 0, exchange.getTree().getHandle());
45 }
46
47 @Test
48 public void txnOnTempVolumeDoesNotWriteToJournal() throws Exception {
49 final Transaction txn = _persistit.getTransaction();
50 final JournalManager jman = _persistit.getJournalManager();
51 int failed = 0;
52 for (int i = 0; i < 10; i++) {
53 final long startingAddress = jman.getCurrentAddress();
54 txn.begin();
55 try {
56 final Volume volume = _persistit.createTemporaryVolume();
57 final Exchange exchange = _persistit.getExchange(volume, "a_temp_tree", true);
58 exchange.clear().append("abc");
59 exchange.getValue().put(RED_FOX);
60 exchange.store();
61 txn.commit();
62 if (jman.getCurrentAddress() != startingAddress) {
63 failed++;
64 }
65 } finally {
66 txn.end();
67 }
68 }
69 /*
70 * Don't require 0 because a checkpoint could write to the journal in a race
71 */
72 assertTrue("Transaction on temporary volume should not have written to journal", failed < 3);
73 }
74
75 @Test
76 public void temporaryVolumesAndTreesNotReloaded() throws Exception {
77 final Set<Integer> permTreeHandleSet = new HashSet<Integer>();
78 final Volume permVolume = _persistit.getVolume("persistit");
79 _persistit.getJournalManager().unitTestAllowHandlesForTemporaryVolumesAndTrees();
80 for (int i = 0; i < 20; i++) {
81 final Volume tempVolume = _persistit.createTemporaryVolume();
82 for (int j = 0; j < 10; j++) {
83 final Tree tempTree = tempVolume.getTree("temp_tree_" + i + "_" + j, true);
84 _persistit.getJournalManager().handleForTree(tempTree);
85 final Tree permTree= permVolume.getTree("perm_tree_" + i + "_" + j, true);
86 _persistit.getJournalManager().handleForTree(permTree);
87 if (!permTreeHandleSet.add(permTree.getHandle())) {
88 fail("Duplicate tree handle " + permTree.getHandle() + " for " + permTree);
89 }
90 }
91 }
92 final Configuration cfg = _persistit.getConfiguration();
93 _persistit.close();
94 _persistit = new Persistit();
95 _persistit.initialize(cfg);
96 Map<Integer, TreeDescriptor> map = _persistit.getJournalManager().queryTreeMap();
97 for (Integer handle : permTreeHandleSet) {
98 TreeDescriptor td = map.remove(handle);
99 assertNotNull("Permanent Tree should be un the tree map", td);
100 }
101 // expect 1: the directory tree
102 assertEquals("Recovered tree map should contain only permanent trees", 1, map.size());
103 }
104}
0105
=== modified file 'src/test/java/com/persistit/Bug932097Test.java'
--- src/test/java/com/persistit/Bug932097Test.java 2012-05-25 18:50:59 +0000
+++ src/test/java/com/persistit/Bug932097Test.java 2012-06-30 15:14:20 +0000
@@ -24,9 +24,6 @@
2424
25import org.junit.Test;25import org.junit.Test;
2626
27import com.persistit.Exchange;
28import com.persistit.Persistit;
29import com.persistit.Transaction;
30import com.persistit.unit.PersistitUnitTestCase;27import com.persistit.unit.PersistitUnitTestCase;
3128
32public class Bug932097Test extends PersistitUnitTestCase {29public class Bug932097Test extends PersistitUnitTestCase {

Subscribers

People subscribed via source and target branches