package org.voltdb.regressionsuites;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import junit.framework.Test;
import org.voltdb.BackendTarget;
import org.voltdb.CatalogContext;
import org.voltdb.VoltSystemProcedure;
import org.voltdb.VoltTable;
import org.voltdb.client.Client;
import org.voltdb.client.ClientResponse;
import org.voltdb.sysprocs.EvictTuples;
import org.voltdb.utils.VoltTableUtil;
import edu.brown.HStoreSiteTestUtil.LatchableProcedureCallback;
import edu.brown.benchmark.users.UsersConstants;
import edu.brown.benchmark.users.UsersLoader;
import edu.brown.benchmark.users.UsersProjectBuilder;
import edu.brown.benchmark.users.procedures.GetUsers;
import edu.brown.hstore.Hstoreservice.Status;
import edu.brown.utils.StringUtil;
/**
* Simple test suite for the Users benchmark
*/
public class TestUsersSuite extends RegressionSuite {
private static final String PREFIX = "users";
private static final int NUM_TUPLES = UsersConstants.USERS_SIZE;
private static final int NOTIFY_TIMEOUT = 2000; // ms
/**
* Constructor needed for JUnit. Should just pass on parameters to superclass.
* @param name The name of the method to test. This is just passed to the superclass.
*/
public TestUsersSuite(String name) {
super(name);
}
private void initializeDatabase(final Client client, final int num_tuples) throws Exception {
String args[] = {
"NOCONNECTIONS=true",
"BENCHMARK.FIXED_SIZE=true",
"BENCHMARK.NUM_RECORDS="+num_tuples,
"BENCHMARK.LOADTHREADS=1",
};
final CatalogContext catalogContext = this.getCatalogContext();
UsersLoader loader = new UsersLoader(args) {
{
this.setCatalogContext(catalogContext);
this.setClientHandle(client);
}
@Override
public CatalogContext getCatalogContext() {
return (catalogContext);
}
};
loader.load();
}
/**
* testInitialize
*/
public void testInitialize() throws Exception {
Client client = this.getClient();
this.initializeDatabase(client, NUM_TUPLES);
String query = "SELECT COUNT(*) FROM " + UsersConstants.TABLENAME_USERS;
ClientResponse cresponse = client.callProcedure("@AdHoc", query);
assertEquals(Status.OK, cresponse.getStatus());
VoltTable results[] = cresponse.getResults();
assertEquals(1, results.length);
assertEquals(NUM_TUPLES, results[0].asScalarLong());
}
/**
* testReadRecord
*/
public void testReadRecords() throws Exception {
Client client = this.getClient();
this.initializeDatabase(client, NUM_TUPLES);
// Force an eviction
Map<Integer, VoltTable> evictResults = this.evictData(client);
for (int partition : evictResults.keySet()) {
System.out.println("Partition " + partition);
System.out.println(StringUtil.prefix(" ", VoltTableUtil.format(evictResults.get(partition))));
}
System.out.println("-------------------------------");
String procName = GetUsers.class.getSimpleName();
long user1 = 99998;
long user2 = 1;
Object params[] = { user1, user2 };
ClientResponse cresponse = client.callProcedure(procName, params);
// String query = "UPDATE USERS SET u_attr01= COUNT(*) FROM " + UsersConstants.TABLENAME_USERS;
// ClientResponse cresponse = client.callProcedure("@AdHoc", query);
assertNotNull(cresponse);
assertEquals(Status.OK, cresponse.getStatus());
assertEquals(1, cresponse.getResults()[0].getRowCount());
}
private Map<Integer, VoltTable> evictData(Client client) throws Exception {
// System.err.printf("Evicting data...");
String procName = VoltSystemProcedure.procCallName(EvictTuples.class);
CatalogContext catalogContext = this.getCatalogContext();
String tableNames[] = { UsersConstants.TABLENAME_USERS };
LatchableProcedureCallback callback = new LatchableProcedureCallback(1);
// long evictBytes[] = { Integer.MAX_VALUE };
long evictBytes[] = {1024 * 10};
int numBlocks[] = { 1 };
int remote_partition = catalogContext.getAllPartitionIdArray()[1];
System.out.printf("Evicting data at partition %d...\n", remote_partition);
String children[] = null;
Object params[] = { remote_partition, tableNames, children, evictBytes, numBlocks };
boolean result = client.callProcedure(callback, procName, params);
assertTrue(result);
// Wait until they all finish
result = callback.latch.await(NOTIFY_TIMEOUT, TimeUnit.MILLISECONDS);
assertTrue(callback.toString(), result);
// Construct a mapping BasePartition->VoltTable
Map<Integer, VoltTable> m = new TreeMap<Integer, VoltTable>();
for (ClientResponse cr : callback.responses) {
assertEquals(cr.toString(), Status.OK, cr.getStatus());
assertEquals(cr.toString(), 1, cr.getResults().length);
m.put(cr.getBasePartition(), cr.getResults()[0]);
} // FOR
assertEquals(1, m.size());
// System.err.printf("Finished evicting data.");
return (m);
}
public static Test suite() {
VoltServerConfig config = null;
// the suite made here will all be using the tests from this class
MultiConfigSuiteBuilder builder = new MultiConfigSuiteBuilder(TestUsersSuite.class);
builder.setGlobalConfParameter("site.exec_voltdb_procinfo", true);
builder.setGlobalConfParameter("site.anticache_enable", true);
builder.setGlobalConfParameter("site.anticache_profiling", false);
builder.setGlobalConfParameter("site.anticache_reset", true);
builder.setGlobalConfParameter("site.anticache_check_interval", Integer.MAX_VALUE);
builder.setGlobalConfParameter("site.network_startup_wait", 60000);
builder.setGlobalConfParameter("site.coordinator_sync_time", false);
builder.setGlobalConfParameter("site.status_enable", false);
builder.setGlobalConfParameter("site.txn_partition_id_managers", false);
UsersProjectBuilder project = new UsersProjectBuilder();
project.addAllDefaults();
project.markTableEvictable(UsersConstants.TABLENAME_USERS);
boolean success;
/////////////////////////////////////////////////////////////
// CONFIG #1: 1 Local Site/Partition running on JNI backend
/////////////////////////////////////////////////////////////
config = new LocalSingleProcessServer(PREFIX+"-1part.jar", 2, BackendTarget.NATIVE_EE_JNI);
success = config.compile(project);
assert(success);
builder.addServerConfig(config);
////////////////////////////////////////////////////////////
// CONFIG #2: cluster of 2 nodes running 2 site each, one replica
////////////////////////////////////////////////////////////
config = new LocalCluster(PREFIX+"-cluster.jar", 2, 1, 0, BackendTarget.NATIVE_EE_JNI);
success = config.compile(project);
assert(success);
builder.addServerConfig(config);
return builder;
}
}