package org.voltdb.regressionsuites.specexecprocs;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.log4j.Logger;
import org.voltdb.ProcInfo;
import org.voltdb.SQLStmt;
import org.voltdb.VoltProcedure;
import org.voltdb.VoltTable;
import edu.brown.benchmark.tm1.TM1Constants;
import edu.brown.profilers.ProfileMeasurement;
/**
* Special distributed transaction that can be blocked programatically
* @author pavlo
*/
@ProcInfo(
partitionParam = 0,
singlePartition = false
)
public class DtxnTester extends VoltProcedure {
private static final Logger LOG = Logger.getLogger(DtxnTester.class);
public static final Semaphore LOCK_BEFORE = new Semaphore(0);
public static final Semaphore NOTIFY_BEFORE = new Semaphore(0);
public static final Semaphore LOCK_AFTER = new Semaphore(0);
public static final Semaphore NOTIFY_AFTER = new Semaphore(0);
/**
* Changing this flag to true will cause the txn to abort
*/
public static final AtomicBoolean SHOULD_ABORT = new AtomicBoolean(false);
public final SQLStmt updateAll = new SQLStmt(
"UPDATE " + TM1Constants.TABLENAME_SUBSCRIBER +
" SET MSC_LOCATION = MSC_LOCATION + 1 "
);
public VoltTable[] run(int partition) {
// -------------------- LOCK BEFORE QUERY --------------------
ProfileMeasurement pm_before = new ProfileMeasurement("BEFORE");
LOG.info(this.getTransactionState() + " - Blocking until LOCK_BEFORE is released");
pm_before.start();
try {
// Notify others before we lock
NOTIFY_BEFORE.release();
LOCK_BEFORE.acquire();
LOCK_BEFORE.release();
} catch (InterruptedException ex) {
ex.printStackTrace();
throw new VoltAbortException(ex.getMessage());
} finally {
NOTIFY_BEFORE.drainPermits();
pm_before.stop();
LOG.info("AWAKE - " + pm_before.debug());
}
// -------------------- DISTRIBUTED QUERY --------------------
voltQueueSQL(updateAll);
final VoltTable results[] = voltExecuteSQL();
assert(results.length == 1);
LOG.info(this.getTransactionState() + " - RESULTS:\n" + results[0]);
// -------------------- LOCK AFTER QUERY --------------------
ProfileMeasurement pm_after = new ProfileMeasurement("AFTER");
LOG.info(this.getTransactionState() + " - Blocking until LOCK_AFTER is released");
pm_after.start();
try {
// Notify others before we lock
NOTIFY_AFTER.release();
LOCK_AFTER.acquire();
LOCK_AFTER.release();
} catch (InterruptedException ex) {
ex.printStackTrace();
throw new VoltAbortException(ex.getMessage());
} finally {
NOTIFY_AFTER.drainPermits();
pm_after.stop();
LOG.info("AWAKE - " + pm_after.debug());
}
if (SHOULD_ABORT.get()) {
String msg = "Txn aborted because somebody asked us to! Deal with it!";
throw new VoltAbortException(msg);
}
return (results);
}
}