package org.marketcetera.module; import org.marketcetera.util.misc.ClassVersion; import java.util.HashMap; import java.util.Map; /* $License$ */ /** * The system sink module. The Sink module accepts data of any type. * * * Any data received by the sink module can be received by any other * component of the system by subscribing as a * {@link SinkDataListener listener} to the * {@link ModuleManager#addSinkListener(SinkDataListener) ModuleManager}. * Other components of syste * <p> * This module is intended as an attach point for mechanisms that can help a * user debug their modules / data flows. Its expected that such debugging * aids will subscribe themselves as listeners to the data received by the * sink module and display that data to users via logs, screens or any * other means. * <p> * Users can append sink module to any of their data flows to examine * / test the output that the data flow is generating. * <p> * Besides routing data to the listeners, the sink module also * maintains statistics on data that it receives and makes those * statistics available via JMX. * <p> * Do note that the sink module's mechanism to receive data is * synchronized. Hence, if it is appended to multiple data flows * that produce copious amounts of data, the performance of those * data flows may be bottlenecked. Its recommended that the sink module * be only used for debugging data flows and not be used on flows * that emit lots of data into it. * <p> * Module Features * <table> * <tr><th>Capabilities</th><td>DataReceiver</td></tr> * <tr><th>Stops data flows</th><td>No</td></tr> * <tr><th>Start Operation</th><td>Does nothing</td></tr> * <tr><th>Stop Operation</th><td>Does nothing</td></tr> * <tr><th>Management Interface</th><td>{@link SinkModuleMXBean}</td></tr> * <tr><th>Factory</th><td>{@link SinkModuleFactory}</td></tr> * </table> * * @author anshul@marketcetera.com * @version $Id: SinkModule.java 16154 2012-07-14 16:34:05Z colin $ * @since 1.0.0 */ @ClassVersion("$Id: SinkModule.java 16154 2012-07-14 16:34:05Z colin $") //$NON-NLS-1$ public class SinkModule extends Module implements DataReceiver, SinkModuleMXBean { @Override public void preStop() throws ModuleException { //do nothing } @Override public void receiveData(DataFlowID inFlowID, Object inData) throws UnsupportedDataTypeException, StopDataFlowException { synchronized(this) { String type = inData == null ? String.valueOf(inData) : inData.getClass().getName(); Counter c = mTypeStats.get(type); if(c == null) { c = new Counter(); mTypeStats.put(type,c); } c.increment(); c = mDataFlowStats.get(inFlowID); if(c == null) { c = new Counter(); mDataFlowStats.put(inFlowID, c); } c.increment(); } if(mManager == null) { Messages.LOG_SINK_MODULE_MISCONFIGURED.error(this); } else { mManager.receiveSinkData(inFlowID, inData); } } @Override public synchronized Map<String, Integer> getTypeStats() { HashMap<String, Integer> map = new HashMap<String, Integer>(); for(String s: mTypeStats.keySet()) { map.put(s, mTypeStats.get(s).getValue()); } return map; } @Override public synchronized Map<DataFlowID, Integer> getDataFlowStats() { HashMap<DataFlowID, Integer> map = new HashMap<DataFlowID, Integer>(); for(DataFlowID id: mDataFlowStats.keySet()) { map.put(id, mDataFlowStats.get(id).getValue()); } return map; } @Override public void resetStats() { synchronized (this) { mTypeStats.clear(); mDataFlowStats.clear(); } } @Override protected void preStart() throws ModuleException { //do nothing } /** * Creates an instance. */ SinkModule() { super(SinkModuleFactory.INSTANCE_URN, true); } /** * Supplies the module manager instance. * * @param inManager the module manager instance */ void setManager(ModuleManager inManager) { mManager = inManager; } private volatile ModuleManager mManager; private final HashMap<String, Counter> mTypeStats = new HashMap<String, Counter>(); private final HashMap<DataFlowID, Counter> mDataFlowStats = new HashMap<DataFlowID, Counter>(); /** * Instances of this class represent various counter values */ private static class Counter { /** * Gets the current value of this counter. * * @return the current value of this counter */ int getValue() { return mValue; } /** * Increments counter value. */ void increment() { mValue++; } private int mValue = 0; } }