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.io.IOException;
23 import java.io.Serializable;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.jcs.auxiliary.AuxiliaryCache;
33 import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes;
34 import org.apache.jcs.engine.CacheConstants;
35 import org.apache.jcs.engine.behavior.ICacheElement;
36 import org.apache.jcs.engine.behavior.ICacheType;
37 import org.apache.jcs.engine.behavior.ICompositeCacheManager;
38 import org.apache.jcs.engine.stats.StatElement;
39 import org.apache.jcs.engine.stats.Stats;
40 import org.apache.jcs.engine.stats.behavior.IStatElement;
41 import org.apache.jcs.engine.stats.behavior.IStats;
42
43 /***
44 * Used to provide access to multiple services under nowait protection. Factory should construct
45 * NoWaitFacade to give to the composite cache out of caches it constructs from the varies manager
46 * to lateral services.
47 * <p>
48 * Typically, we only connect to one remote server per facade. We use a list of one RemoteCacheNoWait.
49 */
50 public class RemoteCacheNoWaitFacade
51 implements AuxiliaryCache
52 {
53 private static final long serialVersionUID = -4529970797620747110L;
54
55 private final static Log log = LogFactory.getLog( RemoteCacheNoWaitFacade.class );
56
57 /*** The connection to a remote server, or a zombie. */
58 public RemoteCacheNoWait[] noWaits;
59
60 private String cacheName;
61
62 /*** holds failover and cluster information */
63 protected RemoteCacheAttributes remoteCacheAttributes;
64
65 private ICompositeCacheManager cacheMgr;
66
67 /***
68 * Gets the remoteCacheAttributes attribute of the RemoteCacheNoWaitFacade object
69 * <p>
70 * @return The remoteCacheAttributes value
71 */
72 public RemoteCacheAttributes getRemoteCacheAttributes()
73 {
74 return remoteCacheAttributes;
75 }
76
77 /***
78 * Sets the remoteCacheAttributes attribute of the RemoteCacheNoWaitFacade object.
79 * <p>
80 * @param rca The new remoteCacheAttributes value
81 */
82 public void setRemoteCacheAttributes( RemoteCacheAttributes rca )
83 {
84 this.remoteCacheAttributes = rca;
85 }
86
87 /***
88 * Constructs with the given remote cache, and fires events to any listeners.
89 * <p>
90 * @param noWaits
91 * @param rca
92 * @param cacheMgr
93 */
94 public RemoteCacheNoWaitFacade( RemoteCacheNoWait[] noWaits, RemoteCacheAttributes rca,
95 ICompositeCacheManager cacheMgr )
96 {
97 if ( log.isDebugEnabled() )
98 {
99 log.debug( "CONSTRUCTING NO WAIT FACADE" );
100 }
101 this.noWaits = noWaits;
102 this.remoteCacheAttributes = rca;
103 this.cacheName = rca.getCacheName();
104 this.cacheMgr = cacheMgr;
105 }
106
107 /***
108 * Put an element in the cache.
109 * <p>
110 * @param ce
111 * @throws IOException
112 */
113 public void update( ICacheElement ce )
114 throws IOException
115 {
116 if ( log.isDebugEnabled() )
117 {
118 log.debug( "updating through cache facade, noWaits.length = " + noWaits.length );
119 }
120 int i = 0;
121 try
122 {
123 for ( ; i < noWaits.length; i++ )
124 {
125 noWaits[i].update( ce );
126
127
128
129
130 }
131 }
132 catch ( Exception ex )
133 {
134 log.error( ex );
135
136
137
138
139 failover( i );
140
141
142
143
144
145
146 }
147 }
148
149 /***
150 * Synchronously reads from the remote cache.
151 * <p>
152 * @param key
153 * @return Either an ICacheElement or null if it is not found.
154 */
155 public ICacheElement get( Serializable key )
156 {
157 for ( int i = 0; i < noWaits.length; i++ )
158 {
159 try
160 {
161 Object obj = noWaits[i].get( key );
162 if ( obj != null )
163 {
164 return (ICacheElement) obj;
165 }
166 }
167 catch ( Exception ex )
168 {
169 log.debug( "Failed to get." );
170 }
171 return null;
172 }
173 return null;
174 }
175
176 /***
177 * Gets the set of keys of objects currently in the group.
178 * <p>
179 * @param group
180 * @return
181 * @throws IOException
182 */
183 public Set getGroupKeys( String group )
184 throws IOException
185 {
186 HashSet allKeys = new HashSet();
187 for ( int i = 0; i < noWaits.length; i++ )
188 {
189 AuxiliaryCache aux = noWaits[i];
190 if ( aux != null )
191 {
192 allKeys.addAll( aux.getGroupKeys( group ) );
193 }
194 }
195 return allKeys;
196 }
197
198 /***
199 * Adds a remove request to the remote cache.
200 * <p>
201 * @param key
202 * @return wether or not it was removed, right now it return false.
203 */
204 public boolean remove( Serializable key )
205 {
206 try
207 {
208 for ( int i = 0; i < noWaits.length; i++ )
209 {
210 noWaits[i].remove( key );
211 }
212 }
213 catch ( Exception ex )
214 {
215 log.error( ex );
216 }
217 return false;
218 }
219
220 /***
221 * Adds a removeAll request to the lateral cache.
222 */
223 public void removeAll()
224 {
225 try
226 {
227 for ( int i = 0; i < noWaits.length; i++ )
228 {
229 noWaits[i].removeAll();
230 }
231 }
232 catch ( Exception ex )
233 {
234 log.error( ex );
235 }
236 }
237
238 /*** Adds a dispose request to the lateral cache. */
239 public void dispose()
240 {
241 try
242 {
243 for ( int i = 0; i < noWaits.length; i++ )
244 {
245 noWaits[i].dispose();
246 }
247 }
248 catch ( Exception ex )
249 {
250 log.error( "Problem in dispose.", ex );
251 }
252 }
253
254 /***
255 * No lateral invocation.
256 * @return The size value
257 */
258 public int getSize()
259 {
260 return 0;
261
262 }
263
264 /***
265 * Gets the cacheType attribute of the RemoteCacheNoWaitFacade object.
266 * <p>
267 * @return The cacheType value
268 */
269 public int getCacheType()
270 {
271 return ICacheType.REMOTE_CACHE;
272 }
273
274 /***
275 * Gets the cacheName attribute of the RemoteCacheNoWaitFacade object.
276 * <p>
277 * @return The cacheName value
278 */
279 public String getCacheName()
280 {
281 return remoteCacheAttributes.getCacheName();
282 }
283
284 /***
285 * Gets the status attribute of the RemoteCacheNoWaitFacade object
286 * <p>
287 * Return ALIVE if any are alive.
288 * <p>
289 * @return The status value
290 */
291 public int getStatus()
292 {
293 for ( int i = 0; i < noWaits.length; i++ )
294 {
295 if ( noWaits[i].getStatus() == CacheConstants.STATUS_ALIVE )
296 {
297 return CacheConstants.STATUS_ALIVE;
298 }
299 }
300 return 0;
301 }
302
303 /***
304 * String form of some of the configuratin information for the remote cache.
305 * <p>
306 * @return Some info for logging.
307 */
308 public String toString()
309 {
310 return "RemoteCacheNoWaitFacade: " + cacheName + ", rca = " + remoteCacheAttributes;
311 }
312
313 /***
314 * Begin the failover process if this is a local cache. Clustered remote caches do not failover.
315 * <p>
316 * @param i The no wait in error.
317 */
318 protected void failover( int i )
319 {
320 if ( log.isDebugEnabled() )
321 {
322 log.info( "in failover for " + i );
323 }
324
325 if ( remoteCacheAttributes.getRemoteType() == RemoteCacheAttributes.LOCAL )
326 {
327 if ( noWaits[i].getStatus() == CacheConstants.STATUS_ERROR )
328 {
329
330 RemoteCacheFailoverRunner runner = new RemoteCacheFailoverRunner( this, cacheMgr );
331
332
333 if ( runner != null )
334 {
335 runner.notifyError();
336 Thread t = new Thread( runner );
337 t.setDaemon( true );
338 t.start();
339 }
340 }
341 else
342 {
343 if ( log.isInfoEnabled() )
344 {
345 log.info( "The noWait is not in error" );
346 }
347 }
348 }
349 }
350
351 /***
352 * @return Returns the AuxiliaryCacheAttributes.
353 */
354 public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes()
355 {
356 return this.remoteCacheAttributes;
357 }
358
359 /***
360 * getStats
361 * @return String
362 */
363 public String getStats()
364 {
365 return getStatistics().toString();
366 }
367
368
369
370
371
372 public IStats getStatistics()
373 {
374 IStats stats = new Stats();
375 stats.setTypeName( "Remote Cache No Wait Facade" );
376
377 ArrayList elems = new ArrayList();
378
379 IStatElement se = null;
380
381 if ( noWaits != null )
382 {
383 se = new StatElement();
384 se.setName( "Number of No Waits" );
385 se.setData( "" + noWaits.length );
386 elems.add( se );
387
388 for ( int i = 0; i < noWaits.length; i++ )
389 {
390
391
392 IStats sStats = noWaits[i].getStatistics();
393 IStatElement[] sSEs = sStats.getStatElements();
394 List sL = Arrays.asList( sSEs );
395 elems.addAll( sL );
396 }
397 }
398
399
400 IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[0] );
401 stats.setStatElements( ses );
402
403 return stats;
404 }
405 }