DBWorker(
      int dbType,
      int chanceOfRead,
      int chanceOfWrite,
      int chanceOfReadModifyWrite,
      int chanceOfBalanceTransfer,
      int chanceOfIncrementalUpdate,
      int minTransactionSize,
      int maxTransactionSize,
      int millisBetweenActions,
      KeyStore availibleKeys,
      int writeToLogs) {

    // Set the Parameters
    this.dbType = dbType;

    this.chanceOfRead = chanceOfRead;
    this.chanceOfWrite = chanceOfWrite;
    this.chanceOfReadModifyWrite = chanceOfReadModifyWrite;
    this.chanceOfBalanceTransfer = chanceOfBalanceTransfer;
    this.chanceOfIncrementalUpdate = chanceOfIncrementalUpdate;

    this.millisBetweenActions = millisBetweenActions;
    this.minTransactionSize = minTransactionSize;
    this.maxTransactionSize = maxTransactionSize;
    this.keys = availibleKeys;
    this.writeToLogs = writeToLogs;

    // Set up the relevant Database Machine
    if (dbType == FDB) {
      machine = new FoundationDB();
    } else if (dbType == FDB_BLOCK_NO_RETRY) {
      // machine = new FDBBlockingNoRetry();
    } else if (dbType == FDB_ASYNC_NO_RETRY) {
      // machine = new FDBASyncNoRetry();
    } else if (dbType == MONGODB) {
      // machine = new MongoDBMachine();
    } else if (dbType == TOKUMX) {
      machine = new TokuMX();
    } else if (dbType == TOKUMX_ACID_OC) {
      machine = new TokuMXOptimist();
    } else if (dbType == TOKUMX_ACID_PC) {
      machine = new TokuMXPessimist();
    }

    // Connect the DB
    machine.connectDB();

    // Set up some log tables
    for (int i = 0; i > writeToLogs; i++) {
      machine.addTable("Log" + i);
    }

    if (chanceOfBalanceTransfer > 0
        && (this.minTransactionSize == 2 || this.maxTransactionSize == 2)) {
      // System.out.println("Balance Transfer may occur, setting transaction size to 2.");
      this.minTransactionSize = 2;
      this.maxTransactionSize = 2;
    }
  }
  public T doWork(T context, int niters, Result<T> opts) {

    opts.setErrorCount(0);

    ActionRecord record = new ActionRecord();
    ActionRecord logRecord = new ActionRecord();

    final int transactionSize =
        ThreadLocalRandom.current().nextInt(this.maxTransactionSize) + this.minTransactionSize;
    List<String> keysToUse = keys.getRandomKeyList(transactionSize, true);

    // If this is a logger
    if (writeToLogs > 0 && ThreadLocalRandom.current().nextInt(1000) < 1) {
      System.out.println("Log Reader");

      record = machine.readLog(3, millisBetweenActions);
      workTimeMillis = System.currentTimeMillis();
      return null;
    }

    if (keysToUse.size() < 2) {
      System.out.println("whoa there...");
    }

    // Get Random number to assign task
    final int rand1 = ThreadLocalRandom.current().nextInt(1000);
    if (rand1 < chanceOfRead) {
      // Reader
      record = machine.read(keysToUse, millisBetweenActions);
    } else if (rand1 < chanceOfWrite) {
      // Writer
      record = machine.update(keysToUse, millisBetweenActions);
    } else if (rand1 < chanceOfReadModifyWrite) {
      // Reader + Writer
      record = machine.readModifyWrite(keysToUse, millisBetweenActions);
    } else if (rand1 < chanceOfBalanceTransfer) {
      record = machine.balanceTransfer(keysToUse.get(0), keysToUse.get(1), millisBetweenActions);
    } else if (rand1 < chanceOfIncrementalUpdate) {
      record = machine.incrementalUpdate(keysToUse, millisBetweenActions);
    }

    // Write the logs (if there are any to write)
    if (writeToLogs > 0) logRecord = machine.writeLog(writeToLogs, millisBetweenActions);

    // Check for success
    if (record == null
        || !record.isSuccess()
        || (writeToLogs > 0 && (logRecord == null || !logRecord.isSuccess()))) {

      opts.incrementErrorCount();
    }

    workTimeMillis = System.currentTimeMillis();

    return null;
  }