Package edu.brown.api

Source Code of edu.brown.api.ClientStatusThread

package edu.brown.api;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;
import org.voltdb.catalog.Database;
import org.voltdb.processtools.ProcessSetManager;

import edu.brown.api.results.BenchmarkComponentResults;
import edu.brown.api.results.BenchmarkResults;
import edu.brown.api.results.ResponseEntries;
import edu.brown.catalog.CatalogUtil;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.utils.JSONUtil;
import edu.brown.utils.StringUtil;

/**
* This thread is started by the BenchmarkController and will process
* updates coming from remotely started BenchmarkComponents
* @author pavlo
*/
public class ClientStatusThread extends Thread {
    private static final Logger LOG = Logger.getLogger(ClientStatusThread.class);
    private static final LoggerBoolean debug = new LoggerBoolean();
    static {
        LoggerUtil.attachObserver(LOG, debug);
    }

//    private final int thread_id;
   
    /** ClientName -> List of all the Previous Messages */
    private final Map<String, List<ProcessSetManager.OutputLine>> previous = new HashMap<String, List<ProcessSetManager.OutputLine>>();
   
    /** ClientName -> Timestamp of Previous Message */
    private final Map<String, Long> lastTimestamps = new HashMap<String, Long>();
   
    /** TransactionName -> # of Executed **/
    private final Map<String, Long> results = new HashMap<String, Long>();
   
    private boolean finished = false;
   
    private final BenchmarkController controller;
    private final BenchmarkResults m_currentResults;
   
    private final BenchmarkComponentResults tc = new BenchmarkComponentResults();
    private final ResponseEntries responseEntries = new ResponseEntries();
    private CountDownLatch responseEntriesLatch;
   
    public ClientStatusThread(BenchmarkController controller, int i) {
        super(String.format("client-status-%02d", i));
        this.controller = controller;
        this.m_currentResults = controller.getBenchmarkResults();
        this.setDaemon(true);
    }
   
    public boolean isFinished() {
        return (this.finished);
    }
   
    @Override
    public void run() {
        this.finished = false;
        final Database catalog_db = CatalogUtil.getDatabase(controller.getCatalog());
        final CountDownLatch resultsToRead = controller.getResultsToReadLatch();
        final ProcessSetManager clientPSM = controller.getClientProcessSetManager();

        while (resultsToRead.getCount() > 0) {
            ProcessSetManager.OutputLine line = clientPSM.nextBlocking();
            if (line == null) {
                continue;
            }
            // Print stderr back-out to the console
            else if (line.stream == ProcessSetManager.StreamType.STDERR) {
                String prefix = String.format("(%s): ", line.processName);
                System.err.println(StringUtil.prefix(line.value, prefix));
                continue;
            }
            // General Debug Output
            else if (line.value.startsWith(BenchmarkComponent.CONTROL_MESSAGE_PREFIX) == false) {
                String prefix = String.format("(%s): ", line.processName);
                System.out.println(StringUtil.prefix(line.value, prefix));
                continue;
            }
           
            // BenchmarkController Coordination Message
            // split the string on commas and strip whitespace
            String control_line = line.value.substring(BenchmarkComponent.CONTROL_MESSAGE_PREFIX.length());
            String[] parts = control_line.split(",");
            for (int i = 0; i < parts.length; i++)
                parts[i] = parts[i].trim();

            // expect at least time and status
            if (parts.length < 2) {
                if (line.value.startsWith("Listening for transport dt_socket at address:") ||
                        line.value.contains("Attempting to load") ||
                        line.value.contains("Successfully loaded native VoltDB library")) {
                    LOG.info(line.processName + ": " + control_line + "\n");
                    continue;
                }
//                m_clientPSM.killProcess(line.processName);
//                LogKeys logkey =
//                    LogKeys.benchmark_BenchmarkController_ProcessReturnedMalformedLine;
//                LOG.l7dlog( Level.ERROR, logkey.name(),
//                        new Object[] { line.processName, line.value }, null);
                continue;
            }

            int clientId = -1;
            long time = -1;
            try {
                clientId = Integer.parseInt(parts[0]);
                time = Long.parseLong(parts[1]);
            } catch (NumberFormatException ex) {
                LOG.warn("Failed to parse line '" + control_line + "'", ex);
                continue; // IGNORE
            }
            final String clientName = BenchmarkControllerUtil.getClientName(line.processName, clientId);
            final ControlState status = ControlState.get(parts[2]);
            assert(status != null) : "Unexpected ControlStatus '" + parts[2] + "'";
           
            if (debug.val)
                LOG.debug(String.format("Client %s -> %s", clientName, status));
           
            // Make sure that we never go back in time!
            Long lastTimestamp = this.lastTimestamps.get(clientName);
            if (lastTimestamp != null) assert(time >= lastTimestamp) :
                String.format("New message from %s is in the past [newTime=%d, lastTime=%d]", clientName, time, lastTimestamp);

            switch (status) {
                // ----------------------------------------------------------------------------
                // READY
                // ----------------------------------------------------------------------------
                case READY: {
                    if (debug.val) LOG.debug(String.format("Got ready message for '%s'.", line.processName));
                    controller.clientIsReady(clientName);
                    break;
                }
                // ----------------------------------------------------------------------------
                // ERROR
                // ----------------------------------------------------------------------------
                case ERROR: {
                    clientPSM.killProcess(line.processName);
                    LOG.error(String.format("(%s) Returned error message:\n\"%s\"", line.processName, parts[2]));
                    break;
                }
                // ----------------------------------------------------------------------------
                // DUMPING
                // ----------------------------------------------------------------------------
                case DUMPING: {
                    ResponseEntries newEntries = new ResponseEntries();
                    String json_line = getPayload(control_line, parts);
                    JSONObject json_object;
                    if (debug.val) LOG.debug("Processing response dump");
                    try {
                        json_object = new JSONObject(json_line);
                        newEntries.fromJSON(json_object, catalog_db);
                    } catch (JSONException ex) {
                        LOG.error("Invalid response:\n" + json_line);
                        throw new RuntimeException(ex);
                    }
                    this.responseEntries.addAll(newEntries);
                    if (this.responseEntriesLatch != null) this.responseEntriesLatch.countDown();
                    resultsToRead.countDown();
                    break;
                }
                // ----------------------------------------------------------------------------
                // RUNNING
                // ----------------------------------------------------------------------------
                case RUNNING: {
                    // System.out.println("Got running message: " + Arrays.toString(parts));
                    if (parts[parts.length-1].equalsIgnoreCase("OK")) continue;
                   
                    this.tc.clear(true);
                    String json_line = getPayload(control_line, parts);
                    JSONObject json_object;
                    try {
                        json_object = new JSONObject(json_line);
                        this.tc.fromJSON(json_object, catalog_db);
                    } catch (JSONException ex) {
                        LOG.error("Invalid response:\n" + json_line);
                        throw new RuntimeException(ex);
                    }
                    assert(json_object != null);
                    if (debug.val) LOG.debug("Base Partitions:\n " + this.tc.basePartitions);
                   
//                    this.results.clear();
//                    for (String txnName : tc.transactions.values()) {
//                        this.results.put(txnName, tc.transactions.get(txnName));
//                    } // FOR
                   
                    try {
                        if (debug.val) LOG.debug("UPDATE: " + line);
                        this.addPollResponseInfo(clientName, time, this.tc, null);
                    } catch (Throwable ex) {
                        List<ProcessSetManager.OutputLine> p = this.previous.get(clientName);
                        LOG.error(String.format("Invalid response from '%s':\n%s\n%s\n", clientName, JSONUtil.format(json_object), line, results), ex);
                        LOG.error(String.format("Previous Lines for %s [%s]:\n%s",
                                                clientName,
                                                (p != null ? p.size() : p),
                                                StringUtil.join("\n", p)));
                        throw new RuntimeException(ex);
                    }
                    List<ProcessSetManager.OutputLine> p = this.previous.get(clientName);
                    if (p == null) {
                        p = new ArrayList<ProcessSetManager.OutputLine>();
                        this.previous.put(clientName, p);
                    }
                    p.add(line);
                    resultsToRead.countDown();
                    break;
                }
                default:
                    assert(false) : "Unexpected ControlStatus " + status;
            } // SWITCH
           
            this.lastTimestamps.put(clientName, time);
        } // WHILE
        if (debug.val)
            LOG.debug("Status thread is finished");
        this.finished = true;
    }
   
