/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Feb 3, 2007 */ package com.bigdata.journal; import java.util.UUID; import com.bigdata.btree.BTree; import com.bigdata.btree.IndexMetadata; import com.bigdata.btree.IIndex; /** * Test suite for restart-safety of {@link BTree}s backed by an * {@link IJournal}. * * @todo explore flushing the indexCache as if a GC had occurred after a commit? * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class TestCommitList extends ProxyTestCase<Journal> { /** * */ public TestCommitList() { } /** * @param name */ public TestCommitList(String name) { super(name); } // public Properties getProperties() { // // if (properties == null) { // // properties = super.getProperties(); // // // we need to use a persistent mode of the journal (not transient). // properties.setProperty(Options.BUFFER_MODE, BufferMode.Direct // .toString()); // // properties.setProperty(Options.CREATE_TEMP_FILE, "true"); // // properties.setProperty(Options.DELETE_ON_EXIT,"true"); // // } // // return properties; // // } // // private Properties properties; // /** // * Re-open the same backing store. // * // * @param store // * the existing store. // * // * @return A new store. // * // * @exception Throwable // * if the existing store is not closed, e.g., from failure to // * obtain a file lock, etc. // */ // protected Journal reopenStore(Journal store) { // // // close the store. // store.close(); // // Properties properties = (Properties)getProperties().clone(); // // // Turn this off now since we want to re-open the same store. // properties.setProperty(Options.CREATE_TEMP_FILE,"false"); // // // The backing file that we need to re-open. // File file = store.getFile(); // // assertNotNull(file); // // // Set the file property explictly. // properties.setProperty(Options.FILE,file.toString()); // // return new Journal( properties ); // // } /** * Return a btree backed by a journal with the indicated branching factor. * * @param branchingFactor * The branching factor. * * @return The btree. */ public BTree getBTree(int branchingFactor, Journal journal) { final BTree btree; { IndexMetadata metadata = new IndexMetadata(UUID.randomUUID()); metadata.setBranchingFactor(branchingFactor); btree = BTree.create(journal, metadata); } return btree; } /** * Test verifies that a named index is found on the commit list when (a) it * is newly created; and (b) when an entry is written on the index. * <p> * Note: {@link #test_commitList_001_restartSafe()} SHOULD be maintained in * parallel with this test -- it additionally verifies that the changes are * made restart safe by the commit. * * @see #test_commitList_001_restartSafe() */ public void test_commitList_001() { final Journal journal = new Journal(getProperties()); try { final String name = "abc"; final IndexMetadata md = new IndexMetadata(name, UUID.randomUUID()); // register index. BTree ndx = journal.registerIndex(name, md); // verify index was flushed to the backing store. assertFalse(ndx.needsCheckpoint()); // verify a new index is on the commit list. assertTrue(journal._getName2Addr().willCommit(name)); // commit. journal.commit(); // same index object after the commit. assertEquals(ndx, journal.getIndex(name)); // no longer on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); // write an entry on the index - the index becomes dirty and should // show up on the commit list. ndx.insert(new byte[] { 1, 2, 3 }, new byte[] { 1, 2, 3 }); // verify on the commit list. assertTrue(journal._getName2Addr().willCommit(name)); // commit. journal.commit(); // same index object after the commit. assertEquals(ndx, journal.getIndex(name)); // no longer on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); // verify entry written by the commit. assertEquals(new byte[] { 1, 2, 3 }, (byte[]) ndx .lookup(new byte[] { 1, 2, 3 })); // still not on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); } finally { journal.destroy(); } } /** * A variant of {@link #test_commitList_001()} in which we re-open the store * after each commit and verify that the record written can be read so that * we know that the commit was made restart safe. */ public void test_commitList_001_restartSafe() { Journal journal = new Journal(getProperties()); try { final String name = "abc"; final IndexMetadata md = new IndexMetadata(name, UUID.randomUUID()); // register index. IIndex ndx = journal.registerIndex(name, md); // verify a new index is on the commit list. assertTrue(journal._getName2Addr().willCommit(name)); // commit. journal.commit(); if (journal.isStable()) { // re-open the store. journal = reopenStore(journal); // get the index object from the re-opened store.. ndx = journal.getIndex(name); assertNotNull(ndx); // not on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); // write an entry on the index - the index becomes dirty and // should // show up on the commit list. ndx.insert(new byte[] { 1, 2, 3 }, new byte[] { 1, 2, 3 }); // verify on the commit list. assertTrue(journal._getName2Addr().willCommit(name)); // commit. journal.commit(); // no longer on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); // re-open the store. journal = reopenStore(journal); // get the index object from the re-opened store.. ndx = journal.getIndex(name); assertNotNull(ndx); // not on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); // verify entry written by the commit. assertEquals(new byte[] { 1, 2, 3 }, (byte[]) ndx .lookup(new byte[] { 1, 2, 3 })); // still not on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); } } finally { journal.destroy(); } } /** * Test creates an index, writes an entry on the index, and then commits the * index (so writing on the index immediately after it is created without an * intervening commit). The test then re-opens the store and verifies that * the data are restart safe. */ public void test_commitList002() { Journal journal = new Journal(getProperties()); try { final String name = "abc"; final IndexMetadata md = new IndexMetadata(name, UUID.randomUUID()); // register index. IIndex ndx = journal.registerIndex(name, md); // verify a new index is on the commit list. assertTrue(journal._getName2Addr().willCommit(name)); // write an entry on the index. ndx.insert(new byte[] { 1, 2, 3 }, new byte[] { 1, 2, 3 }); // verify on the commit list. assertTrue(journal._getName2Addr().willCommit(name)); // commit. journal.commit(); // no longer on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); if (journal.isStable()) { // re-open the store. journal = reopenStore(journal); // get the index object from the re-opened store.. ndx = journal.getIndex(name); assertNotNull(ndx); // not on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); // verify entry written by the commit. assertEquals(new byte[] { 1, 2, 3 }, (byte[]) ndx .lookup(new byte[] { 1, 2, 3 })); // still not on the commit list. assertFalse(journal._getName2Addr().willCommit(name)); } } finally { journal.destroy(); } } }