Coverage report

  %line %branch
org.apache.jcs.auxiliary.remote.RemoteCacheNoWait
59% 
93% 

 1  
 package org.apache.jcs.auxiliary.remote;
 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.remote.behavior.IRemoteCacheClient;
 35  
 import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheService;
 36  
 import org.apache.jcs.engine.CacheAdaptor;
 37  
 import org.apache.jcs.engine.CacheConstants;
 38  
 import org.apache.jcs.engine.CacheEventQueueFactory;
 39  
 import org.apache.jcs.engine.behavior.ICacheElement;
 40  
 import org.apache.jcs.engine.behavior.ICacheEventQueue;
 41  
 import org.apache.jcs.engine.behavior.ICacheType;
 42  
 import org.apache.jcs.engine.stats.StatElement;
 43  
 import org.apache.jcs.engine.stats.Stats;
 44  
 import org.apache.jcs.engine.stats.behavior.IStatElement;
 45  
 import org.apache.jcs.engine.stats.behavior.IStats;
 46  
 
 47  
 /**
 48  
  * Used to queue up update requests to the underlying cache. These requests will be processed in
 49  
  * their order of arrival via the cache event queue processor.
 50  
  * <p>
 51  
  * Typically errors will be handled down stream. We only need to kill the queue if an error makes it
 52  
  * to this level from the queue. That can only happen if the queue is damaged, since the events are
 53  
  * procesed asynchronously.
 54  
  * <p>
 55  
  * There is no reason to create a queue on startup if the remote is not healthy.
 56  
  * <p>
 57  
  * If the remote cache encounters an error it will zombie--create a blaking facade for the service.
 58  
  * The Zombie will queue up items until the conenction is restored. An alternative way to accomplish
 59  
  * the same thing would be to stop, not destroy the queue at this level. That way items would be
 60  
  * added to the queue and then when the connection is restored, we could start the worker threads
 61  
  * again. This is a better long term solution, but it requires some significnat changes to the
 62  
  * complicated worker queues.
 63  
  */
 64  
 public class RemoteCacheNoWait
 65  
     implements AuxiliaryCache
 66  
 {
 67  
     private static final long serialVersionUID = -3104089136003714717L;
 68  
 
 69  28
     private final static Log log = LogFactory.getLog( RemoteCacheNoWait.class );
 70  
 
 71  
     private final IRemoteCacheClient cache;
 72  
 
 73  
     private ICacheEventQueue cacheEventQueue;
 74  
 
 75  63
     private int getCount = 0;
 76  
 
 77  63
     private int removeCount = 0;
 78  
 
 79  63
     private int putCount = 0;
 80  
 
 81  
     /**
 82  
      * Constructs with the given remote cache, and fires up an event queue for aysnchronous
 83  
      * processing.
 84  
      * <p>
 85  
      * @param cache
 86  
      */
 87  
     public RemoteCacheNoWait( IRemoteCacheClient cache )
 88  63
     {
 89  63
         this.cache = cache;
 90  63
         CacheEventQueueFactory fact = new CacheEventQueueFactory();
 91  63
         this.cacheEventQueue = fact.createCacheEventQueue( new CacheAdaptor( cache ), cache.getListenerId(), cache.getCacheName(),
 92  
                                              cache.getAuxiliaryCacheAttributes().getEventQueuePoolName(), cache
 93  
                                                  .getAuxiliaryCacheAttributes().getEventQueueTypeFactoryCode() );
 94  
 
 95  63
         if ( cache.getStatus() == CacheConstants.STATUS_ERROR )
 96  
         {
 97  7
             cacheEventQueue.destroy();
 98  
         }
 99  63
     }
 100  
 
 101  
     /**
 102  
      * Adds a put event to the queue.
 103  
      * <p>
 104  
      * (non-Javadoc)
 105  
      * @see org.apache.jcs.engine.behavior.ICache#update(org.apache.jcs.engine.behavior.ICacheElement)
 106  
      */
 107  
     public void update( ICacheElement ce )
 108  
         throws IOException
 109  
     {
 110  742
         putCount++;
 111  
         try
 112  
         {
 113  742
             cacheEventQueue.addPutEvent( ce );
 114  
         }
 115  0
         catch ( IOException ex )
 116  
         {
 117  0
             log.error( "Problem adding putEvent to queue.", ex );
 118  0
             cacheEventQueue.destroy();
 119  0
             throw ex;
 120  742
         }
 121  742
     }
 122  
 
 123  
     /**
 124  
      * Synchronously reads from the remote cache.
 125  
      * <p>
 126  
      * @param key
 127  
      * @return
 128  
      * @throws IOException
 129  
      */
 130  
     public ICacheElement get( Serializable key )
 131  
         throws IOException
 132  
     {
 133  28
         getCount++;
 134  
         try
 135  
         {
 136  28
             return cache.get( key );
 137  
         }
 138  0
         catch ( UnmarshalException ue )
 139  
         {
 140  0
             if ( log.isDebugEnabled() )
 141  
             {
 142  0
                 log.debug( "Retrying the get owing to UnmarshalException..." );
 143  
             }
 144  
             try
 145  
             {
 146  0
                 return cache.get( key );
 147  
             }
 148  0
             catch ( IOException ex )
 149  
             {
 150  0
                 if ( log.isInfoEnabled() )
 151  
                 {
 152  0
                     log.info( "Failed in retrying the get for the second time. " + ex.getMessage() );
 153  
                 }
 154  
             }
 155  
         }
 156  0
         catch ( IOException ex )
 157  
         {
 158  
             // We don't want to destroy the queue on a get failure.
 159  
             // The RemoteCache will Zombie and queue.
 160  
             // Since get does not use the queue, I dont want to killing the queue.
 161  0
             throw ex;
 162  0
         }
 163  0
         return null;
 164  
     }
 165  
 
 166  
     public Set getGroupKeys( String groupName )
 167  
         throws IOException
 168  
     {
 169  0
         return cache.getGroupKeys( groupName );
 170  
     }
 171  
 
 172  
     /**
 173  
      * Adds a remove request to the remote cache.
 174  
      * <p>
 175  
      * @param key
 176  
      * @return
 177  
      * @throws IOException
 178  
      */
 179  
     public boolean remove( Serializable key )
 180  
         throws IOException
 181  
     {
 182  14
         removeCount++;
 183  
         try
 184  
         {
 185  14
             cacheEventQueue.addRemoveEvent( key );
 186  
         }
 187  0
         catch ( IOException ex )
 188  
         {
 189  0
             log.error( "Problem adding RemoveEvent to queue.", ex );
 190  0
             cacheEventQueue.destroy();
 191  0
             throw ex;
 192  14
         }
 193  14
         return false;
 194  
     }
 195  
 
 196  
     /**
 197  
      * Adds a removeAll request to the remote cache.
 198  
      * <p>
 199  
      * @throws IOException
 200  
      */
 201  
     public void removeAll()
 202  
         throws IOException
 203  
     {
 204  
         try
 205  
         {
 206  0
             cacheEventQueue.addRemoveAllEvent();
 207  
         }
 208  0
         catch ( IOException ex )
 209  
         {
 210  0
             log.error( "Problem adding RemoveAllEvent to queue.", ex );
 211  0
             cacheEventQueue.destroy();
 212  0
             throw ex;
 213  0
         }
 214  0
     }
 215  
 
 216  
     /** Adds a dispose request to the remote cache. */
 217  
     public void dispose()
 218  
     {
 219  
         try
 220  
         {
 221  0
             cacheEventQueue.addDisposeEvent();
 222  
         }
 223  0
         catch ( IOException ex )
 224  
         {
 225  0
             log.error( "Problem adding DisposeEvent to queue.", ex );
 226  0
             cacheEventQueue.destroy();
 227  0
         }
 228  0
     }
 229  
 
 230  
     /**
 231  
      * No remote invocation.
 232  
      * <p>
 233  
      * @return The size value
 234  
      */
 235  
     public int getSize()
 236  
     {
 237  0
         return cache.getSize();
 238  
     }
 239  
 
 240  
     /**
 241  
      * No remote invokation.
 242  
      * <p>
 243  
      * @return The cacheType value
 244  
      */
 245  
     public int getCacheType()
 246  
     {
 247  0
         return ICacheType.REMOTE_CACHE;
 248  
     }
 249  
 
 250  
     /**
 251  
      * Returns the asyn cache status. An error status indicates either the remote connection is not
 252  
      * available, or the asyn queue has been unexpectedly destroyed. No remote invocation.
 253  
      * <p>
 254  
      * @return The status value
 255  
      */
 256  
     public int getStatus()
 257  
     {
 258  14
         return cacheEventQueue.isWorking() ? cache.getStatus() : CacheConstants.STATUS_ERROR;
 259  
     }
 260  
 
 261  
     /**
 262  
      * Gets the cacheName attribute of the RemoteCacheNoWait object
 263  
      * <p>
 264  
      * @return The cacheName value
 265  
      */
 266  
     public String getCacheName()
 267  
     {
 268  0
         return cache.getCacheName();
 269  
     }
 270  
 
 271  
     /**
 272  
      * Replaces the remote cache service handle with the given handle and reset the event queue by
 273  
      * starting up a new instance.
 274  
      * <p>
 275  
      * @param remote
 276  
      */
 277  
     public void fixCache( IRemoteCacheService remote )
 278  
     {
 279  7
         cache.fixCache( remote );
 280  7
         resetEventQ();
 281  7
         return;
 282  
     }
 283  
 
 284  
     /**
 285  
      * Resets the event q by first destroying the existing one and starting up new one.
 286  
      * <p>
 287  
      * There may be no good reason to kill the existing queue. We will sometimes need to set a new
 288  
      * listener id, so we should create a new queue. We should let the old queue drain. If we were
 289  
      * conencted to the failover, it would be best to finish sending items.
 290  
      */
 291  
     public void resetEventQ()
 292  
     {
 293  7
         ICacheEventQueue previousQueue = cacheEventQueue;
 294  
 
 295  7
         CacheEventQueueFactory fact = new CacheEventQueueFactory();
 296  7
         this.cacheEventQueue = fact.createCacheEventQueue( new CacheAdaptor( cache ), cache.getListenerId(), cache.getCacheName(),
 297  
                                              cache.getAuxiliaryCacheAttributes().getEventQueuePoolName(), cache
 298  
                                                  .getAuxiliaryCacheAttributes().getEventQueueTypeFactoryCode() );
 299  
 
 300  7
         if ( previousQueue.isWorking() )
 301  
         {
 302  
             // we don't expect anything, it would have all gone to the zombie
 303  7
             if ( log.isInfoEnabled() )
 304  
             {
 305  7
                 log.info( "resetEventQ, previous queue has [" + previousQueue.size() + "] items queued up." );
 306  
             }
 307  7
             previousQueue.destroy();
 308  
         }
 309  7
     }
 310  
 
 311  
     /**
 312  
      * This is temporary. It allows the manager to get the lister.
 313  
      * <p>
 314  
      * @return
 315  
      */
 316  
     protected IRemoteCacheClient getRemoteCache()
 317  
     {
 318  0
         return cache;
 319  
     }
 320  
 
 321  
     /**
 322  
      * @return Returns the AuxiliaryCacheAttributes.
 323  
      */
 324  
     public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes()
 325  
     {
 326  0
         return cache.getAuxiliaryCacheAttributes();
 327  
     }
 328  
 
 329  
     /**
 330  
      * This is for testing only.  It allows you to take a look at the event queue.
 331  
      * <p>
 332  
      * @return ICacheEventQueue
 333  
      */
 334  
     protected ICacheEventQueue getCacheEventQueue()
 335  
     {
 336  14
         return this.cacheEventQueue;
 337  
     }
 338  
 
 339  
     /**
 340  
      * Returns the stats and the cache.toString().
 341  
      * <p>
 342  
      * (non-Javadoc)
 343  
      * @see java.lang.Object#toString()
 344  
      */
 345  
     public String toString()
 346  
     {
 347  0
         return getStats() + "\n" + cache.toString();
 348  
     }
 349  
 
 350  
     /**
 351  
      * Returns the statistics in String form.
 352  
      * <p>
 353  
      * @return String
 354  
      */
 355  
     public String getStats()
 356  
     {
 357  7
         return getStatistics().toString();
 358  
     }
 359  
 
 360  
     /*
 361  
      * (non-Javadoc)
 362  
      * @see org.apache.jcs.auxiliary.AuxiliaryCache#getStatistics()
 363  
      */
 364  
     public IStats getStatistics()
 365  
     {
 366  7
         IStats stats = new Stats();
 367  7
         stats.setTypeName( "Remote Cache No Wait" );
 368  
 
 369  7
         ArrayList elems = new ArrayList();
 370  
 
 371  7
         IStatElement se = null;
 372  
 
 373  7
         se = new StatElement();
 374  7
         se.setName( "Status" );
 375  7
         int status = this.getStatus();
 376  7
         if ( status == CacheConstants.STATUS_ERROR )
 377  
         {
 378  0
             se.setData( "ERROR" );
 379  0
         }
 380  7
         else if ( status == CacheConstants.STATUS_ALIVE )
 381  
         {
 382  7
             se.setData( "ALIVE" );
 383  7
         }
 384  0
         else if ( status == CacheConstants.STATUS_DISPOSED )
 385  
         {
 386  0
             se.setData( "DISPOSED" );
 387  0
         }
 388  
         else
 389  
         {
 390  0
             se.setData( "" + status );
 391  
         }
 392  7
         elems.add( se );
 393  
 
 394  
         // no data gathered here
 395  
 
 396  
         // get the stats from the cache queue too
 397  
         // get as array, convert to list, add list to our outer list
 398  7
         IStats cStats = this.cache.getStatistics();
 399  7
         if ( cStats != null )
 400  
         {
 401  0
             IStatElement[] cSEs = cStats.getStatElements();
 402  0
             List cL = Arrays.asList( cSEs );
 403  0
             elems.addAll( cL );
 404  
         }
 405  
 
 406  
         // get the stats from the event queue too
 407  
         // get as array, convert to list, add list to our outer list
 408  7
         IStats eqStats = this.cacheEventQueue.getStatistics();
 409  7
         IStatElement[] eqSEs = eqStats.getStatElements();
 410  7
         List eqL = Arrays.asList( eqSEs );
 411  7
         elems.addAll( eqL );
 412  
 
 413  7
         se = new StatElement();
 414  7
         se.setName( "Get Count" );
 415  7
         se.setData( "" + this.getCount );
 416  7
         elems.add( se );
 417  
 
 418  7
         se = new StatElement();
 419  7
         se.setName( "Remove Count" );
 420  7
         se.setData( "" + this.removeCount );
 421  7
         elems.add( se );
 422  
 
 423  7
         se = new StatElement();
 424  7
         se.setName( "Put Count" );
 425  7
         se.setData( "" + this.putCount );
 426  7
         elems.add( se );
 427  
 
 428  
         // get an array and put them in the Stats object
 429  7
         IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[elems.size()] );
 430  7
         stats.setStatElements( ses );
 431  
 
 432  7
         return stats;
 433  
     }
 434  
 
 435  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.