/** * Copyright 2014 SAP AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.spotter.ext.detection.blob; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.aim.api.measurement.dataset.Dataset; import org.aim.api.measurement.dataset.DatasetCollection; import org.aim.artifacts.records.JmsRecord; /** * Processes raw measurement data with respect to messaging. * * @author Alexander Wert * */ public final class DataProcessor { /** * Process the given WrappedMeasurementData. * * @param data * Data to process * @return the processed data */ public static ProcessedData processData(DatasetCollection data) { return new DataProcessor().process(data); } // INFOS private double firstTimestamp; private double lastTimestamp; private Map<String, List<Double>> messageDurations; // TEMP private Map<String, MessageCorrelation> messageMap; private ProcessedData processedData; private Map<String, String> tempStackTraceMap; /** * Hide default constructor. */ private DataProcessor() { } /** * Starts to process the input data. * * @param data * data to process * @return transformed data */ public ProcessedData process(DatasetCollection data) { initVariables(); buildMessageMap(data); evaluateMessageMap(); callcualteMessageDurations(); assignStackTrace(data); return processedData; } private void addMessageDuration(String clientId, double duration) { if (!messageDurations.containsKey(clientId)) { messageDurations.put(clientId, new ArrayList<Double>()); } messageDurations.get(clientId).add(duration); } /** * Assigns to each ComponentInfo the correlating StackTrace */ private void assignStackTrace(DatasetCollection data) { // Assigns a stacktrace to each ComponentInfo // for (WrappedDataSet set : // data.getDataSets(JmsStartConnectionRecord.class)) { // for (JmsStartConnectionRecord jscr : // set.getRecords(JmsStartConnectionRecord.class)) { // processedData.getComponent(jscr.getClientId()).setStackTrace(jscr.getStackTrace()); // } // } for (Entry<String, String> pair : tempStackTraceMap.entrySet()) { processedData.getComponent(pair.getKey()).setStackTrace(pair.getValue()); } } /** * Builds the messageMap out of the input data. Creates relations between * send and received messages. */ private void buildMessageMap(DatasetCollection data) { for (Dataset set : data.getDataSets()) { for (JmsRecord record : set.getRecords(JmsRecord.class)) { if (record.getClientId() == null) { System.err.println("ClientId is null.."); continue; } MessageCorrelation correlation = getMessageCorrelation(record.getMessageCorrelationHash()); if (!record.wasSent()) { correlation.setReceiverId(record.getClientId()); correlation.setTimeReceived(record.getTimeStamp()); } else if (record.wasSent()) { correlation.setSenderId(record.getClientId()); correlation.setTimeSend(record.getTimeStamp()); } else { throw new RuntimeException("'wasSent' must be 0 or 1 and NOT " + record.wasSent()); } if (record.getStackTrace() != null && !record.getStackTrace().isEmpty()) { // TODO client id can have multiple stacktraces because of // multiple method instrumentations tempStackTraceMap.put(record.getClientId(), record.getStackTrace()); } } } } /** * Aggregates the durations of all messages. */ private void callcualteMessageDurations() { for (Component component : processedData.getComponents()) { List<Double> list = messageDurations.get(component.getId()); if (list == null) { continue; } double shortest = Double.MAX_VALUE; double longest = 0; double average = 0; double total = 0; for (double duration : list) { if (duration < shortest) { shortest = duration; } if (duration > longest) { longest = duration; } total += duration; } average = total / list.size(); component.setShortestMessageSentDuration(shortest); component.setLongestMessageSentDuration(longest); component.setAverageMessageSentDuration(average); component.setTotalMessageSentDuration(total); } } /** * Evaluates the messageMap and builds the componentMap during this action. */ private void evaluateMessageMap() { for (MessageCorrelation mc : messageMap.values()) { // Check clientIds if (mc.getSenderId() == null || mc.getReceiverId() == null) { System.err.println("Nullpointer!"); continue; } // Get relevant Component objects Component senderInfo = processedData.getComponent(mc.getSenderId()); Component receiverInfo = processedData.getComponent(mc.getReceiverId()); // Increase their message count senderInfo.increaseMessageSent(); receiverInfo.increaseMessageReceived(); // Increase the messageCount to the specified receiver senderInfo.addSendMessageTo(receiverInfo.getId()); senderInfo.addSendMessageToDuration(receiverInfo.getId(), mc.getDuration()); // Add message duration to sending component addMessageDuration(senderInfo.getId(), mc.getDuration()); // Remember sender receiverInfo.addComponentWhoSentToMe(senderInfo.getId()); // Update timestamps if necessary if (mc.getTimeSend() < firstTimestamp) { firstTimestamp = mc.getTimeSend(); } if (mc.getTimeReceived() > lastTimestamp) { lastTimestamp = mc.getTimeReceived(); } } processedData.setTotalExperimentDuration(lastTimestamp - firstTimestamp); } /** * Returns the MessageCorrelation object of the messageMap which is related * to the given key. If no object is stored with the given key, it will be * created. * * @param key * @return */ private MessageCorrelation getMessageCorrelation(String key) { if (messageMap.containsKey(key)) { return messageMap.get(key); } else { MessageCorrelation correlation = new MessageCorrelation(); messageMap.put(key, correlation); return correlation; } } /** * Initializes all local variables. */ private void initVariables() { messageMap = new HashMap<String, MessageCorrelation>(); processedData = new ProcessedData(); messageDurations = new HashMap<String, List<Double>>(); tempStackTraceMap = new HashMap<String, String>(); firstTimestamp = Double.MAX_VALUE; lastTimestamp = 0; } }