/hazelcast/src/main/java/com/hazelcast/impl/MulticastJoiner.java

https://bitbucket.org/gabral6_gmailcom/hazelcast · Java · 207 lines · 170 code · 16 blank · 21 comment · 48 complexity · b23f2bde983aff2cfb98f77131944b9b MD5 · raw file

  1. /*
  2. * Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.hazelcast.impl;
  17. import com.hazelcast.cluster.JoinInfo;
  18. import com.hazelcast.config.NetworkConfig;
  19. import com.hazelcast.config.TcpIpConfig;
  20. import com.hazelcast.nio.Address;
  21. import com.hazelcast.nio.Connection;
  22. import com.hazelcast.util.Clock;
  23. import java.util.concurrent.BlockingQueue;
  24. import java.util.concurrent.LinkedBlockingQueue;
  25. import java.util.concurrent.TimeUnit;
  26. import java.util.concurrent.atomic.AtomicBoolean;
  27. import java.util.concurrent.atomic.AtomicInteger;
  28. import java.util.logging.Level;
  29. public class MulticastJoiner extends AbstractJoiner {
  30. private final AtomicInteger currentTryCount = new AtomicInteger(0);
  31. private final AtomicInteger maxTryCount;
  32. public MulticastJoiner(Node node) {
  33. super(node);
  34. maxTryCount = new AtomicInteger(calculateTryCount());
  35. }
  36. public void doJoin(AtomicBoolean joined) {
  37. int tryCount = 0;
  38. long joinStartTime = Clock.currentTimeMillis();
  39. long maxJoinMillis = node.getGroupProperties().MAX_JOIN_SECONDS.getInteger() * 1000;
  40. while (node.isActive() && !joined.get() && (Clock.currentTimeMillis() - joinStartTime < maxJoinMillis)) {
  41. String msg = "Joining to master node: " + node.getMasterAddress();
  42. logger.log(Level.FINEST, msg);
  43. systemLogService.logJoin(msg);
  44. final Address masterAddressNow;
  45. if (targetAddress == null) {
  46. masterAddressNow = findMasterWithMulticast();
  47. } else {
  48. // if target address is set explicitly, try to join target address first.
  49. masterAddressNow = targetAddress;
  50. targetAddress = null;
  51. }
  52. node.setMasterAddress(masterAddressNow);
  53. if (masterAddressNow != null) {
  54. systemLogService.logJoin("Setting master address to " + masterAddressNow);
  55. }
  56. if (node.getMasterAddress() == null || node.address.equals(node.getMasterAddress())) {
  57. TcpIpConfig tcpIpConfig = config.getNetworkConfig().getJoin().getTcpIpConfig();
  58. if (tcpIpConfig != null && tcpIpConfig.isEnabled()) {
  59. doTCP(joined);
  60. } else {
  61. node.setAsMaster();
  62. }
  63. return;
  64. }
  65. if (++tryCount > 49) {
  66. failedJoiningToMaster(true, tryCount);
  67. }
  68. if (!node.getMasterAddress().equals(node.address)) {
  69. connectAndSendJoinRequest(node.getMasterAddress());
  70. } else {
  71. node.setMasterAddress(null);
  72. tryCount = 0;
  73. }
  74. try {
  75. //noinspection BusyWait
  76. Thread.sleep(500L);
  77. } catch (InterruptedException ignored) {
  78. }
  79. }
  80. }
  81. private void doTCP(AtomicBoolean joined) {
  82. node.setMasterAddress(null);
  83. logger.log(Level.FINEST, "Multicast couldn't find cluster. Trying TCP/IP");
  84. new TcpIpJoiner(node).join(joined);
  85. }
  86. public void searchForOtherClusters(SplitBrainHandler splitBrainHandler) {
  87. final BlockingQueue q = new LinkedBlockingQueue();
  88. MulticastListener listener = new MulticastListener() {
  89. public void onMessage(Object msg) {
  90. systemLogService.logJoin("MulticastListener onMessage " + msg);
  91. if (msg != null && msg instanceof JoinInfo) {
  92. JoinInfo joinInfo = (JoinInfo) msg;
  93. if (node.address != null && !node.address.equals(joinInfo.address)) {
  94. q.offer(msg);
  95. }
  96. }
  97. }
  98. };
  99. node.multicastService.addMulticastListener(listener);
  100. node.multicastService.send(node.createJoinInfo());
  101. systemLogService.logJoin("Sent multicast join request");
  102. try {
  103. JoinInfo joinInfo = (JoinInfo) q.poll(3, TimeUnit.SECONDS);
  104. if (joinInfo != null) {
  105. if (joinInfo.getMemberCount() == 1) {
  106. // if the other cluster has just single member, that may be a newly starting node
  107. // instead of a split node.
  108. // Wait 2 times 'WAIT_SECONDS_BEFORE_JOIN' seconds before processing merge JoinInfo.
  109. Thread.sleep(node.groupProperties.WAIT_SECONDS_BEFORE_JOIN.getInteger() * 1000L * 2);
  110. }
  111. if (shouldMerge(joinInfo)) {
  112. logger.log(Level.WARNING, node.address + " is merging [multicast] to " + joinInfo.address);
  113. targetAddress = joinInfo.address;
  114. node.clusterManager.sendClusterMergeToOthers(targetAddress);
  115. splitBrainHandler.restart();
  116. return;
  117. }
  118. }
  119. } catch (InterruptedException ignored) {
  120. } catch (Exception e) {
  121. if (logger != null) {
  122. logger.log(Level.WARNING, e.getMessage(), e);
  123. }
  124. } finally {
  125. node.multicastService.removeMulticastListener(listener);
  126. }
  127. }
  128. private boolean connectAndSendJoinRequest(Address masterAddress) {
  129. if (masterAddress == null || masterAddress.equals(node.address)) {
  130. throw new IllegalArgumentException();
  131. }
  132. Connection conn = node.connectionManager.getOrConnect(masterAddress);
  133. logger.log(Level.FINEST, "Master connection " + conn);
  134. systemLogService.logJoin("Master connection " + conn);
  135. if (conn != null) {
  136. return node.clusterManager.sendJoinRequest(masterAddress, true);
  137. } else {
  138. logger.log(Level.INFO, "Connecting to master node: " + masterAddress);
  139. return false;
  140. }
  141. }
  142. private Address findMasterWithMulticast() {
  143. try {
  144. final String ip = System.getProperty("join.ip");
  145. if (ip == null) {
  146. JoinInfo joinInfo = node.createJoinInfo();
  147. for (; node.isActive() && currentTryCount.incrementAndGet() <= maxTryCount.get(); ) {
  148. joinInfo.setTryCount(currentTryCount.get());
  149. node.multicastService.send(joinInfo);
  150. if (node.getMasterAddress() == null) {
  151. //noinspection BusyWait
  152. Thread.sleep(10);
  153. } else {
  154. return node.getMasterAddress();
  155. }
  156. }
  157. } else {
  158. logger.log(Level.FINEST, "RETURNING join.ip");
  159. return new Address(ip, config.getNetworkConfig().getPort());
  160. }
  161. } catch (final Exception e) {
  162. if (logger != null) {
  163. logger.log(Level.WARNING, e.getMessage(), e);
  164. }
  165. } finally {
  166. this.currentTryCount.set(0);
  167. }
  168. return null;
  169. }
  170. private int calculateTryCount() {
  171. final NetworkConfig networkConfig = config.getNetworkConfig();
  172. int timeoutSeconds = networkConfig.getJoin().getMulticastConfig().getMulticastTimeoutSeconds();
  173. int tryCount = timeoutSeconds * 100;
  174. String host = node.address.getHost();
  175. int lastDigits = 0;
  176. try {
  177. lastDigits = Integer.valueOf(host.substring(host.lastIndexOf(".") + 1));
  178. } catch (NumberFormatException e) {
  179. lastDigits = (int) (512 * Math.random());
  180. }
  181. lastDigits = lastDigits % 100;
  182. tryCount += lastDigits + (node.address.getPort() - networkConfig.getPort()) * timeoutSeconds * 3;
  183. return tryCount;
  184. }
  185. public void onReceivedJoinInfo(JoinInfo joinInfo) {
  186. if (joinInfo.getTryCount() > this.currentTryCount.get() + 20) {
  187. int timeoutSeconds = (config.getNetworkConfig().getJoin().getMulticastConfig().getMulticastTimeoutSeconds() + 4) * 100;
  188. this.maxTryCount.set(timeoutSeconds);
  189. }
  190. }
  191. }