Coverage report

  %line %branch
org.apache.jcs.auxiliary.disk.jdbc.JDBCDiskCache
68% 
93% 

 1  
 package org.apache.jcs.auxiliary.disk.jdbc;
 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.sql.Connection;
 25  
 import java.sql.Date;
 26  
 import java.sql.PreparedStatement;
 27  
 import java.sql.ResultSet;
 28  
 import java.sql.SQLException;
 29  
 import java.sql.Statement;
 30  
 import java.util.ArrayList;
 31  
 import java.util.Arrays;
 32  
 import java.util.List;
 33  
 import java.util.Set;
 34  
 
 35  
 import org.apache.commons.logging.Log;
 36  
 import org.apache.commons.logging.LogFactory;
 37  
 import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes;
 38  
 import org.apache.jcs.auxiliary.disk.AbstractDiskCache;
 39  
 import org.apache.jcs.engine.CacheConstants;
 40  
 import org.apache.jcs.engine.behavior.ICacheElement;
 41  
 import org.apache.jcs.engine.behavior.IElementSerializer;
 42  
 import org.apache.jcs.engine.stats.StatElement;
 43  
 import org.apache.jcs.engine.stats.behavior.IStatElement;
 44  
 import org.apache.jcs.engine.stats.behavior.IStats;
 45  
 import org.apache.jcs.utils.serialization.StandardSerializer;
 46  
 
 47  
 /**
 48  
  * This is the jdbc disk cache plugin.
 49  
  * <p>
 50  
  * It expects a table created by the following script. The table name is
 51  
  * configurable.
 52  
  * <p>
 53  
  *
 54  
  * <pre>
 55  
  *                       drop TABLE JCS_STORE;
 56  
  *
 57  
  *                       CREATE TABLE JCS_STORE
 58  
  *                       (
 59  
  *                       CACHE_KEY                  VARCHAR(250)          NOT NULL,
 60  
  *                       REGION                     VARCHAR(250)          NOT NULL,
 61  
  *                       ELEMENT                    BLOB,
 62  
  *                       CREATE_TIME                DATE,
 63  
  *                       CREATE_TIME_SECONDS        BIGINT,
 64  
  *                       MAX_LIFE_SECONDS           BIGINT,
 65  
  *                       SYSTEM_EXPIRE_TIME_SECONDS BIGINT,
 66  
  *                       IS_ETERNAL                 CHAR(1),
 67  
  *                       PRIMARY KEY (CACHE_KEY, REGION)
 68  
  *                       );
 69  
  * </pre>
 70  
  *
 71  
  * <p>
 72  
  * The cleanup thread will delete non eternal items where (now - create time) >
 73  
  * max life seconds * 1000
 74  
  * <p>
 75  
  * To speed up the deletion the SYSTEM_EXPIRE_TIME_SECONDS is used instead. It
 76  
  * is recommended that an index be created on this column is you will have over
 77  
  * a million records.
 78  
  * <p>
 79  
  * @author Aaron Smuts
 80  
  */
 81  
 public class JDBCDiskCache
 82  
     extends AbstractDiskCache
 83  
 {
 84  70
     private final static Log log = LogFactory.getLog( JDBCDiskCache.class );
 85  
 
 86  
     private static final long serialVersionUID = -7169488308515823492L;
 87  
 
 88  49
     private IElementSerializer elementSerializer = new StandardSerializer();
 89  
 
 90  
     private JDBCDiskCacheAttributes jdbcDiskCacheAttributes;
 91  
 
 92  49
     private int updateCount = 0;
 93  
 
 94  49
     private int getCount = 0;
 95  
 
 96  
     // if count % interval == 0 then log
 97  
     private static final int LOG_INTERVAL = 100;
 98  
 
 99  49
     private JDBCDiskCachePoolAccess poolAccess = null;
 100  
 
 101  
     private TableState tableState;
 102  
 
 103  
     /**
 104  
      * Constructs a JDBC Disk Cache for the provided cache attributes. The table
 105  
      * state object is used to mark deletions.
 106  
      * <p>
 107  
      * @param cattr
 108  
      * @param tableState
 109  
      */
 110  
     public JDBCDiskCache( JDBCDiskCacheAttributes cattr, TableState tableState )
 111  
     {
 112  49
         super( cattr );
 113  
 
 114  49
         this.setTableState( tableState );
 115  
 
 116  49
         setJdbcDiskCacheAttributes( cattr );
 117  
 
 118  49
         if ( log.isInfoEnabled() )
 119  
         {
 120  49
             log.info( "jdbcDiskCacheAttributes = " + getJdbcDiskCacheAttributes() );
 121  
         }
 122  
 
 123  
         /**
 124  
          * This initializes the pool access.
 125  
          */
 126  49
         initializePoolAccess( cattr );
 127  
 
 128  
         // Initialization finished successfully, so set alive to true.
 129  49
         alive = true;
 130  49
     }
 131  
 
 132  
     /**
 133  
      * Registers the driver and creates a poolAccess class.
 134  
      * @param cattr
 135  
      */
 136  
     protected void initializePoolAccess( JDBCDiskCacheAttributes cattr )
 137  
     {
 138  
         try
 139  
         {
 140  
             try
 141  
             {
 142  
                 // org.gjt.mm.mysql.Driver
 143  49
                 Class.forName( cattr.getDriverClassName() );
 144  
             }
 145  0
             catch ( ClassNotFoundException e )
 146  
             {
 147  0
                 log.error( "Couldn't find class for driver [" + cattr.getDriverClassName() + "]", e );
 148  49
             }
 149  
 
 150  49
             poolAccess = new JDBCDiskCachePoolAccess( cattr.getName() );
 151  
 
 152  49
             poolAccess.setupDriver( cattr.getUrl() + cattr.getDatabase(), cattr.getUserName(), cattr.getPassword(),
 153  
                                     cattr.getMaxActive() );
 154  
 
 155  49
             poolAccess.logDriverStats();
 156  
         }
 157  0
         catch ( Exception e )
 158  
         {
 159  0
             log.error( "Problem getting connection.", e );
 160  49
         }
 161  49
     }
 162  
 
 163  
     /*
 164  
      * (non-Javadoc)
 165  
      * @see org.apache.jcs.auxiliary.disk.AbstractDiskCache#doUpdate(org.apache.jcs.engine.behavior.ICacheElement)
 166  
      */
 167  
     public void doUpdate( ICacheElement ce )
 168  
     {
 169  6355
         incrementUpdateCount();
 170  
 
 171  6356
         if ( log.isDebugEnabled() )
 172  
         {
 173  0
             log.debug( "updating, ce = " + ce );
 174  
         }
 175  
 
 176  
         Connection con;
 177  
         try
 178  
         {
 179  6351
             con = poolAccess.getConnection();
 180  
         }
 181  0
         catch ( SQLException e )
 182  
         {
 183  0
             log.error( "Problem getting conenction.", e );
 184  0
             return;
 185  6356
         }
 186  
 
 187  
         try
 188  
         {
 189  
             // TEST
 190  6356
             Statement sStatement = null;
 191  
             try
 192  
             {
 193  6356
                 sStatement = con.createStatement();
 194  6356
                 alive = true;
 195  
             }
 196  0
             catch ( SQLException e )
 197  
             {
 198  0
                 log.error( "Problem creating statement.", e );
 199  0
                 alive = false;
 200  
             }
 201  
             finally
 202  
             {
 203  0
                 try
 204  
                 {
 205  6355
                     sStatement.close();
 206  
                 }
 207  0
                 catch ( SQLException e )
 208  
                 {
 209  0
                     log.error( "Problem closing statement.", e );
 210  6356
                 }
 211  0
             }
 212  
 
 213  6356
             if ( !alive )
 214  
             {
 215  0
                 if ( log.isInfoEnabled() )
 216  
                 {
 217  0
                     log.info( "Disk is not alive, aborting put." );
 218  
                 }
 219  
                 return;
 220  
             }
 221  
 
 222  6356
             if ( log.isDebugEnabled() )
 223  
             {
 224  0
                 log.debug( "Putting [" + ce.getKey() + "] on disk." );
 225  
             }
 226  
 
 227  
             byte[] element;
 228  
 
 229  
             try
 230  
             {
 231  6356
                 element = serialize( ce );
 232  
             }
 233  0
             catch ( IOException e )
 234  
             {
 235  0
                 log.error( "Could not serialize element", e );
 236  
                 return;
 237  6355
             }
 238  
 
 239  6355
             boolean exists = false;
 240  
 
 241  
             // First do a query to determine if the element already exists
 242  6354
             if ( this.getJdbcDiskCacheAttributes().isTestBeforeInsert() )
 243  
             {
 244  0
                 exists = doesElementExist( ce );
 245  
             }
 246  
 
 247  
             // If it doesn't exist, insert it, otherwise update
 248  6355
             if ( !exists )
 249  
             {
 250  
                 try
 251  
                 {
 252  6353
                     String sqlI = "insert into "
 253  
                         + getJdbcDiskCacheAttributes().getTableName()
 254  
                         + " (CACHE_KEY, REGION, ELEMENT, MAX_LIFE_SECONDS, IS_ETERNAL, CREATE_TIME, CREATE_TIME_SECONDS, SYSTEM_EXPIRE_TIME_SECONDS) "
 255  
                         + " values (?, ?, ?, ?, ?, ?, ?, ?)";
 256  
 
 257  6356
                     PreparedStatement psInsert = con.prepareStatement( sqlI );
 258  6355
                     psInsert.setString( 1, (String) ce.getKey() );
 259  6356
                     psInsert.setString( 2, this.getCacheName() );
 260  6355
                     psInsert.setBytes( 3, element );
 261  6355
                     psInsert.setLong( 4, ce.getElementAttributes().getMaxLifeSeconds() );
 262  6355
                     if ( ce.getElementAttributes().getIsEternal() )
 263  
                     {
 264  1407
                         psInsert.setString( 5, "T" );
 265  1407
                     }
 266  
                     else
 267  
                     {
 268  4949
                         psInsert.setString( 5, "F" );
 269  
                     }
 270  6355
                     Date createTime = new Date( ce.getElementAttributes().getCreateTime() );
 271  6355
                     psInsert.setDate( 6, createTime );
 272  
 
 273  6356
                     long now = System.currentTimeMillis() / 1000;
 274  6355
                     psInsert.setLong( 7, now );
 275  
 
 276  6356
                     long expireTime = now + ce.getElementAttributes().getMaxLifeSeconds();
 277  6356
                     psInsert.setLong( 8, expireTime );
 278  
 
 279  6356
                     psInsert.execute();
 280  5635
                     psInsert.close();
 281  
                 }
 282  721
                 catch ( SQLException e )
 283  
                 {
 284  721
                     if ( e.toString().indexOf( "Violation of unique index" ) != -1
 285  
                         || e.getMessage().indexOf( "Violation of unique index" ) != -1
 286  
                         || e.getMessage().indexOf( "Duplicate entry" ) != -1 )
 287  
                     {
 288  0
                         exists = true;
 289  0
                     }
 290  
                     else
 291  
                     {
 292  721
                         log.error( "Could not insert element", e );
 293  
                     }
 294  
 
 295  
                     // see if it exists, if we didn't already
 296  721
                     if ( !exists && !this.getJdbcDiskCacheAttributes().isTestBeforeInsert() )
 297  
                     {
 298  721
                         exists = doesElementExist( ce );
 299  
                     }
 300  5635
                 }
 301  
             }
 302  
 
 303  
             // update if it exists.
 304  6356
             if ( exists )
 305  
             {
 306  721
                 String sqlU = null;
 307  
                 try
 308  
                 {
 309  721
                     sqlU = "update " + getJdbcDiskCacheAttributes().getTableName()
 310  
                         + " set ELEMENT  = ?, CREATE_TIME = ?, CREATE_TIME_SECONDS = ?, "
 311  
                         + " SYSTEM_EXPIRE_TIME_SECONDS = ? " + " where CACHE_KEY = ? and REGION = ?";
 312  721
                     PreparedStatement psUpdate = con.prepareStatement( sqlU );
 313  721
                     psUpdate.setBytes( 1, element );
 314  
 
 315  721
                     Date createTime = new Date( ce.getElementAttributes().getCreateTime() );
 316  721
                     psUpdate.setDate( 2, createTime );
 317  
 
 318  721
                     long now = System.currentTimeMillis() / 1000;
 319  721
                     psUpdate.setLong( 3, now );
 320  
 
 321  721
                     long expireTime = now + ce.getElementAttributes().getMaxLifeSeconds();
 322  721
                     psUpdate.setLong( 4, expireTime );
 323  
 
 324  721
                     psUpdate.setString( 5, (String) ce.getKey() );
 325  721
                     psUpdate.setString( 6, this.getCacheName() );
 326  721
                     psUpdate.execute();
 327  721
                     psUpdate.close();
 328  
 
 329  721
                     if ( log.isDebugEnabled() )
 330  
                     {
 331  0
                         log.debug( "ran update " + sqlU );
 332  
                     }
 333  
                 }
 334  0
                 catch ( SQLException e2 )
 335  
                 {
 336  0
                     log.error( "e2 sql [" + sqlU + "] Exception: ", e2 );
 337  721
                 }
 338  
             }
 339  
         }
 340  
         finally
 341  
         {
 342  0
             try
 343  
             {
 344  6354
                 con.close();
 345  
             }
 346  0
             catch ( SQLException e )
 347  
             {
 348  0
                 log.error( "Problem closing connection.", e );
 349  6355
             }
 350  0
         }
 351  
 
 352  6356
         if ( log.isInfoEnabled() )
 353  
         {
 354  6356
             if ( updateCount % LOG_INTERVAL == 0 )
 355  
             {
 356  
                 // TODO make a log stats method
 357  70
                 log.info( "Update Count [" + updateCount + "]" );
 358  
             }
 359  
         }
 360  6356
     }
 361  
 
 362  
     /**
 363  
      * Does an element exist for this key?
 364  
      * <p>
 365  
      * @param ce
 366  
      * @return boolean
 367  
      */
 368  
     protected boolean doesElementExist( ICacheElement ce )
 369  
     {
 370  721
         boolean exists = false;
 371  
 
 372  
         Connection con;
 373  
         try
 374  
         {
 375  721
             con = poolAccess.getConnection();
 376  
         }
 377  0
         catch ( SQLException e )
 378  
         {
 379  0
             log.error( "Problem getting conenction.", e );
 380  0
             return exists;
 381  721
         }
 382  
 
 383  721
         PreparedStatement psSelect = null;
 384  
         try
 385  
         {
 386  
             // don't select the element, since we want this to be fast.
 387  721
             String sqlS = "select CACHE_KEY from " + getJdbcDiskCacheAttributes().getTableName()
 388  
                 + " where REGION = ? and CACHE_KEY = ?";
 389  
 
 390  721
             psSelect = con.prepareStatement( sqlS );
 391  721
             psSelect.setString( 1, this.getCacheName() );
 392  721
             psSelect.setString( 2, (String) ce.getKey() );
 393  
 
 394  721
             ResultSet rs = psSelect.executeQuery();
 395  
 
 396  721
             if ( rs.next() )
 397  
             {
 398  721
                 exists = true;
 399  
             }
 400  
 
 401  721
             if ( log.isDebugEnabled() )
 402  
             {
 403  0
                 log.debug( "[" + ce.getKey() + "] existing status is " + exists );
 404  
             }
 405  
 
 406  721
             rs.close();
 407  
         }
 408  0
         catch ( SQLException e )
 409  
         {
 410  0
             log.error( "Problem looking for item before insert.", e );
 411  
         }
 412  
         finally
 413  
         {
 414  0
             try
 415  
             {
 416  721
                 if ( psSelect != null )
 417  
                 {
 418  721
                     psSelect.close();
 419  
                 }
 420  721
                 psSelect.close();
 421  
             }
 422  0
             catch ( SQLException e1 )
 423  
             {
 424  0
                 log.error( "Problem closing statement.", e1 );
 425  721
             }
 426  
 
 427  
             try
 428  
             {
 429  721
                 con.close();
 430  
             }
 431  0
             catch ( SQLException e )
 432  
             {
 433  0
                 log.error( "Problem closing connection.", e );
 434  721
             }
 435  0
         }
 436  
 
 437  721
         return exists;
 438  
     }
 439  
 
 440  
     /**
 441  
      * Queries the database for the value. If it gets a result, the value is
 442  
      * deserialized.
 443  
      * <p>
 444  
      * @see org.apache.jcs.auxiliary.disk.AbstractDiskCache#doGet(java.io.Serializable)
 445  
      */
 446  
     public ICacheElement doGet( Serializable key )
 447  
     {
 448  10080
         incrementGetCount();
 449  
 
 450  10080
         if ( log.isDebugEnabled() )
 451  
         {
 452  0
             log.debug( "Getting " + key + " from disk" );
 453  
         }
 454  
 
 455  10080
         if ( !alive )
 456  
         {
 457  0
             return null;
 458  
         }
 459  
 
 460  10080
         ICacheElement obj = null;
 461  
 
 462  10080
         byte[] data = null;
 463  
         try
 464  
         {
 465  
             // region, key
 466  10080
             String selectString = "select ELEMENT from " + getJdbcDiskCacheAttributes().getTableName()
 467  
                 + " where REGION = ? and CACHE_KEY = ?";
 468  
 
 469  10080
             Connection con = poolAccess.getConnection();
 470  
             try
 471  
             {
 472  10080
                 PreparedStatement psSelect = null;
 473  
                 try
 474  
                 {
 475  10080
                     psSelect = con.prepareStatement( selectString );
 476  10080
                     psSelect.setString( 1, this.getCacheName() );
 477  10080
                     psSelect.setString( 2, key.toString() );
 478  
 
 479  10080
                     ResultSet rs = psSelect.executeQuery();
 480  
                     try
 481  
                     {
 482  10080
                         if ( rs.next() )
 483  
                         {
 484  5434
                             data = rs.getBytes( 1 );
 485  
                         }
 486  10080
                         if ( data != null )
 487  
                         {
 488  
                             try
 489  
                             {
 490  
                                 // USE THE SERIALIZER
 491  5434
                                 obj = (ICacheElement) getElementSerializer().deSerialize( data );
 492  
                             }
 493  0
                             catch ( IOException ioe )
 494  
                             {
 495  0
                                 log.error( ioe );
 496  
                             }
 497  0
                             catch ( Exception e )
 498  
                             {
 499  0
                                 log.error( "Problem getting item.", e );
 500  5434
                             }
 501  
                         }
 502  
                     }
 503  
                     finally
 504  
                     {
 505  10080
                         if ( rs != null )
 506  
                         {
 507  10080
                             rs.close();
 508  
                         }
 509  10080
                         rs.close();
 510  10080
                     }
 511  
                 }
 512  
                 finally
 513  
                 {
 514  10080
                     if ( psSelect != null )
 515  
                     {
 516  10080
                         psSelect.close();
 517  
                     }
 518  10080
                     psSelect.close();
 519  10080
                 }
 520  
             }
 521  
             finally
 522  
             {
 523  10080
                 if ( con != null )
 524  
                 {
 525  10080
                     con.close();
 526  10080
                 }
 527  0
             }
 528  
         }
 529  0
         catch ( SQLException sqle )
 530  
         {
 531  0
             log.error( sqle );
 532  10080
         }
 533  
 
 534  10080
         if ( log.isInfoEnabled() )
 535  
         {
 536  10080
             if ( getCount % LOG_INTERVAL == 0 )
 537  
             {
 538  
                 // TODO make a log stats method
 539  98
                 log.info( "Get Count [" + getCount + "]" );
 540  
             }
 541  
         }
 542  
 
 543  10080
         return obj;
 544  
     }
 545  
 
 546  
     /**
 547  
      * Returns true if the removal was succesful; or false if there is nothing
 548  
      * to remove. Current implementation always result in a disk orphan.
 549  
      * <p>
 550  
      * @param key
 551  
      * @return boolean
 552  
      */
 553  
     public boolean doRemove( Serializable key )
 554  
     {
 555  
         // remove single item.
 556  5651
         String sql = "delete from " + getJdbcDiskCacheAttributes().getTableName()
 557  
             + " where REGION = ? and CACHE_KEY = ?";
 558  
 
 559  
         try
 560  
         {
 561  5651
             boolean partial = false;
 562  5651
             if ( key instanceof String && key.toString().endsWith( CacheConstants.NAME_COMPONENT_DELIMITER ) )
 563  
             {
 564  
                 // remove all keys of the same name group.
 565  7
                 sql = "delete from " + getJdbcDiskCacheAttributes().getTableName()
 566  
                     + " where REGION = ? and CACHE_KEY like ?";
 567  7
                 partial = true;
 568  
             }
 569  5651
             Connection con = poolAccess.getConnection();
 570  5651
             PreparedStatement psSelect = null;
 571  
             try
 572  
             {
 573  5651
                 psSelect = con.prepareStatement( sql );
 574  5651
                 psSelect.setString( 1, this.getCacheName() );
 575  5651
                 if ( partial )
 576  
                 {
 577  7
                     psSelect.setString( 2, key.toString() + "%" );
 578  7
                 }
 579  
                 else
 580  
                 {
 581  5644
                     psSelect.setString( 2, key.toString() );
 582  
                 }
 583  
 
 584  5651
                 psSelect.executeUpdate( );
 585  
 
 586  5651
                 alive = true;
 587  
             }
 588  0
             catch ( SQLException e )
 589  
             {
 590  0
                 log.error( "Problem creating statement. sql [" + sql + "]", e );
 591  0
                 alive = false;
 592  
             }
 593  
             finally
 594  
             {
 595  0
                 try
 596  
                 {
 597  5651
                     if ( psSelect != null )
 598  
                     {
 599  5651
                         psSelect.close();
 600  
                     }
 601  5651
                     con.close();
 602  
                 }
 603  0
                 catch ( SQLException e1 )
 604  
                 {
 605  0
                     log.error( "Problem closing statement.", e1 );
 606  5651
                 }
 607  0
             }
 608  
 
 609  
         }
 610  0
         catch ( Exception e )
 611  
         {
 612  0
             log.error( "Problem updating cache.", e );
 613  0
             reset();
 614  5651
         }
 615  5651
         return false;
 616  
     }
 617  
 
 618  
     /** This should remove all elements. */
 619  
     public void doRemoveAll()
 620  
     {
 621  
         // it should never get here formt he abstract dis cache.
 622  0
         if ( this.jdbcDiskCacheAttributes.isAllowRemoveAll() )
 623  
         {
 624  
             try
 625  
             {
 626  0
                 String sql = "delete from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = ?";
 627  0
                 Connection con = poolAccess.getConnection();
 628  0
                 PreparedStatement psDelete = null;
 629  
                 try
 630  
                 {
 631  0
                     psDelete = con.prepareStatement( sql );
 632  0
                     psDelete.setString( 1, this.getCacheName() );
 633  0
                     alive = true;
 634  0
                     psDelete.executeUpdate( );
 635  
                 }
 636  0
                 catch ( SQLException e )
 637  
                 {
 638  0
                     log.error( "Problem creating statement.", e );
 639  0
                     alive = false;
 640  
                 }
 641  
                 finally
 642  
                 {
 643  0
                     try
 644  
                     {
 645  0
                         if ( psDelete != null )
 646  
                         {
 647  0
                             psDelete.close();
 648  
                         }
 649  0
                         con.close();
 650  
                     }
 651  0
                     catch ( SQLException e1 )
 652  
                     {
 653  0
                         log.error( "Problem closing statement.", e1 );
 654  0
                     }
 655  0
                 }
 656  
             }
 657  0
             catch ( Exception e )
 658  
             {
 659  0
                 log.error( "Problem removing all.", e );
 660  0
                 reset();
 661  0
             }
 662  0
         }
 663  
         else
 664  
         {
 665  0
             if ( log.isInfoEnabled() )
 666  
             {
 667  0
                 log.info( "RemoveAll was requested but the request was not fulfilled: allowRemoveAll is set to false." );
 668  
             }
 669  
         }
 670  0
     }
 671  
 
 672  
     /**
 673  
      * Removed the expired. (now - create time) > max life seconds * 1000
 674  
      * <p>
 675  
      * @return the number deleted
 676  
      */
 677  
     protected int deleteExpired()
 678  
     {
 679  26
         int deleted = 0;
 680  
 
 681  
         try
 682  
         {
 683  26
             getTableState().setState( TableState.DELETE_RUNNING );
 684  
 
 685  26
             long now = System.currentTimeMillis() / 1000;
 686  
 
 687  
             // This is to slow when we push over a million records
 688  
             // String sql = "delete from " +
 689  
             // getJdbcDiskCacheAttributes().getTableName() + " where REGION = '"
 690  
             // + this.getCacheName() + "' and IS_ETERNAL = 'F' and (" + now
 691  
             // + " - CREATE_TIME_SECONDS) > MAX_LIFE_SECONDS";
 692  
 
 693  26
             String sql = "delete from " + getJdbcDiskCacheAttributes().getTableName()
 694  
                 + " where IS_ETERNAL = ? and REGION = ? and ? > SYSTEM_EXPIRE_TIME_SECONDS";
 695  
 
 696  26
             Connection con = poolAccess.getConnection();
 697  26
             PreparedStatement psDelete = null;
 698  
             try
 699  
             {
 700  26
                 psDelete = con.prepareStatement( sql );
 701  26
                 psDelete.setString( 1, "F" );
 702  26
                 psDelete.setString( 2, this.getCacheName() );
 703  26
                 psDelete.setLong( 3, now );
 704  
 
 705  26
                 alive = true;
 706  
 
 707  26
                 deleted = psDelete.executeUpdate( );
 708  
             }
 709  0
             catch ( SQLException e )
 710  
             {
 711  0
                 log.error( "Problem creating statement.", e );
 712  0
                 alive = false;
 713  
             }
 714  
             finally
 715  
             {
 716  0
                 try
 717  
                 {
 718  26
                     if ( psDelete != null )
 719  
                     {
 720  26
                         psDelete.close();
 721  
                     }
 722  26
                     con.close();
 723  
                 }
 724  0
                 catch ( SQLException e1 )
 725  
                 {
 726  0
                     log.error( "Problem closing statement.", e1 );
 727  26
                 }
 728  0
             }
 729  
         }
 730  0
         catch ( Exception e )
 731  
         {
 732  0
             log.error( "Problem removing expired elements from the table.", e );
 733  0
             reset();
 734  
         }
 735  
         finally
 736  
         {
 737  26
             getTableState().setState( TableState.FREE );
 738  26
         }
 739  
 
 740  26
         return deleted;
 741  
     }
 742  
 
 743  
     /**
 744  
      * Typically this is used to handle errors by last resort, force content
 745  
      * update, or removeall
 746  
      */
 747  
     public void reset()
 748  
     {
 749  
         // nothing
 750  0
     }
 751  
 
 752  
     /** Shuts down the pool */
 753  
     public void doDispose()
 754  
     {
 755  
         try
 756  
         {
 757  0
             poolAccess.shutdownDriver();
 758  
         }
 759  0
         catch ( Exception e )
 760  
         {
 761  0
             log.error( "Problem shutting down.", e );
 762  0
         }
 763  0
     }
 764  
 
 765  
     /**
 766  
      * Returns the current cache size. Just does a count(*) for the region.
 767  
      * <p>
 768  
      * @return The size value
 769  
      */
 770  
     public int getSize()
 771  
     {
 772  112
         int size = 0;
 773  
 
 774  
         // region, key
 775  112
         String selectString = "select count(*) from " + getJdbcDiskCacheAttributes().getTableName()
 776  
             + " where REGION = ?";
 777  
 
 778  
         Connection con;
 779  
         try
 780  
         {
 781  112
             con = poolAccess.getConnection();
 782  
         }
 783  0
         catch ( SQLException e1 )
 784  
         {
 785  0
             log.error( "Problem getting conenction.", e1 );
 786  0
             return size;
 787  112
         }
 788  
         try
 789  
         {
 790  112
             PreparedStatement psSelect = null;
 791  
             try
 792  
             {
 793  112
                 psSelect = con.prepareStatement( selectString );
 794  112
                 psSelect.setString( 1, this.getCacheName() );
 795  112
                 ResultSet rs = null;
 796  
 
 797  112
                 rs = psSelect.executeQuery();
 798  
                 try
 799  
                 {
 800  112
                     if ( rs.next() )
 801  
                     {
 802  112
                         size = rs.getInt( 1 );
 803  
                     }
 804  
                 }
 805  
                 finally
 806  
                 {
 807  112
                     if ( rs != null )
 808  
                     {
 809  112
                         rs.close();
 810  
                     }
 811  112
                     rs.close();
 812  112
                 }
 813  
             }
 814  
             finally
 815  
             {
 816  112
                 if ( psSelect != null )
 817  
                 {
 818  112
                     psSelect.close();
 819  
                 }
 820  112
                 psSelect.close();
 821  112
             }
 822  
         }
 823  0
         catch ( SQLException e )
 824  
         {
 825  0
             log.error( "Problem getting size.", e );
 826  
         }
 827  
         finally
 828  
         {
 829  0
             try
 830  
             {
 831  112
                 con.close();
 832  
             }
 833  0
             catch ( SQLException e )
 834  
             {
 835  0
                 log.error( "Problem closing connection.", e );
 836  112
             }
 837  0
         }
 838  112
         return size;
 839  
     }
 840  
 
 841  
     /**
 842  
      * Returns the serialized form of the given object in a byte array.
 843  
      * <p>
 844  
      * @param obj
 845  
      * @return byte[]
 846  
      * @throws IOException
 847  
      */
 848  
     protected byte[] serialize( Serializable obj )
 849  
         throws IOException
 850  
     {
 851  6356
         return getElementSerializer().serialize( obj );
 852  
     }
 853  
 
 854  
     /**
 855  
      * @param groupName
 856  
      * @return
 857  
      */
 858  
     public Set getGroupKeys( String groupName )
 859  
     {
 860  
         if ( true )
 861  
         {
 862  0
             throw new UnsupportedOperationException( "Groups not implemented." );
 863  
         }
 864  
         return null;
 865  
     }
 866  
 
 867  
     /**
 868  
      * @param elementSerializer
 869  
      *            The elementSerializer to set.
 870  
      */
 871  
     public void setElementSerializer( IElementSerializer elementSerializer )
 872  
     {
 873  0
         this.elementSerializer = elementSerializer;
 874  0
     }
 875  
 
 876  
     /**
 877  
      * @return Returns the elementSerializer.
 878  
      */
 879  
     public IElementSerializer getElementSerializer()
 880  
     {
 881  11788
         return elementSerializer;
 882  
     }
 883  
 
 884  
     /** safely increment */
 885  
     private synchronized void incrementUpdateCount()
 886  
     {
 887  6356
         updateCount++;
 888  6356
     }
 889  
 
 890  
     /** safely increment */
 891  
     private synchronized void incrementGetCount()
 892  
     {
 893  10080
         getCount++;
 894  10080
     }
 895  
 
 896  
     /**
 897  
      * @param jdbcDiskCacheAttributes
 898  
      *            The jdbcDiskCacheAttributes to set.
 899  
      */
 900  
     protected void setJdbcDiskCacheAttributes( JDBCDiskCacheAttributes jdbcDiskCacheAttributes )
 901  
     {
 902  49
         this.jdbcDiskCacheAttributes = jdbcDiskCacheAttributes;
 903  49
     }
 904  
 
 905  
     /**
 906  
      * @return Returns the jdbcDiskCacheAttributes.
 907  
      */
 908  
     protected JDBCDiskCacheAttributes getJdbcDiskCacheAttributes()
 909  
     {
 910  30847
         return jdbcDiskCacheAttributes;
 911  
     }
 912  
 
 913  
     /**
 914  
      * @return Returns the AuxiliaryCacheAttributes.
 915  
      */
 916  
     public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes()
 917  
     {
 918  0
         return this.getJdbcDiskCacheAttributes();
 919  
     }
 920  
 
 921  
     /**
 922  
      * Extends the parent stats.
 923  
      */
 924  
     public IStats getStatistics()
 925  
     {
 926  112
         IStats stats = super.getStatistics();
 927  112
         stats.setTypeName( "JDBC/Abstract Disk Cache" );
 928  112
         stats.getStatElements();
 929  
 
 930  112
         ArrayList elems = new ArrayList();
 931  
 
 932  112
         IStatElement se = null;
 933  
 
 934  112
         se = new StatElement();
 935  112
         se.setName( "Update Count" );
 936  112
         se.setData( "" + updateCount );
 937  112
         elems.add( se );
 938  
 
 939  112
         se = new StatElement();
 940  112
         se.setName( "Get Count" );
 941  112
         se.setData( "" + getCount );
 942  112
         elems.add( se );
 943  
 
 944  112
         se = new StatElement();
 945  112
         se.setName( "Size" );
 946  112
         se.setData( "" + getSize() );
 947  112
         elems.add( se );
 948  
 
 949  112
         se = new StatElement();
 950  112
         se.setName( "Active DB Connections" );
 951  112
         se.setData( "" + poolAccess.getNumActiveInPool() );
 952  112
         elems.add( se );
 953  
 
 954  112
         se = new StatElement();
 955  112
         se.setName( "Idle DB Connections" );
 956  112
         se.setData( "" + poolAccess.getNumIdleInPool() );
 957  112
         elems.add( se );
 958  
 
 959  112
         se = new StatElement();
 960  112
         se.setName( "DB URL" );
 961  112
         se.setData( this.jdbcDiskCacheAttributes.getUrl() );
 962  112
         elems.add( se );
 963  
 
 964  
         // get the stats from the event queue too
 965  
         // get as array, convert to list, add list to our outer list
 966  112
         IStatElement[] eqSEs = stats.getStatElements();
 967  112
         List eqL = Arrays.asList( eqSEs );
 968  112
         elems.addAll( eqL );
 969  
 
 970  
         // get an array and put them in the Stats object
 971  112
         IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[0] );
 972  112
         stats.setStatElements( ses );
 973  
 
 974  112
         return stats;
 975  
     }
 976  
 
 977  
     /**
 978  
      * Returns the name of the table.
 979  
      * <p>
 980  
      * @return the table name or UNDEFINED
 981  
      */
 982  
     protected String getTableName()
 983  
     {
 984  26
         String name = "UNDEFINED";
 985  26
         if ( this.getJdbcDiskCacheAttributes() != null )
 986  
         {
 987  26
             name = this.getJdbcDiskCacheAttributes().getTableName();
 988  
         }
 989  26
         return name;
 990  
     }
 991  
 
 992  
     /**
 993  
      * @param tableState The tableState to set.
 994  
      */
 995  
     public void setTableState( TableState tableState )
 996  
     {
 997  49
         this.tableState = tableState;
 998  49
     }
 999  
 
 1000  
     /**
 1001  
      * @return Returns the tableState.
 1002  
      */
 1003  
     public TableState getTableState()
 1004  
     {
 1005  276
         return tableState;
 1006  
     }
 1007  
 
 1008  
     /**
 1009  
      * For debugging.
 1010  
      */
 1011  
     public String toString()
 1012  
     {
 1013  0
         return this.getStats();
 1014  
     }
 1015  
 }

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