View Javadoc

1   package org.apache.jcs.auxiliary.lateral;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.Serializable;
24  import java.rmi.UnmarshalException;
25  import java.util.ArrayList;
26  import java.util.Arrays;
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.auxiliary.lateral.behavior.ILateralCacheService;
35  import org.apache.jcs.engine.CacheAdaptor;
36  import org.apache.jcs.engine.CacheConstants;
37  import org.apache.jcs.engine.CacheEventQueueFactory;
38  import org.apache.jcs.engine.behavior.ICacheElement;
39  import org.apache.jcs.engine.behavior.ICacheEventQueue;
40  import org.apache.jcs.engine.stats.StatElement;
41  import org.apache.jcs.engine.stats.Stats;
42  import org.apache.jcs.engine.stats.behavior.IStatElement;
43  import org.apache.jcs.engine.stats.behavior.IStats;
44  
45  /***
46   * Used to queue up update requests to the underlying cache. These requests will be processed in
47   * their order of arrival via the cache event queue processor.
48   */
49  public class LateralCacheNoWait
50      implements AuxiliaryCache
51  {
52      private static final long serialVersionUID = -7251187566116178475L;
53  
54      private final static Log log = LogFactory.getLog( LateralCacheNoWait.class );
55  
56      private final LateralCache cache;
57  
58      private ICacheEventQueue q;
59  
60      private int getCount = 0;
61  
62      private int removeCount = 0;
63  
64      private int putCount = 0;
65  
66      /***
67       * Constructs with the given lateral cache, and fires up an event queue for aysnchronous
68       * processing.
69       * <p>
70       * @param cache
71       */
72      public LateralCacheNoWait( LateralCache cache )
73      {
74          this.cache = cache;
75  
76          if ( log.isDebugEnabled() )
77          {
78              log.debug( "Constructing LateralCacheNoWait, LateralCache = [" + cache + "]" );
79          }
80  
81          CacheEventQueueFactory fact = new CacheEventQueueFactory();
82          this.q = fact.createCacheEventQueue( new CacheAdaptor( cache ), LateralCacheInfo.listenerId, cache
83              .getCacheName(), cache.getAuxiliaryCacheAttributes().getEventQueuePoolName(), cache
84              .getAuxiliaryCacheAttributes().getEventQueueTypeFactoryCode() );
85  
86          // need each no wait to handle each of its real updates and removes,
87          // since there may
88          // be more than one per cache? alternative is to have the cache
89          // perform updates using a different method that spcifies the listener
90          // this.q = new CacheEventQueue(new CacheAdaptor(this),
91          // LateralCacheInfo.listenerId, cache.getCacheName());
92          if ( cache.getStatus() == CacheConstants.STATUS_ERROR )
93          {
94              q.destroy();
95          }
96      }
97  
98      /***
99       * @param ce
100      * @throws IOException
101      */
102     public void update( ICacheElement ce )
103         throws IOException
104     {
105         putCount++;
106         try
107         {
108             q.addPutEvent( ce );
109         }
110         catch ( IOException ex )
111         {
112             log.error( ex );
113             q.destroy();
114         }
115     }
116 
117     /***
118      * Synchronously reads from the lateral cache.
119      * <p>
120      * @param key
121      * @return ICacheElement if found, else null
122      */
123     public ICacheElement get( Serializable key )
124     {
125         getCount++;
126         if ( this.getStatus() != CacheConstants.STATUS_ERROR )
127         {
128             try
129             {
130                 return cache.get( key );
131             }
132             catch ( UnmarshalException ue )
133             {
134                 log.debug( "Retrying the get owing to UnmarshalException..." );
135                 try
136                 {
137                     return cache.get( key );
138                 }
139                 catch ( IOException ex )
140                 {
141                     log.error( "Failed in retrying the get for the second time." );
142                     q.destroy();
143                 }
144             }
145             catch ( IOException ex )
146             {
147                 q.destroy();
148             }
149         }
150         return null;
151     }
152 
153     public Set getGroupKeys( String groupName )
154     {
155         return cache.getGroupKeys( groupName );
156     }
157 
158     /***
159      * Adds a remove request to the lateral cache.
160      * <p>
161      * @param key
162      * @return always false
163      */
164     public boolean remove( Serializable key )
165     {
166         removeCount++;
167         try
168         {
169             q.addRemoveEvent( key );
170         }
171         catch ( IOException ex )
172         {
173             log.error( ex );
174             q.destroy();
175         }
176         return false;
177     }
178 
179     /*** Adds a removeAll request to the lateral cache. */
180     public void removeAll()
181     {
182         try
183         {
184             q.addRemoveAllEvent();
185         }
186         catch ( IOException ex )
187         {
188             log.error( ex );
189             q.destroy();
190         }
191     }
192 
193     /*** Adds a dispose request to the lateral cache. */
194     public void dispose()
195     {
196         try
197         {
198             q.addDisposeEvent();
199         }
200         catch ( IOException ex )
201         {
202             log.error( ex );
203             q.destroy();
204         }
205     }
206 
207     /***
208      * No lateral invocation.
209      * <p>
210      * @return The size value
211      */
212     public int getSize()
213     {
214         return cache.getSize();
215     }
216 
217     /***
218      * No lateral invocation.
219      * <p>
220      * @return The cacheType value
221      */
222     public int getCacheType()
223     {
224         return cache.getCacheType();
225     }
226 
227     /***
228      * Returns the asyn cache status. An error status indicates either the lateral connection is not
229      * available, or the asyn queue has been unexpectedly destroyed. No lateral invokation.
230      * <p>
231      * @return The status value
232      */
233     public int getStatus()
234     {
235         return q.isWorking() ? cache.getStatus() : CacheConstants.STATUS_ERROR;
236     }
237 
238     /***
239      * Gets the cacheName attribute of the LateralCacheNoWait object
240      * <p>
241      * @return The cacheName value
242      */
243     public String getCacheName()
244     {
245         return cache.getCacheName();
246     }
247 
248     /***
249      * Replaces the lateral cache service handle with the given handle and reset the queue by
250      * starting up a new instance.
251      * <p>
252      * @param lateral
253      */
254     public void fixCache( ILateralCacheService lateral )
255     {
256         cache.fixCache( lateral );
257         resetEventQ();
258         return;
259     }
260 
261     /***
262      * Resets the event q by first destroying the existing one and starting up new one.
263      */
264     public void resetEventQ()
265     {
266         if ( q.isWorking() )
267         {
268             q.destroy();
269         }
270         CacheEventQueueFactory fact = new CacheEventQueueFactory();
271         this.q = fact.createCacheEventQueue( new CacheAdaptor( cache ), LateralCacheInfo.listenerId, cache
272             .getCacheName(), cache.getAuxiliaryCacheAttributes().getEventQueuePoolName(), cache
273             .getAuxiliaryCacheAttributes().getEventQueueTypeFactoryCode() );
274     }
275 
276     /***
277      * @return Returns the AuxiliaryCacheAttributes.
278      */
279     public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes()
280     {
281         return cache.getAuxiliaryCacheAttributes();
282     }
283 
284     /***
285      * getStats
286      * @return String
287      */
288     public String getStats()
289     {
290         return getStatistics().toString();
291     }
292 
293     /*
294      * (non-Javadoc)
295      * @see org.apache.jcs.auxiliary.AuxiliaryCache#getStatistics()
296      */
297     public IStats getStatistics()
298     {
299         IStats stats = new Stats();
300         stats.setTypeName( "Lateral Cache No Wait" );
301 
302         ArrayList elems = new ArrayList();
303 
304         // IStatElement se = null;
305         // no data gathered here
306 
307         // get the stats from the event queue too
308         // get as array, convert to list, add list to our outer list
309         IStats eqStats = this.q.getStatistics();
310 
311         IStatElement[] eqSEs = eqStats.getStatElements();
312         List eqL = Arrays.asList( eqSEs );
313         elems.addAll( eqL );
314 
315         IStatElement se = null;
316 
317         se = new StatElement();
318         se.setName( "Get Count" );
319         se.setData( "" + this.getCount );
320         elems.add( se );
321 
322         se = new StatElement();
323         se.setName( "Remove Count" );
324         se.setData( "" + this.removeCount );
325         elems.add( se );
326 
327         se = new StatElement();
328         se.setName( "Put Count" );
329         se.setData( "" + this.putCount );
330         elems.add( se );
331 
332         // get an array and put them in the Stats object
333         IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[elems.size()] );
334         stats.setStatElements( ses );
335 
336         return stats;
337     }
338 
339     /*
340      * (non-Javadoc)
341      * @see java.lang.Object#toString()
342      */
343     public String toString()
344     {
345         StringBuffer buf = new StringBuffer();
346         buf.append( " LateralCacheNoWait " );
347         buf.append( " Status = " + this.getStatus() );
348         buf.append( " cache = [" + cache.toString() + "]" );
349         return buf.toString();
350     }
351 }