1 6 package org.logicalcobwebs.proxool; 7 8 import org.logicalcobwebs.concurrent.WriterPreferenceReadWriteLock; 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.logicalcobwebs.proxool.util.FastArrayList; 12 13 import java.sql.Connection ; 14 import java.sql.SQLException ; 15 import java.sql.Statement ; 16 import java.util.Date ; 17 import java.util.Set ; 18 import java.util.HashSet ; 19 import java.util.List ; 20 import java.text.DecimalFormat ; 21 22 30 public class ProxyConnection implements ProxyConnectionIF { 31 32 static final int STATUS_FORCE = -1; 33 34 private WriterPreferenceReadWriteLock statusReadWriteLock = new WriterPreferenceReadWriteLock(); 35 36 private static final Log LOG = LogFactory.getLog(ProxyConnection.class); 37 38 private Connection connection; 39 40 private String delegateUrl; 41 42 private int mark; 43 44 private String reasonForMark; 45 46 private int status; 47 48 private long id; 49 50 private Date birthDate; 51 52 private long timeLastStartActive; 53 54 private long timeLastStopActive; 55 56 private ConnectionPool connectionPool; 57 58 private ConnectionPoolDefinitionIF definition; 59 60 private String requester; 61 62 private Set openStatements = new HashSet (); 63 64 private DecimalFormat idFormat = new DecimalFormat ("0000"); 65 66 private List sqlCalls = new FastArrayList(); 67 68 71 private boolean needToReset = false; 72 73 84 protected ProxyConnection(Connection connection, long id, String delegateUrl, ConnectionPool connectionPool, ConnectionPoolDefinitionIF definition, int status) throws SQLException { 85 this.connection = connection; 86 this.delegateUrl = delegateUrl; 87 setId(id); 88 this.connectionPool = connectionPool; 89 this.definition = definition; 90 setBirthTime(System.currentTimeMillis()); 91 92 this.status = status; 93 if (status == STATUS_ACTIVE) { 94 setTimeLastStartActive(System.currentTimeMillis()); 95 } 96 97 connectionPool.initialiseConnectionResetter(connection); 100 101 if (connection == null) { 102 throw new SQLException ("Unable to create new connection"); 103 } 104 } 105 106 112 public boolean equals(Object obj) { 113 if (obj != null) { 114 if (obj instanceof ProxyConnection) { 115 return connection.hashCode() == ((ProxyConnection) obj).getConnection().hashCode(); 116 } else if (obj instanceof Connection ) { 117 return connection.hashCode() == obj.hashCode(); 118 } else { 119 return super.equals(obj); 120 } 121 } else { 122 return false; 123 } 124 } 125 126 131 public boolean isClosed() { 132 return (getStatus() != STATUS_ACTIVE); 133 } 134 135 143 protected void setNeedToReset(boolean needToReset) { 144 this.needToReset = needToReset; 145 } 146 147 151 protected ConnectionPool getConnectionPool() { 152 return connectionPool; 153 } 154 155 159 public ConnectionPoolDefinitionIF getDefinition() { 160 return definition; 161 } 162 163 169 protected void addOpenStatement(Statement statement) { 170 openStatements.add(statement); 171 } 172 173 176 public void registerClosedStatement(Statement statement) { 177 if (openStatements.contains(statement)) { 178 openStatements.remove(statement); 179 } else { 180 connectionPool.getLog().warn(connectionPool.displayStatistics() + " - #" + getId() + " registered a statement as closed which wasn't known to be open."); 181 } 182 } 183 184 188 public void reallyClose() throws SQLException { 189 try { 190 connectionPool.registerRemovedConnection(getStatus()); 191 connection.close(); 193 } catch (Throwable t) { 194 connectionPool.getLog().error("#" + idFormat.format(getId()) + " encountered errors during destruction: ", t); 195 } 196 197 } 198 199 202 public boolean isReallyClosed() throws SQLException { 203 if (connection == null) { 204 return true; 205 } else { 206 return connection.isClosed(); 207 } 208 } 209 210 213 public void close() throws SQLException { 214 try { 215 boolean removed = false; 216 if (isMarkedForExpiry()) { 217 if (connectionPool.getLog().isDebugEnabled()) { 218 connectionPool.getLog().debug("Closing connection quickly (without reset) because it's marked for expiry anyway"); 219 } 220 } else { 221 Statement [] statements = (Statement []) openStatements.toArray(new Statement [openStatements.size()]); 223 for (int j = 0; j < statements.length; j++) { 224 Statement statement = statements[j]; 225 statement.close(); 226 if (connectionPool.getLog().isDebugEnabled()) { 227 connectionPool.getLog().debug("Closing statement " + Integer.toHexString(statement.hashCode()) + " automatically"); 228 } 229 } 230 openStatements.clear(); 231 232 if (needToReset) { 233 if (!connectionPool.resetConnection(connection, "#" + getId())) { 238 connectionPool.removeProxyConnection(this, "it couldn't be reset", true, true); 239 removed = true; 240 } 241 needToReset = false; 242 } 243 } 244 if (!removed) { 247 connectionPool.putConnection(this); 248 } 249 } catch (Throwable t) { 250 connectionPool.getLog().error("#" + idFormat.format(getId()) + " encountered errors during closure: ", t); 251 } 252 253 } 254 255 259 protected void open() { 260 sqlCalls.clear(); 261 } 262 263 public int getMark() { 264 return mark; 265 } 266 267 public int getStatus() { 268 return status; 269 } 270 271 274 public boolean setStatus(int newStatus) { 275 return setStatus(STATUS_FORCE, newStatus); 276 } 277 278 281 public boolean setStatus(int oldStatus, int newStatus) { 282 boolean success = false; 283 try { 284 statusReadWriteLock.writeLock().acquire(); 285 connectionPool.acquireConnectionStatusWriteLock(); 286 if (this.status == oldStatus || oldStatus == STATUS_FORCE) { 287 connectionPool.changeStatus(this.status, newStatus); 288 this.status = newStatus; 289 success = true; 290 291 if (newStatus == oldStatus) { 292 LOG.warn("Unexpected attempt to change status from " + oldStatus + " to " + newStatus 293 + ". Why would you want to do that?"); 294 } else if (newStatus == STATUS_ACTIVE) { 295 setTimeLastStartActive(System.currentTimeMillis()); 296 } else if (oldStatus == STATUS_ACTIVE) { 297 setTimeLastStopActive(System.currentTimeMillis()); 298 } 299 } 300 } catch (InterruptedException e) { 301 LOG.error("Unable to acquire write lock for status"); 302 } finally { 303 connectionPool.releaseConnectionStatusWriteLock(); 304 statusReadWriteLock.writeLock().release(); 305 } 306 return success; 307 } 308 309 public long getId() { 310 return id; 311 } 312 313 public void setId(long id) { 314 this.id = id; 315 } 316 317 320 public long getBirthTime() { 321 return birthDate.getTime(); 322 } 323 324 327 public Date getBirthDate() { 328 return birthDate; 329 } 330 331 334 public long getAge() { 335 return System.currentTimeMillis() - getBirthTime(); 336 } 337 338 341 public void setBirthTime(long birthTime) { 342 birthDate = new Date (birthTime); 343 } 344 345 348 public long getTimeLastStartActive() { 349 return timeLastStartActive; 350 } 351 352 355 public void setTimeLastStartActive(long timeLastStartActive) { 356 this.timeLastStartActive = timeLastStartActive; 357 setTimeLastStopActive(0); 358 } 359 360 363 public long getTimeLastStopActive() { 364 return timeLastStopActive; 365 } 366 367 370 public void setTimeLastStopActive(long timeLastStopActive) { 371 this.timeLastStopActive = timeLastStopActive; 372 } 373 374 377 public String getRequester() { 378 return requester; 379 } 380 381 384 public void setRequester(String requester) { 385 this.requester = requester; 386 } 387 388 391 public boolean isNull() { 392 return getStatus() == STATUS_NULL; 393 } 394 395 398 public boolean isAvailable() { 399 return getStatus() == STATUS_AVAILABLE; 400 } 401 402 405 public boolean isActive() { 406 return getStatus() == STATUS_ACTIVE; 407 } 408 409 412 public boolean isOffline() { 413 return getStatus() == STATUS_OFFLINE; 414 } 415 416 419 public void markForExpiry(String reason) { 420 mark = MARK_FOR_EXPIRY; 421 reasonForMark = reason; 422 } 423 424 427 public boolean isMarkedForExpiry() { 428 return getMark() == MARK_FOR_EXPIRY; 429 } 430 431 434 public String getReasonForMark() { 435 return reasonForMark; 436 } 437 438 441 public Connection getConnection() { 442 return connection; 443 } 444 445 448 public String toString() { 449 return getId() + " is " + ConnectionPool.getStatusDescription(getStatus()); 450 } 451 452 455 public String getDelegateUrl() { 456 return delegateUrl; 457 } 458 459 462 public String getProxyHashcode() { 463 return Integer.toHexString(hashCode()); 464 } 465 466 469 public String getDelegateHashcode() { 470 if (connection != null) { 471 return Integer.toHexString(connection.hashCode()); 472 } else { 473 return null; 474 } 475 } 476 477 483 public int compareTo(Object o) { 484 return new Long (((ConnectionInfoIF) o).getId()).compareTo(new Long (getId())); 485 } 486 487 public String [] getSqlCalls() { 488 return (String []) sqlCalls.toArray(new String [0]); 489 } 490 491 public String getLastSqlCall() { 492 if (sqlCalls != null && sqlCalls.size() > 0) { 493 return (String ) sqlCalls.get(sqlCalls.size() - 1); 494 } else { 495 return null; 496 } 497 } 498 499 public void addSqlCall(String sqlCall) { 500 this.sqlCalls.add(sqlCall); 501 } 502 } 503 | Popular Tags |