1 package org.apache.jcs.auxiliary.disk.jdbc.mysql;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
56 private static final int DAILY_INTERVAL = 60 * 60 * 24 * 1000;
57
58
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
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
196 if ( daemon == null )
197 {
198
199 daemon = new Timer( true );
200 }
201
202
203 TimerTask runnable = new OptimizerTask( optimizer );
204
205
206
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 }