/* * 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.management.internal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.logging.log4j.Logger; import org.apache.geode.cache.Cache; import org.apache.geode.distributed.DistributedSystemDisconnectedException; import org.apache.geode.distributed.internal.InternalDistributedSystem; import org.apache.geode.internal.logging.LogService; import org.apache.geode.management.ManagementService; /** * Super class to all Management Service * * @since GemFire 7.0 */ public abstract class BaseManagementService extends ManagementService { private static final Logger logger = LogService.getLogger(); /** * The main mapping between different resources and Service instance Object can be Cache */ protected static final Map<Object, BaseManagementService> instances = new HashMap<Object, BaseManagementService>(); /** List of connected <code>DistributedSystem</code>s */ private static final List<InternalDistributedSystem> systems = new ArrayList<InternalDistributedSystem>(1); /** Protected constructor. */ protected BaseManagementService() {} // Static block to initialize the ConnectListener on the System static { initInternalDistributedSystem(); } /** * This method will close the service. Any operation on the service instance will throw exception */ protected abstract void close(); /** * This method will close the service. Any operation on the service instance will throw exception */ protected abstract boolean isClosed(); /** * Returns a ManagementService to use for the specified Cache. * * @param cache defines the scope of resources to be managed */ public static ManagementService getManagementService(Cache cache) { synchronized (instances) { BaseManagementService service = (BaseManagementService) instances.get(cache); if (service == null) { service = SystemManagementService.newSystemManagementService(cache); instances.put(cache, service); } return service; } } public static ManagementService getExistingManagementService(Cache cache) { synchronized (instances) { BaseManagementService service = (BaseManagementService) instances.get(cache); return service; } } /** * Initialises the distributed system listener */ private static void initInternalDistributedSystem() { synchronized (instances) { // Initialize our own list of distributed systems via a connect listener @SuppressWarnings("unchecked") List<InternalDistributedSystem> existingSystems = InternalDistributedSystem .addConnectListener(new InternalDistributedSystem.ConnectListener() { public void onConnect(InternalDistributedSystem sys) { addInternalDistributedSystem(sys); } }); // While still holding the lock on systems, add all currently known // systems to our own list for (InternalDistributedSystem sys : existingSystems) { try { if (sys.isConnected()) { addInternalDistributedSystem(sys); } } catch (DistributedSystemDisconnectedException e) { if (logger.isDebugEnabled()) { logger.debug("DistributedSystemDisconnectedException {}", e.getMessage(), e); } } } } } /** * Add an Distributed System and adds a Discon Listener * * @param sys */ private static void addInternalDistributedSystem(InternalDistributedSystem sys) { synchronized (instances) { sys.addDisconnectListener(new InternalDistributedSystem.DisconnectListener() { @Override public String toString() { return "Disconnect listener for BaseManagementService"; } public void onDisconnect(InternalDistributedSystem ss) { removeInternalDistributedSystem(ss); } }); systems.add(sys); } } /** * Remove a Distributed System from the system lists. If list is empty it closes down all the * services if not closed * * @param sys */ private static void removeInternalDistributedSystem(InternalDistributedSystem sys) { synchronized (instances) { systems.remove(sys); if (systems.isEmpty()) { for (Object key : instances.keySet()) { BaseManagementService service = (BaseManagementService) instances.get(key); try { if (!service.isClosed()) { // Service close method should take care of the cleaning up // activities service.close(); } } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("ManagementException while removing InternalDistributedSystem {}", e.getMessage(), e); } } } instances.clear(); } } } }