/** * Dispatch a serialized command to the BackEnd and get back a serialized response. Mutual * exclusion with itself to preserve dispatching order */ public synchronized byte[] dispatch(byte[] payload, boolean flush) throws ICPException { // Note that we don't even try to dispatch packets while the // device is not reachable to preserve dispatching order. // If dispatching succeeded in fact this command would overcome // any postponed command waiting to be flushed. if (myDisconnectionManager.isReachable()) { // The following check preserves dispatching order when the // device has just reconnected but flushing has not started yet if (waitingForFlush && !flush) { throw new ICPException("Upsetting dispatching order"); } waitingForFlush = false; int sid = outCnt; outCnt = (outCnt + 1) & 0x0f; myLogger.log(Logger.FINE, "Issuing outgoing command " + sid); try { JICPPacket pkt = new JICPPacket(JICPProtocol.COMMAND_TYPE, JICPProtocol.DEFAULT_INFO, payload); pkt.setSessionID((byte) sid); pkt = deliver(pkt); myLogger.log(Logger.FINE, "Response received " + pkt.getSessionID()); if (pkt.getType() == JICPProtocol.ERROR_TYPE) { // Communication OK, but there was a JICP error on the peer throw new ICPException(new String(pkt.getData())); } return pkt.getData(); } catch (IOException ioe) { // Can't reach the BackEnd. Assume we are unreachable myLogger.log(Logger.WARNING, "IOException on output connection", ioe); myDisconnectionManager.setUnreachable(false); throw new ICPException("Dispatching error.", ioe); } } else { throw new ICPException("Unreachable"); } }
/** * Make this HTTPFEDispatcher terminate. Note that when the BackEnd receives the termination * notification (explicitly sent in case of a self-initiated shutdown or attached to the response * to the EXIT command), it closes the input connection. The InputManager gets an exception and, * since it has been killed, terminates. */ public void shutdown() { terminator = Thread.currentThread(); myLogger.log( Logger.INFO, "Dispatcher shutting down. Self-initiated = " + (terminator != myInputManager)); if (terminator != myInputManager) { // Self-initiated shut down // If connected, explicitly notify the BackEnd. if (myDisconnectionManager.isReachable()) { JICPPacket pkt = new JICPPacket(JICPProtocol.COMMAND_TYPE, (byte) (JICPProtocol.DEFAULT_INFO), null); myLogger.log(Logger.INFO, "Pushing termination notification"); try { deliver(pkt); } catch (IOException ioe) { // When the BackEnd receives the termination notification, // it just closes the connection --> we always have this exception myLogger.log(Logger.FINE, "BackEnd closed"); } } // Kill the InputManager myInputManager.kill(); } }