blob: f0ec7ab8a9a155b5a16d43fa849852afb2d8ffd4 [file] [log] [blame]
package org.apache.commons.jcs3.auxiliary.remote.http.client;
/*
* 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.
*/
import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.jcs3.auxiliary.AbstractAuxiliaryCacheMonitor;
import org.apache.commons.jcs3.auxiliary.remote.http.client.behavior.IRemoteHttpCacheClient;
import org.apache.commons.jcs3.engine.CacheStatus;
/**
* Upon the notification of a connection error, the monitor changes to operate in a time driven
* mode. That is, it attempts to recover the connections on a periodic basis. When all failed
* connections are restored, it changes back to the failure driven mode.
*/
public class RemoteHttpCacheMonitor extends AbstractAuxiliaryCacheMonitor
{
/** Set of remote caches to monitor. This are added on error, if not before. */
private final ConcurrentHashMap<RemoteHttpCache<?, ?>, RemoteHttpCache<?, ?>> remoteHttpCaches;
/** Factory instance */
private final RemoteHttpCacheFactory factory;
/**
* Constructor for the RemoteCacheMonitor object
*
* @param factory the factory to set
*/
public RemoteHttpCacheMonitor(final RemoteHttpCacheFactory factory)
{
super("JCS-RemoteHttpCacheMonitor");
this.factory = factory;
this.remoteHttpCaches = new ConcurrentHashMap<>();
setIdlePeriod(3000L);
}
/**
* Notifies the cache monitor that an error occurred, and kicks off the error recovery process.
* <p>
* @param remoteCache
*/
public void notifyError( final RemoteHttpCache<?, ?> remoteCache )
{
if ( log.isInfoEnabled() )
{
log.info( "Notified of an error. " + remoteCache );
}
remoteHttpCaches.put( remoteCache, remoteCache );
notifyError();
}
/**
* Clean up all resources before shutdown
*/
@Override
protected void dispose()
{
this.remoteHttpCaches.clear();
}
// Avoid the use of any synchronization in the process of monitoring for
// performance reasons.
// If exception is thrown owing to synchronization,
// just skip the monitoring until the next round.
/** Main processing method for the RemoteHttpCacheMonitor object */
@Override
protected void doWork()
{
// If no factory has been set, skip
if (factory == null)
{
return;
}
// If any cache is in error, it strongly suggests all caches
// managed by the same RmicCacheManager instance are in error. So we fix
// them once and for all.
for (final RemoteHttpCache<?, ?> remoteCache : this.remoteHttpCaches.values())
{
try
{
if ( remoteCache.getStatus() == CacheStatus.ERROR )
{
final RemoteHttpCacheAttributes attributes = remoteCache.getRemoteHttpCacheAttributes();
final IRemoteHttpCacheClient<Serializable, Serializable> remoteService =
factory.createRemoteHttpCacheClientForAttributes( attributes );
if ( log.isInfoEnabled() )
{
log.info( "Performing Alive check on service " + remoteService );
}
// If we can't fix them, just skip and re-try in
// the next round.
if ( remoteService.isAlive() )
{
remoteCache.fixCache( remoteService );
}
else
{
allright.set(false);
}
break;
}
}
catch ( final IOException ex )
{
allright.set(false);
// Problem encountered in fixing the caches managed by a
// RemoteCacheManager instance.
// Soldier on to the next RemoteHttpCache.
log.error( ex );
}
}
}
}