Package edu.brown.benchmark.smallbank

Source Code of edu.brown.benchmark.smallbank.SmallBankClient$ArgGenerator

/***************************************************************************
*  Copyright (C) 2013 by H-Store Project                                  *
*  Brown University                                                       *
*  Massachusetts Institute of Technology                                  *
*  Yale University                                                        *
*                                                                         *
*  Permission is hereby granted, free of charge, to any person obtaining  *
*  a copy of this software and associated documentation files (the        *
*  "Software"), to deal in the Software without restriction, including    *
*  without limitation the rights to use, copy, modify, merge, publish,    *
*  distribute, sublicense, and/or sell copies of the Software, and to     *
*  permit persons to whom the Software is furnished to do so, subject to  *
*  the following conditions:                                              *
*                                                                         *
*  The above copyright notice and this permission notice shall be         *
*  included in all copies or substantial portions of the Software.        *
*                                                                         *
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        *
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     *
*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
*  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR      *
*  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,  *
*  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR  *
*  OTHER DEALINGS IN THE SOFTWARE.                                        *
***************************************************************************/

package edu.brown.benchmark.smallbank;

import java.io.IOException;
import java.util.Arrays;
import java.util.Random;

import org.apache.log4j.Logger;
import org.voltdb.CatalogContext;
import org.voltdb.TheHashinator;
import org.voltdb.client.ClientResponse;
import org.voltdb.client.ProcedureCallback;

