/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.cache.client.internal.locator.wan; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.distributed.internal.tcpserver.TcpClient; import org.apache.geode.internal.CopyOnWriteHashSet; import org.apache.geode.internal.admin.remote.DistributionLocatorId; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; import org.apache.geode.internal.logging.log4j.LocalizedMessage; import org.apache.logging.log4j.Logger; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * An implementation of * {@link org.apache.geode.cache.client.internal.locator.wan.LocatorMembershipListener} * * */ public class LocatorMembershipListenerImpl implements LocatorMembershipListener { private ConcurrentMap<Integer, Set<DistributionLocatorId>> allLocatorsInfo = new ConcurrentHashMap<Integer, Set<DistributionLocatorId>>(); private ConcurrentMap<Integer, Set<String>> allServerLocatorsInfo = new ConcurrentHashMap<Integer, Set<String>>(); private static final Logger logger = LogService.getLogger(); private DistributionConfig config; private TcpClient tcpClient; private int port; public LocatorMembershipListenerImpl() { this.tcpClient = new TcpClient(); } public void setPort(int port) { this.port = port; } public void setConfig(DistributionConfig config) { this.config = config; } /** * When the new locator is added to remote locator metadata, inform all other locators in remote * locator metadata about the new locator so that they can update their remote locator metadata. * * @param locator */ public void locatorJoined(final int distributedSystemId, final DistributionLocatorId locator, final DistributionLocatorId sourceLocator) { Thread distributeLocator = new Thread(new Runnable() { public void run() { ConcurrentMap<Integer, Set<DistributionLocatorId>> remoteLocators = getAllLocatorsInfo(); ArrayList<DistributionLocatorId> locatorsToRemove = new ArrayList<DistributionLocatorId>(); String localLocator = config.getStartLocator(); DistributionLocatorId localLocatorId = null; if (localLocator.equals(DistributionConfig.DEFAULT_START_LOCATOR)) { localLocatorId = new DistributionLocatorId(port, config.getBindAddress()); } else { localLocatorId = new DistributionLocatorId(localLocator); } locatorsToRemove.add(localLocatorId); locatorsToRemove.add(locator); locatorsToRemove.add(sourceLocator); Map<Integer, Set<DistributionLocatorId>> localCopy = new HashMap<Integer, Set<DistributionLocatorId>>(); for (Map.Entry<Integer, Set<DistributionLocatorId>> entry : remoteLocators.entrySet()) { Set<DistributionLocatorId> value = new CopyOnWriteHashSet<DistributionLocatorId>(entry.getValue()); localCopy.put(entry.getKey(), value); } for (Map.Entry<Integer, Set<DistributionLocatorId>> entry : localCopy.entrySet()) { for (DistributionLocatorId removeLocId : locatorsToRemove) { if (entry.getValue().contains(removeLocId)) { entry.getValue().remove(removeLocId); } } for (DistributionLocatorId value : entry.getValue()) { try { tcpClient.requestToServer(value.getHost(), value.getPort(), new LocatorJoinMessage(distributedSystemId, locator, localLocatorId, ""), 1000, false); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug(LocalizedMessage.create( LocalizedStrings.LOCATOR_MEMBERSHIP_LISTENER_COULD_NOT_EXCHANGE_LOCATOR_INFORMATION_0_1_WIHT_2_3, new Object[] {locator.getHost(), locator.getPort(), value.getHost(), value.getPort()})); } } try { tcpClient.requestToServer(locator.getHost(), locator.getPort(), new LocatorJoinMessage(entry.getKey(), value, localLocatorId, ""), 1000, false); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug(LocalizedMessage.create( LocalizedStrings.LOCATOR_MEMBERSHIP_LISTENER_COULD_NOT_EXCHANGE_LOCATOR_INFORMATION_0_1_WIHT_2_3, new Object[] {value.getHost(), value.getPort(), locator.getHost(), locator.getPort()})); } } } } } }); distributeLocator.setDaemon(true); distributeLocator.start(); } public Object handleRequest(Object request) { Object response = null; if (request instanceof RemoteLocatorJoinRequest) { response = updateAllLocatorInfo((RemoteLocatorJoinRequest) request); } else if (request instanceof LocatorJoinMessage) { response = informAboutRemoteLocators((LocatorJoinMessage) request); } else if (request instanceof RemoteLocatorPingRequest) { response = getPingResponse((RemoteLocatorPingRequest) request); } else if (request instanceof RemoteLocatorRequest) { response = getRemoteLocators((RemoteLocatorRequest) request); } return response; } /** * A locator from the request is checked against the existing remote locator metadata. If it is * not available then added to existing remote locator metadata and LocatorMembershipListener is * invoked to inform about the this newly added locator to all other locators available in remote * locator metadata. As a response, remote locator metadata is sent. * * @param request */ private synchronized Object updateAllLocatorInfo(RemoteLocatorJoinRequest request) { int distributedSystemId = request.getDistributedSystemId(); DistributionLocatorId locator = request.getLocator(); LocatorHelper.addLocator(distributedSystemId, locator, this, null); return new RemoteLocatorJoinResponse(this.getAllLocatorsInfo()); } private Object getPingResponse(RemoteLocatorPingRequest request) { return new RemoteLocatorPingResponse(); } private Object informAboutRemoteLocators(LocatorJoinMessage request) { // TODO: FInd out the importance of list locatorJoinMessages. During // refactoring I could not understand its significance // synchronized (locatorJoinObject) { // if (locatorJoinMessages.contains(request)) { // return null; // } // locatorJoinMessages.add(request); // } int distributedSystemId = request.getDistributedSystemId(); DistributionLocatorId locator = request.getLocator(); DistributionLocatorId sourceLocatorId = request.getSourceLocator(); LocatorHelper.addLocator(distributedSystemId, locator, this, sourceLocatorId); return null; } private Object getRemoteLocators(RemoteLocatorRequest request) { int dsId = request.getDsId(); Set<String> locators = this.getRemoteLocatorInfo(dsId); return new RemoteLocatorResponse(locators); } public Set<String> getRemoteLocatorInfo(int dsId) { return this.allServerLocatorsInfo.get(dsId); } public ConcurrentMap<Integer, Set<DistributionLocatorId>> getAllLocatorsInfo() { return this.allLocatorsInfo; } public ConcurrentMap<Integer, Set<String>> getAllServerLocatorsInfo() { return this.allServerLocatorsInfo; } public void clearLocatorInfo() { allLocatorsInfo.clear(); allServerLocatorsInfo.clear(); } }