1 package org.apache.commons.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.io.IOException;
23 import java.util.List;
24 import java.util.ListIterator;
25
26 import org.apache.commons.jcs.auxiliary.AbstractAuxiliaryCacheMonitor;
27 import org.apache.commons.jcs.auxiliary.remote.behavior.IRemoteCacheAttributes;
28 import org.apache.commons.jcs.engine.CacheStatus;
29 import org.apache.commons.jcs.engine.behavior.ICache;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class RemoteCacheFailoverRunner<K, V> extends AbstractAuxiliaryCacheMonitor
51 {
52
53 private final RemoteCacheNoWaitFacade<K, V> facade;
54
55
56 private final RemoteCacheFactory cacheFactory;
57
58
59
60
61
62
63
64
65 public RemoteCacheFailoverRunner( RemoteCacheNoWaitFacade<K, V> facade, RemoteCacheFactory cacheFactory )
66 {
67 super("JCS-RemoteCacheFailoverRunner");
68 this.facade = facade;
69 this.cacheFactory = cacheFactory;
70 setIdlePeriod(20000L);
71 }
72
73
74
75
76 @Override
77 protected void dispose()
78 {
79
80 }
81
82
83
84
85 @Override
86 protected void doWork()
87 {
88
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 @Override
106 public void run()
107 {
108
109
110 connectAndRestore();
111
112 if ( log.isInfoEnabled() )
113 {
114 int failoverIndex = facade.getAuxiliaryCacheAttributes().getFailoverIndex();
115 log.info( "Exiting failover runner. Failover index = " + failoverIndex);
116
117 if ( failoverIndex <= 0 )
118 {
119 log.info( "Failover index is <= 0, meaning we are not connected to a failover server." );
120 }
121 else if ( failoverIndex > 0 )
122 {
123 log.info( "Failover index is > 0, meaning we are connected to a failover server." );
124 }
125
126 }
127 }
128
129
130
131
132
133
134 private void connectAndRestore()
135 {
136 IRemoteCacheAttributes rca0 = facade.getAuxiliaryCacheAttributes();
137
138 do
139 {
140 log.info( "Remote cache FAILOVER RUNNING." );
141
142
143 if ( !allright.get() )
144 {
145
146
147 List<RemoteLocation> failovers = rca0.getFailovers();
148
149
150
151
152 if ( failovers == null )
153 {
154 log.warn( "Remote is misconfigured, failovers was null." );
155 return;
156 }
157 else if ( failovers.size() == 1 )
158 {
159
160 log.info( "No failovers defined, exiting failover runner." );
161 return;
162 }
163
164 int fidx = rca0.getFailoverIndex();
165 log.debug( "fidx = " + fidx + " failovers.size = " + failovers.size() );
166
167
168
169
170
171 ListIterator<RemoteLocation> i = failovers.listIterator(fidx);
172 if ( log.isDebugEnabled() )
173 {
174 log.debug( "starting at failover i = " + i.nextIndex() );
175 }
176
177
178 for ( ; i.hasNext() && !allright.get();)
179 {
180 RemoteLocation server = i.next();
181 if ( log.isDebugEnabled() )
182 {
183 log.debug( "Trying server [" + server + "] at failover index i = " + i );
184 }
185
186 RemoteCacheAttributes rca = (RemoteCacheAttributes) rca0.clone();
187 rca.setRemoteLocation(server);
188 RemoteCacheManager rcm = cacheFactory.getManager( rca );
189
190 if ( log.isDebugEnabled() )
191 {
192 log.debug( "RemoteCacheAttributes for failover = " + rca.toString() );
193 }
194
195 if (rcm != null)
196 {
197
198
199 ICache<K, V> ic = rcm.getCache( rca );
200 if ( ic.getStatus() == CacheStatus.ALIVE )
201 {
202
203 log.debug( "resetting no wait" );
204 facade.restorePrimaryServer((RemoteCacheNoWait<K, V>) ic);
205 rca0.setFailoverIndex( i.nextIndex() );
206
207 if ( log.isDebugEnabled() )
208 {
209 log.debug( "setting ALLRIGHT to true" );
210 if ( i.hasPrevious() )
211 {
212 log.debug( "Moving to Primary Recovery Mode, failover index = " + i.nextIndex() );
213 }
214 else
215 {
216 log.debug( "No need to connect to failover, the primary server is back up." );
217 }
218 }
219
220 allright.set(true);
221
222 if ( log.isInfoEnabled() )
223 {
224 log.info( "CONNECTED to host = [" + rca.getRemoteLocation() + "]" );
225 }
226 }
227 }
228 }
229 }
230
231
232
233 else
234 {
235 if ( log.isDebugEnabled() )
236 {
237 log.debug( "ALLRIGHT is true " );
238 }
239 if ( log.isInfoEnabled() )
240 {
241 log.info( "Failover runner is in primary recovery mode. Failover index = "
242 + rca0.getFailoverIndex() + "\n" + "Will now try to reconnect to primary server." );
243 }
244 }
245
246 boolean primaryRestoredSuccessfully = false;
247
248 if ( rca0.getFailoverIndex() > 0 )
249 {
250 primaryRestoredSuccessfully = restorePrimary();
251 if ( log.isDebugEnabled() )
252 {
253 log.debug( "Primary recovery success state = " + primaryRestoredSuccessfully );
254 }
255 }
256
257 if ( !primaryRestoredSuccessfully )
258 {
259
260
261 try
262 {
263 log.warn( "Failed to reconnect to primary server. Cache failover runner is going to sleep for "
264 + idlePeriod + " milliseconds." );
265 Thread.sleep( idlePeriod );
266 }
267 catch ( InterruptedException ex )
268 {
269
270 }
271 }
272
273
274 }
275 while ( rca0.getFailoverIndex() > 0 || !allright.get() );
276
277 }
278
279
280
281
282
283
284
285
286
287
288
289 private boolean restorePrimary()
290 {
291 IRemoteCacheAttributes rca0 = facade.getAuxiliaryCacheAttributes();
292
293 RemoteLocation server = rca0.getFailovers().get(0);
294
295 if ( log.isInfoEnabled() )
296 {
297 log.info( "Trying to restore connection to primary remote server [" + server + "]" );
298 }
299
300 RemoteCacheAttributes rca = (RemoteCacheAttributes) rca0.clone();
301 rca.setRemoteLocation(server);
302 RemoteCacheManager rcm = cacheFactory.getManager( rca );
303
304 if (rcm != null)
305 {
306
307
308 ICache<K, V> ic = rcm.getCache( rca );
309
310
311
312
313
314
315
316 if ( ic.getStatus() == CacheStatus.ALIVE )
317 {
318 try
319 {
320
321
322
323
324 if ( facade.getPrimaryServer() != null && facade.getPrimaryServer().getStatus() == CacheStatus.ALIVE )
325 {
326 int fidx = rca0.getFailoverIndex();
327
328 if ( fidx > 0 )
329 {
330 RemoteLocation serverOld = rca0.getFailovers().get(fidx);
331
332 if ( log.isDebugEnabled() )
333 {
334 log.debug( "Failover Index = " + fidx + " the server at that index is ["
335 + serverOld + "]" );
336 }
337
338 if ( serverOld != null )
339 {
340
341
342 RemoteCacheAttributes rcaOld = (RemoteCacheAttributes) rca0.clone();
343 rcaOld.setRemoteLocation(serverOld);
344 RemoteCacheManager rcmOld = cacheFactory.getManager( rcaOld );
345
346 if ( rcmOld != null )
347 {
348
349
350 rcmOld.removeRemoteCacheListener( rcaOld );
351 }
352 if ( log.isInfoEnabled() )
353 {
354 log.info( "Successfully deregistered from FAILOVER remote server = "
355 + serverOld );
356 }
357 }
358 }
359 else if ( fidx == 0 )
360 {
361
362
363 if ( log.isDebugEnabled() )
364 {
365 log.debug( "No need to restore primary, it is already restored." );
366 return true;
367 }
368 }
369 else if ( fidx < 0 )
370 {
371
372 log.warn( "Failover index is less than 0, this shouldn't happen" );
373 }
374 }
375 }
376 catch ( IOException e )
377 {
378
379 log.error("Trouble trying to deregister old failover listener prior to restoring the primary = "
380 + server, e );
381 }
382
383
384
385 RemoteCacheNoWait<K, V> failoverNoWait = facade.getPrimaryServer();
386
387
388 facade.restorePrimaryServer((RemoteCacheNoWait<K, V>) ic);
389 rca0.setFailoverIndex( 0 );
390
391 if ( log.isInfoEnabled() )
392 {
393 String message = "Successfully reconnected to PRIMARY remote server. Substituted primary for failoverNoWait ["
394 + failoverNoWait + "]";
395 log.info( message );
396
397 if ( facade.getCacheEventLogger() != null )
398 {
399 facade.getCacheEventLogger().logApplicationEvent( "RemoteCacheFailoverRunner", "RestoredPrimary", message );
400 }
401 }
402 return true;
403 }
404 }
405
406
407
408
409
410 if ( log.isDebugEnabled() )
411 {
412 log.debug( "Primary server status in error, not connected." );
413 }
414
415 return false;
416 }
417 }