public void testRemoteIdle() throws Exception {
CatalogContext catalogContext = this.getCatalogContext();
Client client = this.getClient();
RegressionSuiteUtil.initializeTPCCDatabase(catalogContext, client, true);
ClientResponse cresponse = null;
String procName = null;
Object params[] = null;
// First execute a single-partition txn that will sleep for a while at the
// partition that we're going to need to execute our dtxn on.
// This will give us time to queue up a bunch of stuff to ensure that the
// SpecExecScheduler has stuff to look at when the PartitionExecutor is idle.
final int sleepBefore = 5000; // ms
final int sleepAfter = 5000; // ms
procName = Sleeper.class.getSimpleName();
params = new Object[]{ WAREHOUSE_ID+1, sleepBefore, sleepAfter };
client.callProcedure(new NullCallback(), procName, params);
// Now fire off a distributed NewOrder transaction
final LatchableProcedureCallback dtxnCallback = new LatchableProcedureCallback(1);
procName = neworder.class.getSimpleName();
params = RegressionSuiteUtil.generateNewOrder(catalogContext.numberOfPartitions, true, WAREHOUSE_ID, DISTRICT_ID);
client.callProcedure(dtxnCallback, procName, params);
long start = System.currentTimeMillis();
// While we're waiting for that to come back, we're going to fire off
// a bunch of single-partition neworder txns that should all be executed
// speculatively at the other partition
final List<ClientResponse> spResponse = new ArrayList<ClientResponse>();
final AtomicInteger spLatch = new AtomicInteger(0);
final ProcedureCallback spCallback = new ProcedureCallback() {
@Override
public void clientCallback(ClientResponse clientResponse) {
spResponse.add(clientResponse);
spLatch.decrementAndGet();
}
};
while (dtxnCallback.responses.isEmpty()) {
// Just sleep for a little bit so that we don't blast the cluster
ThreadUtil.sleep(1000);
spLatch.incrementAndGet();
params = RegressionSuiteUtil.generateNewOrder(catalogContext.numberOfPartitions, true, WAREHOUSE_ID, DISTRICT_ID+1);
client.callProcedure(spCallback, procName, params);
// We'll only check the txns half way through the dtxns expected
// sleep time
long elapsed = System.currentTimeMillis() - start;
assert(elapsed <= (sleepBefore+sleepAfter)*2);
} // WHILE
cresponse = CollectionUtil.first(dtxnCallback.responses);
assertNotNull(cresponse);
assertFalse(cresponse.isSinglePartition());
assertTrue(cresponse.hasDebug());
assertFalse(cresponse.isSpeculative());
// Spin and wait for the single-p txns to finish
while (spLatch.get() > 0) {
long elapsed = System.currentTimeMillis() - start;
assert(elapsed <= (sleepBefore+sleepAfter)*3);