001package org.apache.commons.jcs3.auxiliary.remote;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.concurrent.ConcurrentHashMap;
023
024import org.apache.commons.jcs3.auxiliary.AbstractAuxiliaryCacheMonitor;
025
026/**
027 * Used to monitor and repair any failed connection for the remote cache service. By default the
028 * monitor operates in a failure driven mode. That is, it goes into a wait state until there is an
029 * error.
030 *
031 * TODO consider moving this into an active monitoring mode. Upon the notification of a
032 * connection error, the monitor changes to operate in a time driven mode. That is, it attempts to
033 * recover the connections on a periodic basis. When all failed connections are restored, it changes
034 * back to the failure driven mode.
035 */
036public class RemoteCacheMonitor extends AbstractAuxiliaryCacheMonitor
037{
038    /**
039     * Map of managers to monitor
040     */
041    private final ConcurrentHashMap<RemoteCacheManager, RemoteCacheManager> managers;
042
043    /** Constructor for the RemoteCacheMonitor object */
044    public RemoteCacheMonitor()
045    {
046        super("JCS-RemoteCacheMonitor");
047        this.managers = new ConcurrentHashMap<>();
048        setIdlePeriod(30000L);
049    }
050
051    /**
052     * Add a manager to be monitored
053     *
054     * @param manager the remote cache manager
055     */
056    public void addManager(final RemoteCacheManager manager)
057    {
058        this.managers.put(manager, manager);
059
060        // if not yet started, go ahead
061        if (this.getState() == Thread.State.NEW)
062        {
063            this.start();
064        }
065    }
066
067    /**
068     * Clean up all resources before shutdown
069     */
070    @Override
071    public void dispose()
072    {
073        this.managers.clear();
074    }
075
076    // Avoid the use of any synchronization in the process of monitoring for
077    // performance reason.
078    // If exception is thrown owing to synchronization,
079    // just skip the monitoring until the next round.
080    /** Main processing method for the RemoteCacheMonitor object */
081    @Override
082    public void doWork()
083    {
084        // Monitor each RemoteCacheManager instance one after the other.
085        // Each RemoteCacheManager corresponds to one remote connection.
086        managers.values().forEach(mgr -> {
087            // If we can't fix them, just skip and re-try in
088            // the next round.
089            if ( mgr.canFixCaches() )
090            {
091                mgr.fixCaches();
092            }
093            else
094            {
095                allright.set(false);
096            }
097        });
098    }
099}