/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * 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 ddlwindowing; import java.io.IOException; import java.util.Date; import java.util.Random; import java.util.UUID; import org.voltdb.client.Client; import org.voltdb.client.ClientStats; import org.voltdb.client.ClientStatsContext; import org.voltdb.client.NoConnectionsException; import org.voltdb.client.NullCallback; /** * <p>Given a time duration, insert random tuples into the 'timedata' * table as fast as possible.</p> * * <p>The rate of insertion is probably rate-limited by a user specified * rate limiting parameter passed to the insert client.</p> * */ public class RandomDataInserter { // Global state final WindowingApp app; // Client used just for inserts so stats will be isolated final Client client; // Statistics manager objects from the client final ClientStatsContext periodicStatsContext; // Seed PRNG with a constant for what predictability we can have in the async world... static final Random rand = new Random(42); RandomDataInserter(WindowingApp app, Client client) { this.app = app; this.client = client; // Tracks client-side stats like invocation counts and end2end latency periodicStatsContext = client.createStatsContext(); } void printReport() { // Get the client stats since the last time this method was called. ClientStats stats = periodicStatsContext.fetchAndResetBaseline().getStats(); System.out.printf(" Insert Statistics:\n" + " Throughput %d/s, Aborts/Failures %d/%d, Avg/95%% Latency %.2f/%dms\n", stats.getTxnThroughput(), stats.getInvocationAborts(), stats.getInvocationErrors(), stats.getAverageLatency(), stats.kPercentileLatency(0.95)); } void basicInsert(String uuid, long val, Date update_ts) throws NoConnectionsException, IOException { // Call the proc with the NullCallback because we're not // being super picky about failure handling. If it fails, // it will show up in the client-side statistics we print // out in printReport(). client.callProcedure(new NullCallback(), "TIMEDATA.insert", uuid, val, update_ts); } /** * Run a loop inserting tuples into the database for the amount * of time specified in config.duration. */ public void run() { // Reset the stats managed by the client. periodicStatsContext.fetchAndResetBaseline(); // Run in a loop for config.duration seconds. final long benchmarkEndTime = app.startTS + (1000l * app.config.duration); while (benchmarkEndTime > System.currentTimeMillis()) { // GENERATE A RANDOM ROW // unique identifier and partition key String uuid = UUID.randomUUID().toString(); // millisecond timestamp Date now = new Date(); // for some odd reason, this will give LONG_MAX if the // computed value is > LONG_MAX. long val = (long) (rand.nextGaussian() * 1000.0); try { basicInsert(uuid, val, now); } catch (IOException e) { // Not being super picky about failure handling. If this // fails, it will show up in the client-side statistics we // print out in printReport(). } } // When ready to end processing... try { // Block until all async calls have returned. client.drain(); // Clean close of the client connection. client.close(); } catch (IOException | InterruptedException e) { // Live dangerously and ignore this error that probably // won't happen at shutdown time. } } }