1 package org.apache.jcs.auxiliary.remote;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Iterator;
23
24 import org.apache.jcs.engine.CacheConstants;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 /***
30 * Used to monitor and repair any failed connection for the remote cache
31 * service. By default the monitor operates in a failure driven mode. That is,
32 * it goes into a wait state until there is an error. TODO consider moving this
33 * into an active monitoring mode. Upon the notification of a connection error,
34 * the monitor changes to operate in a time driven mode. That is, it attempts to
35 * recover the connections on a periodic basis. When all failed connections are
36 * restored, it changes back to the failure driven mode.
37 *
38 */
39 public class RemoteCacheMonitor
40 implements Runnable
41 {
42 /*** The logger */
43 private final static Log log = LogFactory.getLog( RemoteCacheMonitor.class );
44
45 /*** The remote cache that we are monitoring */
46 private static RemoteCacheMonitor instance;
47
48 /*** Time between checks */
49 private static long idlePeriod = 30 * 1000;
50
51
52
53
54 /*** Must make sure RemoteCacheMonitor is started before any remote error can
55 * be detected! */
56 private boolean alright = true;
57
58 /*** Time driven mode */
59 final static int TIME = 0;
60
61 /*** Error driven mode -- only check on health if there is an error */
62 final static int ERROR = 1;
63
64 /*** The mode to use */
65 static int mode = ERROR;
66
67 /***
68 * Configures the idle period between repairs.
69 *
70 * @param idlePeriod
71 * The new idlePeriod value
72 */
73 public static void setIdlePeriod( long idlePeriod )
74 {
75 if ( idlePeriod > RemoteCacheMonitor.idlePeriod )
76 {
77 RemoteCacheMonitor.idlePeriod = idlePeriod;
78 }
79 }
80
81 /*** Constructor for the RemoteCacheMonitor object */
82 private RemoteCacheMonitor()
83 {
84 super();
85 }
86
87 /***
88 * Returns the singleton instance;
89 *
90 * @return The instance value
91 */
92 static RemoteCacheMonitor getInstance()
93 {
94 synchronized ( RemoteCacheMonitor.class )
95 {
96 if ( instance == null )
97 {
98 return instance = new RemoteCacheMonitor();
99 }
100 }
101 return instance;
102 }
103
104 /***
105 * Notifies the cache monitor that an error occurred, and kicks off the
106 * error recovery process.
107 */
108 public void notifyError()
109 {
110 log.debug( "Notified of an error." );
111 bad();
112 synchronized ( this )
113 {
114 notify();
115 }
116 }
117
118
119
120
121
122
123
124 /*** Main processing method for the RemoteCacheMonitor object */
125 public void run()
126 {
127 log.debug( "Monitoring daemon started" );
128 do
129 {
130 if ( mode == ERROR )
131 {
132 synchronized ( this )
133 {
134 if ( alright )
135 {
136
137
138
139 try
140 {
141 if ( log.isDebugEnabled() )
142 {
143 log.debug( "FAILURE DRIVEN MODE: cache monitor waiting for error" );
144 }
145 wait();
146
147 }
148 catch ( InterruptedException ignore )
149 {
150
151 }
152 }
153 }
154 }
155 else
156 {
157 if ( log.isDebugEnabled() )
158 {
159 log.debug( "TIME DRIVEN MODE: cache monitor sleeping for " + idlePeriod );
160 }
161
162
163
164 }
165
166 try
167 {
168 Thread.sleep( idlePeriod );
169 }
170 catch ( InterruptedException ex )
171 {
172
173 }
174
175
176
177 synchronized ( this )
178 {
179 alright = true;
180 }
181
182
183
184 for ( Iterator itr = RemoteCacheManager.instances.values().iterator(); itr.hasNext(); )
185 {
186 RemoteCacheManager mgr = (RemoteCacheManager) itr.next();
187 try
188 {
189
190
191
192
193 for ( Iterator itr2 = mgr.caches.values().iterator(); itr2.hasNext(); )
194 {
195 if ( itr2.hasNext() )
196 {
197 RemoteCacheNoWait c = (RemoteCacheNoWait) itr2.next();
198 if ( c.getStatus() == CacheConstants.STATUS_ERROR )
199 {
200 RemoteCacheRestore repairer = new RemoteCacheRestore( mgr );
201
202
203 if ( repairer.canFix() )
204 {
205 repairer.fix();
206 }
207 else
208 {
209 bad();
210 }
211 break;
212 }
213 }
214 }
215 }
216 catch ( Exception ex )
217 {
218 bad();
219
220
221
222 log.error( ex );
223 }
224 }
225 }
226 while ( true );
227 }
228
229 /*** Sets the "alright" flag to false in a critial section. */
230 private synchronized void bad()
231 {
232 alright = false;
233 }
234 }