/** * Creates the connection handle again. We use this method to create a brand new connection * handle. That way if the application (wrongly) tries to do something else with the connection * that has already been "closed", it will fail. * @return ConnectionHandle * @throws SQLException */ public ConnectionHandle recreateConnectionHandle() throws SQLException{ ConnectionHandle handle = new ConnectionHandle(this.connection, this.originatingPartition, this.pool, true); handle.originatingPartition = this.originatingPartition; handle.connectionCreationTimeInMs = this.connectionCreationTimeInMs; handle.connectionLastResetInMs = this.connectionLastResetInMs; handle.connectionLastUsedInMs = this.connectionLastUsedInMs; handle.preparedStatementCache = this.preparedStatementCache; handle.callableStatementCache = this.callableStatementCache; handle.statementCachingEnabled = this.statementCachingEnabled; handle.connectionHook = this.connectionHook; handle.possiblyBroken = this.possiblyBroken; handle.debugHandle = this.debugHandle; this.connection = null; return handle; }
connectionHandle.clearStatementCaches(false); if (connectionHandle.getReplayLog() != null){ connectionHandle.getReplayLog().clear(); connectionHandle.recoveryResult.getReplaceTarget().clear(); if (connectionHandle.isExpired() || (!this.poolShuttingDown && connectionHandle.isPossiblyBroken() && !isConnectionHandleAlive(connectionHandle))){ if (connectionHandle.isExpired()) { connectionHandle.internalClose(); ConnectionPartition connectionPartition = connectionHandle.getOriginatingPartition(); postDestroyConnection(connectionHandle); connectionHandle.clearStatementCaches(true); return; // don't place back in queue - connection is broken or expired. connectionHandle.setConnectionLastUsedInMs(System.currentTimeMillis()); if (!this.poolShuttingDown){ putConnectionBackInPartition(connectionHandle); } else { connectionHandle.internalClose();
/** Update counters and call hooks. * @param handle connection handle. */ protected void postDestroyConnection(ConnectionHandle handle){ ConnectionPartition partition = handle.getOriginatingPartition(); if (this.finalizableRefQueue != null && handle.getInternalConnection() != null){ //safety this.finalizableRefs.remove(handle.getInternalConnection()); // assert o != null : "Did not manage to remove connection from finalizable ref queue"; } partition.updateCreatedConnections(-1); partition.setUnableToCreateMoreTransactions(false); // we can create new ones now, this is an optimization // "Destroying" for us means: don't put it back in the pool. if (handle.getConnectionHook() != null){ handle.getConnectionHook().onDestroy(handle); } }
/** * Physically close off the internal connection. * @param conn */ protected void destroyConnection(ConnectionHandle conn) { postDestroyConnection(conn); conn.setInReplayMode(true); // we're dead, stop attempting to replay anything try { conn.internalClose(); } catch (SQLException e) { logger.error("Error in attempting to close connection", e); } }
/** * Close off the connection. * * @throws SQLException */ protected void internalClose() throws SQLException { try { clearStatementCaches(true); if (this.connection != null){ // safety! this.connection.close(); if (!this.connectionTrackingDisabled && this.finalizableRefs != null){ this.finalizableRefs.remove(this.connection); } } this.logicallyClosed.set(true); } catch (SQLException e) { throw markPossiblyBroken(e); } }
ConnectionHook connectionHook = con.getPool().getConfig().getConnectionHook(); int acquireRetryAttempts = con.getPool().getConfig().getAcquireRetryAttempts(); long acquireRetryDelay = con.getPool().getConfig().getAcquireRetryDelayInMs(); AcquireFailConfig acquireConfig = new AcquireFailConfig(); acquireConfig.setAcquireRetryAttempts(new AtomicInteger(acquireRetryAttempts)); tryAgain = false; con.setInReplayMode(true); // don't go in a loop of saving our saved log! try{ con.clearStatementCaches(true); con.getInternalConnection().close(); } catch(Throwable t){ con.setInternalConnection(memorize(con.getPool().obtainInternalConnection(con), con)); } catch(SQLException e){ throw con.markPossiblyBroken(e); con.getOriginatingPartition().trackConnectionFinalizer(con); // track this too. replaceTarget.put(replay.getTarget(), con.getInternalConnection()); } else if (replay.getTarget() instanceof CallableStatement){ if (replaceTarget.get(replay.getTarget()) == null){
if (con.isInReplayMode()){ // go straight through when flagged as in playback (replay) mode. try{ return method.invoke(this.target, args); if (!con.isInReplayMode() && !method.getName().equals("hashCode") && !method.getName().equals("equals") && !method.getName().equals("toString")){ con.getReplayLog().add(new ReplayLog(this.target, method, args)); if (!con.isInReplayMode() && (this.target instanceof Connection) && clearLogConditions.contains(method.getName())){ con.getReplayLog().clear(); List<ReplayLog> oldReplayLog = con.getReplayLog(); con.setInReplayMode(true); // stop recording con.markPossiblyBroken((SQLException)t.getCause()); if (!con.isPossiblyBroken()){ // connection is possibly recoverable... con.setInReplayMode(false); // start recording again con.getReplayLog().clear(); } else { // connection is possibly recoverable... logger.error("Connection failed. Attempting to recover transaction on Thread #"+ Thread.currentThread().getId()); con.setReplayLog(oldReplayLog); // attemptRecovery will probably destroy our original connection handle con.setInReplayMode(false); // start recording again logger.error("Recovery succeeded on Thread #" + Thread.currentThread().getId()); con.possiblyBroken = false; con.setInReplayMode(false); // start recording again con.getReplayLog().clear();
connection.setOriginatingPartition(this.partition); if (connection.isPossiblyBroken() || ((this.idleMaxAgeInMs > 0) && ( System.currentTimeMillis()-connection.getConnectionLastUsedInMs() > this.idleMaxAgeInMs))){ if (this.idleConnectionTestPeriodInMs > 0 && (currentTimeInMs-connection.getConnectionLastUsedInMs() > this.idleConnectionTestPeriodInMs) && (currentTimeInMs-connection.getConnectionLastResetInMs() >= this.idleConnectionTestPeriodInMs)) { tmp = Math.abs(this.idleConnectionTestPeriodInMs-(currentTimeInMs - connection.getConnectionLastResetInMs())); long tmp2 = Math.abs(this.idleMaxAgeInMs - (currentTimeInMs-connection.getConnectionLastUsedInMs())); if (this.idleMaxAgeInMs > 0){ tmp = Math.min(tmp, tmp2); if (!(connection.getOriginatingPartition().getFreeConnections().offer(connection))){ connection.internalClose();
connection.setOriginatingPartition(this.partition); tmp = this.maxAgeInMs - (currentTime - connection.getConnectionCreationTimeInMs()); if (connection.isExpired(currentTime)){ if (!(connection.getOriginatingPartition().getFreeConnections().offer(connection))){ connection.internalClose();
rs = connection.getMetaData().getTables( null, null, KEEPALIVEMETADATA, METADATATABLE ); } else { stmt = connection.createStatement(); stmt.execute(testStatement); } finally { connection.logicallyClosed.set(logicallyClosed); connection.setConnectionLastResetInMs(System.currentTimeMillis()); result = closeStatement(stmt, result);
boolean tryAgain; Connection result; Connection oldRawConnection = connectionHandle.getInternalConnection(); String url = this.getConfig().getJdbcUrl(); connectionHandle.setInternalConnection(result); ConnectionHandle.sendInitSQL(result, this.getConfig().getInitSQL()); } catch (SQLException e) { result.close(); connectionHandle.setInternalConnection(oldRawConnection); throw e;
/** Closes off this connection * @param connection to close */ protected void closeConnection(ConnectionHandle connection) { if (connection != null && !connection.isClosed()) { try { connection.internalClose(); } catch (SQLException e) { logger.error("Destroy connection exception", e); } finally { this.pool.postDestroyConnection(connection); connection.getOriginatingPartition().getPoolWatchThreadSignalQueue().offer(new Object()); // item being pushed is not important. } } }
/** * Adds a free connection. * * @param connectionHandle * @throws SQLException on error */ protected void addFreeConnection(ConnectionHandle connectionHandle) throws SQLException{ connectionHandle.setOriginatingPartition(this); // assume success to avoid racing where we insert an item in a queue and having that item immediately // taken and closed off thus decrementing the created connection count. updateCreatedConnections(1); if (!this.disableTracking){ trackConnectionFinalizer(connectionHandle); } // the instant the following line is executed, consumers can start making use of this // connection. if (!this.freeConnections.offer(connectionHandle)){ // we failed. rollback. updateCreatedConnections(-1); // compensate our createdConnection count. if (!this.disableTracking){ this.pool.getFinalizableRefs().remove(connectionHandle.getInternalConnection()); } // terminate the internal handle. connectionHandle.internalClose(); } }
/** Places a connection back in the originating partition. * @param connectionHandle to place back * @throws SQLException on error */ protected void putConnectionBackInPartition(ConnectionHandle connectionHandle) throws SQLException { if (this.cachedPoolStrategy && ((CachedConnectionStrategy)this.connectionStrategy).tlConnections.dumbGet().getValue()){ connectionHandle.logicallyClosed.set(true); ((CachedConnectionStrategy)this.connectionStrategy).tlConnections.set(new AbstractMap.SimpleEntry<ConnectionHandle, Boolean>(connectionHandle, false)); } else { BlockingQueue<ConnectionHandle> queue = connectionHandle.getOriginatingPartition().getFreeConnections(); if (!queue.offer(connectionHandle)){ // this shouldn't fail connectionHandle.internalClose(); } } }
boolean alreadyDestroyed = false; ConnectionState connectionState = this.getConnectionHook() != null ? this.getConnectionHook().onMarkPossiblyBroken(this, state, e) : ConnectionState.NOP; if (state == null){ // safety; state = "08999"; this.pool.destroyConnection(this); this.logicallyClosed.set(true); getOriginatingPartition().getPoolWatchThreadSignalQueue().offer(new Object()); // item being pushed is not important. if (this.possiblyBroken && (this.getConnectionHook() != null)){ this.possiblyBroken = this.getConnectionHook().onConnectionException(this, state, e);
/** After obtaining a connection, perform additional tasks. * @param handle * @param statsObtainTime */ protected void postConnection(ConnectionHandle handle, long statsObtainTime){ handle.renewConnection(); // mark it as being logically "open" // Give an application a chance to do something with it. if (handle.getConnectionHook() != null){ handle.getConnectionHook().onCheckOut(handle); } if (this.pool.closeConnectionWatch){ // a debugging tool this.pool.watchConnection(handle); } if (this.pool.statisticsEnabled){ this.pool.statistics.addCumulativeConnectionWaitTime(System.nanoTime()-statsObtainTime); } }
if (!this.disableTracking){ Connection con = connectionHandle.getInternalConnection(); if (con != null && con instanceof Proxy && Proxy.getInvocationHandler(con) instanceof MemorizeTransactionProxy){ try { final BoneCP pool = connectionHandle.getPool(); connectionHandle.getPool().getFinalizableRefs().put(internalDBConnection, new FinalizableWeakReference<ConnectionHandle>(connectionHandle, connectionHandle.getPool().getFinalizableRefQueue()) { @SuppressWarnings("synthetic-access") public void finalizeReferent() {
this.connectionHandle = connectionHandle; this.logStatementsEnabled = logStatementsEnabled; BoneCPConfig config = connectionHandle.getPool().getConfig(); this.connectionHook = config.getConnectionHook(); this.statistics = connectionHandle.getPool().getStatistics(); this.statisticsEnabled = config.isStatisticsEnabled(); this.queryExecuteTimeLimit = connectionHandle.getOriginatingPartition().getQueryExecuteTimeLimitinNanoSeconds(); } catch (Exception e){ // safety!
/** * Releases the given connection back to the pool. This method is not intended to be called by * applications (hence set to protected). Call connection.close() instead which will return * the connection back to the pool. * * @param connection to release * @throws SQLException */ protected void releaseConnection(Connection connection) throws SQLException { ConnectionHandle handle = (ConnectionHandle)connection; // hook calls if (handle.getConnectionHook() != null){ handle.getConnectionHook().onCheckIn(handle); } // release immediately or place it in a queue so that another thread will eventually close it. If we're shutting down, // close off the connection right away because the helper threads have gone away. if (!this.poolShuttingDown){ internalReleaseConnection(handle); } }
/** Returns true if the given connection has exceeded the maxConnectionAge. * @return true if the connection has expired. */ public boolean isExpired() { return this.maxConnectionAgeInMs > 0 && isExpired(System.currentTimeMillis()); }