1 6 package org.logicalcobwebs.proxool; 7 8 import org.logicalcobwebs.concurrent.WriterPreferenceReadWriteLock; 9 import org.logicalcobwebs.logging.Log; 10 import org.logicalcobwebs.logging.LogFactory; 11 12 import java.sql.Connection ; 13 import java.sql.DatabaseMetaData ; 14 import java.sql.SQLException ; 15 import java.sql.Statement ; 16 import java.text.DecimalFormat ; 17 import java.util.Date ; 18 import java.util.HashSet ; 19 import java.util.Set ; 20 21 31 abstract class AbstractProxyConnection implements ProxyConnectionIF { 32 33 static final int STATUS_FORCE = -1; 34 35 private WriterPreferenceReadWriteLock statusReadWriteLock = new WriterPreferenceReadWriteLock(); 36 37 private static final Log LOG = LogFactory.getLog(AbstractProxyConnection.class); 38 39 private Connection connection; 40 41 private String delegateUrl; 42 43 private int mark; 44 45 private String reasonForMark; 46 47 private int status; 48 49 private long id; 50 51 private Date birthDate; 52 53 private long timeLastStartActive; 54 55 private long timeLastStopActive; 56 57 private ConnectionPool connectionPool; 58 59 private String requester; 60 61 private Set openStatements = new HashSet (); 62 63 private DecimalFormat idFormat = new DecimalFormat ("0000"); 64 65 68 private boolean needToReset = false; 69 70 protected AbstractProxyConnection(Connection connection, long id, String delegateUrl, ConnectionPool connectionPool, int status) throws SQLException { 71 this.connection = connection; 72 this.delegateUrl = delegateUrl; 73 setId(id); 74 this.connectionPool = connectionPool; 75 setBirthTime(System.currentTimeMillis()); 76 77 this.status = status; 78 if (status == STATUS_ACTIVE) { 79 setTimeLastStartActive(System.currentTimeMillis()); 80 } 81 82 connectionPool.initialiseConnectionResetter(connection); 85 86 if (connection == null) { 87 throw new SQLException ("Unable to create new connection"); 88 } 89 } 90 91 97 public boolean equals(Object obj) { 98 if (obj != null) { 99 if (obj instanceof ProxyConnection) { 100 return connection.hashCode() == ((ProxyConnection) obj).getConnection().hashCode(); 101 } else if (obj instanceof Connection ) { 102 return connection.hashCode() == obj.hashCode(); 103 } else { 104 return super.equals(obj); 105 } 106 } else { 107 return false; 108 } 109 } 110 111 116 public boolean isClosed() { 117 return (getStatus() != STATUS_ACTIVE); 118 } 119 120 public DatabaseMetaData getMetaData() throws SQLException { 121 return ProxyFactory.getDatabaseMetaData(connection, this); 122 } 123 124 132 protected void setNeedToReset(boolean needToReset) { 133 this.needToReset = needToReset; 134 } 135 136 140 protected ConnectionPool getConnectionPool() { 141 return connectionPool; 142 } 143 144 150 protected void addOpenStatement(Statement statement) { 151 openStatements.add(statement); 152 } 153 154 157 public void registerClosedStatement(Statement statement) { 158 if (openStatements.contains(statement)) { 159 openStatements.remove(statement); 160 } else { 161 connectionPool.getLog().warn(connectionPool.displayStatistics() + " - #" + getId() + " registered a statement as closed which wasn't known to be open."); 162 } 163 } 164 165 169 public void reallyClose() throws SQLException { 170 try { 171 connectionPool.registerRemovedConnection(getStatus()); 172 connection.close(); 174 } catch (Throwable t) { 175 connectionPool.getLog().error("#" + idFormat.format(getId()) + " encountered errors during destruction: " + t); 176 } 177 178 } 179 180 183 public boolean isReallyClosed() throws SQLException { 184 if (connection == null) { 185 return true; 186 } else { 187 return connection.isClosed(); 188 } 189 } 190 191 194 public void close() throws SQLException { 195 try { 196 197 if (isMarkedForExpiry()) { 198 if (connectionPool.getLog().isDebugEnabled()) { 199 connectionPool.getLog().debug("Closing connection quickly (without reset) because it's marked for expiry anyway"); 200 } 201 } else { 202 Statement [] statements = (Statement []) openStatements.toArray(new Statement [openStatements.size()]); 204 for (int j = 0; j < statements.length; j++) { 205 Statement statement = statements[j]; 206 statement.close(); 207 if (connectionPool.getLog().isDebugEnabled()) { 208 connectionPool.getLog().debug("Closing statement " + Integer.toHexString(statement.hashCode()) + " automatically"); 209 } 210 } 211 openStatements.clear(); 212 213 if (needToReset) { 214 if (!connectionPool.resetConnection(connection, "#" + getId())) { 219 connectionPool.removeProxyConnection(this, "it couldn't be reset", true, true); 220 } 221 needToReset = false; 222 } 223 } 224 connectionPool.putConnection(this); 225 } catch (Throwable t) { 226 connectionPool.getLog().error("#" + idFormat.format(getId()) + " encountered errors during closure: ", t); 227 } 228 229 } 230 231 public int getMark() { 232 return mark; 233 } 234 235 public int getStatus() { 236 return status; 237 } 238 239 242 public boolean setStatus(int newStatus) { 243 return setStatus(STATUS_FORCE, newStatus); 244 } 245 246 249 public boolean setStatus(int oldStatus, int newStatus) { 250 boolean success = false; 251 try { 252 statusReadWriteLock.writeLock().acquire(); 253 connectionPool.acquireConnectionStatusWriteLock(); 254 if (this.status == oldStatus || oldStatus == STATUS_FORCE) { 255 connectionPool.changeStatus(this.status, newStatus); 256 this.status = newStatus; 257 success = true; 258 259 if (newStatus == oldStatus) { 260 LOG.warn("Unexpected attempt to change status from " + oldStatus + " to " + newStatus 261 + ". Why would you want to do that?"); 262 } else if (newStatus == STATUS_ACTIVE) { 263 setTimeLastStartActive(System.currentTimeMillis()); 264 } else if (oldStatus == STATUS_ACTIVE) { 265 setTimeLastStopActive(System.currentTimeMillis()); 266 } 267 } 268 } catch (InterruptedException e) { 269 LOG.error("Unable to acquire write lock for status"); 270 } finally { 271 connectionPool.releaseConnectionStatusWriteLock(); 272 statusReadWriteLock.writeLock().release(); 273 } 274 return success; 275 } 276 277 public long getId() { 278 return id; 279 } 280 281 public void setId(long id) { 282 this.id = id; 283 } 284 285 288 public long getBirthTime() { 289 return birthDate.getTime(); 290 } 291 292 295 public Date getBirthDate() { 296 return birthDate; 297 } 298 299 302 public long getAge() { 303 return System.currentTimeMillis() - getBirthTime(); 304 } 305 306 309 public void setBirthTime(long birthTime) { 310 birthDate = new Date (birthTime); 311 } 312 313 316 public long getTimeLastStartActive() { 317 return timeLastStartActive; 318 } 319 320 323 public void setTimeLastStartActive(long timeLastStartActive) { 324 this.timeLastStartActive = timeLastStartActive; 325 setTimeLastStopActive(0); 326 } 327 328 331 public long getTimeLastStopActive() { 332 return timeLastStopActive; 333 } 334 335 338 public void setTimeLastStopActive(long timeLastStopActive) { 339 this.timeLastStopActive = timeLastStopActive; 340 } 341 342 345 public String getRequester() { 346 return requester; 347 } 348 349 352 public void setRequester(String requester) { 353 this.requester = requester; 354 } 355 356 359 public boolean isNull() { 360 return getStatus() == STATUS_NULL; 361 } 362 363 366 public boolean isAvailable() { 367 return getStatus() == STATUS_AVAILABLE; 368 } 369 370 373 public boolean isActive() { 374 return getStatus() == STATUS_ACTIVE; 375 } 376 377 380 public boolean isOffline() { 381 return getStatus() == STATUS_OFFLINE; 382 } 383 384 387 public void markForExpiry(String reason) { 388 mark = MARK_FOR_EXPIRY; 389 reasonForMark = reason; 390 } 391 392 395 public boolean isMarkedForExpiry() { 396 return getMark() == MARK_FOR_EXPIRY; 397 } 398 399 402 public String getReasonForMark() { 403 return reasonForMark; 404 } 405 406 409 public Connection getConnection() { 410 return connection; 411 } 412 413 416 public String toString() { 417 return getId() + " is " + ConnectionPool.getStatusDescription(getStatus()); 418 } 419 420 423 public String getDelegateUrl() { 424 return delegateUrl; 425 } 426 427 430 public String getProxyHashcode() { 431 return Integer.toHexString(hashCode()); 432 } 433 434 437 public String getDelegateHashcode() { 438 if (connection != null) { 439 return Integer.toHexString(connection.hashCode()); 440 } else { 441 return null; 442 } 443 } 444 445 451 public int compareTo(Object o) { 452 return new Long (((ConnectionInfoIF) o).getId()).compareTo(new Long (getId())); 453 } 454 } 455 456 457 | Popular Tags |