1 23 package com.lutris.appserver.server.sql.datasource; 24 25 import java.lang.reflect.Constructor ; 26 import java.sql.SQLException ; 27 import java.util.Date ; 28 import java.util.Hashtable ; 29 import java.util.LinkedList ; 30 import java.util.NoSuchElementException ; 31 32 import javax.sql.DataSource ; 33 import javax.naming.Context ; 34 import javax.naming.InitialContext ; 35 import javax.naming.NamingException ; 36 37 import org.enhydra.dods.CommonConstants; 38 import org.enhydra.dods.DODS; 39 40 import com.lutris.appserver.server.sql.AbstractDBConnectionFactory; 41 import com.lutris.appserver.server.sql.ConnectionAllocator; 42 import com.lutris.appserver.server.sql.DBConnection; 43 import com.lutris.appserver.server.sql.ExtendedConnectionAllocator; 44 import com.lutris.appserver.server.sql.ExtendedDBConnection; 45 import com.lutris.appserver.server.sql.LogicalDatabase; 46 import com.lutris.logging.Logger; 47 import com.lutris.util.Config; 48 import com.lutris.util.ConfigException; 49 import com.lutris.util.KeywordValueException; 50 51 113 122 public class SimpleDataSourceConnectionAllocator implements ExtendedConnectionAllocator { 124 125 128 protected LogicalDatabase logicalDatabase = null; 129 130 133 protected DataSource dataSource; 134 135 138 protected String url; 139 140 143 protected String user; 144 145 148 protected String password; 149 150 153 protected String shutDownStr; 154 155 159 private int maxPoolSize; 160 161 164 private int currentPoolSize; 165 166 170 private long connectionIdileTimeout = -1; 171 172 175 private int biggestPoolSize; 176 177 180 private Date biggestPoolDate; 181 182 185 protected long numRequests; 186 187 190 194 private LinkedList pool; 195 196 204 private Hashtable connectionUsageCounter; 205 206 209 protected int maxWaitingConnections; 210 211 216 private int maxConnectionUsages = -1; 217 218 222 protected boolean sqlLogging; 223 224 227 protected boolean disableConnectionPool = false; 228 229 232 private int timeOut; 233 234 238 protected int queryTimeOut; 239 240 244 protected int transactionTimeOut; 245 246 250 protected int maxPreparedStatements; 251 252 256 protected int generation = 1; 257 258 264 protected DBConnection createConnection() throws java.sql.SQLException { 265 DBConnection dbConnection; 266 if (dataSource != null) 267 dbConnection = new SimpleDataSourceDBConnection(this, dataSource, maxPreparedStatements, sqlLogging, 271 generation); 272 else 273 dbConnection = new SimpleDataSourceDBConnection((ConnectionAllocator) this, url, user, password, 277 maxPreparedStatements, sqlLogging, generation); 278 279 return dbConnection; 280 } 281 282 private AbstractDBConnectionFactory dbConnectionFactory = null; 283 284 private String dbConnectionFactoryName = null; 285 286 private AbstractDBConnectionFactory createDBConnectionFactory(String factoryName) { 287 Class connectionFactoryClass = null; 288 Constructor connectionFactoryConstructor = null; 289 Class [] methodTypes = {}; 290 Object [] methodArgs = {}; 291 AbstractDBConnectionFactory factory = null; 292 if (factoryName != null) { 293 try { 294 connectionFactoryClass = Class.forName(factoryName); 295 factory = (AbstractDBConnectionFactory) connectionFactoryClass.newInstance(); 296 } catch (Exception e) { 297 DODS.getLogChannel().write( 298 Logger.INFO, 299 "Faild to make Connection Factory :" + factoryName 300 + " creating StandardDBConnectionFactory insted"); 301 factory = null; 302 } 303 } 304 if (factoryName == null || factory == null) { 305 try { 306 connectionFactoryClass = Class 307 .forName("com.lutris.appserver.server.sql.standard.StandardDBConnectionFactory"); 308 factory = (AbstractDBConnectionFactory) connectionFactoryClass.newInstance(); 309 } catch (Exception e) { 310 DODS 311 .getLogChannel() 312 .write(Logger.INFO, 313 "Faild to make Standard Connection Factory : com.lutris.appserver.server.sql.standard.StandardDBConnectionFactory"); 314 factory = null; 315 } 316 } 318 return factory; 319 320 } 321 322 334 public SimpleDataSourceConnectionAllocator(LogicalDatabase logicalDatabase, Config conConfig) 335 throws ConfigException { 336 this.logicalDatabase = logicalDatabase; 337 338 try { 340 String stringValue = ""; 341 try { 342 if (conConfig.getDataSource("DataSourceName") != null) { 343 344 if (conConfig.getDataSource("DataSourceName") instanceof DataSource ) 345 dataSource = (DataSource ) conConfig.getDataSource("DataSourceName"); 346 else if (conConfig.getDataSource("DataSourceName") instanceof String ) { 347 String jndiName = (String ) conConfig.getDataSource("DataSourceName"); 348 if (jndiName.startsWith("jndi:")) { 349 stringValue = jndiName.substring(5); 350 } else 351 stringValue = jndiName; 352 353 InitialContext context = null; 354 Context envCtx = null; 355 356 try { 357 context = new InitialContext (); 358 envCtx = (Context ) context.lookup("java:comp/env"); 359 360 } catch (NamingException ex) { 361 envCtx = null; 362 } 363 try { 364 dataSource = (DataSource ) envCtx.lookup(stringValue); 365 } catch (Exception ex) { 366 dataSource = null; 367 } 368 if (dataSource == null) { 369 try { 370 dataSource = (DataSource ) context.lookup(stringValue); 371 } catch (Exception ex) { 372 dataSource = null; 373 } 374 } 375 } else 376 dataSource = null; 377 } 378 } catch (Exception ex) { 379 dataSource = null; 380 } 381 if (dataSource == null) { 382 url = conConfig.getString("Url"); 383 user = conConfig.getString("User"); 384 password = conConfig.getString("Password"); 385 } 386 timeOut = conConfig.getInt("AllocationTimeout", 1000); 387 maxPoolSize = conConfig.getInt("MaxPoolSize", 0); 388 sqlLogging = conConfig.getBoolean("Logging", false); 389 disableConnectionPool = conConfig.getBoolean("DisableConnectionPool", false); 390 queryTimeOut = conConfig.getInt("QueryTimeout", 0); 391 transactionTimeOut = conConfig.getInt("TransactionTimeout", 0); 392 connectionIdileTimeout = conConfig.getLong("ConnectionIdleTimeout", -1); 393 maxPreparedStatements = conConfig.getInt("MaxPreparedStatements", -1); 394 maxConnectionUsages = conConfig.getInt("MaxConnectionUsages", -1); 395 maxWaitingConnections = conConfig.getInt("MaxWaitingConnections", Integer.MAX_VALUE); 396 shutDownStr = conConfig.getString("ShutDownString", null); 397 398 dbConnectionFactoryName = conConfig.getString(CommonConstants.CONNECTION_FACTORY, null); 399 dbConnectionFactory = createDBConnectionFactory(dbConnectionFactoryName); 400 401 } catch (KeywordValueException except) { 402 throw new ConfigException("Bad DatabaseManager.DB." + logicalDatabase.getName() 403 + ".Connection section defined in config file."); 404 } 405 currentPoolSize = 0; 406 410 pool = new LinkedList (); 411 if (maxConnectionUsages > 0) { 412 connectionUsageCounter = new Hashtable (); 413 } 414 biggestPoolSize = 0; 416 biggestPoolDate = new Date (); 417 numRequests = 0; 418 } 419 420 433 public synchronized DBConnection allocate() throws SQLException { 434 boolean createNewConn = true; 442 446 DBConnection conn = null; 447 if (disableConnectionPool) { 448 try { 449 conn = createConnection(); 450 } catch (SQLException e) { 451 DODS.getLogChannel().write( 452 Logger.EMERGENCY, 453 "ConnectionAllocator: " 454 + "failed to allocate a new connection" 455 + "\n (connection pool is not used!) \n"); 456 throw e; 457 } 458 } else { 459 while (conn == null) { 460 while (pool.isEmpty()) { 461 if (createNewConn && ((currentPoolSize < maxPoolSize) || (maxPoolSize <= 0))) { 463 try { 464 468 DBConnection newConnection = createConnection(); 469 470 if (connectionUsageCounter != null) { 471 connectionUsageCounter.put(newConnection, new Integer (maxConnectionUsages)); 472 } 473 pool.addLast(newConnection); 474 currentPoolSize++; 476 if (currentPoolSize > biggestPoolSize) { 477 biggestPoolSize = currentPoolSize; 478 biggestPoolDate = new Date (); 479 } 480 } catch (SQLException e) { 481 if (currentPoolSize > 0) { 482 DODS.getLogChannel().write( 483 Logger.INFO, 484 "ConnectionAllocator: " + "failed to allocate a new connection due to" 485 + e.toString() + "Error code: " + e.getErrorCode() 486 + "\n" + "SQLState: " + e.getSQLState() + "\n" 487 + "\nCurrent pool size is: " + currentPoolSize 488 + "\nMaximum configured pool size is now " 489 + maxPoolSize + "\nContinuing...\n"); 490 createNewConn = false; 491 } else { 492 DODS.getLogChannel().write( 493 Logger.EMERGENCY, 494 "ConnectionAllocator: " + "failed to allocate a new connection" 495 + "\nThe connection pool is empty!\n"); 496 throw e; 497 } 498 } 499 } else { 500 try { 501 if (timeOut > 0) { 502 wait(timeOut); 503 507 if (pool.isEmpty()) { 508 DODS.getLogChannel().write( 510 Logger.EMERGENCY, 511 "ConnectionAllocator: " 512 + "allocation of a new connection timed out." 513 + "Possible dead lock avoided."); 514 String msg = "Connections are currently unavailable.\n" 515 + "Possible dead lock avoided."; 516 517 throw new SQLException (msg); 518 } 519 } else { 520 wait(); 521 } 522 } catch (InterruptedException intEx) { 523 } 524 } 525 } 526 533 try { 535 conn = (DBConnection) pool.removeFirst(); 536 } catch (NoSuchElementException e) { 537 } 538 if (connectionUsageCounter != null) { 539 Integer connUsages = (Integer ) connectionUsageCounter.get(conn); 540 541 if (connUsages != null && connUsages.intValue() > 0) { 542 connectionUsageCounter.put(conn, new Integer (connUsages.intValue() - 1)); 544 } else { conn.close(); 546 currentPoolSize--; 547 connectionUsageCounter.remove(conn); 548 DODS.getLogChannel().write( 549 Logger.DEBUG, 550 "ConnectionAllocator: connection closed due to usage counter. currentPoolSize=" 551 + currentPoolSize + "\n"); 552 conn = null; 553 } 554 } 555 if ((conn != null) && (conn.getConnection().isClosed())) { 556 conn.close(); 557 currentPoolSize--; 558 if (connectionUsageCounter != null && connectionUsageCounter.contains(conn)) { 559 connectionUsageCounter.remove(conn); 560 } 561 DODS.getLogChannel().write( 562 Logger.DEBUG, 563 "ConnectionAllocator: Inactiv connection closed due allocate() operation. Geting new one. currentPoolSize=" 564 + currentPoolSize + "\n"); 565 conn = null; 566 } 567 if ((conn != null) && (connectionIdileTimeout > 0)) { 568 if ((System.currentTimeMillis() - ((ExtendedDBConnection) conn).getConnectionEnterPoolTime()) > connectionIdileTimeout) { 569 conn.close(); 570 currentPoolSize--; 571 DODS.getLogChannel().write( 572 Logger.DEBUG, 573 "ConnectionAllocator: Connection closed due allocate() operation - long connection idile time. Geting new one. currentPoolSize=" 574 + currentPoolSize + "\n"); 575 conn = null; 576 } 577 } 578 } 579 } 580 conn.allocate(); 581 return conn; 582 } 583 584 590 public synchronized void release(DBConnection dbConnection) { 591 try { 592 if (disableConnectionPool) { 593 dbConnection.close(); 594 dbConnection = null; 595 } else { 596 if ((dbConnection.getGeneration() < generation) || (dbConnection.isMarkedForDrop()) 597 || (dbConnection.getConnection().isClosed()) || (pool.size() >= maxWaitingConnections)) { 598 dbConnection.close(); 599 dbConnection = null; 600 currentPoolSize--; 601 } else { 602 606 if (connectionIdileTimeout > 0) { 607 ((ExtendedDBConnection) dbConnection).setConnectionEnterPoolTime(System.currentTimeMillis()); 608 } 609 pool.addLast(dbConnection); 610 } 612 } 613 } catch (SQLException ex) { 614 DODS.getLogChannel().write(Logger.DEBUG, "Eror relasing connection"); 615 } 616 notify(); 617 } 618 619 631 public synchronized void drop(DBConnection dbConnection) { 632 if (generation <= dbConnection.getGeneration()) { 633 generation++; } 635 645 LinkedList newPool = new LinkedList (); 646 647 try { 648 while (!pool.isEmpty()) { 649 DBConnection connect = (DBConnection) pool.removeFirst(); 650 651 if (connect.getGeneration() < generation) { 652 connect.close(); 653 currentPoolSize--; 654 } else { 655 newPool.addLast(connect); 656 } 657 } 658 } catch (NoSuchElementException e) { 659 } 660 pool = newPool; 663 notify(); 665 } 666 667 671 public synchronized void dropAllNow() { 672 677 678 if (shutDownStr != null) { 679 try { 680 DBConnection tmpConn = allocate(); 681 tmpConn.execute(shutDownStr); 682 tmpConn.release(); 683 } catch (SQLException e1) { 684 } 685 } 686 687 try { 688 while (!pool.isEmpty()) { 689 DBConnection connect = (DBConnection) pool.removeFirst(); 690 691 connect.close(); 692 currentPoolSize--; 693 } 694 } catch (NoSuchElementException e) { 695 } 696 } 698 699 704 public int getActiveCount() { 705 return currentPoolSize; 706 } 707 708 713 public int getMaxCount() { 714 return biggestPoolSize; 715 } 716 717 723 public Date getMaxCountDate() { 724 return biggestPoolDate; 725 } 726 727 730 public void resetMaxCount() { 731 biggestPoolSize = currentPoolSize; 732 biggestPoolDate = new Date (); 733 } 734 735 740 public long getRequestCount() { 741 return numRequests; 742 } 743 744 748 protected void finalize() { 749 dropAllNow(); 750 } 751 752 756 public String getDatabaseName() { 757 return logicalDatabase.getName(); 758 } 759 760 public void IncrementRequesteCount() { 761 numRequests++; 762 } 763 } | Popular Tags |