Skip to content

Commit

Permalink
Working on building out the SmallBankClient implementation #117
Browse files Browse the repository at this point in the history
  • Loading branch information
apavlo committed May 5, 2013
1 parent deda192 commit 475bcd1
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 40 deletions.
177 changes: 157 additions & 20 deletions src/benchmarks/edu/brown/benchmark/smallbank/SmallBankClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,49 +31,186 @@
package edu.brown.benchmark.smallbank;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Random;

import org.voltdb.VoltTable;
import org.voltdb.client.Client;
import org.apache.log4j.Logger;
import org.voltdb.client.ClientResponse;
import org.voltdb.client.ProcedureCallback;

import weka.classifiers.meta.Vote;

import edu.brown.api.BenchmarkComponent;
import edu.brown.hstore.Hstoreservice.Status;
import edu.brown.rand.RandomDistribution.FlatHistogram;
import edu.brown.statistics.Histogram;
import edu.brown.statistics.ObjectHistogram;
import edu.brown.utils.StringUtil;

/**
* SmallBank Client Driver
* @author pavlo
*/
public class SmallBankClient extends BenchmarkComponent {
private static final Logger LOG = Logger.getLogger(SmallBankClient.class);

/**
* Each Transaction element provides an ArgGenerator to create the proper
* arguments used to invoke the stored procedure
*/
private static interface ArgGenerator {
/**
* Generate the proper arguments used to invoke the given stored procedure
* @param acct0
* @param acct1
* @return
*/
public Object[] genArgs(long acct0, long acct1);
}

/**
* Set of transactions structs with their appropriate parameters
*/
public static enum Transaction {
AMALGAMATE(SmallBankConstants.FREQUENCY_AMALGAMATE, new ArgGenerator() {
public Object[] genArgs(long acct0, long acct1) {
return (null);
}
}),
BALANCE(SmallBankConstants.FREQUENCY_BALANCE, new ArgGenerator() {
public Object[] genArgs(long acct0, long acct1) {
return (null);
}
}),
DEPOSIT_CHECKING(SmallBankConstants.FREQUENCY_DEPOSIT_CHECKING, new ArgGenerator() {
public Object[] genArgs(long acct0, long acct1) {
return (null);
}
}),
TRANSACT_SAVINGS(SmallBankConstants.FREQUENCY_TRANSACT_SAVINGS, new ArgGenerator() {
public Object[] genArgs(long acct0, long acct1) {
return (null);
}
}),
WRITE_CHECK(SmallBankConstants.FREQUENCY_WRITE_CHECK, new ArgGenerator() {
public Object[] genArgs(long acct0, long acct1) {
return (null);
}
});

/**
* Constructor
*/
private Transaction(int weight, ArgGenerator ag) {
this.displayName = StringUtil.title(this.name().replace("_", " ").toLowerCase());
this.callName = this.displayName.replace(" ", "");
this.weight = weight;
this.ag = ag;
}

public Object[] generateParams(Random rand, int numAccounts) {
long acct0, acct1;

// Outside the hotspot
if (rand.nextInt(100) < SmallBankConstants.HOTSPOT_PROBABILITY) {
acct0 = rand.nextInt(numAccounts - SmallBankConstants.HOTSPOT_SIZE) + SmallBankConstants.HOTSPOT_SIZE;
acct1 = rand.nextInt(numAccounts - SmallBankConstants.HOTSPOT_SIZE) + SmallBankConstants.HOTSPOT_SIZE;
LOG.debug(String.format("Random number outside hotspot: %s [%d, %d]",
this, acct0, acct1));
}
// Inside the hotspot
else {
acct0 = rand.nextInt(SmallBankConstants.HOTSPOT_SIZE);
acct1 = rand.nextInt(SmallBankConstants.HOTSPOT_SIZE);
LOG.debug(String.format("Random number inside hotspot: %s [%d, %d]",
this, acct0, acct1));
}
return (this.ag.genArgs(acct0, acct1));
}

private final String displayName;
private final String callName;
private final int weight;
private final ArgGenerator ag;
};

/**
* Callback Class
*/
private class SmallBankCallback implements ProcedureCallback {
private final Transaction txnType;

public SmallBankCallback(Transaction txnType) {
this.txnType = txnType;
}

@Override
public void clientCallback(ClientResponse clientResponse) {
incrementTransactionCounter(clientResponse, this.txnType.ordinal());
// LOG.info(clientResponse);
}
} // END CLASS

private final FlatHistogram<Transaction> txnWeights;
private final SmallBankCallback callbacks[];
private final int numAccounts;
private final Random rand = new Random();

public static void main(String args[]) {
BenchmarkComponent.main(SmallBankClient.class, args, false);
}

public SmallBankClient(String args[]) {
super(args);

this.numAccounts = (int)Math.round(SmallBankConstants.NUM_ACCOUNTS * this.getScaleFactor());

// Initialize the sampling table
Histogram<Transaction> txns = new ObjectHistogram<Transaction>();
for (Transaction t : Transaction.values()) {
Integer weight = this.getTransactionWeight(t.callName);
if (weight == null) {
weight = t.weight;
}
txns.put(t, weight);
} // FOR
assert(txns.getSampleCount() == 100) : "Invalid txn percentage total: " + txns.getSampleCount() + "\n" + txns;
Random rand = new Random(); // FIXME
this.txnWeights = new FlatHistogram<Transaction>(rand, txns);
if (LOG.isDebugEnabled())
LOG.debug("Transaction Workload Distribution:\n" + txns);

// Setup callbacks
int num_txns = Transaction.values().length;
this.callbacks = new SmallBankCallback[num_txns];
for (Transaction txnType : Transaction.values()) {
this.callbacks[txnType.ordinal()] = new SmallBankCallback(txnType);
} // FOR
}

@Override
protected void runLoop() throws IOException {
// Not needed.
}

@Override
protected boolean runOnce() throws IOException {
Transaction target = this.txnWeights.nextValue();

return (true);
}
this.startComputeTime(target.displayName);
Object params[] = target.generateParams(this.rand, this.numAccounts);
this.stopComputeTime(target.displayName);

@Override
public String[] getTransactionDisplayNames() {
// Return an array of transaction names
String procNames[] = new String[]{
Vote.class.getSimpleName()
};
return (procNames);
ProcedureCallback callback = this.callbacks[target.ordinal()];
boolean ret = this.getClientHandle().callProcedure(callback, target.callName, params);
LOG.debug("Executing txn " + target);
return (ret);
}

@Override
protected void runLoop() throws IOException {
// TODO Auto-generated method stub

public String[] getTransactionDisplayNames() {
String names[] = new String[Transaction.values().length];
int ii = 0;
for (Transaction transaction : Transaction.values()) {
names[ii++] = transaction.displayName;
}
return names;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,44 @@

public abstract class SmallBankConstants {

// ----------------------------------------------------------------
// STORED PROCEDURE EXECUTION FREQUENCIES (0-100)
// ----------------------------------------------------------------
public static final int FREQUENCY_AMALGAMATE = 5;
public static final int FREQUENCY_BALANCE = 35;
public static final int FREQUENCY_DEPOSIT_CHECKING = 20;
public static final int FREQUENCY_TRANSACT_SAVINGS = 20;
public static final int FREQUENCY_WRITE_CHECK = 20;

// ----------------------------------------------------------------
// TABLE NAMES
// ----------------------------------------------------------------
public static final String TABLENAME_ACCOUNTS = "ACCOUNTS";
public static final String TABLENAME_SAVINGS = "SAVINGS";
public static final String TABLENAME_CHECKING = "CHECKING";

public static final int BATCH_SIZE = 1000;

// ----------------------------------------------------------------
// ACCOUNT INFORMATION
// ----------------------------------------------------------------

// Default number of customers in bank
public static final int NUM_ACCOUNTS = 1000000;

public static final int HOTSPOT_PROBABILITY = 10;
public static final int HOTSPOT_SIZE = 100;

// ----------------------------------------------------------------
// ADDITIONAL CONFIGURATION SETTINGS
// ----------------------------------------------------------------

// Percentage of customers that do not have a SAVINGS account [0-100%]
public static final int PERCENTAGE_NO_SAVINGS = 0;

// Percentage of customers that do not have a CHECKING account [0-100%]
public static final int PERCENTAGE_NO_CHECKING = 0;

// Default number of customers in bank
public static final int NUM_ACCOUNTS = 1000000;

// Initial balance amount
public static final int MIN_BALANCE = 1;
public static final int MAX_BALANCE = 1000;
Expand Down
31 changes: 14 additions & 17 deletions src/benchmarks/edu/brown/benchmark/tm1/TM1Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import edu.brown.api.BenchmarkComponent;
import edu.brown.rand.RandomDistribution.FlatHistogram;
import edu.brown.statistics.ObjectHistogram;
import edu.brown.utils.StringUtil;

/**
* TM1Client
Expand Down Expand Up @@ -71,7 +72,7 @@ private static interface ArgGenerator {
* Set of transactions structs with their appropriate parameters
*/
public static enum Transaction {
DELETE_CALL_FORWARDING("Delete Call Forwarding", TM1Constants.FREQUENCY_DELETE_CALL_FORWARDING, new ArgGenerator() {
DELETE_CALL_FORWARDING(TM1Constants.FREQUENCY_DELETE_CALL_FORWARDING, new ArgGenerator() {
public Object[] genArgs(long subscriberSize) {
long s_id = TM1Util.getSubscriberId(subscriberSize);
return new Object[] { TM1Util.padWithZero(s_id), // s_id
Expand All @@ -80,15 +81,15 @@ public Object[] genArgs(long subscriberSize) {
};
}
}),
GET_ACCESS_DATA("Get Access Data", TM1Constants.FREQUENCY_GET_ACCESS_DATA, new ArgGenerator() {
GET_ACCESS_DATA(TM1Constants.FREQUENCY_GET_ACCESS_DATA, new ArgGenerator() {
public Object[] genArgs(long subscriberSize) {
long s_id = TM1Util.getSubscriberId(subscriberSize);
return new Object[] { s_id, // s_id
TM1Util.number(1, 4) // ai_type
};
}
}),
GET_NEW_DESTINATION("Get New Destination", TM1Constants.FREQUENCY_GET_NEW_DESTINATION, new ArgGenerator() {
GET_NEW_DESTINATION(TM1Constants.FREQUENCY_GET_NEW_DESTINATION, new ArgGenerator() {
public Object[] genArgs(long subscriberSize) {
long s_id = TM1Util.getSubscriberId(subscriberSize);
return new Object[] { s_id, // s_id
Expand All @@ -98,14 +99,14 @@ public Object[] genArgs(long subscriberSize) {
};
}
}),
GET_SUBSCRIBER_DATA("Get Subscriber Data", TM1Constants.FREQUENCY_GET_SUBSCRIBER_DATA, new ArgGenerator() {
GET_SUBSCRIBER_DATA(TM1Constants.FREQUENCY_GET_SUBSCRIBER_DATA, new ArgGenerator() {
public Object[] genArgs(long subscriberSize) {
long s_id = TM1Util.getSubscriberId(subscriberSize);
return new Object[] { s_id // s_id
};
}
}),
INSERT_CALL_FORWARDING("Insert Call Forwarding", TM1Constants.FREQUENCY_INSERT_CALL_FORWARDING, new ArgGenerator() {
INSERT_CALL_FORWARDING(TM1Constants.FREQUENCY_INSERT_CALL_FORWARDING, new ArgGenerator() {
public Object[] genArgs(long subscriberSize) {
long s_id = TM1Util.getSubscriberId(subscriberSize);
return new Object[] {
Expand All @@ -117,15 +118,15 @@ public Object[] genArgs(long subscriberSize) {
};
}
}),
UPDATE_LOCATION("Update Location", TM1Constants.FREQUENCY_UPDATE_LOCATION, new ArgGenerator() {
UPDATE_LOCATION(TM1Constants.FREQUENCY_UPDATE_LOCATION, new ArgGenerator() {
public Object[] genArgs(long subscriberSize) {
long s_id = TM1Util.getSubscriberId(subscriberSize);
return new Object[] { TM1Util.number(0, Integer.MAX_VALUE), // vlr_location
TM1Util.padWithZero(s_id) // sub_nbr
};
}
}),
UPDATE_SUBSCRIBER_DATA("Update Subscriber Data", TM1Constants.FREQUENCY_UPDATE_SUBSCRIBER_DATA, new ArgGenerator() {
UPDATE_SUBSCRIBER_DATA(TM1Constants.FREQUENCY_UPDATE_SUBSCRIBER_DATA, new ArgGenerator() {
public Object[] genArgs(long subscriberSize) {
long s_id = TM1Util.getSubscriberId(subscriberSize);
return new Object[] { s_id, // s_id
Expand All @@ -139,9 +140,9 @@ public Object[] genArgs(long subscriberSize) {
/**
* Constructor
*/
private Transaction(String displayName, int weight, ArgGenerator ag) {
this.displayName = displayName;
this.callName = displayName.replace(" ", "");
private Transaction(int weight, ArgGenerator ag) {
this.displayName = StringUtil.title(this.name().replace("_", " ").toLowerCase());
this.callName = this.displayName.replace(" ", "");
this.weight = weight;
this.ag = ag;
}
Expand All @@ -152,9 +153,8 @@ public Object[] generateParams(long subscriberSize) {

public final String displayName;
public final String callName;
public final int weight; // probability (in terms of percentage) the
// transaction gets executed
public final ArgGenerator ag;
private final int weight;
private final ArgGenerator ag;
} // TRANSCTION ENUM

/**
Expand All @@ -178,10 +178,7 @@ public void clientCallback(ClientResponse clientResponse) {
/**
* Data Members
*/

// Storing the ordinals of transaction per tm1 probability distribution
private final FlatHistogram<Transaction> txnWeights;
// private final int[] txnWeights = new int[100];

// Callbacks
protected final TM1Callback callbacks[];
Expand Down Expand Up @@ -250,7 +247,7 @@ public void runLoop() {

@Override
protected boolean runOnce() throws IOException {
final Transaction target = this.txnWeights.nextValue();
Transaction target = this.txnWeights.nextValue();

this.startComputeTime(target.displayName);
Object params[] = target.ag.genArgs(subscriberSize);
Expand Down

0 comments on commit 475bcd1

Please sign in to comment.