/hazelcast/src/main/java/com/hazelcast/cluster/ClusterManager.java

https://bitbucket.org/gabral6_gmailcom/hazelcast · Java · 1077 lines · 949 code · 98 blank · 30 comment · 227 complexity · 7dc83eb3e86032a595e6a7bfab2872af 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.cluster;
  17. import com.hazelcast.core.Member;
  18. import com.hazelcast.impl.*;
  19. import com.hazelcast.impl.base.Call;
  20. import com.hazelcast.impl.base.PacketProcessor;
  21. import com.hazelcast.impl.base.ScheduledAction;
  22. import com.hazelcast.logging.ILogger;
  23. import com.hazelcast.nio.*;
  24. import com.hazelcast.security.Credentials;
  25. import com.hazelcast.util.Clock;
  26. import com.hazelcast.util.Prioritized;
  27. import javax.security.auth.login.LoginContext;
  28. import javax.security.auth.login.LoginException;
  29. import java.net.ConnectException;
  30. import java.util.*;
  31. import java.util.concurrent.TimeUnit;
  32. import java.util.logging.Level;
  33. import static com.hazelcast.nio.IOUtil.toData;
  34. import static com.hazelcast.nio.IOUtil.toObject;
  35. public final class ClusterManager extends BaseManager implements ConnectionListener {
  36. private final long WAIT_MILLIS_BEFORE_JOIN;
  37. private final long MAX_WAIT_SECONDS_BEFORE_JOIN;
  38. private final long MAX_NO_HEARTBEAT_MILLIS;
  39. private final long MAX_NO_MASTER_CONFIRMATION_MILLIS;
  40. private final boolean ICMP_ENABLED;
  41. private final int ICMP_TTL;
  42. private final int ICMP_TIMEOUT;
  43. private final Set<ScheduledAction> setScheduledActions = new LinkedHashSet<ScheduledAction>(1000);
  44. private final Set<MemberInfo> setJoins = new LinkedHashSet<MemberInfo>(100);
  45. private boolean joinInProgress = false;
  46. private long timeToStartJoin = 0;
  47. private long firstJoinRequest = 0;
  48. private final Map<MemberImpl, Long> memberMasterConfirmationTimes = new HashMap<MemberImpl, Long>();
  49. public ClusterManager(final Node node) {
  50. super(node);
  51. WAIT_MILLIS_BEFORE_JOIN = node.groupProperties.WAIT_SECONDS_BEFORE_JOIN.getInteger() * 1000L;
  52. MAX_WAIT_SECONDS_BEFORE_JOIN = node.groupProperties.MAX_WAIT_SECONDS_BEFORE_JOIN.getInteger();
  53. MAX_NO_HEARTBEAT_MILLIS = node.groupProperties.MAX_NO_HEARTBEAT_SECONDS.getInteger() * 1000L;
  54. long heartbeatIntervalMillis = node.groupProperties.HEARTBEAT_INTERVAL_SECONDS.getInteger() * 1000L;
  55. MAX_NO_MASTER_CONFIRMATION_MILLIS = node.groupProperties.MAX_NO_MASTER_CONFIRMATION_SECONDS.getInteger() * 1000L;
  56. long masterConfirmationIntervalMillis = node.groupProperties.MASTER_CONFIRMATION_INTERVAL_SECONDS.getInteger() * 1000L;
  57. long memberListPublishIntervalMillis = node.groupProperties.MEMBER_LIST_PUBLISH_INTERVAL_SECONDS.getInteger() * 1000L;
  58. ICMP_ENABLED = node.groupProperties.ICMP_ENABLED.getBoolean();
  59. ICMP_TTL = node.groupProperties.ICMP_TTL.getInteger();
  60. ICMP_TIMEOUT = node.groupProperties.ICMP_TIMEOUT.getInteger();
  61. registerPeriodicProcessable(new Processable() {
  62. public void process() {
  63. heartBeater();
  64. }
  65. }, heartbeatIntervalMillis, heartbeatIntervalMillis);
  66. registerPeriodicProcessable(new Processable() {
  67. public void process() {
  68. sendMasterConfirmation();
  69. }
  70. }, masterConfirmationIntervalMillis, masterConfirmationIntervalMillis);
  71. registerPeriodicProcessable(new Processable() {
  72. public void process() {
  73. sendMemberListToOthers();
  74. }
  75. }, memberListPublishIntervalMillis, memberListPublishIntervalMillis);
  76. registerPeriodicProcessable(new Processable() {
  77. public void process() {
  78. checkScheduledActions();
  79. }
  80. }, 0, 1000);
  81. final SplitBrainHandler splitBrainHandler = new SplitBrainHandler(node);
  82. registerPeriodicProcessable(splitBrainHandler,
  83. splitBrainHandler.getFirstRunDelayMillis(), splitBrainHandler.getNextRunDelayMillis());
  84. registerPeriodicProcessable(new Processable() {
  85. public void process() {
  86. node.clusterService.checkIdle();
  87. }
  88. }, 0, 1000);
  89. node.connectionManager.addConnectionListener(this);
  90. registerPacketProcessor(ClusterOperation.RESPONSE, new PacketProcessor() {
  91. public void process(Packet packet) {
  92. handleResponse(packet);
  93. }
  94. });
  95. registerPacketProcessor(ClusterOperation.HEARTBEAT, new PacketProcessor() {
  96. public void process(Packet packet) {
  97. releasePacket(packet);
  98. }
  99. });
  100. registerPacketProcessor(ClusterOperation.LOG, new PacketProcessor() {
  101. public void process(Packet packet) {
  102. logger.log(Level.parse(packet.name), toObject(packet.getValueData()).toString());
  103. releasePacket(packet);
  104. }
  105. });
  106. registerPacketProcessor(ClusterOperation.JOIN_CHECK, new PacketProcessor() {
  107. public void process(Packet packet) {
  108. Connection conn = packet.conn;
  109. Request request = Request.copyFromPacket(packet);
  110. Data value = request.value;
  111. request.clearForResponse();
  112. if (node.isMaster() && node.joined() && node.isActive()) {
  113. JoinInfo joinInfo = (JoinInfo) toObject(value);
  114. if (joinInfo != null) {
  115. try {
  116. node.validateJoinRequest(joinInfo);
  117. request.response = toData(node.createJoinInfo());
  118. } catch (Exception e) {
  119. request.response = toData(e);
  120. }
  121. }
  122. }
  123. returnResponse(request, conn);
  124. releasePacket(packet);
  125. }
  126. });
  127. registerPacketProcessor(ClusterOperation.REMOTELY_PROCESS_AND_RESPOND,
  128. new PacketProcessor() {
  129. public void process(Packet packet) {
  130. Data data = packet.getValueData();
  131. RemotelyProcessable rp = (RemotelyProcessable) toObject(data);
  132. rp.setConnection(packet.conn);
  133. rp.setNode(node);
  134. rp.process();
  135. sendResponse(packet);
  136. }
  137. });
  138. registerPacketProcessor(ClusterOperation.REMOTELY_PROCESS,
  139. new PacketProcessor() {
  140. public void process(Packet packet) {
  141. Data data = packet.getValueData();
  142. RemotelyProcessable rp = (RemotelyProcessable) toObject(data);
  143. rp.setConnection(packet.conn);
  144. rp.setNode(node);
  145. rp.process();
  146. releasePacket(packet);
  147. }
  148. });
  149. registerPacketProcessor(ClusterOperation.REMOTELY_CALLABLE_BOOLEAN,
  150. new PacketProcessor() {
  151. public void process(Packet packet) {
  152. Boolean result;
  153. AbstractRemotelyCallable<Boolean> callable = null;
  154. try {
  155. Data data = packet.getValueData();
  156. callable = (AbstractRemotelyCallable<Boolean>) toObject(data);
  157. callable.setConnection(packet.conn);
  158. callable.setNode(node);
  159. result = callable.call();
  160. } catch (Exception e) {
  161. logger.log(Level.SEVERE, "Error processing " + callable, e);
  162. result = Boolean.FALSE;
  163. }
  164. if (result == Boolean.TRUE) {
  165. sendResponse(packet);
  166. } else {
  167. sendResponseFailure(packet);
  168. }
  169. }
  170. });
  171. registerPacketProcessor(ClusterOperation.REMOTELY_CALLABLE_OBJECT,
  172. new PacketProcessor() {
  173. public void process(Packet packet) {
  174. Object result;
  175. AbstractRemotelyCallable<Boolean> callable = null;
  176. try {
  177. Data data = packet.getValueData();
  178. callable = (AbstractRemotelyCallable) toObject(data);
  179. callable.setConnection(packet.conn);
  180. callable.setNode(node);
  181. result = callable.call();
  182. } catch (Exception e) {
  183. logger.log(Level.SEVERE, "Error processing " + callable, e);
  184. result = null;
  185. }
  186. if (result != null) {
  187. Data value;
  188. if (result instanceof Data) {
  189. value = (Data) result;
  190. } else {
  191. value = toData(result);
  192. }
  193. packet.setValue(value);
  194. }
  195. sendResponse(packet);
  196. }
  197. });
  198. }
  199. private void registerPeriodicProcessable(final Processable p, long delay, long period) {
  200. delay = delay < 0 ? 0 : delay;
  201. period = period <= 0 ? 1: period;
  202. node.executorManager.getScheduledExecutorService().scheduleAtFixedRate(new Runnable() {
  203. public void run() {
  204. node.clusterService.enqueuePriorityAndReturn(p);
  205. }
  206. }, delay, period, TimeUnit.MILLISECONDS);
  207. }
  208. public boolean shouldTryMerge() {
  209. return !joinInProgress && setJoins.size() == 0;
  210. }
  211. public JoinInfo checkJoin(Connection conn) {
  212. return new JoinCall(conn).checkJoin();
  213. }
  214. public void appendState(StringBuffer sbState) {
  215. sbState.append("\nClusterManager {");
  216. for (ScheduledAction sa : setScheduledActions) {
  217. sbState.append("\n\t" + sa + ", from:" + sa.getRequest().caller);
  218. }
  219. sbState.append("\n}");
  220. }
  221. class JoinCall extends ConnectionAwareOp {
  222. JoinCall(Connection target) {
  223. super(target);
  224. }
  225. JoinInfo checkJoin() {
  226. setLocal(ClusterOperation.JOIN_CHECK, "join", null, node.createJoinInfo(), -1, 0);
  227. doOp();
  228. return (JoinInfo) getResultAsObject();
  229. }
  230. }
  231. void logMissingConnection(Address address) {
  232. String msg = thisMember + " has no connection to " + address;
  233. logAtMaster(Level.WARNING, msg);
  234. logger.log(Level.WARNING, msg);
  235. }
  236. public void logAtMaster(Level level, String msg) {
  237. Address master = getMasterAddress();
  238. if (!isMaster() && master != null) {
  239. Connection connMaster = node.connectionManager.getOrConnect(getMasterAddress());
  240. if (connMaster != null) {
  241. Packet packet = obtainPacket(level.toString(), null, toData(msg), ClusterOperation.LOG, 0);
  242. sendOrReleasePacket(packet, connMaster);
  243. }
  244. } else {
  245. logger.log(level, msg);
  246. }
  247. }
  248. public final void heartBeater() {
  249. if (!node.joined() || !node.isActive()) return;
  250. long now = Clock.currentTimeMillis();
  251. if (isMaster()) {
  252. List<Address> lsDeadAddresses = null;
  253. for (MemberImpl memberImpl : lsMembers) {
  254. final Address address = memberImpl.getAddress();
  255. if (!thisAddress.equals(address)) {
  256. try {
  257. Connection conn = node.connectionManager.getOrConnect(address);
  258. if (conn != null && conn.live()) {
  259. if ((now - memberImpl.getLastRead()) >= (MAX_NO_HEARTBEAT_MILLIS)) {
  260. conn = null;
  261. if (lsDeadAddresses == null) {
  262. lsDeadAddresses = new ArrayList<Address>();
  263. }
  264. logger.log(Level.WARNING, "Added " + address
  265. + " to list of dead addresses because of timeout since last read");
  266. lsDeadAddresses.add(address);
  267. } else if ((now - memberImpl.getLastRead()) >= 5000 && (now - memberImpl.getLastPing()) >= 5000) {
  268. ping(memberImpl);
  269. }
  270. if ((now - memberImpl.getLastWrite()) > 500) {
  271. sendHeartbeat(conn);
  272. }
  273. Long lastConfirmation = memberMasterConfirmationTimes.get(memberImpl);
  274. if (lastConfirmation == null || (now - lastConfirmation > MAX_NO_MASTER_CONFIRMATION_MILLIS)) {
  275. if (lsDeadAddresses == null) {
  276. lsDeadAddresses = new ArrayList<Address>();
  277. }
  278. logger.log(Level.WARNING, "Added " + address
  279. + " to list of dead addresses because it has not sent a master confirmation recently");
  280. lsDeadAddresses.add(address);
  281. }
  282. } else if (conn == null && (now - memberImpl.getLastRead()) > 5000) {
  283. logMissingConnection(address);
  284. memberImpl.didRead();
  285. }
  286. } catch (Exception e) {
  287. logger.log(Level.SEVERE, e.getMessage(), e);
  288. }
  289. }
  290. }
  291. if (lsDeadAddresses != null) {
  292. for (Address address : lsDeadAddresses) {
  293. logger.log(Level.FINEST, "No heartbeat should remove " + address);
  294. doRemoveAddress(address);
  295. }
  296. }
  297. } else {
  298. // send heartbeat to master
  299. Address masterAddress = getMasterAddress();
  300. if (masterAddress != null) {
  301. final Connection connMaster = node.connectionManager.getOrConnect(masterAddress);
  302. MemberImpl masterMember = getMember(masterAddress);
  303. boolean removed = false;
  304. if (masterMember != null) {
  305. if ((now - masterMember.getLastRead()) >= (MAX_NO_HEARTBEAT_MILLIS)) {
  306. logger.log(Level.WARNING, "Master node has timed out its heartbeat and will be removed");
  307. doRemoveAddress(masterAddress);
  308. removed = true;
  309. } else if ((now - masterMember.getLastRead()) >= 5000 && (now - masterMember.getLastPing()) >= 5000) {
  310. ping(masterMember);
  311. }
  312. }
  313. if (!removed) {
  314. sendHeartbeat(connMaster);
  315. }
  316. }
  317. for (MemberImpl member : lsMembers) {
  318. if (!member.localMember()) {
  319. Address address = member.getAddress();
  320. Connection conn = node.connectionManager.getOrConnect(address);
  321. if (conn != null) {
  322. sendHeartbeat(conn);
  323. } else {
  324. logger.log(Level.FINEST, "Could not connect to " + address + " to send heartbeat");
  325. }
  326. }
  327. }
  328. }
  329. }
  330. private void sendMasterConfirmation() {
  331. if (!node.joined() || !node.isActive() || isMaster()) {
  332. return;
  333. }
  334. final Address masterAddress = getMasterAddress();
  335. if (masterAddress == null) {
  336. logger.log(Level.FINEST, "Could not send MasterConfirmation, master is null!");
  337. return;
  338. }
  339. final MemberImpl masterMember = getMember(masterAddress);
  340. if (masterMember == null) {
  341. logger.log(Level.FINEST, "Could not send MasterConfirmation, master is null!");
  342. return;
  343. }
  344. if (logger.isLoggable(Level.FINEST)) {
  345. logger.log(Level.FINEST, "Sending MasterConfirmation to " + masterMember);
  346. }
  347. sendProcessableTo(new MasterConfirmation(), masterAddress);
  348. }
  349. public static class MasterConfirmation extends AbstractRemotelyProcessable {
  350. public void process() {
  351. final Address endPoint = conn.getEndPoint();
  352. if (endPoint == null) {
  353. return;
  354. }
  355. final ILogger logger = node.getLogger(MasterConfirmation.class.getName());
  356. final ClusterManager clusterManager = node.clusterManager;
  357. final MemberImpl member = clusterManager.getMember(endPoint);
  358. if (member != null) {
  359. if (getNode().isMaster()) {
  360. if (logger.isLoggable(Level.FINEST)) {
  361. logger.log(Level.FINEST, "MasterConfirmation has been received from " + member);
  362. }
  363. clusterManager.memberMasterConfirmationTimes.put(member, Clock.currentTimeMillis());
  364. } else {
  365. logger.log(Level.WARNING, endPoint + " has sent MasterConfirmation, but this node is not master!");
  366. }
  367. } else {
  368. logger.log(Level.WARNING, "MasterConfirmation has been received from " + endPoint
  369. + ", but it is not a member of this cluster!");
  370. clusterManager.sendProcessableTo(new MemberRemover(clusterManager.thisAddress), conn);
  371. }
  372. }
  373. }
  374. private void ping(final MemberImpl memberImpl) {
  375. memberImpl.didPing();
  376. if (!ICMP_ENABLED) return;
  377. node.executorManager.executeNow(new Runnable() {
  378. public void run() {
  379. try {
  380. final Address address = memberImpl.getAddress();
  381. logger.log(Level.WARNING, thisAddress + " will ping " + address);
  382. for (int i = 0; i < 5; i++) {
  383. try {
  384. if (address.getInetAddress().isReachable(null, ICMP_TTL, ICMP_TIMEOUT)) {
  385. logger.log(Level.INFO, thisAddress + " pings successfully. Target: " + address);
  386. return;
  387. }
  388. } catch (ConnectException ignored) {
  389. // no route to host
  390. // means we cannot connect anymore
  391. }
  392. }
  393. logger.log(Level.WARNING, thisAddress + " couldn't ping " + address);
  394. // not reachable.
  395. enqueueAndReturn(new Processable() {
  396. public void process() {
  397. doRemoveAddress(address);
  398. }
  399. });
  400. } catch (Throwable ignored) {
  401. }
  402. }
  403. });
  404. }
  405. void sendHeartbeat(Connection conn) {
  406. if (conn == null) return;
  407. Packet packet = obtainPacket("heartbeat", null, null, ClusterOperation.HEARTBEAT, 0);
  408. sendOrReleasePacket(packet, conn);
  409. }
  410. private void sendRemoveMemberToOthers(final Address deadAddress) {
  411. for (MemberImpl member : lsMembers) {
  412. Address address = member.getAddress();
  413. if (!thisAddress.equals(address) && !address.equals(deadAddress)) {
  414. sendProcessableTo(new MemberRemover(deadAddress), address);
  415. }
  416. }
  417. }
  418. // Will be called just before this node becomes the master
  419. private void resetMemberMasterConfirmations() {
  420. checkServiceThread();
  421. for (MemberImpl member : lsMembers) {
  422. memberMasterConfirmationTimes.put(member, Clock.currentTimeMillis());
  423. }
  424. }
  425. private void sendMemberListToOthers() {
  426. checkServiceThread();
  427. if (!isMaster()) {
  428. return;
  429. }
  430. sendProcessableToAll(new MembersUpdateCall(lsMembers, node.getClusterImpl().getClusterTime()), false);
  431. }
  432. public void sendClusterMergeToOthers(final Address newTargetAddress) {
  433. sendProcessableToAll(new MergeClusters(newTargetAddress), false);
  434. }
  435. public void handleMaster(Master master) {
  436. if (!node.joined() && !thisAddress.equals(master.address)) {
  437. logger.log(Level.FINEST, "Handling master response: " + master);
  438. final Address currentMaster = node.getMasterAddress();
  439. if (currentMaster != null && !currentMaster.equals(master.address)) {
  440. final Connection conn = node.connectionManager.getConnection(currentMaster);
  441. if (conn != null && conn.live()) {
  442. logger.log(Level.FINEST, "Ignoring master response " + master +
  443. " since node has an active master: " + currentMaster);
  444. return;
  445. }
  446. }
  447. node.setMasterAddress(master.address);
  448. node.connectionManager.getOrConnect(master.address);
  449. if (!sendJoinRequest(master.address, true)) {
  450. logger.log(Level.WARNING, "Could not create connection to possible master " + master.address);
  451. }
  452. }
  453. }
  454. public void handleAddRemoveConnection(final AddOrRemoveConnection connection) {
  455. if (connection.add) { // Just connect to the new address if not connected already.
  456. if (!connection.address.equals(thisAddress)) {
  457. node.connectionManager.getOrConnect(connection.address);
  458. }
  459. } else { // Remove dead member
  460. if (connection.address != null) {
  461. logger.log(Level.FINEST, "Disconnected from " + connection.address + "... will be removed!");
  462. doRemoveAddress(connection.address);
  463. }
  464. } // end of REMOVE CONNECTION
  465. }
  466. void doRemoveAddress(Address deadAddress) {
  467. doRemoveAddress(deadAddress, true);
  468. }
  469. void doRemoveAddress(Address deadAddress, boolean destroyConnection) {
  470. checkServiceThread();
  471. logger.log(Level.INFO, "Removing Address " + deadAddress);
  472. if (!node.joined()) {
  473. node.failedConnection(deadAddress);
  474. return;
  475. }
  476. if (deadAddress.equals(thisAddress))
  477. return;
  478. if (deadAddress.equals(getMasterAddress())) {
  479. if (node.joined()) {
  480. MemberImpl newMaster = getNextMemberAfter(deadAddress, false, 1);
  481. if (newMaster != null)
  482. node.setMasterAddress(newMaster.getAddress());
  483. else
  484. node.setMasterAddress(null);
  485. } else {
  486. node.setMasterAddress(null);
  487. }
  488. logger.log(Level.FINEST, "Now Master " + node.getMasterAddress());
  489. }
  490. if (isMaster()) {
  491. setJoins.remove(new MemberInfo(deadAddress));
  492. resetMemberMasterConfirmations();
  493. }
  494. final Connection conn = node.connectionManager.getConnection(deadAddress);
  495. if (destroyConnection && conn != null) {
  496. node.connectionManager.destroyConnection(conn);
  497. }
  498. MemberImpl deadMember = getMember(deadAddress);
  499. if (deadMember != null) {
  500. removeMember(deadMember);
  501. node.getClusterImpl().setMembers(lsMembers);
  502. node.concurrentMapManager.syncForDead(deadMember);
  503. node.blockingQueueManager.syncForDead(deadAddress);
  504. node.listenerManager.syncForDead(deadAddress);
  505. node.topicManager.syncForDead(deadAddress);
  506. // node.getClusterImpl().setMembers(lsMembers); // shifted up to get members in syncForDead methods
  507. disconnectExistingCalls(deadAddress);
  508. if (isMaster()) {
  509. logger.log(Level.FINEST, deadAddress + " is dead. Sending remove to all other members.");
  510. sendRemoveMemberToOthers(deadAddress);
  511. }
  512. logger.log(Level.INFO, this.toString());
  513. }
  514. }
  515. public void disconnectExistingCalls(Address deadAddress) {
  516. Object[] calls = mapCalls.values().toArray();
  517. for (Object call : calls) {
  518. ((Call) call).onDisconnect(deadAddress);
  519. }
  520. }
  521. void handleJoinRequest(JoinRequest joinRequest) {
  522. final long now = Clock.currentTimeMillis();
  523. String msg = "Handling join from " + joinRequest.address + ", inProgress: " + joinInProgress
  524. + (timeToStartJoin > 0 ? ", timeToStart: " + (timeToStartJoin - now) : "");
  525. logger.log(Level.FINEST, msg);
  526. boolean validJoinRequest;
  527. try {
  528. validJoinRequest = node.validateJoinRequest(joinRequest);
  529. } catch (Exception e) {
  530. validJoinRequest = false;
  531. }
  532. final Connection conn = joinRequest.getConnection();
  533. if (validJoinRequest) {
  534. final MemberImpl member = getMember(joinRequest.address);
  535. if (member != null) {
  536. if (joinRequest.getUuid().equals(member.getUuid())) {
  537. String message = "Ignoring join request, member already exists.. => " + joinRequest;
  538. logger.log(Level.FINEST, message);
  539. // send members update back to node trying to join again...
  540. final long clusterTime = node.getClusterImpl().getClusterTime();
  541. sendProcessableTo(new MembersUpdateCall(lsMembers, clusterTime), conn);
  542. sendProcessableTo(new SyncProcess(), conn);
  543. return;
  544. }
  545. // If this node is master then remove old member and process join request.
  546. // If requesting address is equal to master node's address, that means master node
  547. // somehow disconnected and wants to join back.
  548. // So drop old member and process join request if this node becomes master.
  549. if (isMaster() || member.getAddress().equals(getMasterAddress())) {
  550. logger.log(Level.WARNING, "New join request has been received from an existing endpoint! => " + member
  551. + " Removing old member and processing join request...");
  552. // If existing connection of endpoint is different from current connection
  553. // destroy it, otherwise keep it.
  554. // final Connection existingConnection = node.connectionManager.getConnection(joinRequest.address);
  555. // final boolean destroyExistingConnection = existingConnection != conn;
  556. doRemoveAddress(member.getAddress(), false);
  557. }
  558. }
  559. if (!node.getConfig().getNetworkConfig().getJoin().getMulticastConfig().isEnabled()) {
  560. if (node.isActive() && node.joined() && node.getMasterAddress() != null && !isMaster()) {
  561. sendProcessableTo(new Master(node.getMasterAddress()), conn);
  562. }
  563. }
  564. if (isMaster() && node.joined() && node.isActive()) {
  565. final MemberInfo newMemberInfo = new MemberInfo(joinRequest.address, joinRequest.nodeType, joinRequest.getUuid());
  566. if (node.securityContext != null && !setJoins.contains(newMemberInfo)) {
  567. final ILogger securityLogger = node.loggingService.getLogger("com.hazelcast.security");
  568. final Credentials cr = joinRequest.getCredentials();
  569. if (cr == null) {
  570. securityLogger.log(Level.SEVERE, "Expecting security credentials " +
  571. "but credentials could not be found in JoinRequest!");
  572. sendAuthFail(conn);
  573. return;
  574. } else {
  575. try {
  576. LoginContext lc = node.securityContext.createMemberLoginContext(cr);
  577. lc.login();
  578. } catch (LoginException e) {
  579. securityLogger.log(Level.SEVERE, "Authentication has failed for " + cr.getPrincipal()
  580. + '@' + cr.getEndpoint() + " => (" + e.getMessage() + ")");
  581. securityLogger.log(Level.FINEST, e.getMessage(), e);
  582. sendAuthFail(conn);
  583. return;
  584. }
  585. }
  586. }
  587. if (joinRequest.to != null && !joinRequest.to.equals(thisAddress)) {
  588. sendProcessableTo(new Master(node.getMasterAddress()), conn);
  589. return;
  590. }
  591. if (!joinInProgress) {
  592. if (firstJoinRequest != 0 && now - firstJoinRequest >= MAX_WAIT_SECONDS_BEFORE_JOIN * 1000) {
  593. startJoin();
  594. } else {
  595. if (setJoins.add(newMemberInfo)) {
  596. sendProcessableTo(new Master(node.getMasterAddress()), conn);
  597. if (firstJoinRequest == 0) {
  598. firstJoinRequest = now;
  599. }
  600. if (now - firstJoinRequest < MAX_WAIT_SECONDS_BEFORE_JOIN * 1000) {
  601. timeToStartJoin = now + WAIT_MILLIS_BEFORE_JOIN;
  602. }
  603. }
  604. if (now > timeToStartJoin) {
  605. startJoin();
  606. }
  607. }
  608. }
  609. }
  610. } else {
  611. conn.close();
  612. }
  613. }
  614. public static class AuthenticationFailureProcessable extends AbstractRemotelyProcessable implements RemotelyProcessable {
  615. public void process() {
  616. node.executorManager.executeNow(new Runnable() {
  617. public void run() {
  618. final ILogger logger = node.loggingService.getLogger("com.hazelcast.security");
  619. logger.log(Level.SEVERE, "Authentication failed on master node! Node is going to shutdown now!");
  620. node.shutdown(true, true);
  621. }
  622. });
  623. }
  624. }
  625. private void sendAuthFail(Connection conn) {
  626. sendProcessableTo(new AuthenticationFailureProcessable(), conn);
  627. }
  628. @Override
  629. public String toString() {
  630. StringBuilder sb = new StringBuilder("\n\nMembers [");
  631. sb.append(lsMembers.size());
  632. sb.append("] {");
  633. for (MemberImpl member : lsMembers) {
  634. sb.append("\n\t").append(member);
  635. }
  636. sb.append("\n}\n");
  637. return sb.toString();
  638. }
  639. void joinReset() {
  640. joinInProgress = false;
  641. setJoins.clear();
  642. timeToStartJoin = Clock.currentTimeMillis() + WAIT_MILLIS_BEFORE_JOIN;
  643. firstJoinRequest = 0;
  644. }
  645. public void onRestart() {
  646. enqueueAndWait(new Processable() {
  647. public void process() {
  648. joinReset();
  649. lsMembers.clear();
  650. mapMembers.clear();
  651. dataMemberCount.reset();
  652. memberMasterConfirmationTimes.clear();
  653. }
  654. }, 5);
  655. }
  656. public boolean checkAuthorization(String groupName, String groupPassword, Address target) {
  657. AbstractRemotelyCallable<Boolean> authorizationCall = new AuthorizationCall(groupName, groupPassword);
  658. AsyncRemotelyBooleanOp op = new NoneMemberAsyncRemotelyBooleanOp(authorizationCall, target, true);
  659. op.execute();
  660. return op.getResultAsBoolean();
  661. }
  662. public class NoneMemberAsyncRemotelyBooleanOp extends AsyncRemotelyBooleanOp {
  663. public NoneMemberAsyncRemotelyBooleanOp(final AbstractRemotelyCallable<Boolean> arp,
  664. final Address target, final boolean canTimeout) {
  665. super(arp, target, canTimeout);
  666. }
  667. @Override
  668. protected boolean memberOnly() {
  669. return false;
  670. }
  671. }
  672. public class AsyncRemotelyBooleanOp extends TargetAwareOp {
  673. private final AbstractRemotelyCallable<Boolean> arp;
  674. private final boolean canTimeout;
  675. public AsyncRemotelyBooleanOp(final AbstractRemotelyCallable<Boolean> arp,
  676. final Address target, final boolean canTimeout) {
  677. this.arp = arp;
  678. this.target = target;
  679. this.canTimeout = canTimeout;
  680. }
  681. public void execute() {
  682. arp.setNode(node);
  683. setLocal(ClusterOperation.REMOTELY_CALLABLE_BOOLEAN, "call", null, arp, 0, -1);
  684. request.setBooleanRequest();
  685. doOp();
  686. }
  687. @Override
  688. public Address getTarget() {
  689. return target;
  690. }
  691. @Override
  692. public void onDisconnect(final Address dead) {
  693. if (dead.equals(target)) {
  694. removeRemoteCall(getCallId());
  695. setResult(Boolean.FALSE);
  696. }
  697. }
  698. @Override
  699. public void doLocalOp() {
  700. Boolean result;
  701. try {
  702. result = arp.call();
  703. setResult(result);
  704. } catch (Exception e) {
  705. logger.log(Level.FINEST, e.getMessage(), e);
  706. }
  707. }
  708. @Override
  709. public void setTarget() {
  710. }
  711. @Override
  712. public void redo(int redoTypeCode) {
  713. removeRemoteCall(getCallId());
  714. setResult(Boolean.FALSE);
  715. }
  716. @Override
  717. protected void memberDoesNotExist() {
  718. setResult(Boolean.FALSE);
  719. }
  720. @Override
  721. protected void packetNotSent() {
  722. setResult(Boolean.FALSE);
  723. }
  724. @Override
  725. protected final boolean canTimeout() {
  726. return canTimeout;
  727. }
  728. }
  729. public void finalizeJoin() {
  730. Set<Member> members = node.getClusterImpl().getMembers();
  731. List<AsyncRemotelyBooleanOp> calls = new ArrayList<AsyncRemotelyBooleanOp>();
  732. for (Member m : members) {
  733. MemberImpl member = (MemberImpl) m;
  734. if (!member.localMember()) {
  735. AsyncRemotelyBooleanOp op = new AsyncRemotelyBooleanOp(
  736. new FinalizeJoin(), member.getAddress(), false);
  737. op.execute();
  738. calls.add(op);
  739. }
  740. }
  741. for (AsyncRemotelyBooleanOp call : calls) {
  742. call.getResultAsBoolean();
  743. }
  744. }
  745. class JoinRunnable extends FallThroughRunnable implements Prioritized {
  746. final MembersUpdateCall membersUpdate;
  747. JoinRunnable(MembersUpdateCall membersUpdate) {
  748. this.membersUpdate = membersUpdate;
  749. }
  750. @Override
  751. public void doRun() {
  752. Collection<MemberInfo> lsMemberInfos = membersUpdate.getMemberInfos();
  753. List<Address> newMemberList = new ArrayList<Address>(lsMemberInfos.size());
  754. for (final MemberInfo memberInfo : lsMemberInfos) {
  755. newMemberList.add(memberInfo.address);
  756. }
  757. doCall(membersUpdate, newMemberList, true);
  758. systemLogService.logJoin("JoinRunnable update members done.");
  759. doCall(new SyncProcess(), newMemberList, false);
  760. systemLogService.logJoin("JoinRunnable sync done.");
  761. doCall(new ConnectionCheckCall(), newMemberList, false);
  762. systemLogService.logJoin("JoinRunnable connection check done.");
  763. }
  764. void doCall(AbstractRemotelyCallable callable, List<Address> targets, boolean ignoreThis) {
  765. List<AsyncRemotelyBooleanOp> calls = new ArrayList<AsyncRemotelyBooleanOp>(targets.size());
  766. for (final Address target : targets) {
  767. boolean skip = ignoreThis && thisAddress.equals(target);
  768. if (!skip) {
  769. AsyncRemotelyBooleanOp op = new AsyncRemotelyBooleanOp(callable, target, false);
  770. op.execute();
  771. calls.add(op);
  772. }
  773. }
  774. for (AsyncRemotelyBooleanOp call : calls) {
  775. if (!call.getResultAsBoolean(5)) {
  776. targets.remove(call.getTarget());
  777. }
  778. }
  779. }
  780. }
  781. void startJoin() {
  782. logger.log(Level.FINEST, "Starting Join.");
  783. joinInProgress = true;
  784. final MembersUpdateCall membersUpdate = new MembersUpdateCall(lsMembers, node.getClusterImpl().getClusterTime());
  785. if (setJoins != null && setJoins.size() > 0) {
  786. for (MemberInfo memberJoined : setJoins) {
  787. membersUpdate.addMemberInfo(memberJoined);
  788. }
  789. }
  790. membersUpdate.setNode(node);
  791. membersUpdate.call();
  792. node.executorManager.executeNow(new JoinRunnable(membersUpdate));
  793. }
  794. void updateMembers(Collection<MemberInfo> lsMemberInfos) {
  795. checkServiceThread();
  796. final Map<Address, MemberImpl> mapOldMembers = new HashMap<Address, MemberImpl>();
  797. for (MemberImpl member : lsMembers) {
  798. mapOldMembers.put(member.getAddress(), member);
  799. }
  800. if (mapOldMembers.size() == lsMemberInfos.size()) {
  801. boolean same = true;
  802. for (MemberInfo memberInfo : lsMemberInfos) {
  803. MemberImpl member = mapOldMembers.get(memberInfo.getAddress());
  804. if (member == null || !member.getUuid().equals(memberInfo.uuid)) {
  805. same = false;
  806. break;
  807. }
  808. }
  809. if (same) {
  810. logger.log(Level.FINEST, "No need to process member update...");
  811. return;
  812. }
  813. }
  814. logger.log(Level.FINEST, "Updating Members");
  815. lsMembers.clear();
  816. dataMemberCount.reset();
  817. mapMembers.clear();
  818. memberMasterConfirmationTimes.clear();
  819. for (MemberInfo memberInfo : lsMemberInfos) {
  820. MemberImpl member = mapOldMembers.get(memberInfo.address);
  821. if (member == null) {
  822. member = addMember(memberInfo.address, memberInfo.nodeType, memberInfo.uuid);
  823. } else {
  824. addMember(member);
  825. }
  826. member.didRead();
  827. }
  828. if (!lsMembers.contains(thisMember)) {
  829. throw new RuntimeException("Member list doesn't contain local member!");
  830. }
  831. heartBeater();
  832. node.getClusterImpl().setMembers(lsMembers);
  833. node.setJoined();
  834. logger.log(Level.INFO, this.toString());
  835. }
  836. public boolean sendJoinRequest(Address toAddress, boolean withCredentials) {
  837. if (toAddress == null) {
  838. toAddress = node.getMasterAddress();
  839. }
  840. logger.log(Level.FINEST, "Sending join request to " + toAddress);
  841. final boolean send = sendProcessableTo(node.createJoinInfo(withCredentials), toAddress);
  842. if (!send) {
  843. logger.log(Level.WARNING, "Could not send join request to " + toAddress);
  844. }
  845. return send;
  846. }
  847. public void registerScheduledAction(ScheduledAction scheduledAction) {
  848. setScheduledActions.add(scheduledAction);
  849. }
  850. public void deregisterScheduledAction(ScheduledAction scheduledAction) {
  851. setScheduledActions.remove(scheduledAction);
  852. }
  853. public void checkScheduledActions() {
  854. if (!node.joined() || !node.isActive()) return;
  855. if (setScheduledActions.size() > 0) {
  856. Iterator<ScheduledAction> it = setScheduledActions.iterator();
  857. while (it.hasNext()) {
  858. ScheduledAction sa = it.next();
  859. if (sa.expired() && sa.isValid()) {
  860. sa.onExpire();
  861. it.remove();
  862. } else if (!sa.isValid()) {
  863. it.remove();
  864. }
  865. }
  866. }
  867. }
  868. public void invalidateScheduledActionsFor(Address endpoint, Set<Integer> threadIds) {
  869. if (!node.joined() || !node.isActive()) return;
  870. if (setScheduledActions.size() > 0) {
  871. Iterator<ScheduledAction> it = setScheduledActions.iterator();
  872. while (it.hasNext()) {
  873. ScheduledAction sa = it.next();
  874. Request request = sa.getRequest();
  875. if (endpoint.equals(request.caller) && threadIds.contains(request.lockThreadId)) {
  876. sa.setValid(false);
  877. it.remove();
  878. }
  879. }
  880. }
  881. }
  882. public void connectionAdded(final Connection connection) {
  883. enqueueAndReturn(new Processable() {
  884. public void process() {
  885. MemberImpl member = getMember(connection.getEndPoint());
  886. if (member != null) {
  887. member.didRead();
  888. }
  889. }
  890. });
  891. }
  892. public void connectionRemoved(Connection connection) {
  893. logger.log(Level.FINEST, "Connection is removed " + connection.getEndPoint());
  894. if (!node.joined()) {
  895. if (getMasterAddress() != null) {
  896. if (getMasterAddress().equals(connection.getEndPoint())) {
  897. node.setMasterAddress(null);
  898. }
  899. }
  900. }
  901. }
  902. public Member addMember(MemberImpl member) {
  903. return addMember(true, member);
  904. }
  905. public Member addMember(boolean checkServiceThread, MemberImpl member) {
  906. if (checkServiceThread) {
  907. checkServiceThread();
  908. }
  909. logger.log(Level.FINEST, "ClusterManager adding " + member);
  910. if (lsMembers.contains(member)) {
  911. for (MemberImpl m : lsMembers) {
  912. if (m.equals(member)) {
  913. member = m;
  914. }
  915. }
  916. mapMembers.put(member.getAddress(), member);
  917. } else {
  918. lsMembers.add(member);
  919. mapMembers.put(member.getAddress(), member);
  920. if (!member.isLiteMember()) {
  921. dataMemberCount.increment();
  922. }
  923. }
  924. memberMasterConfirmationTimes.put(member, Clock.currentTimeMillis());
  925. return member;
  926. }
  927. public void removeMember(MemberImpl member) {
  928. checkServiceThread();
  929. logger.log(Level.FINEST, "ClusterManager removing " + member);
  930. mapMembers.remove(member.getAddress());
  931. lsMembers.remove(member);
  932. memberMasterConfirmationTimes.remove(member);
  933. if (!member.isLiteMember()) {
  934. dataMemberCount.decrement();
  935. }
  936. }
  937. protected MemberImpl createMember(Address address, NodeType nodeType, String nodeUuid, String ipV6ScopeId) {
  938. address.setScopeId(ipV6ScopeId);
  939. return new MemberImpl(address, thisAddress.equals(address), nodeType, nodeUuid);
  940. }
  941. public MemberImpl getMember(Address address) {
  942. if (address == null) {
  943. return null;
  944. }
  945. return mapMembers.get(address);
  946. }
  947. final public MemberImpl addMember(Address address, NodeType nodeType, String nodeUuid) {
  948. checkServiceThread();
  949. if (address == null) {
  950. logger.log(Level.FINEST, "Address cannot be null");
  951. return null;
  952. }
  953. MemberImpl member = getMember(address);
  954. if (member == null) {
  955. member = createMember(address, nodeType, nodeUuid, thisAddress.getScopeId());
  956. }
  957. addMember(member);
  958. return member;
  959. }
  960. public void stop() {
  961. if (setJoins != null) {
  962. setJoins.clear();
  963. }
  964. timeToStartJoin = 0;
  965. if (lsMembers != null) {
  966. lsMembers.clear();
  967. }
  968. dataMemberCount.reset();
  969. if (mapMembers != null) {
  970. mapMembers.clear();
  971. }
  972. if (mapCalls != null) {
  973. mapCalls.clear();
  974. }
  975. if (memberMasterConfirmationTimes != null) {
  976. memberMasterConfirmationTimes.clear();
  977. }
  978. }
  979. }