blob: 7a2e187a3f708db4365a203503f02e93b95dfe70 [file] [log] [blame]
/*
* 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.dubbo.registry.support;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.registry.NotifyListener;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.client.ServiceDiscovery;
import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_FETCH_INSTANCE;
/**
* Application Level, used to collect Registries
*/
public class RegistryManager {
private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(RegistryManager.class);
private ApplicationModel applicationModel;
/**
* Registry Collection Map<RegistryAddress, Registry>
*/
private final Map<String, Registry> registries = new ConcurrentHashMap<>();
/**
* The lock for the acquisition process of the registry
*/
protected final ReentrantLock lock = new ReentrantLock();
private final AtomicBoolean destroyed = new AtomicBoolean(false);
public RegistryManager(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
/**
* Get all registries
*
* @return all registries
*/
public Collection<Registry> getRegistries() {
return Collections.unmodifiableCollection(new LinkedList<>(registries.values()));
}
public Registry getRegistry(String key) {
return registries.get(key);
}
public void putRegistry(String key, Registry registry) {
registries.put(key, registry);
}
public List<ServiceDiscovery> getServiceDiscoveries() {
return getRegistries()
.stream()
.filter(registry -> registry instanceof ServiceDiscoveryRegistry)
.map(registry -> (ServiceDiscoveryRegistry) registry)
.map(ServiceDiscoveryRegistry::getServiceDiscovery)
.collect(Collectors.toList());
}
/**
* Close all created registries
*/
public void destroyAll() {
if (!destroyed.compareAndSet(false, true)) {
return;
}
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Close all registries " + getRegistries());
}
// Lock up the registry shutdown process
lock.lock();
try {
for (Registry registry : getRegistries()) {
try {
registry.destroy();
} catch (Throwable e) {
LOGGER.warn(e.getMessage(), e);
}
}
registries.clear();
} finally {
// Release the lock
lock.unlock();
}
}
/**
* Reset state of AbstractRegistryFactory
*/
public void reset() {
destroyed.set(false);
registries.clear();
}
protected Registry getDefaultNopRegistryIfDestroyed() {
if (destroyed.get()) {
// 1-12 Failed to fetch (server) instance since the registry instances have been destroyed.
LOGGER.warn(REGISTRY_FAILED_FETCH_INSTANCE, "misuse of the methods", "",
"All registry instances have been destroyed, failed to fetch any instance. " +
"Usually, this means no need to try to do unnecessary redundant resource clearance, all registries has been taken care of.");
return DEFAULT_NOP_REGISTRY;
}
return null;
}
protected Lock getRegistryLock() {
return lock;
}
public void removeDestroyedRegistry(Registry toRm) {
lock.lock();
try {
registries.entrySet().removeIf(entry -> entry.getValue().equals(toRm));
} finally {
lock.unlock();
}
}
// for unit test
public void clearRegistryNotDestroy() {
registries.clear();
}
public static RegistryManager getInstance(ApplicationModel applicationModel) {
return applicationModel.getBeanFactory().getBean(RegistryManager.class);
}
private static final Registry DEFAULT_NOP_REGISTRY = new Registry() {
@Override
public URL getUrl() {
return null;
}
@Override
public boolean isAvailable() {
return false;
}
@Override
public void destroy() {
}
@Override
public void register(URL url) {
}
@Override
public void unregister(URL url) {
}
@Override
public void subscribe(URL url, NotifyListener listener) {
}
@Override
public void unsubscribe(URL url, NotifyListener listener) {
}
@Override
public List<URL> lookup(URL url) {
return null;
}
};
}