package com.zillabyte.motherbrain.flow.rpc.queues; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; import net.sf.json.JSONObject; import org.apache.log4j.Logger; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.javatuples.Pair; import com.zillabyte.motherbrain.flow.MapTuple; import com.zillabyte.motherbrain.flow.rpc.RPCRequest; import com.zillabyte.motherbrain.flow.rpc.RPCResponse; import com.zillabyte.motherbrain.flow.rpc.RPCSink; import com.zillabyte.motherbrain.flow.rpc.RPCSource; import com.zillabyte.motherbrain.universe.Universe; import com.zillabyte.motherbrain.utils.JSONUtil; import com.zillabyte.motherbrain.utils.SerializableMonitor; import com.zillabyte.motherbrain.utils.Utils; @NonNullByDefault public final class MockQueueFactory implements QueueFactory { private static final long serialVersionUID = 8009800068003744010L; final LinkedBlockingQueue<RPCRequest> _inputs = new LinkedBlockingQueue<>(); final ConcurrentHashMap<String, List<MapTuple>> _outputs = new ConcurrentHashMap<>(); final SerializableMonitor outputMonitor; static final Logger _log = Utils.getLogger(MockQueueFactory.class); public MockQueueFactory() { outputMonitor = new SerializableMonitor(); } /*** * * @author jake * */ public final class Input implements InputQueue { /** * Serialization ID */ private static final long serialVersionUID = -9068751590216675151L; @Override public RPCRequest getNextRequest() throws InterruptedException { final RPCRequest request = _inputs.poll(); return request; } @Override public void init() { if(Universe.instance().env().isLocal()) { JSONObject rpcArgs = JSONUtil.parseObj((String)Universe.instance().config().getOrException("rpc.args")); MockQueueFactory queue = (MockQueueFactory) Universe.instance().rpcQueueFactory(); // Queue up rpc args Set<String> rpcInputStreams = rpcArgs.keySet(); for(String inputStream : rpcInputStreams) { Integer count = 0; RPCRequest req = RPCRequest.create("request-"+count); Iterator<?> i = rpcArgs.getJSONArray(inputStream).iterator(); while(i.hasNext()) { JSONObject inputStreamArg = (JSONObject) i.next(); _log.info("Adding "+inputStreamArg+" to input queue."); req.addTuple(inputStream, MapTuple.create(inputStreamArg)); } try { queue.addInput(req); } catch (InterruptedException e) { e.printStackTrace(); } } } } @Override public void shutdown() { // Do nothing } @Override public boolean nextRequestAvailable() { return !_inputs.isEmpty(); } } /*** * * @author jake * */ public final class Output implements OutputQueue { /** * */ private static final long serialVersionUID = 1586591978391066585L; @Override public void init() { // Do nothing } @Override public void shutdown() { // Do nothing } @Override public void sendResponse(RPCResponse response) { _log.info("response added: " + response); synchronized(outputMonitor) { if (_outputs.contains(response.getId()) == false) { _outputs.put(response.getId(), new LinkedList<MapTuple>()); } List<MapTuple> out = _outputs.get(response.getId()); for (final Pair<String, MapTuple> pair : response.getTuples()) { out.add(pair.getValue1()); } outputMonitor.notifyAll(); } } } /*** * */ @Override public InputQueue getInputQueue(RPCSource source) { return new Input(); } /*** * */ @Override public OutputQueue getOutputQueue(RPCSink sink) { return new Output(); } /*** * * @param request */ public void addInput(RPCRequest request) throws InterruptedException { _inputs.put(request); } /*** * * @param id */ public List<MapTuple> getResponse(String id) { return _outputs.get(id); } /*** * * @param id * @param size * @param maxWait * @return * @throws InterruptedException */ public boolean waitForResponse(final String id, final int size, final long maxWait) throws InterruptedException { final long start = System.currentTimeMillis(); synchronized (outputMonitor) { while (true) { // First check if timeout has expired... long waitTime = maxWait - (System.currentTimeMillis() - start); if (waitTime <= 0) { _log.info("timeout exceeded (" + maxWait + " " + waitTime + "). _outputs: " + _outputs); return false; } // Then check if we are free to exit... List<MapTuple> array = this.getResponse(id); if (array != null && array.size() == size) { return true; } // System.err.println("output queue wait: " + waitTime); outputMonitor.wait(waitTime); } } } /*** * * @param tuple */ public boolean outputContains(final String uuid, final @Nullable MapTuple tuple) { List<MapTuple> out = this._outputs.get(uuid); if (out != null) { for (final MapTuple t : out) { if (t.equalsTuple(tuple)) { return true; } } } return false; } public void clear() { // System.err.println("clear input queue"); _outputs.clear(); _inputs.clear(); } }