00001
00025 package org.objectweb.cjdbc.controller.cache.parsing;
00026
00027
import java.sql.SQLException;
00028
import java.util.Hashtable;
00029
00030
import org.objectweb.cjdbc.common.i18n.Translate;
00031
import org.objectweb.cjdbc.common.sql.AbstractRequest;
00032
import org.objectweb.cjdbc.common.sql.ParsingGranularities;
00033
import org.objectweb.cjdbc.common.sql.RequestType;
00034
import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
00035
import org.objectweb.cjdbc.controller.requestmanager.ParserThread;
00036
import org.objectweb.cjdbc.controller.requestmanager.RequestManager;
00037
00044 public class ParsingCache
00045 {
00046 private Hashtable
cache;
00047 private Hashtable
currentlyParsing;
00048 private RequestManager
requestManager;
00049 private int granularity;
00050 private int maxNbOfEntries;
00051 private boolean backgroundParsing;
00052 private boolean caseSensitiveParsing;
00053
00061 private class CurrentlyParsingEntry
00062 {
00063 private ParserThread
parserThread;
00064 private AbstractRequest
request;
00065
00072 public CurrentlyParsingEntry(ParserThread parserThread,
00073 AbstractRequest request)
00074 {
00075
this.parserThread = parserThread;
00076
this.request = request;
00077 }
00078
00084 public ParserThread
getParserThread()
00085 {
00086
return parserThread;
00087 }
00088
00094 public AbstractRequest
getRequest()
00095 {
00096
return request;
00097 }
00098
00099 }
00100
00108 public ParsingCache(
int size,
boolean backgroundParsing)
00109 {
00110
cache =
new Hashtable(size == 0 ? 10000 : size);
00111
currentlyParsing =
new Hashtable();
00112
if (size < 0)
00113
throw new RuntimeException(
Translate.get(
"cache.parsing.invalid.size",
00114 size));
00115
if (size == 0)
00116
this.maxNbOfEntries = Integer.MAX_VALUE;
00117
else
00118
this.maxNbOfEntries = size;
00119
this.backgroundParsing = backgroundParsing;
00120
caseSensitiveParsing =
false;
00121 }
00122
00128 public int getGranularity()
00129 {
00130
return granularity;
00131 }
00132
00138 public void setGranularity(
int granularity)
00139 {
00140
this.granularity = granularity;
00141 }
00142
00148 public RequestManager
getRequestManager()
00149 {
00150
return requestManager;
00151 }
00152
00158 public void setRequestManager(RequestManager requestManager)
00159 {
00160
this.requestManager = requestManager;
00161 }
00162
00171 public void getParsingFromCache(
AbstractRequest request)
00172 {
00173
if (request.
isParsed())
00174
return;
00175
00176 String sql = request.
getSqlSkeleton();
00177
if (sql == null)
00178 sql = request.
getSQL();
00179
AbstractRequest parsedRequest = (
AbstractRequest)
cache.get(sql);
00180
00181
if (parsedRequest != null)
00182 {
00183 request.
cloneParsing(parsedRequest);
00184
return;
00185 }
00186
else if (
backgroundParsing)
00187 {
00188
synchronized (
currentlyParsing)
00189 {
00190
if (!
currentlyParsing.contains(sql))
00191 {
00192
ParserThread pt =
new ParserThread(request,
requestManager
00193 .getDatabaseSchema(),
granularity,
caseSensitiveParsing);
00194
currentlyParsing.put(sql,
new CurrentlyParsingEntry(pt, request));
00195 }
00196 }
00197 }
00198 }
00199
00206 public void getParsingFromCacheAndParseIfMissing(
AbstractRequest request)
00207
throws SQLException
00208 {
00209
if (request.isParsed())
00210
return;
00211
00212
00213 String instanciatedSQL = request.getSQL();
00214
AbstractRequest parsedRequest = (
AbstractRequest)
cache
00215 .get(instanciatedSQL);
00216
00217
if (parsedRequest == null)
00218 {
00219 String sqlSkeleton = request.getSqlSkeleton();
00220 String sql;
00221
if (sqlSkeleton != null)
00222 {
00223 sql = sqlSkeleton;
00224 parsedRequest = (
AbstractRequest)
cache.get(sql);
00225
if (parsedRequest != null)
00226 {
00227 request.cloneParsing(parsedRequest);
00228
return;
00229 }
00230 }
00231
else
00232 sql = instanciatedSQL;
00233
00234
00235
00236
00237
00238
while (
cache.size() >
maxNbOfEntries)
00239 {
00240
00241
00242
synchronized (
cache)
00243 {
00244
try
00245 {
00246
cache.remove(
cache.keys().nextElement());
00247 }
00248
catch (Exception ignore)
00249 {
00250
break;
00251 }
00252 }
00253 }
00254
00255
00256
if (
backgroundParsing)
00257 {
00258
00259
00260
CurrentlyParsingEntry cpe = (
CurrentlyParsingEntry)
currentlyParsing
00261 .get(sql);
00262
if (cpe != null)
00263 {
00264
ParserThread pt = cpe.
getParserThread();
00265
try
00266 {
00267
if (pt != null)
00268 {
00269
00270 pt.join();
00271
synchronized (
currentlyParsing)
00272 {
00273
currentlyParsing.remove(sql);
00274 }
00275
00276
00277
if ((
granularity !=
ParsingGranularities.COLUMN_UNIQUE)
00278 || (sqlSkeleton == null))
00279
00280
cache.put(instanciatedSQL, cpe.
getRequest());
00281
else
00282 {
00283
if (request.getCacheAbility() !=
RequestType.UNIQUE_CACHEABLE)
00284
00285
cache.put(sqlSkeleton, cpe.
getRequest());
00286
else
00287
00288
cache.put(instanciatedSQL, cpe.
getRequest());
00289 }
00290 }
00291 }
00292
catch (InterruptedException failed)
00293 {
00294
throw new SQLException(
Translate.get(
00295
"cache.parsing.failed.join.parser.thread",
new String[]{
00296
"" + request.getId(), failed.getMessage()}));
00297 }
00298 }
00299 }
00300
00301
00302 request.parse(
requestManager.getDatabaseSchema(),
granularity,
00303
caseSensitiveParsing);
00304
00305
00306
if ((sqlSkeleton != null)
00307 && (
granularity ==
ParsingGranularities.COLUMN_UNIQUE)
00308 && (request.getCacheAbility() ==
RequestType.UNIQUE_CACHEABLE))
00309
00310
00311
cache.put(instanciatedSQL, request);
00312
else
00313
cache.put(sql, request);
00314 }
00315
else
00316
00317 request.cloneParsing(parsedRequest);
00318 }
00319
00325 public boolean isBackgroundParsing()
00326 {
00327
return backgroundParsing;
00328 }
00329
00336 public void setBackgroundParsing(
boolean backgroundParsing)
00337 {
00338
this.backgroundParsing = backgroundParsing;
00339 }
00340
00346 public void setCaseSensitiveParsing(
boolean isCaseSensitiveParsing)
00347 {
00348
this.caseSensitiveParsing = isCaseSensitiveParsing;
00349 }
00350
00356 public boolean isCaseSensitiveParsing()
00357 {
00358
return caseSensitiveParsing;
00359 }
00360
00366 public String getXml()
00367 {
00368
return "<" +
DatabasesXmlTags.ELT_ParsingCache +
" "
00369 +
DatabasesXmlTags.ATT_backgroundParsing +
"=\"" + backgroundParsing
00370 +
"\" " +
DatabasesXmlTags.ATT_maxNbOfEntries +
"=\"" + maxNbOfEntries
00371 +
"\"/>";
00372 }
00373
00374 }