1 23 package org.hammurapi.results.persistent.jdbc; 24 25 import java.lang.reflect.Constructor ; 26 import java.lang.reflect.InvocationHandler ; 27 import java.lang.reflect.InvocationTargetException ; 28 import java.lang.reflect.Method ; 29 import java.lang.reflect.Proxy ; 30 import java.sql.Connection ; 31 import java.sql.PreparedStatement ; 32 import java.sql.ResultSet ; 33 import java.sql.SQLException ; 34 import java.sql.Timestamp ; 35 import java.util.LinkedList ; 36 import java.util.Set ; 37 38 import org.hammurapi.HammurapiException; 39 import org.hammurapi.HammurapiRuntimeException; 40 import org.hammurapi.InspectorDescriptor; 41 import org.hammurapi.InspectorSet; 42 import org.hammurapi.WaiverSet; 43 import org.hammurapi.results.persistent.jdbc.sql.Report; 44 import org.hammurapi.results.persistent.jdbc.sql.ReportImpl; 45 import org.hammurapi.results.persistent.jdbc.sql.ResultsEngine; 46 47 import com.pavelvlasov.cache.AbstractProducer; 48 import com.pavelvlasov.cache.Entry; 49 import com.pavelvlasov.cache.MemoryCache; 50 import com.pavelvlasov.convert.CompositeConverter; 51 import com.pavelvlasov.jsel.CompilationUnit; 52 import com.pavelvlasov.jsel.JselException; 53 import com.pavelvlasov.jsel.Repository; 54 import com.pavelvlasov.jsel.impl.DbRepositoryImpl; 55 import com.pavelvlasov.metrics.MeasurementCategoryFactory; 56 import com.pavelvlasov.persistence.Storage; 57 import com.pavelvlasov.sql.Parameterizer; 58 import com.pavelvlasov.sql.RowProcessor; 59 import com.pavelvlasov.sql.RowProcessorEx; 60 import com.pavelvlasov.sql.SQLProcessor; 61 import com.pavelvlasov.wrap.WrapperHandler; 62 63 67 public class ResultsFactory extends org.hammurapi.results.ResultsFactory { 68 private final class Deferrer implements InvocationHandler { 69 private final AggregatedResults results; 70 71 private Deferrer(AggregatedResults results) { 72 super(); 73 this.results = results; 74 } 75 76 public Object invoke(Object proxy, final Method method, final Object [] args) throws Throwable { 77 if (joined || Thread.currentThread()==taskThread) { 78 return method.invoke(results, args); 79 } 80 81 if (method.getDeclaringClass().getName().equals("java.lang.Object")) { 82 return method.invoke(results, args); 83 } else if (method.getReturnType().equals(void.class)) { 84 execute( 85 new Task() { 86 87 public void execute() throws HammurapiException { 88 try { 89 method.invoke(results, args); 90 } catch (IllegalArgumentException e) { 91 throw new HammurapiException(e); 92 } catch (IllegalAccessException e) { 93 throw new HammurapiException(e); 94 } catch (InvocationTargetException e) { 95 throw new HammurapiException(e); 96 } 97 } 98 99 }); 100 return null; 101 } else { 102 throw new HammurapiException("Non-void method "+method+" can't be executed in a separate thread"); 103 } 104 } 105 } 106 107 private WaiverSet waiverSet; 108 private SQLProcessor sqlProcessor; 109 110 private MemoryCache resultsCache=new MemoryCache(new AbstractProducer() { 111 112 public Entry get(Object key) { 113 try { 114 int resultId=((Number ) key).intValue(); 115 Class resultClass=getClass().getClassLoader().loadClass(getResultsEngine().getResultType(resultId)); 117 Constructor resultConstructor=resultClass.getConstructor(new Class []{int.class,ResultsFactory.class}); 119 final Object result = resultConstructor.newInstance(new Object []{CompositeConverter.getDefaultConverter().convert(key, Integer .class, false),ResultsFactory.this}); 120 return new Entry() { 121 122 public long getExpirationTime() { 123 return 0; 124 } 125 126 public long getTime() { 127 return 0; 128 } 129 130 public Object get() { 131 return result; 132 } 133 134 }; 135 136 } catch (IllegalArgumentException e) { 137 throw new HammurapiRuntimeException(e); 138 } catch (SecurityException e) { 139 throw new HammurapiRuntimeException(e); 140 } catch (InstantiationException e) { 141 throw new HammurapiRuntimeException(e); 142 } catch (IllegalAccessException e) { 143 throw new HammurapiRuntimeException(e); 144 } catch (InvocationTargetException e) { 145 throw new HammurapiRuntimeException(e); 146 } catch (NoSuchMethodException e) { 147 throw new HammurapiRuntimeException(e); 148 } catch (ClassNotFoundException e) { 149 throw new HammurapiRuntimeException(e); 150 } catch (SQLException e) { 151 throw new HammurapiRuntimeException(e); 152 } 153 } 154 155 public Set keySet() { 156 return null; 157 } 158 159 }, 160 null, 161 MeasurementCategoryFactory.getCategory(getClass().getName()+".resultsCache")); 162 163 SQLProcessor getSQLProcessor() { 164 return sqlProcessor; 165 } 166 167 private ResultsEngine resultsEngine; 168 private Number baseLineId; 169 private String name; 170 171 ResultsEngine getResultsEngine() { 172 if (resultsEngine==null) { 173 resultsEngine=new ResultsEngine(getSQLProcessor()); 174 } 175 return resultsEngine; 176 } 177 178 int nextPK(final String keyName) throws SQLException { 179 Connection con=sqlProcessor.getConnection(); 180 try { 181 boolean ac=con.getAutoCommit(); 182 try { 183 con.setAutoCommit(false); 184 final Parameterizer parameterizer=new Parameterizer() { 185 public void parameterize(PreparedStatement preparedStatement) throws SQLException { 186 preparedStatement.setString(1, keyName); 187 } 188 }; 189 190 final int[] value={0}; 191 192 sqlProcessor.processSelect( 193 "SELECT KEY_VALUE FROM PRIMARY_KEY WHERE KEY_NAME=?", 194 parameterizer, 195 new RowProcessorEx() { 196 public boolean process(ResultSet resultSet) throws SQLException { 197 value[0]=resultSet.getInt("KEY_VALUE")+1; 198 sqlProcessor.processUpdate("UPDATE PRIMARY_KEY SET KEY_VALUE=KEY_VALUE+1 WHERE KEY_NAME=?", parameterizer); 199 return false; 200 } 201 202 public void onEmptyResultSet() throws SQLException { 203 sqlProcessor.processUpdate("INSERT INTO PRIMARY_KEY (KEY_NAME, KEY_VALUE) VALUES (?, 0)", parameterizer); 204 } 205 }); 206 207 return value[0]; 208 } finally { 209 con.setAutoCommit(ac); 210 } 211 } finally { 212 sqlProcessor.releaseConnection(con); 213 } 214 } 215 216 public ResultsFactory(final ResultsFactoryConfig config) throws SQLException , HammurapiException { 217 this.sqlProcessor=config.getSqlProcessor(); 218 this.waiverSet=config.getWaiverSet(); 220 this.inspectorSet=config.getInspectorSet(); 221 this.repository=config.getRepository(); 222 this.storage=config.getStorage(); 223 this.name=config.getName(); 224 225 reportId=nextPK("REPORT"); 226 Report report=new ReportImpl(true); 227 report.setId(reportId); 228 report.setName(config.getName()); 229 report.setDescription(config.getDescription()); 230 report.setReportNumber(new Integer (config.getReportNumber())); 231 report.setHostId(config.getHostId()); 232 report.setHostName(config.getHostName()); 233 getResultsEngine().insertReport(report); 234 235 if (config.getBaseLine()!=null) { 236 baseLineId=getResultsEngine().getBaseLineIdByDate(config.getName(), new Timestamp (config.getBaseLine().getTime())); 237 if (baseLineId==null) { 238 throw new HammurapiException("Baseline report not found for "+config.getBaseLine()); 239 } 240 } 241 } 242 243 public void setSummary(final org.hammurapi.results.AggregatedResults results) { 244 try { 245 AggregatedResults aggregatedResults = unWrap(results); 246 getResultsEngine().setReportResult(aggregatedResults.getId(), reportId); 247 aggregatedResults.setBaseLineId((Integer ) CompositeConverter.getDefaultConverter().convert(baseLineId, Integer .class, false)); 248 } catch (SQLException e) { 249 throw new HammurapiRuntimeException(e); 250 } 251 } 252 253 257 AggregatedResults unWrap(final org.hammurapi.results.AggregatedResults results) { 258 return Proxy.isProxyClass(results.getClass()) ? ((Deferrer) Proxy.getInvocationHandler(results)).results : (AggregatedResults) results; 259 } 260 261 public org.hammurapi.results.AggregatedResults newAggregatedResults() { 262 try { 263 return (org.hammurapi.results.AggregatedResults) proxy(new AggregatedResults(waiverSet, this)); 264 } catch (SQLException e) { 265 throw new HammurapiRuntimeException(e); 266 } 267 } 268 269 public org.hammurapi.results.NamedResults newNamedResults(String name) { 270 try { 271 return (org.hammurapi.results.NamedResults) proxy(new NamedResults(name, waiverSet, this)); 272 } catch (SQLException e) { 273 throw new HammurapiRuntimeException(e); 274 } 275 } 276 277 public org.hammurapi.results.DetailedResults newDetailedResults(String name) { 278 try { 279 return (org.hammurapi.results.DetailedResults) proxy(new DetailedResults(name, waiverSet, this)); 280 } catch (SQLException e) { 281 throw new HammurapiRuntimeException(e); 282 } 283 } 284 285 public org.hammurapi.results.CompositeResults newCompositeResults(String name) { 286 try { 287 return (org.hammurapi.results.CompositeResults) proxy(new CompositeResults(name, waiverSet, this)); 288 } catch (SQLException e) { 289 throw new HammurapiRuntimeException(e); 290 } 291 } 292 293 public org.hammurapi.results.ReviewResults newReviewResults(CompilationUnit compilationUnit) { 294 try { 295 return (org.hammurapi.results.ReviewResults) proxy(new ReviewResults(compilationUnit, waiverSet, this)); 296 } catch (SQLException e) { 297 throw new HammurapiRuntimeException(e); 298 } 299 } 300 301 private InspectorSet inspectorSet; 302 private int reportId; 303 304 307 public int getReportId() { 308 return reportId; 309 } 310 311 private Storage storage; 312 313 public Storage getStorage() { 314 return storage; 315 } 316 317 public InspectorDescriptor getInspectorDescriptor(String string) { 318 return inspectorSet.getDescriptor(string); 319 } 320 321 private Repository repository; 322 323 public static final String HYPERSONIC_INIT_SCRIPT = "org/hammurapi/results/persistent/jdbc/Hammurapi.Hypersonic.sql"; 324 public static final String CLOUDSCAPE_INIT_SCRIPT = "org/hammurapi/results/persistent/jdbc/Hammurapi.Cloudscape.sql"; 325 326 public CompilationUnit getCompilationUnit(int id) throws JselException { 327 return repository.getCompilationUnit(id); 328 } 329 330 public org.hammurapi.results.ReviewResults findReviewResults(final CompilationUnit cu) { 331 try { 332 final ReviewResults[] ret={null}; 333 getSQLProcessor().processSelect( 334 "SELECT ID, TYPE FROM RESULT WHERE COMPILATION_UNIT=? AND COMMITED=1", 335 new Parameterizer() { 336 public void parameterize(PreparedStatement ps) throws SQLException { 337 ps.setInt(1, cu.getSourceId().intValue()); 338 } 339 }, 340 new RowProcessor() { 341 public boolean process(final ResultSet rs) { 342 try { 343 Constructor constructor = getClass().getClassLoader().loadClass( 344 rs.getString("TYPE")).getConstructor(new Class []{int.class,ResultsFactory.class}); 345 ret[0]=(ReviewResults) constructor.newInstance(new Object []{ 346 new Integer (rs.getInt("ID")), 347 ResultsFactory.this}); 348 349 sqlProcessor.processUpdate( 350 "UPDATE RESULT SET IS_NEW=0 WHERE ID=?", 351 new Parameterizer() { 352 public void parameterize(PreparedStatement ps) throws SQLException { 353 ps.setInt(1, rs.getInt("ID")); 354 } 355 }); 356 } catch (IllegalArgumentException e) { 357 throw new HammurapiRuntimeException(e); 358 } catch (SecurityException e) { 359 throw new HammurapiRuntimeException(e); 360 } catch (InstantiationException e) { 361 throw new HammurapiRuntimeException(e); 362 } catch (IllegalAccessException e) { 363 throw new HammurapiRuntimeException(e); 364 } catch (InvocationTargetException e) { 365 throw new HammurapiRuntimeException(e); 366 } catch (NoSuchMethodException e) { 367 throw new HammurapiRuntimeException(e); 368 } catch (ClassNotFoundException e) { 369 throw new HammurapiRuntimeException(e); 370 } catch (SQLException e) { 371 throw new HammurapiRuntimeException(e); 372 } 373 return false; 374 } 375 }); 376 return ret[0]; 377 } catch (SQLException e) { 378 throw new HammurapiRuntimeException(e); 379 } 380 } 381 382 public void commit(long executionTime) { 383 try { 384 getResultsEngine().setReportExecutionTime(executionTime, reportId); 385 } catch (SQLException e) { 386 throw new HammurapiRuntimeException(e); 387 } 388 } 389 390 394 int addMessage(String message) { 395 return ((DbRepositoryImpl) repository).addMessage(message); 396 } 397 398 public void shutdown() { 399 resultsCache.stop(); 400 } 401 402 405 void addToCache(BasicResults results) { 406 resultsCache.put(new Integer (results.getId()), results, 0, 0); 407 } 408 409 BasicResults getResult(Object id) { 410 Entry entry = resultsCache.get(id); 411 return (BasicResults) (entry==null ? null : entry.get()); 412 } 413 414 418 public void cleanupOldReports() throws HammurapiException { 419 try { 420 getResultsEngine().setOldReports(getReportId(), name); 421 getResultsEngine().deleteOldResults(); 422 } catch (SQLException e) { 423 throw new HammurapiException("Could not delete old results: "+e, e); 424 } 425 426 } 427 428 private LinkedList tasks=new LinkedList (); 429 private static final int MAX_QUEUE=1000; 430 431 private boolean terminated; 432 433 private void checkTerminated() throws HammurapiException { 434 synchronized (tasks) { 435 if (terminated) { 436 throw new HammurapiException("Results processing thread was terminated prematurely"); 437 } 438 } 439 } 440 441 private Thread taskThread=new Thread () { 442 { 443 setName("Results processing thread"); 444 start(); 445 } 446 447 public void run() { 448 try { 449 while (true) { 450 Task task; 451 synchronized (tasks) { 452 while (tasks.isEmpty()) { 453 try { 454 tasks.wait(); 455 } catch (InterruptedException e) { 456 return; 457 } 458 } 459 460 task=(Task) tasks.removeFirst(); 461 if (tasks.size()<MAX_QUEUE) { 462 tasks.notifyAll(); 463 } 464 } 465 466 if (task==null) { 467 return; 468 } 469 470 task.execute(); 471 } 472 } catch (Exception e) { 473 e.printStackTrace(); 474 } finally { 475 synchronized (tasks) { 476 terminated=true; 477 tasks.notifyAll(); 478 } 479 } 480 } 481 }; 482 483 486 public void execute(Task task) throws HammurapiException { 487 if (task!=null) { 488 synchronized (tasks) { 489 checkTerminated(); 490 491 if (tasks.size()>=MAX_QUEUE) { 492 try { 493 tasks.wait(); 494 checkTerminated(); 495 } catch (InterruptedException e) { 496 throw new HammurapiException(e); 497 } 498 } 499 500 tasks.add(task); 501 tasks.notifyAll(); 502 } 503 } 504 } 505 506 private Object proxy(final AggregatedResults results) { 507 return Proxy.newProxyInstance( 508 results.getClass().getClassLoader(), 509 WrapperHandler.getClassInterfaces(results.getClass()), 510 new Deferrer(results)); 511 } 512 513 private boolean joined; 514 515 public void join() throws HammurapiException { 516 checkTerminated(); 517 518 synchronized (tasks) { 519 tasks.add(null); 520 tasks.notifyAll(); 521 } 522 523 try { 524 taskThread.join(); 525 } catch (InterruptedException e) { 526 throw new HammurapiException(e); 527 } 528 529 joined=true; 530 } 531 532 String getName() { 533 return name; 534 } 535 } 536 | Popular Tags |