/*
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 Nov 3, 2008
*/
package com.bigdata.journal;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import com.bigdata.btree.AbstractBTreeTestCase;
import com.bigdata.btree.BTree;
import com.bigdata.btree.IndexMetadata;
import com.bigdata.btree.keys.KV;
/**
* Test suite for {@link Journal#compact(java.io.File)}.
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
*/
public class TestCompactJournal extends ProxyTestCase<Journal> {
/**
*
*/
public TestCompactJournal() {
}
/**
* @param name
*/
public TestCompactJournal(String name) {
super(name);
}
/**
* Verifies exception if there are no commits on the journal (the
* lastCommitTime will be zero which does not identify a valid commit
* point).
*
* @throws IOException
* @throws InterruptedException
* @throws ExecutionException
*/
public void test_emptyJournal() throws IOException, InterruptedException,
ExecutionException {
final File out = File.createTempFile(getName(), Options.JNL);
try {
final Journal src = getStore(getProperties());
try {
try {
// create task.
final Future<Journal> f = src.compact(out);
// obtain new journal (expected to fail).
final Journal newJournal = f.get();
try {
// destroy new journal if succeeded (clean up).
newJournal.destroy();
} finally {
// notify test error.
fail("Expecting " + IllegalArgumentException.class);
}
} catch (IllegalArgumentException ex) {
// log expected exception.
log.info("Ignoring expected exception: " + ex);
}
} finally {
src.destroy();
}
} finally {
out.delete();
}
}
/**
* Test of a journal on which a single index has been register (and the
* journal committed) but no data was written onto the index.
*
* @throws IOException
* @throws InterruptedException
* @throws ExecutionException
*/
public void test_journal_oneIndexNoData() throws IOException,
InterruptedException, ExecutionException {
final File out = File.createTempFile(getName(), Options.JNL);
try {
final Journal src = getStore(getProperties());
try {
// register an index and commit the journal.
final String NAME = "testIndex";
src.registerIndex(new IndexMetadata(NAME, UUID.randomUUID()));
src.commit();
final Future<Journal> f = src.compact(out);
final Journal newJournal = f.get();
// verify state
try {
// verify index exists.
assertNotNull(newJournal.getIndex(NAME));
// verify data is the same.
AbstractBTreeTestCase.assertSameBTree(src.getIndex(NAME),
newJournal.getIndex(NAME));
} finally {
newJournal.destroy();
}
} finally {
src.destroy();
}
} finally {
out.delete();
}
}
/**
* Test with a journal on which a single index has been registered with
* random data on the index.
*
* @throws IOException
* @throws InterruptedException
* @throws ExecutionException
*/
public void test_journal_oneIndexRandomData() throws IOException,
InterruptedException, ExecutionException {
final File out = File.createTempFile(getName(), Options.JNL);
try {
final Journal src = getStore(getProperties());
try {
// register an index and commit the journal.
final String NAME = "testIndex";
src.registerIndex(new IndexMetadata(NAME, UUID.randomUUID()));
{
BTree ndx = src.getIndex(NAME);
KV[] a = AbstractBTreeTestCase
.getRandomKeyValues(1000/* ntuples */);
for (KV kv : a) {
ndx.insert(kv.key, kv.val);
}
}
src.commit();
Future<Journal> f = src.compact(out);
Journal newJournal = f.get();
// verify state
try {
// verify index exists.
assertNotNull(newJournal.getIndex(NAME));
// verify data is the same.
AbstractBTreeTestCase.assertSameBTree(src.getIndex(NAME),
newJournal.getIndex(NAME));
} finally {
newJournal.destroy();
}
} finally {
src.destroy();
}
} finally {
out.delete();
}
}
/**
* Test with a journal on which many indies have been registered and
* populated with random data.
*
* @throws IOException
* @throws InterruptedException
* @throws ExecutionException
*/
public void test_journal_manyIndicesRandomData() throws IOException,
InterruptedException, ExecutionException {
final File out = File.createTempFile(getName(), Options.JNL);
try {
final Journal src = getStore(getProperties());
final String PREFIX = "testIndex#";
final int NUM_INDICES = 20;
for (int i = 0; i < NUM_INDICES; i++) {
// register an index
final String name = PREFIX + i;
src.registerIndex(new IndexMetadata(name, UUID.randomUUID()));
{
// lookup the index.
final BTree ndx = src.getIndex(name);
// #of tuples to write.
final int ntuples = r.nextInt(10000);
// generate random data.
final KV[] a = AbstractBTreeTestCase.getRandomKeyValues(ntuples);
// write tuples (in random order)
for (KV kv : a) {
ndx.insert(kv.key, kv.val);
if (r.nextInt(100) < 10) {
// randomly increment the counter (10% of the time).
ndx.getCounter().incrementAndGet();
}
}
}
}
// commit the journal (!)
src.commit();
try {
final Future<Journal> f = src.compact(out);
final Journal newJournal = f.get();
// verify state
try {
for (int i = 0; i < NUM_INDICES; i++) {
final String name = PREFIX + i;
// verify index exists.
assertNotNull(newJournal.getIndex(name));
// verify data is the same.
AbstractBTreeTestCase.assertSameBTree(src.getIndex(name),
newJournal.getIndex(name));
// and verify the counter was correctly propagated.
assertEquals(src.getIndex(name).getCounter().get(),
newJournal.getIndex(name).getCounter().get());
}
} finally {
newJournal.destroy();
}
} finally {
src.destroy();
}
} finally {
out.delete();
}
}
}