/** * Copyright 2011-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.assertEquals; import static org.junit.Assert.assertTrue; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import com.persistit.Accumulator.SumAccumulator; import com.persistit.exception.RollbackException; /** * TableStatusRecoveryIT and RenameTableIT fail intermittently * * These two tests have been failing intermittently since the new MVCC code came * in. I'm going to mark them as @Ignore to unblock other merges, but we have to * fix them before we can release MVCC into the wild. * * Since the failure is intermittent, I recommend several runs of both of these * tests, on various machines including the AMIs, before we mark this as * fix-released. We should also un-ignore those two tests. * * The intermittent failure in RenameTableIT may or may not be related to bug * 852142. We should treat the two bugs as separate for now, since that other * bug was observed only once before (and this one is now fairly frequent). * * * ===== * * This test looks for possible mechanism. Persistit#initialize(Properties) * starts the CheckpointManager's polling thread before applying transactions. * The setting of the initial timestamp for new transactions is updated _while_ * transactions are being applied. This provides an opportunity for the * checkpoint transaction to have the same start timestamp or commit timestamp * as one of the transactions being recovered. * * This can lead to two effects, both of which have been observed: * * - recovery can issue an error message saying that a transaction already * exists having the same start timestamp * * - A previously committed transactions can fail to be recovered. * */ public class Bug911849Test extends PersistitUnitTestCase { private final static int ROW_COUNT_ACCUMULATOR_INDEX = 0; private final Random random = new Random(); private final AtomicInteger counter = new AtomicInteger(); @Test public void testOverlappingCheckpointTransactions() throws Exception { for (int i = 0; i < 10; i++) { accumulateRows(10000); _persistit.getJournalManager().force(); _persistit.crash(); _persistit = new Persistit(_config); final Exchange exchange = _persistit.getExchange("persistit", "AccumulatorRecoveryTest", false); final Accumulator rowCount = exchange.getTree().getAccumulator(Accumulator.Type.SUM, ROW_COUNT_ACCUMULATOR_INDEX); assertEquals(counter.get(), rowCount.getLiveValue()); } } private void accumulateRows(final int max) throws Exception { final Exchange exchange = _persistit.getExchange("persistit", "AccumulatorRecoveryTest", true); final Transaction txn = _persistit.getTransaction(); int count = 0; while (count++ < max) { int retryCount = 0; txn.begin(); try { final SumAccumulator rowCount = exchange.getTree().getSumAccumulator(ROW_COUNT_ACCUMULATOR_INDEX); rowCount.add(1); txn.commit(); counter.incrementAndGet(); if ((count % 10) == 0) { Thread.sleep(1); } } catch (final RollbackException re) { retryCount++; assertTrue(retryCount < 5); System.out.println("(Acceptable) rollback in " + Thread.currentThread().getName()); } finally { txn.end(); } } } }