in dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java [94:181]
public void notify(List<URL> urls) {
if (urls == null || urls.isEmpty()) {
return;
}
// Map<category, Map<servicename, Map<Long, URL>>>
final Map<String, Map<String, Map<String, URL>>> categories = new HashMap<>();
String interfaceName = null;
for (URL url : urls) {
if (url instanceof InstanceAddressURL) {
continue;
}
String category = url.getUrlParam().getParameter(Constants.CATEGORY_KEY);
if (category == null) {
// Assign an initial value to category according to the information in url
if (Constants.CONSUMER_SIDE.equals(url.getSide()) || Constants.CONSUMER_PROTOCOL.equals(url.getProtocol())) {
category = Constants.CONSUMERS_CATEGORY;
} else {
category = Constants.PROVIDERS_CATEGORY;
}
}
// NOTE: group and version in empty protocol is *
if (Constants.EMPTY_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
ConcurrentMap<String, Map<String, URL>> services = interfaceRegistryCache.get(category);
if (services != null) {
String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
// NOTE: group and version in empty protocol is *
if (!Constants.ANY_VALUE.equals(group) && !Constants.ANY_VALUE.equals(version)) {
services.remove(getServiceInterface(url));
} else {
for (Map.Entry<String, Map<String, URL>> serviceEntry : services.entrySet()) {
String service = serviceEntry.getKey();
if (Tool.getInterface(service).equals(getServiceInterface(url))
&& (Constants.ANY_VALUE.equals(group) || StringUtils.isEquals(group, Tool.getGroup(service)))
&& (Constants.ANY_VALUE.equals(version) || StringUtils.isEquals(version, Tool.getVersion(service)))) {
services.remove(service);
}
}
}
}
} else {
if (StringUtils.isEmpty(interfaceName)) {
interfaceName = getServiceInterface(url);
}
Map<String, Map<String, URL>> services = categories.get(category);
if (services == null) {
services = new HashMap<>();
categories.put(category, services);
}
String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
String service = BaseServiceMetadata.buildServiceKey(getServiceInterface(url), group, version);
Map<String, URL> ids = services.get(service);
if (ids == null) {
ids = new HashMap<>();
services.put(service, ids);
}
// Make sure we use the same ID for the same URL
if (URL_IDS_MAPPER.containsKey(url.toFullString())) {
ids.put(URL_IDS_MAPPER.get(url.toFullString()), url);
} else {
String md5 = CoderUtil.MD5_16bit(url.toFullString());
ids.put(md5, url);
URL_IDS_MAPPER.putIfAbsent(url.toFullString(), md5);
}
}
}
if (categories.size() == 0) {
return;
}
for (Map.Entry<String, Map<String, Map<String, URL>>> categoryEntry : categories.entrySet()) {
String category = categoryEntry.getKey();
ConcurrentMap<String, Map<String, URL>> services = interfaceRegistryCache.get(category);
if (services == null) {
services = new ConcurrentHashMap<>();
interfaceRegistryCache.put(category, services);
} else {// Fix map can not be cleared when service is unregistered: when a unique “group/service:version” service is unregistered, but we still have the same services with different version or group, so empty protocols can not be invoked.
Set<String> keys = new HashSet<>(services.keySet());
for (String key : keys) {
if (Tool.getInterface(key).equals(interfaceName) && !categoryEntry.getValue().containsKey(key)) {
services.remove(key);
}
}
}
services.putAll(categoryEntry.getValue());
}
}