import edu.brown.api.BenchmarkComponent;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
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);
    private static final LoggerBoolean debug = new LoggerBoolean();
    static {
        LoggerUtil.attachObserver(LOG, debug);
    }
   
    /**
     * 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, true, new ArgGenerator() {
            public Object[] genArgs(long acct0, long acct1) {
                return new Object[] {
                    acct0,  // acctId0
                    acct1,  // acctId1
                };
            }
        }),
        BALANCE(SmallBankConstants.FREQUENCY_BALANCE, false, new ArgGenerator() {
            public Object[] genArgs(long acct0, long acct1) {
                return new Object[] {
                    acct0,  // acctId
                };
            }
        }),
        DEPOSIT_CHECKING(SmallBankConstants.FREQUENCY_DEPOSIT_CHECKING, false, new ArgGenerator() {
            public Object[] genArgs(long acct0, long acct1) {
                return new Object[] {
                    acct0,  // acctId0
                    1.3     // amount (from original code)
                };
            }
        }),
        SEND_PAYMENT(SmallBankConstants.FREQUENCY_SEND_PAYMENT, true, new ArgGenerator() {
            public Object[] genArgs(long acct0, long acct1) {
                return new Object[] {
                    acct0,  // sendAcct
                    acct1,  // destAcct
                    5.00    // amount
                };
            }
        }),
        TRANSACT_SAVINGS(SmallBankConstants.FREQUENCY_TRANSACT_SAVINGS, false, new ArgGenerator() {
            public Object[] genArgs(long acct0, long acct1) {
                return new Object[] {
                    acct0,  // acctId
                    20.20   // amount (from original code)
                };
            }
        }),
        WRITE_CHECK(SmallBankConstants.FREQUENCY_WRITE_CHECK, false, new ArgGenerator() {
            public Object[] genArgs(long acct0, long acct1) {
                return new Object[] {
                    acct0,  // acctId
                    5.0     // amount (from original code)
                };
            }
        });

        private final String displayName;
        private final String callName;
        private final int weight;
        private final ArgGenerator ag;
        private final boolean needsTwoAccts;

        /**
         * Constructor
         * @param weight Default txn frequency rate
         * @param needsTwoAccts If set to true, then generateParams() will create two acctIds for this txn type
         * @param ag The parameter generator
         */
        private Transaction(int weight, boolean needsTwoAccts, ArgGenerator ag) {
            this.displayName = StringUtil.title(this.name().replace("_", " ").toLowerCase());
            this.callName = this.displayName.replace(" ", "");
            this.weight = weight;
            this.needsTwoAccts = needsTwoAccts;
            this.ag = 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());
            checkTransaction(txnType.callName, clientResponse, true, false);
        }
    } // END CLASS
   
    private final FlatHistogram<Transaction> txnWeights;
    private final SmallBankCallback callbacks[];
    private final int numAccounts;
    private final Random rand = new Random();
   
    // HOTSPOT INFO
    private double hotspot_percentage = SmallBankConstants.HOTSPOT_PERCENTAGE;
    private boolean hotspot_use_fixed_size = SmallBankConstants.HOTSPOT_USE_FIXED_SIZE;
    private int hotspot_size = SmallBankConstants.HOTSPOT_FIXED_SIZE;
   
    // DTXN CONTROL PARAMETERS
    private double prob_account_hotspot = 0d;
    private double prob_multiaccount_dtxn = 50d;
    private boolean force_multisite_dtxns = false;
    private boolean force_singlesite_dtxns = false;
   
    public static void main(String args[]) {
        BenchmarkComponent.main(SmallBankClient.class, args, false);
    }

    public SmallBankClient(String args[]) {
        super(args);
        CatalogContext catalogContext = this.getCatalogContext();
        TheHashinator.initialize(catalogContext.catalog);
       
        this.numAccounts = (int)Math.round(SmallBankConstants.NUM_ACCOUNTS * this.getScaleFactor());
       
        for (String key : m_extraParams.keySet()) {
            String value = m_extraParams.get(key);
           
            // Probability that accounts are chosen from the hotspot
            if (key.equalsIgnoreCase("prob_account_hotspot")) {
                this.prob_account_hotspot = Double.parseDouble(value);
            }
            // Probability that multi-accounts will be on different partitions
            else if (key.equalsIgnoreCase("prob_multiaccount_dtxn")) {
                this.prob_multiaccount_dtxn = Double.parseDouble(value);
            }
            // Force all distributed txns to be multi-site
            else if (key.equalsIgnoreCase("force_multisite_dtxns")) {
                this.force_multisite_dtxns = Boolean.parseBoolean(value);
            }
            // Force all distributed txns to be single-sited
            else if (key.equalsIgnoreCase("force_singlesite_dtxns")) {
                this.force_singlesite_dtxns = Boolean.parseBoolean(value);
            }
            // Percentage-based hotspot
            else if (key.equalsIgnoreCase("hotspot_percentage")) {
                this.hotspot_percentage = Double.parseDouble(value);
            }
            // Use a fixed-size hotspot
            else if (key.equalsIgnoreCase("hotspot_use_fixed_size")) {
                this.hotspot_use_fixed_size = Boolean.parseBoolean(value);
            }
            // Fixed-size hotspot
            else if (key.equalsIgnoreCase("hotspot_fixed_size")) {
                this.hotspot_size = Integer.parseInt(value);
            }
        } // FOR
        if (catalogContext.numberOfPartitions == 1) {
            this.prob_multiaccount_dtxn = 0;
        }
        if (catalogContext.sites.size() == 1) {
            this.force_multisite_dtxns = false;
        }
        // Disable all multi-partition txns
        if (this.isSinglePartitionOnly()) {
            this.force_multisite_dtxns = false;
            this.prob_multiaccount_dtxn = 0;
        }
        // Compute hotspot size
        if (this.hotspot_use_fixed_size == false) {
            this.hotspot_size = (int)((this.hotspot_percentage/100d) * this.numAccounts);
        }
       
        // 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;
        this.txnWeights = new FlatHistogram<Transaction>(this.rand, txns);
        if (debug.val)
            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();

        this.startComputeTime(target.displayName);
        Object params[] = this.generateParams(target);
        this.stopComputeTime(target.displayName);

        ProcedureCallback callback = this.callbacks[target.ordinal()];
        boolean ret = this.getClientHandle().callProcedure(callback, target.callName, params);
        if (debug.val) LOG.debug("Executing txn " + target);
        return (ret);
    }
   
    /**
     * Generate the txn input parameters for a new invocation.
     * @param target
     * @return
     */
    protected Object[] generateParams(Transaction target) {
        final CatalogContext catalogContext = this.getCatalogContext();
        long acctIds[] = new long[]{ -1, -1 };
        int partitions[] = new int[acctIds.length];
        int sites[] = new int[acctIds.length];
       
        boolean is_hotspot = (this.rand.nextInt(100) < this.prob_account_hotspot);
        boolean is_dtxn = (this.rand.nextInt(100) < this.prob_multiaccount_dtxn);
       
        boolean retry = false;
        for (int i = 0; i < acctIds.length; i++) {
            // Outside the hotspot
            if (is_hotspot == false) {
                acctIds[i] = this.rand.nextInt(this.numAccounts - this.hotspot_size) + this.hotspot_size;
            }
            // Inside the hotspot
            else {
                acctIds[i] = this.rand.nextInt(this.hotspot_size);
            }
           
            // They can never be the same!
            if (i > 0 && acctIds[i-1] == acctIds[i]) {
                continue;
            }
           
            partitions[i] = TheHashinator.hashToPartition(acctIds[i]);
            sites[i] = catalogContext.getSiteIdForPartitionId(partitions[i]);
           
            // If we only need one acctId, break out here.
            if (i == 0 && target.needsTwoAccts == false) break;
            // If we need two acctIds, then we need to go generate the second one
            if (i == 0) continue;
           
            // DTXN
            if (is_dtxn) {
                // Check whether the accounts need to be on different sites
                if (this.force_multisite_dtxns) {
                    retry = (sites[0] == sites[1]);
                }
                // Or they need to be on the same site
                else if (this.force_singlesite_dtxns) {
                    retry = (sites[0] != sites[1] || partitions[0] == partitions[1]);
                }
                // Or at least on the same partition
                else {
                    retry = (partitions[0] == partitions[1]);
                }
            }
            // SINGLE-PARTITON
            else {
                retry = (partitions[0] != partitions[1]);
            }
            if (retry) {
                i -= 1;
                continue;
            }
        } // FOR
        if (debug.val)
            LOG.debug(String.format("Accounts: %s [hotspot=%s, dtxn=%s]",
                      Arrays.toString(acctIds), is_hotspot, is_dtxn));

        return (target.ag.genArgs(acctIds[0], acctIds[1]));
    }
   
    @Override
    public String[] getTransactionDisplayNames() {
        String names[] = new String[Transaction.values().length];
        int ii = 0;
        for (Transaction transaction : Transaction.values()) {
            names[ii++] = transaction.displayName;
        }
        return names;
    }

}
TOP

Related Classes of edu.brown.benchmark.smallbank.SmallBankClient$ArgGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.