/** * Dianping.com Inc. * Copyright (c) 2003-2013 All Rights Reserved. */ package com.dianping.pigeon.remoting.invoker.listener; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import com.dianping.pigeon.log.Logger; import com.dianping.pigeon.util.NetUtils; import org.springframework.util.CollectionUtils; import com.dianping.pigeon.log.LoggerLoader; import com.dianping.pigeon.registry.listener.RegistryEventListener; import com.dianping.pigeon.registry.listener.ServiceProviderChangeEvent; import com.dianping.pigeon.registry.listener.ServiceProviderChangeListener; import com.dianping.pigeon.remoting.common.domain.Disposable; import com.dianping.pigeon.remoting.invoker.Client; import com.dianping.pigeon.remoting.invoker.domain.ConnectInfo; public class ClusterListenerManager implements Disposable { private static final Logger logger = LoggerLoader.getLogger(ClusterListenerManager.class); public static final String PLACEHOLDER = ":"; private List<ClusterListener> listeners = new CopyOnWriteArrayList<ClusterListener>(); private ServiceProviderChangeListener providerChangeListener = new InnerServiceProviderChangeListener(); private ConcurrentHashMap<String, ConnectInfo> connectInfoMap = new ConcurrentHashMap<String, ConnectInfo>(); private static ClusterListenerManager instance = new ClusterListenerManager(); public static ClusterListenerManager getInstance() { return instance; } private ClusterListenerManager() { RegistryEventListener.addListener(providerChangeListener); } public void addConnect(ConnectInfo cmd) { ConnectInfo connectInfo = this.connectInfoMap.get(cmd.getConnect()); if (connectInfo == null) { ConnectInfo oldConnectInfo = this.connectInfoMap.putIfAbsent(cmd.getConnect(), cmd); if (oldConnectInfo != null) { connectInfo = oldConnectInfo; } } if (connectInfo != null) { connectInfo.addServiceNames(cmd.getServiceNames()); if (CollectionUtils.isEmpty(cmd.getServiceNames())) { if (logger.isInfoEnabled()) { logger.info("[cluster-listener-mgr] add services from:" + connectInfo); } cmd.addServiceNames(connectInfo.getServiceNames()); } } for (ClusterListener listener : listeners) { listener.addConnect(cmd); } } public void addListener(ClusterListener listener) { this.listeners.add(listener); } @Override public void destroy() throws Exception { RegistryEventListener.removeListener(providerChangeListener); } class InnerServiceProviderChangeListener implements ServiceProviderChangeListener { @Override public void hostWeightChanged(ServiceProviderChangeEvent event) { } @Override public void providerAdded(ServiceProviderChangeEvent event) { } @Override public void providerRemoved(ServiceProviderChangeEvent event) { // addConnect的逆操作 String connect = NetUtils.toAddress(event.getHost(), event.getPort()); if (logger.isInfoEnabled()) { logger.info("[cluster-listener-mgr] remove:" + connect + " from " + event.getServiceName()); } ConnectInfo cmd = connectInfoMap.get(connect); if (cmd != null) { cmd.getServiceNames().remove(event.getServiceName()); if (cmd.getServiceNames().size() == 0) { connectInfoMap.remove(connect); } } for (ClusterListener listener : listeners) { listener.doNotUse(event.getServiceName(), event.getHost(), event.getPort()); } } } }