/* This file is part of VoltDB.
* Copyright (C) 2008-2010 VoltDB Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.voltdb.jni;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicReference;
import junit.framework.TestCase;
import org.voltdb.EELibraryLoader;
import org.voltdb.SysProcSelector;
import org.voltdb.TableStreamType;
import org.voltdb.VoltDB;
import org.voltdb.VoltTable;
import org.voltdb.VoltType;
import org.voltdb.catalog.Catalog;
import org.voltdb.catalog.LoadCatalogToString;
import org.voltdb.exceptions.EEException;
import org.voltdb.utils.DBBPool;
import org.voltdb.utils.DBBPool.BBContainer;
import org.voltdb.utils.Pair;
/**
* Tests native execution engine JNI interface.
*/
public class TestExecutionEngine extends TestCase {
public void testLoadCatalogs() throws Exception {
Catalog catalog = new Catalog();
catalog.execute(LoadCatalogToString.THE_CATALOG);
sourceEngine.loadCatalog(catalog.serialize());
}
public void testLoadBadCatalogs() throws Exception {
/*
* Tests if the intended EE exception will be thrown when bad catalog is
* loaded. We are really expecting an ERROR message on the terminal in
* this case.
*/
String badCatalog = LoadCatalogToString.THE_CATALOG.replaceFirst("set", "bad");
try {
sourceEngine.loadCatalog(badCatalog);
} catch (final EEException e) {
return;
}
assertFalse(true);
}
private void loadTestTables(Catalog catalog) throws Exception
{
final boolean allowExport = false;
int WAREHOUSE_TABLEID = warehouseTableId(catalog);
int STOCK_TABLEID = stockTableId(catalog);
VoltTable warehousedata = new VoltTable(
new VoltTable.ColumnInfo("W_ID", VoltType.INTEGER),
new VoltTable.ColumnInfo("W_NAME", VoltType.STRING)
);
for (int i = 0; i < 200; ++i) {
warehousedata.addRow(i, "str" + i);
}
System.out.println(warehousedata.toString());
sourceEngine.loadTable(WAREHOUSE_TABLEID, warehousedata, 0, 0, Long.MAX_VALUE, allowExport);
VoltTable stockdata = new VoltTable(
new VoltTable.ColumnInfo("S_I_ID", VoltType.INTEGER),
new VoltTable.ColumnInfo("S_W_ID", VoltType.INTEGER),
new VoltTable.ColumnInfo("S_QUANTITY", VoltType.INTEGER)
);
for (int i = 0; i < 1000; ++i) {
stockdata.addRow(i, i % 200, i * i);
}
sourceEngine.loadTable(STOCK_TABLEID, stockdata, 0, 0, Long.MAX_VALUE, allowExport);
}
public void testLoadTable() throws Exception {
Catalog catalog = new Catalog();
catalog.execute(LoadCatalogToString.THE_CATALOG);
sourceEngine.loadCatalog(catalog.serialize());
int WAREHOUSE_TABLEID = warehouseTableId(catalog);
int STOCK_TABLEID = stockTableId(catalog);
loadTestTables(catalog);
assertEquals(200, sourceEngine.serializeTable(WAREHOUSE_TABLEID).getRowCount());
assertEquals(1000, sourceEngine.serializeTable(STOCK_TABLEID).getRowCount());
}
public void testStreamTables() throws Exception {
final Catalog catalog = new Catalog();
catalog.execute(LoadCatalogToString.THE_CATALOG);
sourceEngine.loadCatalog(catalog.serialize());
ExecutionEngine destinationEngine = new ExecutionEngineJNI(null, CLUSTER_ID, NODE_ID, 0, 0, "");
destinationEngine.loadCatalog(catalog.serialize());
int WAREHOUSE_TABLEID = warehouseTableId(catalog);
int STOCK_TABLEID = stockTableId(catalog);
loadTestTables(catalog);
sourceEngine.activateTableStream( WAREHOUSE_TABLEID, TableStreamType.RECOVERY );
sourceEngine.activateTableStream( STOCK_TABLEID, TableStreamType.RECOVERY );
BBContainer origin = DBBPool.allocateDirect(1024 * 1024 * 2);
try {
origin.b.clear();
long address = org.voltdb.utils.DBBPool.getBufferAddress(origin.b);
BBContainer container = new BBContainer(origin.b, address){
@Override
public void discard() {
}};
int serialized = sourceEngine.tableStreamSerializeMore( container, WAREHOUSE_TABLEID, TableStreamType.RECOVERY);
assertTrue(serialized > 0);
container.b.limit(serialized);
destinationEngine.processRecoveryMessage( container.b, container.address);
serialized = sourceEngine.tableStreamSerializeMore( container, WAREHOUSE_TABLEID, TableStreamType.RECOVERY);
assertEquals( 21, serialized);
int id = container.b.get();
assert(id >= 0);
// assertEquals( RecoveryMessageType.Complete.ordinal(), container.b.get());
assertEquals( WAREHOUSE_TABLEID, container.b.getInt());
assertEquals( sourceEngine.tableHashCode(WAREHOUSE_TABLEID), destinationEngine.tableHashCode(WAREHOUSE_TABLEID));
container.b.clear();
serialized = sourceEngine.tableStreamSerializeMore( container, STOCK_TABLEID, TableStreamType.RECOVERY);
assertTrue(serialized > 0);
container.b.limit(serialized);
destinationEngine.processRecoveryMessage( container.b, container.address);
serialized = sourceEngine.tableStreamSerializeMore( container, STOCK_TABLEID, TableStreamType.RECOVERY);
assertEquals( 21, serialized);
id = container.b.get();
assert(id >= 0);
// assertEquals( RecoveryMessageType.Complete.ordinal(), container.b.get());
assertEquals( STOCK_TABLEID, container.b.getInt());
assertEquals( sourceEngine.tableHashCode(STOCK_TABLEID), destinationEngine.tableHashCode(STOCK_TABLEID));
} finally {
origin.discard();
}
}
// public void testRecoveryProcessors() throws Exception {
// final int sourceId = 0;
// final int destinationId = 32;
// final AtomicReference<Boolean> sourceCompleted = new AtomicReference<Boolean>(false);
// final AtomicReference<Boolean> destinationCompleted = new AtomicReference<Boolean>(false);
// final Catalog catalog = new Catalog();
// catalog.execute(LoadCatalogToString.THE_CATALOG);
// sourceEngine.loadCatalog(catalog.serialize());
// final ExecutionEngine destinationEngine =
// new ExecutionEngineJNI(null, CLUSTER_ID, NODE_ID, destinationId, destinationId, "");
// destinationEngine.loadCatalog(catalog.serialize());
//
// int WAREHOUSE_TABLEID = warehouseTableId(catalog);
// int STOCK_TABLEID = stockTableId(catalog);
//
// loadTestTables(catalog);
//
// final HashMap<Pair<String, Integer>, HashSet<Integer>> tablesAndDestinations =
// new HashMap<Pair<String, Integer>, HashSet<Integer>>();
// HashSet<Integer> destinations = new HashSet<Integer>();
// destinations.add(destinationId);
// tablesAndDestinations.put(Pair.of( "STOCK", STOCK_TABLEID), destinations);
// tablesAndDestinations.put(Pair.of( "WAREHOUSE", WAREHOUSE_TABLEID), destinations);
//
// final MockMailbox sourceMailbox = new MockMailbox();
// MockMailbox.registerMailbox( sourceId, sourceMailbox);
//
// final Runnable onSourceCompletion = new Runnable() {
// @Override
// public void run() {
// sourceCompleted.set(true);
// }
// };
//
// final MessageHandler mh = new MessageHandler() {
//
// @Override
// public void handleMessage(VoltMessage message) {
// fail();
// }
// };
//
// Thread sourceThread = new Thread("Source thread") {
// @Override
// public void run() {
// try {
// VoltMessage message = sourceMailbox.recvBlocking();
// assertTrue(message != null);
// assertTrue(message instanceof RecoveryMessage);
// RecoveryMessage rm = (RecoveryMessage)message;
// SocketChannel sc = RecoverySiteProcessorSource.createRecoveryConnection(rm.address(), rm.port());
// final RecoverySiteProcessorSource sourceProcessor =
// new RecoverySiteProcessorSource(
// rm.txnId(),
// rm.sourceSite(),
// tablesAndDestinations,
// sourceEngine,
// sourceMailbox,
// sourceId,
// onSourceCompletion,
// mh,
// sc);
// sourceProcessor.doRecoveryWork(0);
// } catch (java.io.IOException e) {
// e.printStackTrace();
// return;
// }
// }
// };
// sourceThread.start();
//
// final HashMap<Pair<String, Integer>, Integer> tablesAndSources =
// new HashMap<Pair<String, Integer>, Integer>();
// tablesAndSources.put(Pair.of( "STOCK", STOCK_TABLEID), sourceId);
// tablesAndSources.put(Pair.of( "WAREHOUSE", WAREHOUSE_TABLEID), sourceId);
//
// final MockMailbox destinationMailbox = new MockMailbox();
// MockMailbox.registerMailbox( destinationId, destinationMailbox);
//
// final Runnable onDestinationCompletion = new Runnable() {
// @Override
// public void run() {
// destinationCompleted.set(true);
// }
// };
//
// Thread destinationThread = new Thread("Destination thread") {
// @Override
// public void run() {
// RecoverySiteProcessorDestination destinationProcess =
// new RecoverySiteProcessorDestination(
// tablesAndSources,
// destinationEngine,
// destinationMailbox,
// destinationId,
// 0,
// onDestinationCompletion,
// mh);
// /*
// * Do a lot of craziness so we can intercept the mailbox calls
// * and discard the buffer so it is returned to the source
// */
// destinationProcess.doRecoveryWork(-1);
// destinationProcess.doRecoveryWork(0);
// assert(destinationCompleted.get());
// }
// };
// destinationThread.start();
//
// destinationThread.join();
// sourceThread.join();
//
// assertEquals( sourceEngine.tableHashCode(STOCK_TABLEID), destinationEngine.tableHashCode(STOCK_TABLEID));
// assertEquals( sourceEngine.tableHashCode(WAREHOUSE_TABLEID), destinationEngine.tableHashCode(WAREHOUSE_TABLEID));
//
// assertEquals(200, sourceEngine.serializeTable(WAREHOUSE_TABLEID).getRowCount());
// assertEquals(1000, sourceEngine.serializeTable(STOCK_TABLEID).getRowCount());
// assertEquals(200, destinationEngine.serializeTable(WAREHOUSE_TABLEID).getRowCount());
// assertEquals(1000, destinationEngine.serializeTable(STOCK_TABLEID).getRowCount());
// }
private int warehouseTableId(Catalog catalog) {
return catalog.getClusters().get("cluster").getDatabases().get("database").getTables().get("WAREHOUSE").getRelativeIndex();
}
private int stockTableId(Catalog catalog) {
return catalog.getClusters().get("cluster").getDatabases().get("database").getTables().get("STOCK").getRelativeIndex();
}
public void testGetStats() throws Exception {
final Catalog catalog = new Catalog();
catalog.execute(LoadCatalogToString.THE_CATALOG);
sourceEngine.loadCatalog(catalog.serialize());
final int WAREHOUSE_TABLEID = catalog.getClusters().get("cluster").getDatabases().get("database").getTables().get("WAREHOUSE").getRelativeIndex();
final int STOCK_TABLEID = catalog.getClusters().get("cluster").getDatabases().get("database").getTables().get("STOCK").getRelativeIndex();
final int locators[] = new int[] { WAREHOUSE_TABLEID, STOCK_TABLEID };
final VoltTable results[] = sourceEngine.getStats(SysProcSelector.TABLE, locators, false, 0L);
assertNotNull(results);
assertEquals(1, results.length);
assertNotNull(results[0]);
final VoltTable resultTable = results[0];
assertEquals(2, resultTable.getRowCount());
while (resultTable.advanceRow()) {
String tn = resultTable.getString("TABLE_NAME");
assertTrue(tn.equals("WAREHOUSE") || tn.equals("STOCK"));
}
}
private ExecutionEngine sourceEngine;
private static final int CLUSTER_ID = 2;
private static final int NODE_ID = 1;
@Override
protected void setUp() throws Exception {
super.setUp();
EELibraryLoader.loadExecutionEngineLibrary(true);
// VoltDB.instance().readBuildInfo();
sourceEngine = new ExecutionEngineJNI(null, CLUSTER_ID, NODE_ID, 0, 0, "");
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
sourceEngine.release();
sourceEngine = null;
}
}