1 22 23 package org.continuent.sequoia.controller.cache.parsing; 24 25 import java.sql.SQLException ; 26 import java.util.Hashtable ; 27 28 import org.continuent.sequoia.common.i18n.Translate; 29 import org.continuent.sequoia.common.log.Trace; 30 import org.continuent.sequoia.common.xml.DatabasesXmlTags; 31 import org.continuent.sequoia.controller.requestmanager.ParserThread; 32 import org.continuent.sequoia.controller.requestmanager.RequestManager; 33 import org.continuent.sequoia.controller.requests.AbstractRequest; 34 import org.continuent.sequoia.controller.requests.ParsingGranularities; 35 import org.continuent.sequoia.controller.requests.RequestType; 36 import org.continuent.sequoia.controller.semantic.SemanticBehavior; 37 import org.continuent.sequoia.controller.semantic.SemanticManager; 38 39 45 public class ParsingCache 46 { 47 private static Trace logger = Trace 48 .getLogger(ParsingCache.class.getName()); 49 private Hashtable cache; 51 private Hashtable currentlyParsing; 53 private RequestManager requestManager; 54 private int granularity; 55 private int maxNbOfEntries; 56 private boolean backgroundParsing; 58 private boolean caseSensitiveParsing; 60 private SemanticManager semanticManager; 61 62 69 private class CurrentlyParsingEntry 70 { 71 private ParserThread parserThread; 72 private AbstractRequest request; 73 74 80 public CurrentlyParsingEntry(ParserThread parserThread, 81 AbstractRequest request) 82 { 83 this.parserThread = parserThread; 84 this.request = request; 85 } 86 87 92 public ParserThread getParserThread() 93 { 94 return parserThread; 95 } 96 97 102 public AbstractRequest getRequest() 103 { 104 return request; 105 } 106 107 } 108 109 118 public ParsingCache(SemanticManager semanticManager, int size, 119 boolean backgroundParsing) 120 { 121 this.semanticManager = semanticManager; 122 cache = new Hashtable (size == 0 ? 10000 : size); 123 currentlyParsing = new Hashtable (); 124 if (size < 0) 125 throw new RuntimeException (Translate.get("cache.parsing.invalid.size", 126 size)); 127 if (size == 0) 128 this.maxNbOfEntries = Integer.MAX_VALUE; 129 else 130 this.maxNbOfEntries = size; 131 this.backgroundParsing = backgroundParsing; 132 caseSensitiveParsing = false; 133 } 134 135 140 public int getGranularity() 141 { 142 return granularity; 143 } 144 145 150 public void setGranularity(int granularity) 151 { 152 this.granularity = granularity; 153 } 154 155 160 public RequestManager getRequestManager() 161 { 162 return requestManager; 163 } 164 165 170 public void setRequestManager(RequestManager requestManager) 171 { 172 this.requestManager = requestManager; 173 } 174 175 182 public void getParsingFromCacheAndParseIfMissing(AbstractRequest request) 183 throws SQLException 184 { 185 if (request.isParsed()) 186 return; 187 188 String instanciatedSQL = request.getUniqueKey(); 190 AbstractRequest parsedRequest = (AbstractRequest) cache 191 .get(instanciatedSQL); 192 193 try 194 { 195 if (parsedRequest != null) 196 { 197 request.cloneParsing(parsedRequest); 199 return; 200 } 201 202 204 request.setSemanticManager(semanticManager); 206 SemanticBehavior semantic = semanticManager.getRequestSemantic(request); 207 if (semantic != null) 208 { 209 request.setSemantic(semantic); 210 return; 211 } 212 213 String sqlSkeleton = request.getSqlOrTemplate(); 215 String sql; 216 if (sqlSkeleton != null) 217 { sql = sqlSkeleton; 219 parsedRequest = (AbstractRequest) cache.get(sql); 220 if (parsedRequest != null) 221 { request.cloneParsing(parsedRequest); 223 return; 224 } 225 } 226 else 227 sql = instanciatedSQL; 228 229 while (cache.size() > maxNbOfEntries) 234 { synchronized (cache) 239 { 240 try 241 { 242 cache.remove(cache.keys().nextElement()); 243 } 244 catch (Exception ignore) 245 { 246 break; 247 } 248 } 249 } 250 251 if (backgroundParsing) 253 { 254 CurrentlyParsingEntry cpe = (CurrentlyParsingEntry) currentlyParsing 257 .get(sql); 258 if (cpe != null) 259 { 260 ParserThread pt = cpe.getParserThread(); 261 try 262 { 263 if (pt != null) 264 { 265 pt.join(); 267 synchronized (currentlyParsing) 268 { 269 currentlyParsing.remove(sql); 270 } 271 272 if ((granularity != ParsingGranularities.COLUMN_UNIQUE) 274 || (sqlSkeleton == null)) 275 cache.put(instanciatedSQL, cpe.getRequest()); 277 else 278 { if (request.getCacheAbility() != RequestType.UNIQUE_CACHEABLE) 280 cache.put(sqlSkeleton, cpe.getRequest()); 282 else 283 cache.put(instanciatedSQL, cpe.getRequest()); 285 } 286 } 287 } 288 catch (InterruptedException failed) 289 { 290 throw new SQLException (Translate.get( 291 "cache.parsing.failed.join.parser.thread", new String []{ 292 "" + request.getId(), failed.getMessage()})); 293 } 294 } 295 } 296 request.parse(requestManager.getDatabaseSchema(), granularity, 299 caseSensitiveParsing); 300 301 if ((sqlSkeleton != null) 303 && (granularity == ParsingGranularities.COLUMN_UNIQUE) 304 && (request.getCacheAbility() == RequestType.UNIQUE_CACHEABLE)) 305 cache.put(instanciatedSQL, request); 308 else 309 cache.put(sql, request); 310 } 311 catch (OutOfMemoryError oome) 312 { 313 synchronized (cache) 314 { 315 cache.clear(); 316 } 317 System.gc(); 318 logger.warn(Translate.get("cache.memory.error.cache.flushed", this 319 .getClass())); 320 } 321 } 322 323 328 public boolean isBackgroundParsing() 329 { 330 return backgroundParsing; 331 } 332 333 339 public void setBackgroundParsing(boolean backgroundParsing) 340 { 341 this.backgroundParsing = backgroundParsing; 342 } 343 344 349 public void setCaseSensitiveParsing(boolean isCaseSensitiveParsing) 350 { 351 this.caseSensitiveParsing = isCaseSensitiveParsing; 352 } 353 354 359 public boolean isCaseSensitiveParsing() 360 { 361 return caseSensitiveParsing; 362 } 363 364 369 public String getXml() 370 { 371 return "<" + DatabasesXmlTags.ELT_ParsingCache + " " 372 + DatabasesXmlTags.ATT_backgroundParsing + "=\"" + backgroundParsing 373 + "\" " + DatabasesXmlTags.ATT_maxNbOfEntries + "=\"" + maxNbOfEntries 374 + "\"/>"; 375 } 376 377 389 public String dumpCacheConfig() 390 { 391 StringBuffer sb = new StringBuffer (); 392 sb.append(Translate.get("cache.dump")); sb.append(Translate.get( 394 "cache.granularity", ParsingGranularities.getInformation(granularity))); sb.append(Translate.get("cache.max.entries", maxNbOfEntries)); sb.append(Translate.get("cache.background.parsing", backgroundParsing)); sb.append(Translate.get("cache.case.sensitive", caseSensitiveParsing)); return sb.toString(); 399 } 400 401 406 public int getNumberOfCacheEntries() 407 { 408 return cache.size(); 409 } 410 411 421 public String dumpCacheEntries(int beginIndex, int max) 422 { 423 StringBuffer sb = new StringBuffer (); 424 int i = beginIndex; 425 Object [] keys = cache.keySet().toArray(); 426 while (i < keys.length && i < (beginIndex + max)) 427 { 428 sb.append(Translate.get("cache.entry", new String []{ keys[i].toString(), 430 ((AbstractRequest) cache.get(keys[i])).toShortDebugString()})); 431 i++; 432 } 433 return sb.toString(); 434 } 435 436 442 public String dumpCurrentlyParsedEntries() 443 { 444 StringBuffer sb = new StringBuffer (); 445 if (currentlyParsing != null && currentlyParsing.size() > 0) 446 { 447 sb.append(Translate.get("cache.currently.parsing.entries")); for (int i = 0; i < currentlyParsing.size(); i++) 449 { 450 sb.append(Translate.get("cache.currently.parsing.entry", new String []{ currentlyParsing.keySet().toArray()[i].toString(), 452 ((CurrentlyParsingEntry) currentlyParsing.get(currentlyParsing 453 .keySet().toArray()[i])).request.toShortDebugString()})); 454 } 455 } 456 return sb.toString(); 457 } 458 } 459 | Popular Tags |