public void searchForOtherClusters(SplitBrainHandler splitBrainHandler) { final BlockingQueue q = new LinkedBlockingQueue(); MulticastListener listener = new MulticastListener() { public void onMessage(Object msg) { systemLogService.logJoin("MulticastListener onMessage " + msg); if (msg != null && msg instanceof JoinInfo) { JoinInfo joinInfo = (JoinInfo) msg; if (node.address != null && !node.address.equals(joinInfo.address)) { q.offer(msg); } } } }; node.multicastService.addMulticastListener(listener); node.multicastService.send(node.createJoinInfo()); systemLogService.logJoin("Sent multicast join request"); try { JoinInfo joinInfo = (JoinInfo) q.poll(3, TimeUnit.SECONDS); if (joinInfo != null) { if (joinInfo.getMemberCount() == 1) { // if the other cluster has just single member, that may be a newly starting node // instead of a split node. // Wait 2 times 'WAIT_SECONDS_BEFORE_JOIN' seconds before processing merge JoinInfo. Thread.sleep(node.groupProperties.WAIT_SECONDS_BEFORE_JOIN.getInteger() * 1000L * 2); } if (shouldMerge(joinInfo)) { logger.log( Level.WARNING, node.address + " is merging [multicast] to " + joinInfo.address); targetAddress = joinInfo.address; node.clusterManager.sendClusterMergeToOthers(targetAddress); splitBrainHandler.restart(); return; } } } catch (InterruptedException ignored) { } catch (Exception e) { if (logger != null) { logger.log(Level.WARNING, e.getMessage(), e); } } finally { node.multicastService.removeMulticastListener(listener); } }
public ClusterManager(final Node node) { super(node); WAIT_MILLIS_BEFORE_JOIN = node.groupProperties.WAIT_SECONDS_BEFORE_JOIN.getInteger() * 1000L; MAX_WAIT_SECONDS_BEFORE_JOIN = node.groupProperties.MAX_WAIT_SECONDS_BEFORE_JOIN.getInteger(); MAX_NO_HEARTBEAT_MILLIS = node.groupProperties.MAX_NO_HEARTBEAT_SECONDS.getInteger() * 1000L; HEARTBEAT_INTERVAL_MILLIS = node.groupProperties.HEARTBEAT_INTERVAL_SECONDS.getInteger() * 1000L; MAX_NO_MASTER_CONFIRMATION_MILLIS = node.groupProperties.MAX_NO_MASTER_CONFIRMATION_SECONDS.getInteger() * 1000L; MASTER_CONFIRMATION_INTERVAL_MILLIS = node.groupProperties.MASTER_CONFIRMATION_INTERVAL_SECONDS.getInteger() * 1000L; MEMBER_LIST_PUBLISH_INTERVAL_MILLIS = node.groupProperties.MEMBER_LIST_PUBLISH_INTERVAL_SECONDS.getInteger() * 1000L; ICMP_ENABLED = node.groupProperties.ICMP_ENABLED.getBoolean(); ICMP_TTL = node.groupProperties.ICMP_TTL.getInteger(); ICMP_TIMEOUT = node.groupProperties.ICMP_TIMEOUT.getInteger(); node.clusterService.registerPeriodicRunnable(new SplitBrainHandler(node)); node.clusterService.registerPeriodicRunnable( new Runnable() { public void run() { long now = Clock.currentTimeMillis(); if (now - lastHeartbeat >= HEARTBEAT_INTERVAL_MILLIS) { heartBeater(); lastHeartbeat = now; } if (now - lastMasterConfirmation >= MASTER_CONFIRMATION_INTERVAL_MILLIS) { sendMasterConfirmation(); lastMasterConfirmation = now; } if (now - lastMemberListPublish >= MEMBER_LIST_PUBLISH_INTERVAL_MILLIS) { sendMemberListToOthers(); lastMemberListPublish = now; } } }); node.clusterService.registerPeriodicRunnable( new Runnable() { public void run() { checkScheduledActions(); } }); node.connectionManager.addConnectionListener(this); registerPacketProcessor( ClusterOperation.RESPONSE, new PacketProcessor() { public void process(Packet packet) { handleResponse(packet); } }); registerPacketProcessor( ClusterOperation.HEARTBEAT, new PacketProcessor() { public void process(Packet packet) { releasePacket(packet); } }); registerPacketProcessor( ClusterOperation.LOG, new PacketProcessor() { public void process(Packet packet) { logger.log(Level.parse(packet.name), toObject(packet.getValueData()).toString()); releasePacket(packet); } }); registerPacketProcessor( ClusterOperation.JOIN_CHECK, new PacketProcessor() { public void process(Packet packet) { Connection conn = packet.conn; Request request = Request.copyFromPacket(packet); Data value = request.value; request.clearForResponse(); if (node.isMaster() && node.joined() && node.isActive()) { JoinInfo joinInfo = (JoinInfo) toObject(value); if (joinInfo != null) { try { node.validateJoinRequest(joinInfo); request.response = toData(node.createJoinInfo()); } catch (Exception e) { request.response = toData(e); } } } returnResponse(request, conn); releasePacket(packet); } }); registerPacketProcessor( ClusterOperation.REMOTELY_PROCESS_AND_RESPOND, new PacketProcessor() { public void process(Packet packet) { Data data = packet.getValueData(); RemotelyProcessable rp = (RemotelyProcessable) toObject(data); rp.setConnection(packet.conn); rp.setNode(node); rp.process(); sendResponse(packet); } }); registerPacketProcessor( ClusterOperation.REMOTELY_PROCESS, new PacketProcessor() { public void process(Packet packet) { Data data = packet.getValueData(); RemotelyProcessable rp = (RemotelyProcessable) toObject(data); rp.setConnection(packet.conn); rp.setNode(node); rp.process(); releasePacket(packet); } }); registerPacketProcessor( ClusterOperation.REMOTELY_CALLABLE_BOOLEAN, new PacketProcessor() { public void process(Packet packet) { Boolean result; AbstractRemotelyCallable<Boolean> callable = null; try { Data data = packet.getValueData(); callable = (AbstractRemotelyCallable<Boolean>) toObject(data); callable.setConnection(packet.conn); callable.setNode(node); result = callable.call(); } catch (Exception e) { logger.log(Level.SEVERE, "Error processing " + callable, e); result = Boolean.FALSE; } if (result == Boolean.TRUE) { sendResponse(packet); } else { sendResponseFailure(packet); } } }); registerPacketProcessor( ClusterOperation.REMOTELY_CALLABLE_OBJECT, new PacketProcessor() { public void process(Packet packet) { Object result; AbstractRemotelyCallable<Boolean> callable = null; try { Data data = packet.getValueData(); callable = (AbstractRemotelyCallable) toObject(data); callable.setConnection(packet.conn); callable.setNode(node); result = callable.call(); } catch (Exception e) { logger.log(Level.SEVERE, "Error processing " + callable, e); result = null; } if (result != null) { Data value; if (result instanceof Data) { value = (Data) result; } else { value = toData(result); } packet.setValue(value); } sendResponse(packet); } }); }