/** INTERNAL: Send out an announcement that we are here. */ public void announceSession() { rcm.logDebug("sending_announcement", (Object[]) null); ServiceAnnouncement outMsg = new ServiceAnnouncement(rcm.getServiceId()); byte[] outBytes = outMsg.toBytes(); try { // Create a packet to send and send it out to everyone listening DatagramPacket sendPacket = new DatagramPacket( outBytes, outBytes.length, InetAddress.getByName(multicastGroupAddress), multicastPort); getCommunicationSocket().send(sendPacket); Object[] args = null; rcm.logInfo("announcement_sent", args); } catch (Exception ex) { // We got an exception. Map it to an RCM exception and call the handler DiscoveryException discoveryEx = DiscoveryException.errorSendingAnnouncement(ex); rcm.handleException(discoveryEx); } }
/** ADVANCED: Announce the local service and join the cluster */ public void startDiscovery() { if (rcm.isCommandProcessorASession()) { rcm.getCommandProcessor().processCommand(new ProfileDiscoveryStartedCommand()); } // Only start if we are currently stopped if (this.isDiscoveryStopped()) { this.rcm.getServerPlatform().launchContainerRunnable(this); } }
/** INTERNAL: Create the multicast socket and join the multicast group. */ public void createCommunicationSocket() { Object[] args = {multicastGroupAddress, "" + multicastPort}; rcm.logDebug("initializing_discovery_resources", args); if (communicationSocket == null) { try { communicationSocket = new MulticastSocket(multicastPort); communicationSocket.setTimeToLive(getPacketTimeToLive()); communicationSocket.joinGroup(InetAddress.getByName(multicastGroupAddress)); } catch (IOException ex) { // Either we couldn't create the socket or we couldn't join the group DiscoveryException discoveryEx = DiscoveryException.errorJoiningMulticastGroup(ex); rcm.handleException(discoveryEx); } } }
/** * ADVANCED: Stop accepting announcements from other services becoming available. Note that this * does not remove the local service from the cluster. */ public void stopDiscovery() { if (rcm.isCommandProcessorASession()) { this.rcm.getCommandProcessor().processCommand(new ProfileDiscoveryStoppedCommand()); } stopListening(); try { // Put in a sleep to give the listener thread a chance to stop Thread.sleep(500); } catch (InterruptedException exception) { } communicationSocket = null; }
/** * INTERNAL: This is the main execution method of discovery. It will create a socket to listen on, * create a local connection for this service and announce that we are open for business. */ public void run() { // Initialize the communication socket createCommunicationSocket(); // Create the local connection from which we will receive commands rcm.getTransportManager().createLocalConnection(); // Announce to all other discovery managers that this service is up. The // delay allows time for posting of connections to the name service try { Thread.sleep(announcementDelay); } catch (InterruptedException exception) { } announceSession(); // Listen for other sessions that are joining startListening(); }
/** * INTERNAL: This method puts us into the listening mode loop. This thread blocks, waiting on * announcements that we receive from other discovery managers. */ public void startListening() { byte[] recvBuf = new byte[128]; // Only stop when we get the directive to stop stopListening = false; rcm.logInfo("discovery_manager_active", (Object[]) null); while (!stopListening) { DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length); ServiceAnnouncement inMsg; // Block waiting for a message try { getCommunicationSocket().receive(recvPacket); } catch (IOException exception) { if (stopListening) { // We caused the exception by closing the socket rcm.logInfo("discovery_manager_stopped", (Object[]) null); return; } else { // Exception was caused by something else (e.g. network error, etc.) rcm.handleException(DiscoveryException.errorReceivingAnnouncement(exception)); } } // We received a message, unmarshall it into an announcement try { inMsg = new ServiceAnnouncement(recvPacket.getData()); } catch (Exception ex) { // Log a warning that we couldn't process the announcement Object[] args = {ex}; rcm.logWarning("received_corrupt_announcement", args); continue; } // If the msg is not from ourselves, and is announcing a service on // the same channel as we are on then we should do something about it if (!rcm.getServiceId().getId().equals(inMsg.getServiceId().getId()) && (rcm.getServiceId() .getChannel() .equalsIgnoreCase(inMsg.getServiceId().getChannel()))) { receivedAnnouncement(inMsg.getServiceId()); } } }
/** INTERNAL: Process the announcement that indicates that a new service is online */ public void receivedAnnouncement(ServiceId serviceId) { Object[] args = {serviceId}; rcm.logInfo("announcement_received", args); // Notify the RCM that a new service has been detected rcm.newServiceDiscovered(serviceId); }