1 package org.apache.commons.jcs3.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.sql.Connection;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.sql.Statement;
26
27 import javax.sql.DataSource;
28
29 import org.apache.commons.jcs3.auxiliary.disk.jdbc.TableState;
30 import org.apache.commons.jcs3.log.Log;
31 import org.apache.commons.jcs3.log.LogManager;
32 import org.apache.commons.jcs3.utils.timing.ElapsedTimer;
33
34
35
36
37
38
39
40
41
42 public class MySQLTableOptimizer
43 {
44
45 private static final Log log = LogManager.getLog( MySQLTableOptimizer.class );
46
47
48 private final DataSource dataSource;
49
50
51 private String tableName;
52
53
54 private final TableState tableState;
55
56
57
58
59
60
61
62
63 public MySQLTableOptimizer( final MySQLDiskCacheAttributes attributes, final TableState tableState, final DataSource dataSource )
64 {
65 setTableName( attributes.getTableName() );
66
67 this.tableState = tableState;
68 this.dataSource = dataSource;
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public boolean optimizeTable()
117 {
118 final ElapsedTimer timer = new ElapsedTimer();
119 boolean success = false;
120
121 if ( tableState.getState() == TableState.OPTIMIZATION_RUNNING )
122 {
123 log.warn( "Skipping optimization. Optimize was called, but the "
124 + "table state indicates that an optimization is currently running." );
125 return false;
126 }
127
128 try
129 {
130 tableState.setState( TableState.OPTIMIZATION_RUNNING );
131 log.info( "Optimizing table [{0}]", this.getTableName());
132
133 try (Connection con = dataSource.getConnection())
134 {
135
136 try (Statement sStatement = con.createStatement())
137 {
138 try (ResultSet rs = sStatement.executeQuery( "optimize table " + this.getTableName() ))
139 {
140
141
142
143
144 if ( rs.next() )
145 {
146 final String status = rs.getString( "Msg_type" );
147 final String message = rs.getString( "Msg_text" );
148
149 log.info( "Message Type: {0}", status );
150 log.info( "Message: {0}", message );
151
152 if ( "error".equals( status ) )
153 {
154 log.warn( "Optimization was in error. Will attempt "
155 + "to repair the table. Message: {0}", message);
156
157
158 success = repairTable( sStatement );
159 }
160 else
161 {
162 success = true;
163 }
164 }
165 }
166
167
168 final String statusString = getTableStatus( sStatement );
169 log.info( "Table status after optimizing table [{0}]: {1}",
170 this.getTableName(), statusString );
171 }
172 catch ( final SQLException e )
173 {
174 log.error( "Problem optimizing table [{0}]",
175 this.getTableName(), e );
176 return false;
177 }
178 }
179 catch ( final SQLException e )
180 {
181 log.error( "Problem getting connection.", e );
182 }
183 }
184 finally
185 {
186 tableState.setState( TableState.FREE );
187
188 log.info( "Optimization of table [{0}] took {1} ms.",
189 this::getTableName, timer::getElapsedTime);
190 }
191
192 return success;
193 }
194
195
196
197
198
199
200
201
202 protected String getTableStatus( final Statement sStatement )
203 throws SQLException
204 {
205 final StringBuilder statusString = new StringBuilder();
206 try (ResultSet statusResultSet = sStatement.executeQuery( "show table status" ))
207 {
208 final int numColumns = statusResultSet.getMetaData().getColumnCount();
209 while ( statusResultSet.next() )
210 {
211 statusString.append( "\n" );
212 for ( int i = 1; i <= numColumns; i++ )
213 {
214 statusString.append(statusResultSet.getMetaData().getColumnLabel(i))
215 .append(" [")
216 .append(statusResultSet.getString(i))
217 .append("] | ");
218 }
219 }
220 }
221 return statusString.toString();
222 }
223
224
225
226
227
228
229
230
231
232
233
234 protected boolean repairTable( final Statement sStatement )
235 throws SQLException
236 {
237 boolean success = false;
238
239
240 final StringBuilder repairString = new StringBuilder();
241 try (ResultSet repairResult = sStatement.executeQuery( "repair table " + this.getTableName()))
242 {
243 final int numColumns = repairResult.getMetaData().getColumnCount();
244 while ( repairResult.next() )
245 {
246 for ( int i = 1; i <= numColumns; i++ )
247 {
248 repairString.append(repairResult.getMetaData().getColumnLabel(i))
249 .append(" [")
250 .append(repairResult.getString(i))
251 .append("] | ");
252 }
253
254 final String message = repairResult.getString( "Msg_text" );
255 if ( "OK".equals( message ) )
256 {
257 success = true;
258 }
259 }
260 }
261
262 log.info("{0}", repairString);
263
264 if ( !success )
265 {
266 log.warn( "Failed to repair the table. {0}", repairString );
267 }
268 return success;
269 }
270
271
272
273
274 public void setTableName( final String tableName )
275 {
276 this.tableName = tableName;
277 }
278
279
280
281
282 public String getTableName()
283 {
284 return tableName;
285 }
286 }