package edu.brown.hstore;
import java.io.File;
import org.junit.Before;
import org.junit.Test;
import org.voltdb.SysProcSelector;
import org.voltdb.VoltTable;
import org.voltdb.benchmark.tpcc.TPCCConstants;
import org.voltdb.benchmark.tpcc.TPCCProjectBuilder;
import org.voltdb.catalog.Site;
import org.voltdb.catalog.Table;
import org.voltdb.client.Client;
import org.voltdb.jni.ExecutionEngine;
import org.voltdb.utils.VoltTableUtil;
import edu.brown.BaseTestCase;
import edu.brown.benchmark.AbstractProjectBuilder;
import edu.brown.catalog.CatalogUtil;
import edu.brown.hstore.conf.HStoreConf;
import edu.brown.profilers.AntiCacheManagerProfiler;
import edu.brown.utils.CollectionUtil;
import edu.brown.utils.FileUtil;
/**
* Anti-Cache Manager Test Cases for TPC-C
* @author pavlo
*/
public class TestAntiCacheMultiTable extends BaseTestCase {
private static final int NUM_PARTITIONS = 1;
private static final int NUM_TUPLES = 1000;
private static final String TARGET_TABLES[] = {
TPCCConstants.TABLENAME_ORDER_LINE,
TPCCConstants.TABLENAME_HISTORY,
};
// private static final String SEQSCAN_PROCEDURE = "GetRecordNoLimit";
// private static final String SEQSCANLIMIT_PROCEDURE = "GetRecordWithLimit";
// private static final String INDEXSCAN_PROCEDURE = "GetRecordWithIndex";
private static final String statsFields[] = {
"ANTICACHE_TUPLES_EVICTED",
"ANTICACHE_BLOCKS_EVICTED",
"ANTICACHE_BYTES_EVICTED"
};
private HStoreSite hstore_site;
private HStoreConf hstore_conf;
private File anticache_dir;
private Client client;
private PartitionExecutor executor;
private ExecutionEngine ee;
private AntiCacheManagerProfiler profiler;
private int locators[];
private final AbstractProjectBuilder builder = new TPCCProjectBuilder() {
{
for (String table : TARGET_TABLES)
this.markTableEvictable(table);
this.addAllDefaults();
// this.addStmtProcedure(SEQSCAN_PROCEDURE,
// "SELECT * FROM " + TARGET_TABLE);
// this.addStmtProcedure(SEQSCANLIMIT_PROCEDURE,
// "SELECT * FROM " + TARGET_TABLE + " LIMIT ?");
// this.addStmtProcedure(INDEXSCAN_PROCEDURE,
// "SELECT * FROM " + TARGET_TABLE +
// " WHERE OL_O_ID >= ?" +
// " AND OL_D_ID >= ?" +
// " AND OL_W_ID >= ?" +
// " LIMIT ?");
}
};
@Before
public void setUp() throws Exception {
super.setUp(builder, false);
initializeCatalog(1, 1, NUM_PARTITIONS);
this.anticache_dir = FileUtil.getTempDirectory();
// Just make sure that the Table has the evictable flag set to true
this.locators = new int[TARGET_TABLES.length];
for (int i = 0; i < TARGET_TABLES.length; i++) {
Table catalog_tbl = getTable(TARGET_TABLES[i]);
assertTrue(catalog_tbl.getEvictable());
this.locators[i] = catalog_tbl.getRelativeIndex();
} // FOR
Site catalog_site = CollectionUtil.first(catalogContext.sites);
this.hstore_conf = HStoreConf.singleton();
this.hstore_conf.site.anticache_enable = true;
this.hstore_conf.site.anticache_profiling = true;
this.hstore_conf.site.anticache_check_interval = Integer.MAX_VALUE;
this.hstore_conf.site.anticache_dir = this.anticache_dir.getAbsolutePath();
this.hstore_site = createHStoreSite(catalog_site, hstore_conf);
this.executor = hstore_site.getPartitionExecutor(0);
assertNotNull(this.executor);
this.ee = executor.getExecutionEngine();
assertNotNull(this.executor);
this.profiler = hstore_site.getAntiCacheManager().getDebugContext().getProfiler(0);
assertNotNull(profiler);
this.client = createClient();
}
@Override
protected void tearDown() throws Exception {
if (this.client != null) this.client.close();
if (this.hstore_site != null) this.hstore_site.shutdown();
FileUtil.deleteDirectory(this.anticache_dir);
}
// --------------------------------------------------------------------------------------------
// UTILITY METHODS
// --------------------------------------------------------------------------------------------
private void loadData(Table catalog_tbl) throws Exception {
// Load in a bunch of dummy data for this table
VoltTable vt = CatalogUtil.getVoltTable(catalog_tbl);
assertNotNull(vt);
for (int i = 0; i < NUM_TUPLES; i++) {
Object row[] = VoltTableUtil.getRandomRow(catalog_tbl);
if (catalog_tbl.getName().equalsIgnoreCase(TPCCConstants.TABLENAME_ORDER_LINE)) {
row[0] = i; // OL_O_ID
row[1] = (byte)i; // OL_D_ID
row[2] = (short)i; // OL_W_ID
}
vt.addRow(row);
} // FOR
this.executor.loadTable(1000l, catalog_tbl, vt, false);
int statsLocators[] = { catalog_tbl.getRelativeIndex() };
VoltTable stats[] = this.ee.getStats(SysProcSelector.TABLE, statsLocators, false, 0L);
assertEquals(1, stats.length);
// System.err.println(VoltTableUtil.format(stats));
}
private VoltTable evictData(Table catalog_tbl) throws Exception {
VoltTable results[] = this.ee.getStats(SysProcSelector.TABLE, this.locators, false, 0L);
assertEquals(1, results.length);
// System.err.println(VoltTableUtil.format(results));
while (results[0].advanceRow()) {
if (results[0].getString("TABLE_NAME").equalsIgnoreCase(catalog_tbl.getName()) == false)
continue;
for (String col : statsFields) {
int idx = results[0].getColumnIndex(col);
assertEquals(0, results[0].getLong(idx));
} // FOR
} // WHILE
// Now force the EE to evict our boys out
// We'll tell it to remove 1MB, which is guaranteed to include all of our tuples
VoltTable evictResult = this.ee.antiCacheEvictBlock(catalog_tbl, 1024 * 1024, 1);
// System.err.println("-------------------------------");
// System.err.println(VoltTableUtil.format(evictResult));
assertNotNull(evictResult);
assertEquals(1, evictResult.getRowCount());
assertNotSame(results[0].getColumnCount(), evictResult.getColumnCount());
evictResult.resetRowPosition();
boolean adv = evictResult.advanceRow();
assertTrue(adv);
return (evictResult);
}
// --------------------------------------------------------------------------------------------
// TEST CASES
// --------------------------------------------------------------------------------------------
/**
* testEvictTuples
*/
@Test
public void testEvictTuples() throws Exception {
// First load some stuff into the database
for (String tableName : TARGET_TABLES) {
this.loadData(this.getTable(tableName));
}
// Then make sure that we can evict from each of them
for (String tableName : TARGET_TABLES) {
Table catalog_tbl = this.getTable(tableName);
VoltTable evictResult = this.evictData(catalog_tbl);
evictResult.advanceRow();
// Our stats should now come back with at least one block evicted
VoltTable results[] = this.ee.getStats(SysProcSelector.TABLE, this.locators, false, 0L);
assertEquals(1, results.length);
// System.err.println("-------------------------------");
// System.err.println(VoltTableUtil.format(results));
while (results[0].advanceRow()) {
if (results[0].getString("TABLE_NAME").equalsIgnoreCase(catalog_tbl.getName()) == false)
continue;
for (String col : statsFields) {
assertEquals(col, evictResult.getLong(col), results[0].getLong(col));
if (col == "ANTICACHE_BLOCKS_EVICTED") {
assertEquals(col, 1, results[0].getLong(col));
} else {
assertNotSame(col, 0, results[0].getLong(col));
}
} // FOR
} // WHILE
} // FOR
}
}