PageRenderTime 40ms CodeModel.GetById 10ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

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