    public ResponseEntries getResponseEntries() {
        return (this.responseEntries);
    }
   
    public void addResponseEntriesLatch(CountDownLatch latch) {
        this.responseEntriesLatch = latch;
    }
   
    private String getPayload(String control_line, String parts[]) {
        int offset = 1;
        for (int i = 0; i < 3; i++) {
            offset += parts[i].length() + 1;
        } // FOR
        return (control_line.substring(offset));
    }
   
    private void addPollResponseInfo(String clientName, long time, BenchmarkComponentResults tc, String errMsg) {
        assert(m_currentResults != null);
       
        // Update Transaction Counters
        BenchmarkResults resultCopy = m_currentResults.addPollResponseInfo(
                clientName,
                controller.m_pollIndex - 1,
                time,
                tc,
                errMsg);
        if (resultCopy != null) {
            // notify interested parties
            for (BenchmarkInterest interest : controller.getBenchmarkInterests()) {
                interest.benchmarkHasUpdated(resultCopy);
            } // FOR
            controller.m_maxCompletedPoll = resultCopy.getCompletedIntervalCount();
        }

            // get total transactions run for this segment
//            long txnDelta = 0;
//            for (String client : resultCopy.getClientNames()) {
//                try {
//                    for (String txn : resultCopy.getTransactionNames()) {
//                        Result[] rs = resultCopy.getResultsForClientAndTransaction(client, txn);
//                        Result r = rs[rs.length - 1];
//                        txnDelta += r.transactionCount;
//                    } // FOR
//                } catch (Throwable ex) {
//                    LOG.error(StringUtil.columns(m_currentResults.toString(), resultCopy.toString()));
//                    LOG.error(client + " PREVIOUS:\n" + CollectionUtil.first(m_statusThreads).previous.get(client));
//                    throw new RuntimeException(ex);
//                }
//
//            } // FOR

            // if nothing done this segment, dump everything
//            if (txnDelta == 0) {
//                tryDumpAll();
//                System.out.println("\nDUMPING!\n");
//            }
//        }


    }
}
TOP

Related Classes of edu.brown.api.ClientStatusThread

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.