001package org.apache.commons.jcs3.auxiliary.remote.http.client; 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.io.IOException; 023import java.io.Serializable; 024import java.util.concurrent.ConcurrentHashMap; 025 026import org.apache.commons.jcs3.auxiliary.AbstractAuxiliaryCacheMonitor; 027import org.apache.commons.jcs3.auxiliary.remote.http.client.behavior.IRemoteHttpCacheClient; 028import org.apache.commons.jcs3.engine.CacheStatus; 029 030/** 031 * Upon the notification of a connection error, the monitor changes to operate in a time driven 032 * mode. That is, it attempts to recover the connections on a periodic basis. When all failed 033 * connections are restored, it changes back to the failure driven mode. 034 */ 035public class RemoteHttpCacheMonitor extends AbstractAuxiliaryCacheMonitor 036{ 037 /** Set of remote caches to monitor. This are added on error, if not before. */ 038 private final ConcurrentHashMap<RemoteHttpCache<?, ?>, RemoteHttpCache<?, ?>> remoteHttpCaches; 039 040 /** Factory instance */ 041 private final RemoteHttpCacheFactory factory; 042 043 /** 044 * Constructor for the RemoteCacheMonitor object 045 * 046 * @param factory the factory to set 047 */ 048 public RemoteHttpCacheMonitor(final RemoteHttpCacheFactory factory) 049 { 050 super("JCS-RemoteHttpCacheMonitor"); 051 this.factory = factory; 052 this.remoteHttpCaches = new ConcurrentHashMap<>(); 053 setIdlePeriod(3000L); 054 } 055 056 /** 057 * Notifies the cache monitor that an error occurred, and kicks off the error recovery process. 058 * <p> 059 * @param remoteCache 060 */ 061 public void notifyError( final RemoteHttpCache<?, ?> remoteCache ) 062 { 063 if ( log.isInfoEnabled() ) 064 { 065 log.info( "Notified of an error. " + remoteCache ); 066 } 067 068 remoteHttpCaches.put( remoteCache, remoteCache ); 069 notifyError(); 070 } 071 072 /** 073 * Clean up all resources before shutdown 074 */ 075 @Override 076 protected void dispose() 077 { 078 this.remoteHttpCaches.clear(); 079 } 080 081 // Avoid the use of any synchronization in the process of monitoring for 082 // performance reasons. 083 // If exception is thrown owing to synchronization, 084 // just skip the monitoring until the next round. 085 /** Main processing method for the RemoteHttpCacheMonitor object */ 086 @Override 087 protected void doWork() 088 { 089 // If no factory has been set, skip 090 if (factory == null) 091 { 092 return; 093 } 094 095 // If any cache is in error, it strongly suggests all caches 096 // managed by the same RmicCacheManager instance are in error. So we fix 097 // them once and for all. 098 for (final RemoteHttpCache<?, ?> remoteCache : this.remoteHttpCaches.values()) 099 { 100 try 101 { 102 if ( remoteCache.getStatus() == CacheStatus.ERROR ) 103 { 104 final RemoteHttpCacheAttributes attributes = remoteCache.getRemoteHttpCacheAttributes(); 105 106 final IRemoteHttpCacheClient<Serializable, Serializable> remoteService = 107 factory.createRemoteHttpCacheClientForAttributes( attributes ); 108 109 if ( log.isInfoEnabled() ) 110 { 111 log.info( "Performing Alive check on service " + remoteService ); 112 } 113 // If we can't fix them, just skip and re-try in 114 // the next round. 115 if ( remoteService.isAlive() ) 116 { 117 remoteCache.fixCache( remoteService ); 118 } 119 else 120 { 121 allright.set(false); 122 } 123 break; 124 } 125 } 126 catch ( final IOException ex ) 127 { 128 allright.set(false); 129 // Problem encountered in fixing the caches managed by a 130 // RemoteCacheManager instance. 131 // Soldier on to the next RemoteHttpCache. 132 log.error( ex ); 133 } 134 } 135 } 136}