Package org.voltdb.benchmark.bingo

Source Code of org.voltdb.benchmark.bingo.BingoClient$Tourney$Callback

/* This file is part of VoltDB.
* Copyright (C) 2008-2010 VoltDB L.L.C.
*
* 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 org.voltdb.benchmark.bingo;

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

import org.apache.log4j.Logger;
import org.voltdb.benchmark.Verification;
import org.voltdb.benchmark.Verification.Expression;
import org.voltdb.client.ClientResponse;
import org.voltdb.client.NullCallback;
import org.voltdb.client.ProcedureCallback;
import org.voltdb.types.ExpressionType;

import edu.brown.api.BenchmarkComponent;
import edu.brown.hstore.Hstoreservice.Status;
import edu.brown.hstore.conf.HStoreConf;
import edu.brown.logging.LoggerUtil.LoggerBoolean;

public class BingoClient extends BenchmarkComponent {
    private static final Logger LOG = Logger.getLogger(BingoClient.class);
    private static final LoggerBoolean debug = new LoggerBoolean();
   
    public static enum Transaction {
        CREATE("Create Tournament"),
        DELETE("Delete Tournament"),
        PLAY("Play Round"),
        GETAVGPOT("Get Average Pot Value"),
        ERROR("Client error executing transaction");

        private Transaction(String displayName) { this.displayName = displayName; }
        public final String displayName;
    }

    private final Random random = new Random();

    // an array of tournaments with a randomized starting round to get better
    // tournament progress distribution at startup. The result of this is that
    // the tournaments at startup run for fewer rounds (and so do smaller deletes).
    // All subsequent tournaments, though, run the full number of rounds. Without
    // something like this, tournament creations and deletions are clumpy.
    protected class Tourney {
        int tid;
        boolean initialized = false;
        int round = 0;

        private class Callback implements ProcedureCallback {
            private final Transaction t;

            public Callback(Transaction t) {
                this.t = t;
            }

            @Override
            public void clientCallback(ClientResponse clientResponse) {
                final Status status = clientResponse.getStatus();
                if (status != Status.OK) {
                    if (status == Status.ABORT_CONNECTION_LOST){
                        /*
                         * Status of the last transaction involving the tournament
                         * is unknown it could have committed. Recovery code would
                         * go here.
                         */
                        return;
                    }

                    if (clientResponse.getException() != null) {
                        clientResponse.getException().printStackTrace();
                    }
                    if (debug.val && clientResponse.getStatusString() != null) {
                        LOG.warn(clientResponse.getStatusString());
                    }
                    return;
                }
                synchronized (tournaments) {
                    tournaments.offer(Tourney.this);
                    tournaments.notifyAll();
                }
                incrementTransactionCounter(clientResponse, t.ordinal());
            }

        }
    }

    private final ArrayDeque<Tourney> tournaments = new ArrayDeque<Tourney>();

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

    public BingoClient(String args[]) {
        super(args);
        Random r = new Random();
       
        // Load our good old friend Mister HStoreConf
        HStoreConf hstore_conf = this.getHStoreConf();
       
        final int num_tournaments = (int)Math.round(BingoConstants.maxTournaments * hstore_conf.client.scalefactor);
        final int num_clients = this.getNumClients();
        final int client_id = this.getClientId();
        for (int i=1; i <= num_tournaments; i++) {
            if (i % num_clients != client_id) continue;
            final Tourney t = new Tourney();
            t.tid = 10000 + i; //  | (getClientId() << 24));
            t.initialized = false;
            t.round = Math.abs(r.nextInt() % BingoConstants.maxRounds);
            tournaments.offer(t);
        }

        // Set up checking
        buildConstraints();
    }

    @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;
    }

    /**
     * Delete all games that may have existed previously
     * @return
     */
    protected boolean cleanupLastRun() {
        try {
            for (Tourney t : tournaments) {
                this.getClientHandle().callProcedure(
                        new NullCallback(),
                        "DeleteTournament",
                        (long)t.tid);
            }
            this.getClientHandle().drain();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    protected void buildConstraints() {
        Expression constraint = null;

        // PlayRound table 0: 0 <= C4 < 100 (max round is 100)
        constraint = Verification.inRange("C4", 0L, 99L);
        addConstraint("PlayRound", 0, constraint);

        // PlayRound table 1: 0 <= R_POT < 900 (because the max round is 100, we
        // only add at most 9 each time)
        Expression r_pot = Verification.inRange("R_POT", 0, 899);
        Expression t_id = Verification.compareWithConstant(ExpressionType.COMPARE_GREATERTHANOREQUALTO,
                                                           "T_ID", 0);
        Expression b_id = Verification.compareWithConstant(ExpressionType.COMPARE_GREATERTHANOREQUALTO,
                                                           "B_ID", 0);
        Expression r_id = Verification.compareWithConstant(ExpressionType.COMPARE_GREATERTHANOREQUALTO,
                                                           "R_ID", 0);
        constraint = Verification.conjunction(ExpressionType.CONJUNCTION_AND,
                                              r_pot, t_id, b_id, r_id);
        addConstraint("PlayRound", 1, constraint);

        // For the tables
        addConstraint("T", 0, t_id);

        constraint = Verification.conjunction(ExpressionType.CONJUNCTION_AND,
                                              t_id, b_id);
        addConstraint("B", 0, constraint);

        constraint = Verification.conjunction(ExpressionType.CONJUNCTION_AND,
                                              r_pot, t_id, r_id);
        addConstraint("R", 0, constraint);
    }

    @Override
    public void runLoop() {
        if (!cleanupLastRun()) {
            return;
        }

        try {
            while (true) {
                invokeBingo();
                this.getClientHandle().backpressureBarrier();
            }
        } catch (IOException e) {
            /*
             * Client has no clean mechanism for terminating with the DB.
             */
            return;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected boolean runOnce() throws IOException {
        return invokeBingo();
    }

    private boolean invokeBingo() throws IOException {
        // which Transaction enum value to execute.
        Transaction proc = Transaction.ERROR;
        boolean queued = false;
        Tourney t;
        synchronized (tournaments) {
            while (true) {

                t = tournaments.poll();
                if (t == null) {
                    return false;
                }

                double prob = random.nextDouble();
                if (prob > .7) {
                    break;
                } else {
                    tournaments.offer(t);
                }
            }
        }

        // tournament id does not exist, CREATE
        if (t.initialized == false) {
            final Tourney tourney = t;
            proc = Transaction.CREATE;

            Tourney.Callback callback = t.new Callback(proc) {
                @Override
                public void clientCallback(ClientResponse clientResponse) {
                    if (clientResponse.getStatus() == Status.OK) {
                        tourney.initialized = true;
                    }
                    super.clientCallback(clientResponse);
                }
            };

            if (debug.val)
                LOG.debug("[" + getClientId() + "] CREATE TOURNEY: " + t.tid);
            queued = this.getClientHandle().callProcedure(
                    callback,
                    "CreateTournament",
                    (long)t.tid,
                    (long)BingoConstants.boardsPerTournament);
        }
        // tournament is over, DELETE, mark uninitialized and at round 0.
        else if (!(t.round < BingoConstants.maxRounds)) {
            final Tourney tourney = t;
            proc = Transaction.DELETE;

            Tourney.Callback callback = t.new Callback(proc) {
                @Override
                public void clientCallback(ClientResponse clientResponse) {
                    if (clientResponse.getStatus() == Status.OK) {
                        tourney.initialized = false;
                        tourney.round = 0;
                    }
                    super.clientCallback(clientResponse);
                }
            };

            queued = this.getClientHandle().callProcedure(
                    callback,
                    "DeleteTournament",
                    (long)t.tid);
        }
        // increment round and PLAY
        else {
            final Tourney tourney = t;

            //Occasionally instead of playing a round check the avg pot value
            if (random.nextInt(BingoConstants.GETAVGPOT_MAX) > BingoConstants.GETAVGPOT_MIN) {
                proc = Transaction.GETAVGPOT;

                /*
                 * Retrieve 9 more tournaments to be included in the average
                 */
                final long tourneyIds[] = new long[10];
                final Tourney tourneys[] = new Tourney[9];
                synchronized (tournaments) {
                    for (int ii = 0; ii < 9; ii++) {
                        while (true) {
                            tourneys[ii] = tournaments.poll();
                            if (tourneys[ii] != null) {
                                break;
                            }
                            try {
                                tournaments.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }

                /*
                 * Create an array of the ids to be sent with the invocation
                 * and store the Tourneys themselves in the callback
                 * so they can be placed back into the queue upon completion
                 */
                tourneyIds[0] = t.tid;
                for (int ii = 1; ii < 10; ii++) {
                    tourneyIds[ii] = tourneys[ii - 1].tid;
                }
                Tourney.Callback callback = t.new Callback(proc) {
                    @Override
                    public void clientCallback(ClientResponse clientResponse) {
                        synchronized (tournaments) {
                            for (int ii = 0; ii < tourneys.length; ii++) {
                                tournaments.offer(tourneys[ii]);
                            }
                        super.clientCallback(clientResponse);
                        }
                    }
                };

                queued = this.getClientHandle().callProcedure(
                        callback,
                        "GetAvgPot", tourneyIds);
            } else {
                proc = Transaction.PLAY;

                Tourney.Callback callback = t.new Callback(proc) {
                    @Override
                    public void clientCallback(ClientResponse clientResponse) {
                        if (clientResponse.getStatus() == Status.OK) {
                            tourney.round++;
                        }
                        if (checkTransaction("PlayRound", clientResponse, false, false)) {
                            super.clientCallback(clientResponse);
                        }
                    }
                };

                queued = this.getClientHandle().callProcedure(
                        callback,
                        "PlayRound", (long)t.tid,
                        (long)t.round,
                        "A7 Again!?");
            }
        }

        /*
         * It wasn't successfully queued so put it back in the list of eligible tournaments
         */
        if (!queued) {
            tournaments.offer(t);
        }

        return queued;
    }
}
TOP

Related Classes of org.voltdb.benchmark.bingo.BingoClient$Tourney$Callback

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.