/**
* Copyright 2012 Akiban Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.persistit;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* https://bugs.launchpad.net/akiban-persistit/+bug/1010079
*
* Various symptoms found while running stress test mixture_txn_1, including
* CorruptVolumeException, CorruptValueException, and several different asserts.
* These all stem from new code introduced in
* lp:~pbeaman/akiban-persistit/fix_1006576_long_record_pruning. This bug is
* related to 1005206 and 1006576. Diagnosis:
*
* New code added to prune LongRecord MVVs operates on a copy of the original
* buffer and then atomically refreshes the original buffer from the copy. That
* operation fails to invalidate the FastIndex of the original buffer in the
* event a key is removed due to a LongRecord MVV becoming a primordial
* anti-value.
*
* In addition, pruneLongMvvValues uses a Value object obtained from a
* ThreadLocal. However, this same Value is already in use by
* Exchange#storeInternal.
*
* @author peter
*
*/
public class Bug1010079Test extends MVCCTestBase {
@Test
public void induceCorruption() throws Exception {
/*
* 1. Create a page with a long record MVV.
*
* 2. Read the value to set up the LevelCache
*
* 3. Abort the transaction so that long record MVV will become an
* AntiValue
*
* 4. Prune the Buffer to liberate the long record chain.
*
* 5. Store a value in the page (not yet certain why this is needed to
* induce the bug, but it is.)
*
* 6. Attempt to the read the first value back in.
*
* Theory of bug is that the read attempt will not see a generation
* change, will use the LevelCache, and will attempt to read a long
* record from a page that has now become a data page.
*/
/*
* Disable background pruning
*/
_persistit.getCleanupManager().setPollInterval(-1);
/*
* Bump the generation number -- perhaps unnecessary
*/
for (int i = 0; i < 10; i++) {
ex1.to(i).store();
ex1.remove();
}
/*
* Store a single Long MVV
*/
trx1.begin();
storeLongMVV(ex1, 1);
ex1.fetch();
trx1.rollback();
trx1.end();
_persistit.getTransactionIndex().updateActiveTransactionCache();
ex1.prune();
ex1.getValue().put(RED_FOX);
ex1.to(0).store();
/*
* This method throws a CorruptVolumeException
*/
ex1.to(1).fetch();
assertTrue("Value should have been removed by rollback", !ex1.getValue().isDefined());
}
}