/** * 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 com.persistit.unit.UnitTestProperties.DATA_PATH; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.junit.Ignore; import org.junit.Test; public class CreateAndDeleteVolumeTest extends PersistitUnitTestCase { /** * Test for https://bugs.launchpad.net/akiban-persistit/+bug/1045971 * * Dynamically loaded volumes not recovered "cleanly" * * When a program creates new volumes using VolumeSpecifications, they * subsequently cause a "missing volume" warning from the journal copier and * prevent the removal of journal files containing the references. The * journal files accumulate seemingly without end, and each initialization * of the database seems to process more and more of the old transactions. * * With thanks to jb5 * * @throws Exception */ @Test public void recoverDynamicVolumes() throws Exception { VolumeSpecification volumeSpec; _persistit.close(); int remainingJournalFiles = 0; for (int i = 5; --i >= 0;) { final Persistit db = new Persistit(_config); try { volumeSpec = new VolumeSpecification(DATA_PATH + "/hwdemo" + i, null, 16384, 1, 1000, 1, true, false, false); db.loadVolume(volumeSpec); final Exchange dbex = db.getExchange("hwdemo" + i, "greetings", true); dbex.getKey().append("Hello"); dbex.getValue().put("World"); dbex.store(); dbex.getKey().to(Key.BEFORE); db.releaseExchange(dbex); } finally { if (i == 0) { db.copyBackPages(); } remainingJournalFiles = db.getJournalManager().getJournalFileCount(); db.close(); } } assertEquals("Should be only one remaining journal file", 1, remainingJournalFiles); } @Test public void useOldVSpecInducesExpectedFailure() throws Exception { VolumeSpecification volumeSpec; final Configuration configuration = _persistit.getConfiguration(); _persistit.close(); int remainingJournalFiles = 0; configuration.setUseOldVSpec(true); for (int i = 5; --i >= 0;) { final Persistit db = new Persistit(_config); try { volumeSpec = new VolumeSpecification(DATA_PATH + "/hwdemo" + i, null, 16384, 1, 1000, 1, true, false, false); db.loadVolume(volumeSpec); final Exchange dbex = db.getExchange("hwdemo" + i, "greetings", true); dbex.getKey().append("Hello"); dbex.getValue().put("World"); dbex.store(); dbex.getKey().to(Key.BEFORE); db.releaseExchange(dbex); } finally { if (i == 0) { db.copyBackPages(); } remainingJournalFiles = db.getJournalManager().getJournalFileCount(); db.close(); } } assertTrue("Should be only one remaining journal file", remainingJournalFiles > 1); } /** * Test for bug https://bugs.launchpad.net/akiban-persistit/+bug/1045983 * * Truncating a dynamically created volume results in corrupted journal If * you dynamically load a volume, truncate it (without adding any trees), * and then close it, the next time the database is initialized a fatal * exception is thrown: * * <code><pre> * * [JOURNAL_COPIER] WARNING Missing volume truncated referenced at journal address 364 * [main] WARNING Missing volume truncated referenced at journal address 17,004 (6 similar occurrences in 0 seconds) * Exception in thread "main" com.persistit.exception.InvalidPageAddressException: Page 1 out of bounds [0-1] * at com.persistit.VolumeStorageV2.readPage(VolumeStorageV2.java:426) * at com.persistit.Buffer.load(Buffer.java:456) * at com.persistit.BufferPool.get(BufferPool.java:780) * at com.persistit.Tree.setRootPageAddress(Tree.java:203) * at com.persistit.VolumeStructure.init(VolumeStructure.java:70) * at com.persistit.VolumeStorageV2.open(VolumeStorageV2.java:217) * at com.persistit.Volume.open(Volume.java:442) * at com.persistit.Persistit.loadVolume(Persistit.java:1066) * at Truncate.main(Truncate.java:30) * * @throws Exception * * </pre></code> * * This test is currently disabled pending a fix. * */ @Test @Ignore public void truncateDynamicVolumes() throws Exception { VolumeSpecification volumeSpec; _persistit.close(); final Persistit db = new Persistit(_config); for (int i = 0; i < 2; i++) { try { volumeSpec = new VolumeSpecification(DATA_PATH + "/truncated", null, 16384, 1, 1000, 1, true, false, false); final Volume volume = db.loadVolume(volumeSpec); volume.truncate(); // the following may be omitted, and the problem still exhibited final Exchange dbex = db.getExchange("truncated", "greetings", true); dbex.getKey().append("ave"); dbex.getValue().put("mundus"); dbex.store(); dbex.getKey().to(Key.BEFORE); while (dbex.next()) { System.out.println(dbex.getKey().reset().decode() + " " + dbex.getValue().get()); } db.releaseExchange(dbex); // the preceding may be omitted, and the problem still exhibited } finally { db.close(); } } } }