Coverage report

  %line %branch
org.apache.jcs.engine.control.event.ElementEventQueue
70% 
87% 

 1  
 package org.apache.jcs.engine.control.event;
 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  
 
 24  
 import org.apache.commons.logging.Log;
 25  
 import org.apache.commons.logging.LogFactory;
 26  
 
 27  
 import org.apache.jcs.engine.control.event.behavior.IElementEventQueue;
 28  
 import org.apache.jcs.engine.control.event.behavior.IElementEventHandler;
 29  
 import org.apache.jcs.engine.control.event.behavior.IElementEvent;
 30  
 
 31  
 /**
 32  
  * An event queue is used to propagate ordered cache events to one and only one
 33  
  * target listener.
 34  
  */
 35  3498694
 public class ElementEventQueue
 36  
     implements IElementEventQueue
 37  
 {
 38  424
     private final static Log log = LogFactory.getLog( ElementEventQueue.class );
 39  
 
 40  227
     private static int processorInstanceCount = 0;
 41  
 
 42  
     private String cacheName;
 43  
 
 44  221
     private boolean destroyed = false;
 45  
 
 46  
     private Thread t;
 47  
 
 48  
     // Internal queue implementation
 49  
 
 50  215
     private Object queueLock = new Object();
 51  
 
 52  
     // Dummy node
 53  
 
 54  215
     private Node head = new Node();
 55  
 
 56  215
     private Node tail = head;
 57  
 
 58  
     /**
 59  
      * Constructor for the ElementEventQueue object
 60  
      *
 61  
      * @param cacheName
 62  
      */
 63  6
     public ElementEventQueue( String cacheName )
 64  209
     {
 65  
 
 66  215
         this.cacheName = cacheName;
 67  
 
 68  215
         t = new QProcessor();
 69  215
         t.start();
 70  
 
 71  215
         if ( log.isDebugEnabled() )
 72  
         {
 73  0
             log.debug( "Constructed: " + this );
 74  
         }
 75  215
     }
 76  
 
 77  
     /**
 78  
      * Event Q is emtpy.
 79  
      */
 80  
     public synchronized void destroy()
 81  
     {
 82  0
         if ( !destroyed )
 83  
         {
 84  0
             destroyed = true;
 85  
 
 86  
             // sychronize on queue so the thread will not wait forever,
 87  
             // and then interrupt the QueueProcessor
 88  
 
 89  0
             synchronized ( queueLock )
 90  
             {
 91  0
                 t.interrupt();
 92  0
             }
 93  
 
 94  0
             t = null;
 95  
 
 96  0
             log.info( "Element event queue destroyed: " + this );
 97  
         }
 98  0
     }
 99  
 
 100  
     /**
 101  
      * @return the region name for the event queue
 102  
      */
 103  
     public String toString()
 104  
     {
 105  0
         return "cacheName=" + cacheName;
 106  
     }
 107  
 
 108  
     /**
 109  
      * @return The destroyed value
 110  
      */
 111  
     public boolean isAlive()
 112  
     {
 113  0
         return ( !destroyed );
 114  
     }
 115  
 
 116  
     /**
 117  
      * Adds an ElementEvent to be handled
 118  
      *
 119  
      * @param hand
 120  
      *            The IElementEventHandler
 121  
      * @param event
 122  
      *            The IElementEventHandler IElementEvent event
 123  
      * @throws IOException
 124  
      */
 125  
     public void addElementEvent( IElementEventHandler hand, IElementEvent event )
 126  
         throws IOException
 127  
     {
 128  
 
 129  700035
         if ( log.isDebugEnabled() )
 130  
         {
 131  0
             log.debug( "Adding Event Handler to QUEUE, !destroyed = " + !destroyed );
 132  
         }
 133  
 
 134  700035
         if ( !destroyed )
 135  
         {
 136  700035
             ElementEventRunner runner = new ElementEventRunner( hand, event );
 137  
 
 138  700035
             if ( log.isDebugEnabled() )
 139  
             {
 140  0
                 log.debug( "runner = " + runner );
 141  
             }
 142  
 
 143  700035
             put( runner );
 144  
         }
 145  700035
     }
 146  
 
 147  
     /**
 148  
      * Adds an event to the queue.
 149  
      *
 150  
      * @param event
 151  
      */
 152  
     private void put( AbstractElementEventRunner event )
 153  
     {
 154  700035
         Node newNode = new Node();
 155  
 
 156  700035
         newNode.event = event;
 157  
 
 158  700035
         synchronized ( queueLock )
 159  
         {
 160  700035
             tail.next = newNode;
 161  700035
             tail = newNode;
 162  
 
 163  700035
             queueLock.notify();
 164  700035
         }
 165  700035
     }
 166  
 
 167  6
     private AbstractElementEventRunner take()
 168  
         throws InterruptedException
 169  
     {
 170  700250
         synchronized ( queueLock )
 171  
         {
 172  
             // wait until there is something to read
 173  
 
 174  890369
             while ( head == tail )
 175  
             {
 176  190328
                 if ( log.isDebugEnabled() )
 177  
                 {
 178  0
                     log.debug( "Waiting for something to come into the Q" );
 179  
                 }
 180  
 
 181  190328
                 queueLock.wait();
 182  
 
 183  190113
                 if ( log.isDebugEnabled() )
 184  
                 {
 185  0
                     log.debug( "Something came into the Q" );
 186  0
                 }
 187  
             }
 188  
 
 189  
             // we have the lock, and the list is not empty
 190  
 
 191  700035
             Node node = head.next;
 192  
 
 193  700035
             AbstractElementEventRunner value = node.event;
 194  
 
 195  700035
             if ( log.isDebugEnabled() )
 196  
             {
 197  0
                 log.debug( "head.event = " + head.event );
 198  0
                 log.debug( "node.event = " + node.event );
 199  
             }
 200  
 
 201  
             // Node becomes the new head (head is always empty)
 202  
 
 203  700035
             node.event = null;
 204  700035
             head = node;
 205  
 
 206  700035
             return value;
 207  0
         }
 208  
     }
 209  
 
 210  
     ///////////////////////////// Inner classes /////////////////////////////
 211  
 
 212  
     private static class Node
 213  
     {
 214  
         Node next = null;
 215  
 
 216  
         ElementEventQueue.AbstractElementEventRunner event = null;
 217  
     }
 218  
 
 219  
     /**
 220  
      */
 221  
     private class QProcessor
 222  
         extends Thread
 223  
     {
 224  
         /**
 225  
          * Constructor for the QProcessor object
 226  
          */
 227  
         QProcessor()
 228  
         {
 229  
             super( "ElementEventQueue.QProcessor-" + ( ++processorInstanceCount ) );
 230  
 
 231  
             setDaemon( true );
 232  
         }
 233  
 
 234  
         /**
 235  
          * Main processing method for the QProcessor object
 236  
          */
 237  
         public void run()
 238  
         {
 239  
             AbstractElementEventRunner r = null;
 240  
 
 241  
             while ( !destroyed )
 242  
             {
 243  
                 try
 244  
                 {
 245  
                     r = take();
 246  
 
 247  
                     if ( log.isDebugEnabled() )
 248  
                     {
 249  
                         log.debug( "r from take() = " + r );
 250  
                     }
 251  
 
 252  
                 }
 253  
                 catch ( InterruptedException e )
 254  
                 {
 255  
                     // We were interrupted, so terminate gracefully.
 256  
 
 257  
                     this.destroy();
 258  
                 }
 259  
 
 260  
                 if ( !destroyed && r != null )
 261  
                 {
 262  
                     r.run();
 263  
                 }
 264  
             }
 265  
 
 266  
             log.info( "QProcessor exiting for " + ElementEventQueue.this );
 267  
         }
 268  
     }
 269  
 
 270  
     /**
 271  
      * Retries before declaring failure.
 272  
      *
 273  
      */
 274  
     private abstract class AbstractElementEventRunner
 275  
         implements Runnable
 276  
     {
 277  
         /**
 278  
          * Main processing method for the AbstractElementEvent object
 279  
          */
 280  
         public void run()
 281  
         {
 282  
             IOException ex = null;
 283  
 
 284  
             try
 285  
             {
 286  
                 ex = null;
 287  
                 doRun();
 288  
                 return;
 289  
                 // happy and done.
 290  
             }
 291  
             catch ( IOException e )
 292  
             {
 293  
                 ex = e;
 294  
             }
 295  
 
 296  
             // Too bad. The handler has problems.
 297  
             if ( ex != null )
 298  
             {
 299  
                 log.warn( "Giving up element event handling " + ElementEventQueue.this, ex );
 300  
 
 301  
             }
 302  
             return;
 303  
         }
 304  
 
 305  
         /**
 306  
          * Description of the Method
 307  
          *
 308  
          * @exception IOException
 309  
          */
 310  
         protected abstract void doRun()
 311  
             throws IOException;
 312  
     }
 313  
 
 314  
     /**
 315  
      */
 316  
     private class ElementEventRunner
 317  
         extends AbstractElementEventRunner
 318  
     {
 319  
 
 320  
         private IElementEventHandler hand;
 321  
 
 322  
         private IElementEvent event;
 323  
 
 324  
         /**
 325  
          * Constructor for the PutEvent object
 326  
          * @param hand
 327  
          * @param event
 328  
          * @exception IOException
 329  
          */
 330  
         ElementEventRunner( IElementEventHandler hand, IElementEvent event )
 331  
             throws IOException
 332  
         {
 333  
             if ( log.isDebugEnabled() )
 334  
             {
 335  
                 log.debug( "Constructing " + this );
 336  
             }
 337  
             this.hand = hand;
 338  
             this.event = event;
 339  
         }
 340  
 
 341  
         /**
 342  
          * Description of the Method
 343  
          *
 344  
          * @exception IOException
 345  
          */
 346  
         protected void doRun()
 347  
             throws IOException
 348  
         {
 349  
             hand.handleElementEvent( event );
 350  
         }
 351  
     }
 352  
 }

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