/* * Copyright 1999-2011 Alibaba Group. * * Licensed 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 com.alibaba.dubbo.registry.dubbo; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.registry.NotifyListener; import com.alibaba.dubbo.registry.RegistryService; /** * AbstractRegistryService * * @author william.liangf */ public abstract class AbstractRegistryService implements RegistryService { // 日志输出 protected final Logger logger = LoggerFactory.getLogger(getClass()); // 已注册的服务 // Map<serviceName, Map<url, queryString>> private final ConcurrentMap<String, List<URL>> registered = new ConcurrentHashMap<String, List<URL>>(); // 已订阅的服务 // Map<serviceName, queryString> private final ConcurrentMap<String, Map<String, String>> subscribed = new ConcurrentHashMap<String, Map<String, String>>(); // 已通知的服务 // Map<serviceName, Map<url, queryString>> private final ConcurrentMap<String, List<URL>> notified = new ConcurrentHashMap<String, List<URL>>(); // 已订阅服务的监听器列表 // Map<serviceName, List<notificationListener>> private final ConcurrentMap<String, List<NotifyListener>> notifyListeners = new ConcurrentHashMap<String, List<NotifyListener>>(); public void register(URL url) { if (logger.isInfoEnabled()) { logger.info("Register service: " + url.getServiceKey() + ",url:" + url); } register(url.getServiceKey(), url); } public void unregister(URL url) { if (logger.isInfoEnabled()) { logger.info("Unregister service: " + url.getServiceKey() + ",url:" + url); } unregister(url.getServiceKey(), url); } public void subscribe(URL url, NotifyListener listener) { if (logger.isInfoEnabled()) { logger.info("Subscribe service: " + url.getServiceKey() + ",url:" + url); } subscribe(url.getServiceKey(), url, listener); } public void unsubscribe(URL url, NotifyListener listener) { if (logger.isInfoEnabled()) { logger.info("Unsubscribe service: " + url.getServiceKey() + ",url:" + url); } unsubscribe(url.getServiceKey(), url, listener); } public List<URL> lookup(URL url) { return getRegistered(url.getServiceKey()); } public void register(String service, URL url) { if (service == null) { throw new IllegalArgumentException("service == null"); } if (url == null) { throw new IllegalArgumentException("url == null"); } List<URL> urls = registered.get(service); if (urls == null) { registered.putIfAbsent(service, new CopyOnWriteArrayList<URL>()); urls = registered.get(service); } if (! urls.contains(url)) { urls.add(url); } } public void unregister(String service, URL url) { if (service == null) { throw new IllegalArgumentException("service == null"); } if (url == null) { throw new IllegalArgumentException("url == null"); } List<URL> urls = registered.get(service); if (urls != null) { URL deleteURL = null; for (URL u : urls) { if (u.toIdentityString().equals(url.toIdentityString())) { deleteURL = u; break; } } if (deleteURL != null) { urls.remove(deleteURL); } } } public void subscribe(String service, URL url, NotifyListener listener) { if (service == null) { throw new IllegalArgumentException("service == null"); } if (url == null) { throw new IllegalArgumentException("parameters == null"); } if (listener == null) { throw new IllegalArgumentException("listener == null"); } subscribed.put(service, url.getParameters()); addListener(service, listener); } public void unsubscribe(String service, URL url, NotifyListener listener) { if (service == null) { throw new IllegalArgumentException("service == null"); } if (url == null) { throw new IllegalArgumentException("parameters == null"); } if (listener == null) { throw new IllegalArgumentException("listener == null"); } subscribed.remove(service); removeListener(service, listener); } //consumer 与 provider的 listener可以一起存储,都是根据服务名称共享 private void addListener(final String service, final NotifyListener listener){ if (listener == null) { return; } List<NotifyListener> listeners = notifyListeners.get(service); if (listeners == null) { notifyListeners.putIfAbsent(service, new CopyOnWriteArrayList<NotifyListener>()); listeners = notifyListeners.get(service); } if (listeners != null && !listeners.contains(listener)){ listeners.add(listener); } } private void removeListener(final String service, final NotifyListener listener){ if (listener == null) { return; } List<NotifyListener> listeners = notifyListeners.get(service); if (listeners != null) { listeners.remove(listener); } } private void doNotify(String service, List<URL> urls) { notified.put(service, urls); List<NotifyListener> listeners = notifyListeners.get(service); if (listeners != null) { for (NotifyListener listener : listeners) { try { notify(service, urls, listener); } catch (Throwable t) { logger.error("Failed to notify registry event, service: " + service + ", urls: " + urls + ", cause: " + t.getMessage(), t); } } } } protected void notify(String service, List<URL> urls, NotifyListener listener) { listener.notify(urls); } protected final void forbid(String service) { doNotify(service, new ArrayList<URL>(0)); } protected final void notify(String service, List<URL> urls) { if (service == null || service.length() == 0 || urls == null || urls.size() == 0) { return; } doNotify(service, urls); } public Map<String, List<URL>> getRegistered() { return Collections.unmodifiableMap(registered); } public List<URL> getRegistered(String service) { return Collections.unmodifiableList(registered.get(service)); } public Map<String, Map<String, String>> getSubscribed() { return Collections.unmodifiableMap(subscribed); } public Map<String, String> getSubscribed(String service) { return subscribed.get(service); } public Map<String, List<URL>> getNotified() { return Collections.unmodifiableMap(notified); } public List<URL> getNotified(String service) { return Collections.unmodifiableList(notified.get(service)); } public Map<String, List<NotifyListener>> getListeners() { return Collections.unmodifiableMap(notifyListeners); } }