View Javadoc

1   package org.apache.jcs.auxiliary.disk.jdbc.mysql;
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.util.Date;
23  import java.util.Timer;
24  import java.util.TimerTask;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.jcs.auxiliary.AuxiliaryCache;
29  import org.apache.jcs.auxiliary.disk.jdbc.JDBCDiskCacheAttributes;
30  import org.apache.jcs.auxiliary.disk.jdbc.JDBCDiskCacheManagerAbstractTemplate;
31  import org.apache.jcs.auxiliary.disk.jdbc.TableState;
32  import org.apache.jcs.auxiliary.disk.jdbc.mysql.util.ScheduleFormatException;
33  import org.apache.jcs.auxiliary.disk.jdbc.mysql.util.ScheduleParser;
34  
35  /***
36   * This manages instances of the MySQL jdbc disk cache. It maintains one for
37   * each region. One for all regions would work, but this gives us more detailed
38   * stats by region.
39   * <p>
40   * Although the generic JDBC Disk Cache Manager can be used for MySQL, the MySQL
41   * JDBC Disk Cache has additional features, such as table optimization that are
42   * particular to MySQL.
43   */
44  public class MySQLDiskCacheManager
45      extends JDBCDiskCacheManagerAbstractTemplate
46  {
47      private static final long serialVersionUID = -8258856770927857896L;
48  
49      private static final Log log = LogFactory.getLog( MySQLDiskCacheManager.class );
50  
51      private static MySQLDiskCacheManager instance;
52  
53      private MySQLDiskCacheAttributes defaultJDBCDiskCacheAttributes;
54  
55      // ms in a day
56      private static final int DAILY_INTERVAL = 60 * 60 * 24 * 1000;
57  
58      // for schedule optimizations
59      private Timer daemon = null;
60  
61      /***
62       * Constructor for the HSQLCacheManager object
63       * <p>
64       * @param cattr
65       */
66      private MySQLDiskCacheManager( MySQLDiskCacheAttributes cattr )
67      {
68          if ( log.isInfoEnabled() )
69          {
70              log.info( "Creating MySQLDiskCacheManager with " + cattr );
71          }
72          defaultJDBCDiskCacheAttributes = cattr;
73      }
74  
75      /***
76       * Gets the defaultCattr attribute of the HSQLCacheManager object
77       * <p>
78       * @return The defaultCattr value
79       */
80      public MySQLDiskCacheAttributes getDefaultJDBCDiskCacheAttributes()
81      {
82          return defaultJDBCDiskCacheAttributes;
83      }
84  
85      /***
86       * Gets the instance attribute of the HSQLCacheManager class
87       * <p>
88       * @param cattr
89       * @return The instance value
90       */
91      public static MySQLDiskCacheManager getInstance( MySQLDiskCacheAttributes cattr )
92      {
93          synchronized ( MySQLDiskCacheManager.class )
94          {
95              if ( instance == null )
96              {
97                  instance = new MySQLDiskCacheManager( cattr );
98              }
99          }
100         clients++;
101         return instance;
102     }
103 
104     /***
105      * Gets the cache attribute of the HSQLCacheManager object
106      * <p>
107      * @param cacheName
108      * @return The cache value
109      */
110     public AuxiliaryCache getCache( String cacheName )
111     {
112         MySQLDiskCacheAttributes cattr = (MySQLDiskCacheAttributes) defaultJDBCDiskCacheAttributes.copy();
113         cattr.setCacheName( cacheName );
114         return getCache( cattr );
115     }
116 
117     /***
118      * Creates a JDBCDiskCache using the supplied attributes.
119      * <p>
120      * @param cattr
121      * @return
122      */
123     protected AuxiliaryCache createJDBCDiskCache( JDBCDiskCacheAttributes cattr, TableState tableState )
124     {
125         AuxiliaryCache raf = new MySQLDiskCache( (MySQLDiskCacheAttributes) cattr, tableState );
126 
127         scheduleOptimizations( (MySQLDiskCacheAttributes) cattr, tableState );
128 
129         return raf;
130     }
131 
132     /***
133      * For each time in the optimization schedule, this calls schedule
134      * Optimizaiton.
135      * <p>
136      * @param attributes
137      * @param tableState
138      */
139     protected void scheduleOptimizations( MySQLDiskCacheAttributes attributes, TableState tableState )
140     {
141         if ( attributes != null )
142         {
143             if ( attributes.getOptimizationSchedule() != null )
144             {
145                 if ( log.isInfoEnabled() )
146                 {
147                     log.info( "Will try to configure optimization for table [" + attributes.getTableName()
148                         + "] on schdule [" + attributes.getOptimizationSchedule() + "]" );
149                 }
150 
151                 MySQLTableOptimizer optimizer = new MySQLTableOptimizer( attributes, tableState );
152 
153                 // loop through the dates.
154                 try
155                 {
156                     Date[] dates = ScheduleParser.createDatesForSchedule( attributes.getOptimizationSchedule() );
157                     if ( dates != null )
158                     {
159                         for ( int i = 0; i < dates.length; i++ )
160                         {
161                             this.scheduleOptimization( dates[i], optimizer );
162                         }
163                     }
164                 }
165                 catch ( ScheduleFormatException e )
166                 {
167                     log.warn( "Problem creating optimization schedule for table [" + attributes.getTableName() + "]" );
168                 }
169             }
170             else
171             {
172                 if ( log.isInfoEnabled() )
173                 {
174                     log.info( "Optimization is not configured for table [" + attributes.getTableName() + "]" );
175                 }
176             }
177         }
178     }
179 
180     /***
181      * This takes in a single time and schedules the optimizer to be called at
182      * that time every day.
183      * <p>
184      * @param startTime --
185      *            HH:MM:SS format
186      * @param optimizer
187      */
188     protected void scheduleOptimization( Date startTime, MySQLTableOptimizer optimizer )
189     {
190         if ( log.isInfoEnabled() )
191         {
192             log.info( "startTime [" + startTime + "] for optimizer " + optimizer );
193         }
194 
195         // create clock daemon if necessary
196         if ( daemon == null )
197         {
198             // true for daemon status
199             daemon = new Timer( true );
200         }
201 
202         // get the runnable from the factory
203         TimerTask runnable = new OptimizerTask( optimizer );
204 
205         // have the daemon execut our runnable
206         // false to not execute immediately.
207         daemon.scheduleAtFixedRate( runnable, startTime, DAILY_INTERVAL );
208 
209         if ( log.isInfoEnabled() )
210         {
211             log.info( "Scheduled optimization to begin at [" + startTime + "]" );
212         }
213     }
214 
215     /***
216      * This calls the optimizers' optimize table method. This is used by the
217      * timer.
218      * <p>
219      * @author Aaron Smuts
220      */
221     private class OptimizerTask
222         extends TimerTask
223     {
224         private MySQLTableOptimizer optimizer = null;
225 
226         /***
227          * Get a handle on the optimizer.
228          * <p>
229          * @param optimizer
230          */
231         public OptimizerTask( MySQLTableOptimizer optimizer )
232         {
233             this.optimizer = optimizer;
234         }
235 
236         /***
237          * This calls optimize on the optimizer.
238          * <p>
239          * @see java.lang.Runnable#run()
240          */
241         public void run()
242         {
243             if ( optimizer != null )
244             {
245                 boolean success = optimizer.optimizeTable();
246                 if ( log.isInfoEnabled() )
247                 {
248                     log.info( "Optimization success status [" + success + "]" );
249                 }
250             }
251             else
252             {
253                 log.warn( "OptimizerRunner: The optimizer is null.  Could not optimize table." );
254             }
255         }
256     }
257 }