Package com

Source Code of com.DeletesClient

/* This file is part of VoltDB.
* Copyright (C) 2008-2014 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 com;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import org.voltdb.VoltTable;
import org.voltdb.VoltTableRow;
import org.voltdb.client.Client;
import org.voltdb.client.ClientConfig;
import org.voltdb.client.ClientFactory;
import org.voltdb.client.ClientResponse;
import org.voltdb.client.NoConnectionsException;
import org.voltdb.client.ProcCallException;
import org.voltdb.client.ProcedureCallback;
import org.voltdb.client.exampleutils.AppHelper;
import org.voltdb.utils.SnapshotVerifier;

import com.deletes.Insert;

public class DeletesClient
{
    final static int NUM_NAMES = 50;
    static int m_averageBatchSize = 25000;
    static int m_batchesToKeep = 12;
    static int m_deceasedCleanupFreq = -1;
    static int m_snapshotFreq = -1;
    static int m_maxBatchFreq = 10;
    static boolean m_blockingSnapshots = false;
    static boolean m_smallStrings = false;
    static String m_snapshotId = "Deletes";
    static String m_snapshotDir = "/tmp/deletes";
    static String[] m_names = new String[NUM_NAMES];
    static Random m_rand = new Random(System.currentTimeMillis());
    static long m_batchNumber = 1000;
    static int m_totalRows;
    static long m_highAllocMem = 0;
    static long m_highAllocMemTime = 0;
    static long m_highUsedMem = 0;
    static long m_highUsedMemTime = 0;
    static long m_highRss = 0;
    static long m_highRssTime = 0;
    static long m_totalInserts = 0;
    static long m_totalInsertedRows = 0;
    static long m_totalInsertTime = 0;
    static long m_expectedInserts = 0;
    static long m_totalDeletes = 0;
    static long m_totalDeletedRows = 0;
    static long m_totalDeleteTime = 0;
    static long m_expectedDeletes = 0;
    static long m_totalDeadDeletes = 0;
    static long m_totalDeadDeleteTime = 0;
    static long m_expectedDeadDeletes = 0;
    static long m_expectedCounts = 0;
    static ArrayList<Integer> m_snapshotSizes = new ArrayList<Integer>();
    static boolean m_snapshotInProgress = false;

    static String randomString(int maxStringSize)
    {
        final String lazyletters = "abcdefghijklmnopqrstuvwxyz";
        StringBuilder sb = new StringBuilder();
        int stringSize = m_rand.nextInt(maxStringSize) + 1;
        for (int j = 0; j < stringSize; j++)
        {
            int index = m_rand.nextInt(lazyletters.length());
            sb.append(lazyletters.charAt(index));
        }
        return sb.toString();
    }

    static void generateNames(int nameSize)
    {
        for (int i = 0; i < NUM_NAMES; i++)
        {
            m_names[i] = randomString(nameSize);
        }
    }

    static void insertNewRecord(Client client, long batchNumber)
    {
        int name_idx = m_rand.nextInt(NUM_NAMES);
        long age = m_rand.nextInt(100);
        long weight = m_rand.nextInt(200);
        long ts = batchNumber;

        String desc1 = null;
        String desc2 = null;
        String addr1 = null;
        String addr2 = null;
        String addr3 = null;
        String text1 = null;
        String text2 = null;
        String sig = null;
        String company = null;
        String co_addr = null;

        if (m_smallStrings)
        {
            desc1 = randomString(60);
            desc2 = randomString(60);
            addr1 = randomString(30);
            addr2 = randomString(60);
            addr3 = randomString(60);
            text1 = randomString(60);
            text2 = randomString(32);
            sig = randomString(16);
            company = randomString(60);
            co_addr = randomString(60);
        }
        else
        {
            desc1 = randomString(250);
            desc2 = randomString(250);
            addr1 = randomString(30);
            addr2 = randomString(120);
            addr3 = randomString(60);
            text1 = randomString(120);
            text2 = randomString(32);
            sig = randomString(16);
            company = randomString(60);
            co_addr = randomString(250);
        }

        byte deceased = (byte) (m_rand.nextBoolean() ? 1 : 0);
        try
        {
            while (!client.callProcedure(new ProcedureCallback()
                {
                    @Override
                    public void clientCallback(ClientResponse response) {
                        if (response.getStatus() != ClientResponse.SUCCESS){
                            System.out.println("failed insert");
                            System.out.println(response.getStatusString());
                        }
                        m_expectedInserts--; //we don't care if tx fail, but don't get stuck in yield
                    }
                },
                Insert.class.getSimpleName(),
                m_names[name_idx],
                age,
                weight,
                desc1,
                desc2,
                addr1,
                addr2,
                addr3,
                text1,
                text2,
                sig,
                ts,
                company,
                co_addr,
                deceased)
                )
            {
                try
                {
                    client.backpressureBarrier();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        } catch (NoConnectionsException e) {
            System.err.println("Lost connection to database, terminating");
            System.exit(-1);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static void insertBatch(Client client, boolean max_batch)
    {
        Date date = new Date();
        System.out.println(date.toString() + "\n\tTotal rows currently: " + m_totalRows);
        int to_insert = m_rand.nextInt(m_averageBatchSize * 2) + 1;
        if (max_batch)
        {
            to_insert = m_averageBatchSize * 2;
        }
        System.out.println("\tInserting: " + to_insert + " rows");
        m_expectedInserts = to_insert;
        long start_time = System.currentTimeMillis();
        for (int j = 0; j < to_insert; j++)
        {
            insertNewRecord(client, m_batchNumber);
        }
        m_batchNumber++;
        m_totalRows += to_insert;
        while (m_expectedInserts != 0)
        {
            Thread.yield();
        }
        long elapsed = System.currentTimeMillis() - start_time;
        m_totalInserts += to_insert;
        m_totalInsertTime += elapsed;
        System.out.println("\tBatch: " + to_insert + " took " +
                           elapsed + " millis");
        System.out.println("\t\t (" + ((to_insert * 1000)/elapsed) + " tps)");
        System.out.println("\tTotal insert TPS: " + (m_totalInserts * 1000)/m_totalInsertTime);
    }


    static void parseStats(ClientResponse resp)
    {
        // Go ghetto for now and assume we're running on one host.
        VoltTable memory_stats = resp.getResults()[0];
        //System.out.println("mem stats: " + memory_stats);
        long rss = memory_stats.fetchRow(0).getLong("RSS");
        if (rss > m_highRss)
        {
            m_highRss = rss;
            m_highRssTime = System.currentTimeMillis();
        }
        long alloc_mem = 0;
        long used_mem = 0;
        alloc_mem += memory_stats.fetchRow(0).getLong("JAVAUSED");
        alloc_mem += memory_stats.fetchRow(0).getLong("TUPLEALLOCATED");
        alloc_mem += memory_stats.fetchRow(0).getLong("INDEXMEMORY");
        alloc_mem += memory_stats.fetchRow(0).getLong("POOLEDMEMORY");
        used_mem += memory_stats.fetchRow(0).getLong("JAVAUSED");
        used_mem += memory_stats.fetchRow(0).getLong("TUPLEDATA");
        used_mem += memory_stats.fetchRow(0).getLong("INDEXMEMORY");
        used_mem += memory_stats.fetchRow(0).getLong("STRINGMEMORY");
        if (alloc_mem > m_highAllocMem)
        {
            m_highAllocMem = alloc_mem;
            m_highAllocMemTime = System.currentTimeMillis();
        }
        if (used_mem > m_highUsedMem)
        {
            m_highUsedMem = used_mem;
            m_highUsedMemTime = System.currentTimeMillis();
        }
        System.out.println("CURRENT MEMORY TOTALS (USED, ALLOCATED, RSS):");
        System.out.println("CURRENT," + used_mem * 1000 + "," + alloc_mem * 1000 + "," + rss * 1000);
        Date blah = new Date(m_highUsedMemTime);
        System.out.println("LARGEST MEMORY USED: " + m_highUsedMem * 1000 + " at " + blah.toString());
        blah = new Date(m_highAllocMemTime);
        System.out.println("LARGEST MEMORY ALLOCATED: " + m_highAllocMem * 1000 + " at " + blah.toString());
        blah = new Date(m_highRssTime);
        System.out.println("LARGEST RSS: " + m_highRss * 1000 + " at " + blah.toString());
    }

    static void collectStats(Client client)
    {
        try {
            ClientResponse resp = client.callProcedure("@Statistics", "management", 0);
            parseStats(resp);
        } catch (NoConnectionsException e) {
            System.err.println("Lost connection to database, terminating");
            System.exit(-1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        catch (ProcCallException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    static void deleteBatch(Client client, long batchesToKeep)
    {
        long prune_ts = m_batchNumber - batchesToKeep;
        Date date = new Date();
        System.out.println(date.toString() + "\n\tPruning batches older than batch: " + prune_ts);
        m_expectedDeletes = NUM_NAMES;
        long start_time = System.currentTimeMillis();
        for (int i = 0; i < NUM_NAMES; i++)
        {
            try
            {
                while (!client.callProcedure(new ProcedureCallback()
                {
                    @Override
                    public void clientCallback(ClientResponse response) {
                        if (response.getStatus() != ClientResponse.SUCCESS){
                            System.out.println("failed delete batch");
                            System.out.println(response.getStatusString());
                        }
                        else
                        {
                            m_totalRows -= response.getResults()[0].asScalarLong();
                            m_totalDeletedRows += response.getResults()[0].asScalarLong();
                        }
                        m_expectedDeletes--;  //we don't care if tx fail, but don't get stuck in yield
                    }
                },
                "DeleteOldBatches", m_names[i], prune_ts)
                )
                {
                    try
                    {
                        client.backpressureBarrier();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            catch (NoConnectionsException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        while (m_expectedDeletes != 0)
        {
            Thread.yield();
        }
        long elapsed = System.currentTimeMillis() - start_time;
        m_totalDeletes += NUM_NAMES;
        m_totalDeleteTime += elapsed;
        System.out.println("\tAfter delete, total rows: " + m_totalRows);
        System.out.println("\tDeleting batch: " + NUM_NAMES + " took " +
                           elapsed + " millis");
        System.out.println("\t\t (" + ((NUM_NAMES * 1000)/elapsed) + " tps)");
        System.out.println("\tTotal delete TPS: " + (m_totalDeletes * 1000)/m_totalDeleteTime);
        System.out.println("\tTotal delete RPS: " + (m_totalDeletedRows * 1000)/m_totalDeleteTime);
    }

    static void deleteDeceased(Client client)
    {
        Date date = new Date();
        System.out.println(date.toString() + "\n\tDeleting deceased records...");
        m_expectedDeadDeletes = NUM_NAMES;
        long start_time = System.currentTimeMillis();
        for (int i = 0; i < NUM_NAMES; i++)
        {
            try
            {
                while (!client.callProcedure(new ProcedureCallback()
                {
                    @Override
                    public void clientCallback(ClientResponse response) {
                        if (response.getStatus() != ClientResponse.SUCCESS){
                            System.out.println("failed delete deceased");
                            System.out.println(response.getStatusString());
                        }
                        else
                        {
                            m_totalRows -= response.getResults()[0].asScalarLong();
                        }
                        m_expectedDeadDeletes--; //we don't care if tx fail, but don't get stuck in yield
                    }
                },
                "DeleteDeceased", m_names[i])
                )
                {
                    try {
                        client.backpressureBarrier();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            catch (NoConnectionsException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        while (m_expectedDeadDeletes != 0)
        {
            Thread.yield();
        }
        long elapsed = System.currentTimeMillis() - start_time;
        m_totalDeadDeletes += NUM_NAMES;
        m_totalDeadDeleteTime += elapsed;
        System.out.println("\tAfter dead deletes, total rows: " + m_totalRows);
        System.out.println("\tDeleting deceased: " + NUM_NAMES + " took " +
                           elapsed + " millis");
        System.out.println("\t\t (" + ((NUM_NAMES * 1000)/elapsed) + " tps)");
        System.out.println("\tTotal delete TPS: " + (m_totalDeadDeletes * 1000)/m_totalDeadDeleteTime);
    }

    static void countBatch(Client client, long batch)
    {
        Date date = new Date();
        System.out.println(date.toString() + "\n\tCounting batch: " + batch);
        m_expectedCounts = 1;
        long start_time = System.currentTimeMillis();
        for (int i = 0; i < 1; i++)
        {
            try
            {
                while (!client.callProcedure(new ProcedureCallback()
                {
                    @Override
                    public void clientCallback(ClientResponse response) {
                        if (response.getStatus() != ClientResponse.SUCCESS){
                            System.out.println("failed count batch");
                            System.out.println(response.getStatusString());
                        }
                        else
                        {
                            System.out.println("\tBatch has " +
                                               response.getResults()[0].asScalarLong() +
                                               " items");
                        }
                        m_expectedCounts--; //we don't care if tx fail, but don't get stuck in yield
                    }
                },
                "CountBatchSize", "", batch)
                )
                {
                    try
                    {
                        client.backpressureBarrier();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            catch (NoConnectionsException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        while (m_expectedCounts != 0)
        {
            Thread.yield();
        }
        long elapsed = System.currentTimeMillis() - start_time;
    }

    // stolen from TestSaveRestoreSysproc
    static void validateSnapshot()
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos);
        PrintStream original = System.out;
        try {
            System.setOut(ps);
            String args[] = new String[] {
                    m_snapshotId,
                    "--dir",
                    m_snapshotDir
            };
            SnapshotVerifier.main(args);
            ps.flush();
            String reportString = baos.toString("UTF-8");
            if (reportString.startsWith("Snapshot corrupted"))
            {
                System.err.println(reportString);
                System.exit(-1);
            }
        } catch (UnsupportedEncodingException e) {}
          finally {
            System.setOut(original);
        }
    }

    public static void checkSnapshotComplete(Client client)
    {
        // Check for outstanding snapshot
        VoltTable[] results = null;
        try
        {
            results = client.callProcedure("@SnapshotStatus").getResults();
            //System.out.println(results[0]);
        }
        catch (NoConnectionsException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        catch (IOException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        catch (ProcCallException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        m_snapshotInProgress = false;
        while (results[0].advanceRow())
        {
            Long end_time = results[0].getLong("END_TIME");
            if (end_time == 0)
            {
                m_snapshotInProgress = true;
                return;
            }
        }
        if (results[0].getRowCount() > 0)
        {
            validateSnapshot();
        }
    }

    public static void performSnapshot(Client client)
    {
        checkSnapshotComplete(client);
        if (m_snapshotInProgress)
        {
            System.out.println("Snapshot still in progress, bailing");
            return;
        }
        try
        {
            VoltTable[] results = client.callProcedure("@SnapshotDelete", new String[] {m_snapshotDir},
                                 new String[] {m_snapshotId}).getResults();
        }
        catch (NoConnectionsException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        catch (IOException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        catch (ProcCallException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        // m_totalRows should be accurate at this point
        m_snapshotSizes.add(m_totalRows);
        System.out.println("Performing Snapshot with total rows: " + m_totalRows);
        try
        {
            if (m_blockingSnapshots) {
                ClientResponse response = client.callProcedure("@SnapshotSave", m_snapshotDir, m_snapshotId, 1);
                if (response.getStatus() != ClientResponse.SUCCESS)
                {
                    System.out.println("failed snapshot");
                    System.out.println(response.getStatusString());
                }
            }
            else {
                client.callProcedure(
                                     new ProcedureCallback()
                                     {
                                         @Override
                                         public void clientCallback(ClientResponse response) {
                                             if (response.getStatus() != ClientResponse.SUCCESS)
                                             {
                                                 System.out.println("failed snapshot");
                                                 System.out.println(response.getStatusString());
                                             }
                                         }
                                     },
                                     "@SnapshotSave", m_snapshotDir, m_snapshotId, 0);
            }
        }
        catch (NoConnectionsException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (ProcCallException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        // Use the AppHelper utility class to retrieve command line application parameters
        // Define parameters and pull from command line
        AppHelper apph = new AppHelper(DeletesClient.class.getCanonicalName())
            .add("duration", "run_duration_in_seconds", "Benchmark duration, in seconds.", 240)
            .add("average-batch-size", "average_batch_size", "Average batch size", 150000)
            .add("batches", "num_batches_to_keep", "Number of batches to keep", 5)
            .add("cleanup-freq", "cleanup_frequency", "Cleanup frequency, in seconds.", 6)
            .add("snapshot-freq", "cycles_between_snapshots", "Snapshot frequency, in seconds. -1 to turn off snapshots", -1)
            .add("block-snapshots", "use_blocking_snapshots_snapshots", "Blocking snapshots (true|false)", "false")
            .add("small-strings", "use_inline_strings", "Forces all the strings to be inlined strings (true|false)", "false")
            .add("servers", "comma_separated_server_list", "List of VoltDB servers to connect to.", "localhost")

            .setArguments(args)
            ;

        m_averageBatchSize = apph.intValue("average-batch-size");
        m_batchesToKeep = apph.intValue("batches");
        m_deceasedCleanupFreq = apph.intValue("cleanup-freq");
        m_snapshotFreq = apph.intValue("snapshot-freq");
        m_blockingSnapshots = apph.booleanValue("block-snapshots");
        m_smallStrings = apph.booleanValue("small-strings");
        long duration = apph.longValue("duration");
        String commaSeparatedServers = apph.stringValue("servers");

        apph.validate("average-batch-size", (m_averageBatchSize > 0));
        apph.validate("batches", (m_batchesToKeep >= 0));
        apph.validate("duration", (duration >= 0));
        apph.validate("cleanup-freq", (m_deceasedCleanupFreq > 0));

        apph.printActualUsage();

        System.out.println("Starting Deletes app with:");
        System.out.printf("\tAverage batch size of %d\n", m_averageBatchSize);
        System.out.printf("\tKeeping %d batches\n", m_batchesToKeep);
        System.out.printf("\tCleaning up deceased every %d batches\n", m_deceasedCleanupFreq);
        System.out.printf("\tSnapshotting every %d batches\n", m_snapshotFreq);

        // parse the server list
        List<String> servers = new LinkedList<String>();
        String[] commaSeparatedServersParts = commaSeparatedServers.split(",");
        for (String server : commaSeparatedServersParts) {
            servers.add(server.trim());
        }

        File tmpdir = new File(m_snapshotDir);
        tmpdir.mkdir();

        generateNames(16);
        Client client = null;
        ClientConfig config = new ClientConfig("program", "none");
        config.setProcedureCallTimeout(Long.MAX_VALUE);
        client = ClientFactory.createClient(config);
        for (String server : servers) {
            try {
                client.createConnection(server);
            } catch (UnknownHostException e) {
                e.printStackTrace();
                System.exit(-1);
            } catch (IOException e) {
                System.err.println("Could not connect to database, terminating: (" + server + ")");
                System.exit(-1);
            }
        }

        // Start with the maximum data set we could possibly fill
        for (int i = 0; i < m_batchesToKeep; i++)
        {
            insertBatch(client, true);
        }

        // now add a batch and remove a batch
        long deceased_counter = 0;
        long snapshot_counter = 0;
        long max_batch_counter = 0;
        boolean fill_max = false;
        long max_batch_remaining = 0;

        final long endTime = System.currentTimeMillis() + (1000l * duration);
        final long startTime = System.currentTimeMillis();
        while (endTime > System.currentTimeMillis())
        {
            // if (max_batch_counter == m_maxBatchFreq)
            // {
            //     fill_max = true;
            //     max_batch_remaining = m_batchesToKeep;
            //     max_batch_counter = 0;
            // }
            // else if (fill_max)
            // {
            //     max_batch_remaining--;
            //     fill_max = true;
            //     if (max_batch_remaining == 0)
            //     {
            //         fill_max = false;
            //     }
            // }
            // else
            // {
            //     max_batch_counter++;
            //     fill_max = false;
            // }

            insertBatch(client, fill_max);

            collectStats(client);

            snapshot_counter++;
            if (snapshot_counter == m_snapshotFreq)
            {
                performSnapshot(client);
                snapshot_counter = 0;
            }

            deceased_counter++;
            if (deceased_counter == m_deceasedCleanupFreq)
            {
                deleteDeceased(client);
                deceased_counter = 0;
            }
            countBatch(client, m_batchNumber - m_batchesToKeep - 1);

            deleteBatch(client, m_batchesToKeep);
        }
        System.out.printf("\tTotal runtime: %d seconds\n", (System.currentTimeMillis() - startTime) / 1000l);
    }
}
TOP

Related Classes of com.DeletesClient

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.