/* This file is part of VoltDB.
 * Copyright (C) 2008-2015 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.
 */
/*
 * This samples uses multiple threads to post synchronous requests to the
 * VoltDB server, simulating multiple client application posting
 * synchronous requests to the database, using the native VoltDB client
 * library.
 *
 * While synchronous processing can cause performance bottlenecks (each
 * caller waits for a transaction answer before calling another
 * transaction), the VoltDB cluster at large is still able to perform at
 * blazing speeds when many clients are connected to it.
 */

package exportbenchmark;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicLong;

import org.json_voltpatches.JSONException;
import org.json_voltpatches.JSONObject;
import org.voltcore.logging.VoltLogger;
import org.voltdb.export.AdvertisedDataSource;
import org.voltdb.exportclient.ExportClientBase;
import org.voltdb.exportclient.ExportDecoderBase;

/**
 * Export class for performance measuring.
 * Export statistics are checked for timestamps, and performance metrics are
 * periodically pushed to a UDP socket for collection.
 */
public class SocketExporter extends ExportClientBase {

    private static final VoltLogger m_logger = new VoltLogger("ExportClient");

    String host;
    int port;
    int statsDuration;
    InetSocketAddress address;
    DatagramChannel channel;

    // Statistics
    AtomicLong transactions = new AtomicLong();
    AtomicLong totalDecodeTime = new AtomicLong();

    @Override
    public void configure(Properties config) throws Exception {
        host = config.getProperty("socket.dest", "localhost");
        port = Integer.parseInt(config.getProperty("socket.port", "5001"));
        statsDuration = Integer.parseInt(config.getProperty("stats.duration", "5"));

        if (host == "localhost") {
            address = new InetSocketAddress(InetAddress.getLocalHost(), port);
        } else {
            address = new InetSocketAddress(host, port);
        }
        channel = DatagramChannel.open();
    }

    class SocketExportDecoder extends ExportDecoderBase {
        Timer timer;

        SocketExportDecoder(AdvertisedDataSource source) {
            super(source);

            schedulePeriodicStats();
        }

        /**
         * Periodically print statistics to a UDP socket
         */
        public void schedulePeriodicStats() {
            timer = new Timer();
            TimerTask statsPrinting = new TimerTask() {
                @Override
                public void run() { sendStatistics(); }
            };
            timer.scheduleAtFixedRate(statsPrinting,
                                      statsDuration * 1000,
                                      statsDuration * 1000);
        }

        /**
         * Prints performance statistics to a socket. Stats are:
         *   -Transactions per second
         *   -Average time for decodeRow() to run
         *   -Partition ID
         */
        public void sendStatistics() {
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            // Calculate statistics
            double tps, averageDecodeTime;
            try {
                tps = transactions.get() / statsDuration;
                averageDecodeTime = totalDecodeTime.get() / transactions.get();
            } catch (ArithmeticException e) {
                // Divide by zero error. No transactions, so nothing to report
                return;
            }

            transactions.set(0);
            totalDecodeTime.set(0);

            // Create message
            JSONObject message = new JSONObject();
            try {
                message.put("tps", tps);
                message.put("decodeTime", averageDecodeTime);
                message.put("partitionId", m_source.partitionId);
            } catch (JSONException e) {
                m_logger.error("Couldn't create JSON object: " + e.getLocalizedMessage());
            }

            String messageString = message.toString();
            buffer.clear();
            buffer.put((byte)messageString.length());
            buffer.put(messageString.getBytes());
            buffer.flip();

            // Send message over socket
            try {
                int sent = channel.send(buffer, address);
                if (sent != messageString.getBytes().length+1) {
                    // Should always send the whole packet.
                    m_logger.error("Error sending entire stats message");
                }
            } catch (IOException e) {
                m_logger.error("Couldn't send stats to socket");
            }
        }

        @Override
        public void sourceNoLongerAdvertised(AdvertisedDataSource source) {
            timer.cancel();
            try {
                channel.close();
            } catch (IOException ignore) {}
        }

        @Override
        /**
         * Logs the transactions, and determines how long it take to decode
         * the row.
         */
        public boolean processRow(int rowSize, byte[] rowData) throws RestartBlockException {
            // Transaction count
            transactions.incrementAndGet();

            // Time decodeRow
            try {
                long startTime = System.nanoTime();
                decodeRow(rowData);
                long endTime = System.nanoTime();

                totalDecodeTime.addAndGet(endTime - startTime);
            } catch (IOException e) {
                m_logger.error(e.getLocalizedMessage());
            }

            return true;
        }
    }

    @Override
    public ExportDecoderBase constructExportDecoder(AdvertisedDataSource source) {
        return new SocketExportDecoder(source);
    }
}
@@ -1683,37 +1683,8 @@
 on;%0A
-import java.net.InetAddress;%0A
 impo
@@ -2032,24 +2032,61 @@
 VoltLogger;%0A
+import org.voltcore.utils.CoreUtils;%0A
 import org.v
@@ -3158,32 +3158,38 @@
 ess(
-InetAddress.getLocalHost
+CoreUtils.getHostnameOrAddress
 (), 

fix licensecheck.