/** * 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(); } }
/** * Send the CREATE_MEDIATOR command with the necessary parameter in order to create the BackEnd in * the fixed network. Executed - at bootstrap time by the thread that creates the * FrontEndContainer. - To re-attach to the platform after a fault of the BackEnd */ private synchronized void createBackEnd() throws IMTPException { StringBuffer sb = BackEndStub.encodeCreateMediatorRequest(props); if (myMediatorID != null) { // This is a request to re-create my expired back-end BackEndStub.appendProp(sb, JICPProtocol.MEDIATOR_ID_KEY, myMediatorID); BackEndStub.appendProp(sb, "outcnt", String.valueOf(outCnt)); BackEndStub.appendProp(sb, "lastsid", String.valueOf(lastSid)); } JICPPacket pkt = new JICPPacket( JICPProtocol.CREATE_MEDIATOR_TYPE, JICPProtocol.DEFAULT_INFO, null, sb.toString().getBytes()); // Try first with the current transport address, then with the various backup addresses for (int i = -1; i < backEndAddresses.length; i++) { if (i >= 0) { // Set the mediator address to a new address.. String addr = backEndAddresses[i]; int colonPos = addr.indexOf(':'); String host = addr.substring(0, colonPos); String port = addr.substring(colonPos + 1, addr.length()); mediatorTA = new JICPAddress(host, port, myMediatorID, ""); } try { HTTPClientConnection hc = (HTTPClientConnection) getConnection(mediatorTA); myLogger.log( Logger.INFO, "Creating BackEnd on " + hc.getProtocol() + mediatorTA.getHost() + ":" + mediatorTA.getPort()); pkt = deliver(pkt); String replyMsg = new String(pkt.getData()); if (pkt.getType() != JICPProtocol.ERROR_TYPE) { // BackEnd creation successful BackEndStub.parseCreateMediatorResponse(replyMsg, props); myMediatorID = props.getProperty(JICPProtocol.MEDIATOR_ID_KEY); // Complete the mediator address with the mediator ID mediatorTA = new JICPAddress(mediatorTA.getHost(), mediatorTA.getPort(), myMediatorID, null); myDisconnectionManager.setReachable(); myKeepAliveManager.update(); myLogger.log(Logger.INFO, "BackEnd OK. Mediator ID is " + myMediatorID); return; } else { myLogger.log(Logger.WARNING, "Mediator error: " + replyMsg); } } catch (IOException ioe) { // Ignore it, and try the next address... myLogger.log(Logger.WARNING, "Connection error", ioe); } } // No address succeeded! throw new IMTPException("Error creating the BackEnd."); }