use of com.unboundid.ldap.protocol.LDAPResponse in project ldapsdk by pingidentity.
the class ExtendedRequest method processSync.
/**
* Processes this extended operation in synchronous mode, in which the same
* thread will send the request and read the response.
*
* @param connection The connection to use to communicate with the directory
* server.
*
* @return An LDAP result object that provides information about the result
* of the extended processing.
*
* @throws LDAPException If a problem occurs while sending the request or
* reading the response.
*/
@NotNull()
private ExtendedResult processSync(@NotNull final LDAPConnection connection) throws LDAPException {
// Create the LDAP message.
messageID = connection.nextMessageID();
final LDAPMessage message = new LDAPMessage(messageID, this, getControls());
// Send the request to the server.
final long requestTime = System.nanoTime();
Debug.debugLDAPRequest(Level.INFO, this, messageID, connection);
final LDAPConnectionLogger logger = connection.getConnectionOptions().getConnectionLogger();
if (logger != null) {
logger.logExtendedRequest(connection, messageID, this);
}
connection.getConnectionStatistics().incrementNumExtendedRequests();
connection.sendMessage(message, getResponseTimeoutMillis(connection));
while (true) {
final LDAPResponse response;
try {
response = connection.readResponse(messageID);
} catch (final LDAPException le) {
Debug.debugException(le);
if ((le.getResultCode() == ResultCode.TIMEOUT) && connection.getConnectionOptions().abandonOnTimeout()) {
connection.abandon(messageID);
}
throw le;
}
if (response instanceof IntermediateResponse) {
final IntermediateResponseListener listener = getIntermediateResponseListener();
if (listener != null) {
listener.intermediateResponseReturned((IntermediateResponse) response);
}
} else {
return handleResponse(connection, response, requestTime);
}
}
}
use of com.unboundid.ldap.protocol.LDAPResponse in project ldapsdk by pingidentity.
the class ExtendedRequest method process.
/**
* Sends this extended request to the directory server over the provided
* connection and returns the associated response.
*
* @param connection The connection to use to communicate with the directory
* server.
* @param depth The current referral depth for this request. It should
* always be one for the initial request, and should only
* be incremented when following referrals.
*
* @return An LDAP result object that provides information about the result
* of the extended operation processing.
*
* @throws LDAPException If a problem occurs while sending the request or
* reading the response.
*/
@Override()
@NotNull()
protected ExtendedResult process(@NotNull final LDAPConnection connection, final int depth) throws LDAPException {
if (connection.synchronousMode()) {
return processSync(connection);
}
// Create the LDAP message.
messageID = connection.nextMessageID();
final LDAPMessage message = new LDAPMessage(messageID, this, getControls());
// Register with the connection reader to be notified of responses for the
// request that we've created.
connection.registerResponseAcceptor(messageID, this);
try {
// Send the request to the server.
final long responseTimeout = getResponseTimeoutMillis(connection);
Debug.debugLDAPRequest(Level.INFO, this, messageID, connection);
final LDAPConnectionLogger logger = connection.getConnectionOptions().getConnectionLogger();
if (logger != null) {
logger.logExtendedRequest(connection, messageID, this);
}
final long requestTime = System.nanoTime();
connection.getConnectionStatistics().incrementNumExtendedRequests();
if (this instanceof StartTLSExtendedRequest) {
connection.sendMessage(message, 50L);
} else {
connection.sendMessage(message, responseTimeout);
}
// Wait for and process the response.
final LDAPResponse response;
try {
if (responseTimeout > 0) {
response = responseQueue.poll(responseTimeout, TimeUnit.MILLISECONDS);
} else {
response = responseQueue.take();
}
} catch (final InterruptedException ie) {
Debug.debugException(ie);
Thread.currentThread().interrupt();
throw new LDAPException(ResultCode.LOCAL_ERROR, ERR_EXTOP_INTERRUPTED.get(connection.getHostPort()), ie);
}
return handleResponse(connection, response, requestTime);
} finally {
connection.deregisterResponseAcceptor(messageID);
}
}
use of com.unboundid.ldap.protocol.LDAPResponse in project ldapsdk by pingidentity.
the class LDAPConnectionPool method invokeHealthCheck.
/**
* Invokes a synchronous one-time health-check against the connections in this
* pool that are not currently in use. This will be independent of any
* background health checking that may be automatically performed by the pool.
*
* @param healthCheck The health check to use. If this is
* {@code null}, then the pool's
* currently-configured health check (if any)
* will be used. If this is {@code null} and
* there is no health check configured for the
* pool, then only a basic set of checks.
* @param checkForExpiration Indicates whether to check to see if any
* connections have been established for
* longer than the maximum connection age. If
* this is {@code true} then any expired
* connections will be closed and replaced
* with newly-established connections.
* @param checkMinConnectionGoal Indicates whether to check to see if the
* currently-available number of connections
* is less than the minimum available
* connection goal. If this is {@code true}
* the minimum available connection goal is
* greater than zero, and the number of
* currently-available connections is less
* than the goal, then this method will
* attempt to create enough new connections to
* reach the goal.
*
* @return An object with information about the result of the health check
* processing.
*/
@NotNull()
public LDAPConnectionPoolHealthCheckResult invokeHealthCheck(@Nullable final LDAPConnectionPoolHealthCheck healthCheck, final boolean checkForExpiration, final boolean checkMinConnectionGoal) {
// Determine which health check to use.
final LDAPConnectionPoolHealthCheck hc;
if (healthCheck == null) {
hc = this.healthCheck;
} else {
hc = healthCheck;
}
// Create a set used to hold connections that we've already examined. If we
// encounter the same connection twice, then we know that we don't need to
// do any more work.
final HashSet<LDAPConnection> examinedConnections = new HashSet<>(StaticUtils.computeMapCapacity(numConnections));
int numExamined = 0;
int numDefunct = 0;
int numExpired = 0;
for (int i = 0; i < numConnections; i++) {
LDAPConnection conn = availableConnections.poll();
if (conn == null) {
break;
} else if (examinedConnections.contains(conn)) {
if (!availableConnections.offer(conn)) {
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_UNNEEDED, null, null);
poolStatistics.incrementNumConnectionsClosedUnneeded();
Debug.debugConnectionPool(Level.INFO, this, conn, "Closing a connection that had just been health checked " + "because the pool is now full", null);
conn.terminate(null);
}
break;
}
numExamined++;
if (!conn.isConnected()) {
numDefunct++;
poolStatistics.incrementNumConnectionsClosedDefunct();
Debug.debugConnectionPool(Level.WARNING, this, conn, "Closing a connection that was identified as not established " + "during health check processing", null);
conn = handleDefunctConnection(conn);
if (conn != null) {
examinedConnections.add(conn);
}
} else {
if (checkForExpiration && connectionIsExpired(conn)) {
numExpired++;
try {
final LDAPConnection newConnection = createConnection();
if (availableConnections.offer(newConnection)) {
examinedConnections.add(newConnection);
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_EXPIRED, null, null);
conn.terminate(null);
poolStatistics.incrementNumConnectionsClosedExpired();
Debug.debugConnectionPool(Level.INFO, this, conn, "Closing a connection that was identified as expired " + "during health check processing", null);
lastExpiredDisconnectTime = System.currentTimeMillis();
continue;
} else {
newConnection.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_UNNEEDED, null, null);
newConnection.terminate(null);
poolStatistics.incrementNumConnectionsClosedUnneeded();
Debug.debugConnectionPool(Level.INFO, this, newConnection, "Closing a newly created connection created to replace " + "an expired connection because the pool is already " + "full", null);
}
} catch (final LDAPException le) {
Debug.debugException(le);
}
}
// use the connection.
if (trySynchronousReadDuringHealthCheck && conn.synchronousMode()) {
int previousTimeout = Integer.MIN_VALUE;
Socket s = null;
try {
s = conn.getConnectionInternals(true).getSocket();
previousTimeout = s.getSoTimeout();
InternalSDKHelper.setSoTimeout(conn, 1);
final LDAPResponse response = conn.readResponse(0);
if (response instanceof ConnectionClosedResponse) {
numDefunct++;
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_DEFUNCT, ERR_POOL_HEALTH_CHECK_CONN_CLOSED.get(), null);
poolStatistics.incrementNumConnectionsClosedDefunct();
Debug.debugConnectionPool(Level.WARNING, this, conn, "Closing existing connection discovered to be " + "disconnected during health check processing", null);
conn = handleDefunctConnection(conn);
if (conn != null) {
examinedConnections.add(conn);
}
continue;
} else if (response instanceof ExtendedResult) {
// This means we got an unsolicited response. It could be a
// notice of disconnection, or it could be something else, but in
// any case we'll send it to the connection's unsolicited
// notification handler (if one is defined).
final UnsolicitedNotificationHandler h = conn.getConnectionOptions().getUnsolicitedNotificationHandler();
if (h != null) {
h.handleUnsolicitedNotification(conn, (ExtendedResult) response);
}
} else if (response instanceof LDAPResult) {
final LDAPResult r = (LDAPResult) response;
if (r.getResultCode() == ResultCode.SERVER_DOWN) {
numDefunct++;
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_DEFUNCT, ERR_POOL_HEALTH_CHECK_CONN_CLOSED.get(), null);
poolStatistics.incrementNumConnectionsClosedDefunct();
Debug.debugConnectionPool(Level.WARNING, this, conn, "Closing existing connection discovered to be invalid " + "with result " + r + " during health check " + "processing", null);
conn = handleDefunctConnection(conn);
if (conn != null) {
examinedConnections.add(conn);
}
continue;
}
}
} catch (final LDAPException le) {
if (le.getResultCode() == ResultCode.TIMEOUT) {
Debug.debugException(Level.FINEST, le);
} else {
Debug.debugException(le);
numDefunct++;
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_DEFUNCT, ERR_POOL_HEALTH_CHECK_READ_FAILURE.get(StaticUtils.getExceptionMessage(le)), le);
poolStatistics.incrementNumConnectionsClosedDefunct();
Debug.debugConnectionPool(Level.WARNING, this, conn, "Closing existing connection discovered to be invalid " + "during health check processing", le);
conn = handleDefunctConnection(conn);
if (conn != null) {
examinedConnections.add(conn);
}
continue;
}
} catch (final Exception e) {
Debug.debugException(e);
numDefunct++;
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_DEFUNCT, ERR_POOL_HEALTH_CHECK_READ_FAILURE.get(StaticUtils.getExceptionMessage(e)), e);
poolStatistics.incrementNumConnectionsClosedDefunct();
Debug.debugConnectionPool(Level.SEVERE, this, conn, "Closing existing connection discovered to be invalid " + "with an unexpected exception type during health check " + "processing", e);
conn = handleDefunctConnection(conn);
if (conn != null) {
examinedConnections.add(conn);
}
continue;
} finally {
if (previousTimeout != Integer.MIN_VALUE) {
try {
if (s != null) {
InternalSDKHelper.setSoTimeout(conn, previousTimeout);
}
} catch (final Exception e) {
Debug.debugException(e);
numDefunct++;
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_DEFUNCT, null, e);
poolStatistics.incrementNumConnectionsClosedDefunct();
Debug.debugConnectionPool(Level.SEVERE, this, conn, "Closing existing connection during health check " + "processing because an error occurred while " + "attempting to set the SO_TIMEOUT", e);
conn = handleDefunctConnection(conn);
if (conn != null) {
examinedConnections.add(conn);
}
continue;
}
}
}
}
try {
hc.ensureConnectionValidForContinuedUse(conn);
if (availableConnections.offer(conn)) {
examinedConnections.add(conn);
} else {
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_UNNEEDED, null, null);
poolStatistics.incrementNumConnectionsClosedUnneeded();
Debug.debugConnectionPool(Level.INFO, this, conn, "Closing existing connection that passed health check " + "processing because the pool is already full", null);
conn.terminate(null);
}
} catch (final Exception e) {
Debug.debugException(e);
numDefunct++;
poolStatistics.incrementNumConnectionsClosedDefunct();
Debug.debugConnectionPool(Level.WARNING, this, conn, "Closing existing connection that failed health check " + "processing", e);
conn = handleDefunctConnection(conn);
if (conn != null) {
examinedConnections.add(conn);
}
}
}
}
if (checkMinConnectionGoal) {
try {
final int neededConnections = minConnectionGoal - availableConnections.size();
for (int i = 0; i < neededConnections; i++) {
final LDAPConnection conn = createConnection(hc);
if (!availableConnections.offer(conn)) {
conn.setDisconnectInfo(DisconnectType.POOLED_CONNECTION_UNNEEDED, null, null);
poolStatistics.incrementNumConnectionsClosedUnneeded();
Debug.debugConnectionPool(Level.INFO, this, conn, "Closing a new connection that was created during health " + "check processing in achieve the minimum connection " + "goal, but the pool had already become full after the " + "connection was created", null);
conn.terminate(null);
break;
}
}
} catch (final Exception e) {
Debug.debugException(e);
}
}
return new LDAPConnectionPoolHealthCheckResult(numExamined, numExpired, numDefunct);
}
use of com.unboundid.ldap.protocol.LDAPResponse in project ldapsdk by pingidentity.
the class DeleteRequest method processSync.
/**
* Processes this delete operation in synchronous mode, in which the same
* thread will send the request and read the response.
*
* @param connection The connection to use to communicate with the directory
* server.
* @param depth The current referral depth for this request. It should
* always be one for the initial request, and should only
* be incremented when following referrals.
* @param allowRetry Indicates whether the request may be re-tried on a
* re-established connection if the initial attempt fails
* in a way that indicates the connection is no longer
* valid and autoReconnect is true.
*
* @return An LDAP result object that provides information about the result
* of the delete processing.
*
* @throws LDAPException If a problem occurs while sending the request or
* reading the response.
*/
@NotNull()
private LDAPResult processSync(@NotNull final LDAPConnection connection, final int depth, final boolean allowRetry) throws LDAPException {
// Create the LDAP message.
messageID = connection.nextMessageID();
final LDAPMessage message = new LDAPMessage(messageID, this, getControls());
// Send the request to the server.
final long requestTime = System.nanoTime();
Debug.debugLDAPRequest(Level.INFO, this, messageID, connection);
final LDAPConnectionLogger logger = connection.getConnectionOptions().getConnectionLogger();
if (logger != null) {
logger.logDeleteRequest(connection, messageID, this);
}
connection.getConnectionStatistics().incrementNumDeleteRequests();
try {
connection.sendMessage(message, getResponseTimeoutMillis(connection));
} catch (final LDAPException le) {
Debug.debugException(le);
if (allowRetry) {
final LDAPResult retryResult = reconnectAndRetry(connection, depth, le.getResultCode());
if (retryResult != null) {
return retryResult;
}
}
throw le;
}
while (true) {
final LDAPResponse response;
try {
response = connection.readResponse(messageID);
} catch (final LDAPException le) {
Debug.debugException(le);
if ((le.getResultCode() == ResultCode.TIMEOUT) && connection.getConnectionOptions().abandonOnTimeout()) {
connection.abandon(messageID);
}
if (allowRetry) {
final LDAPResult retryResult = reconnectAndRetry(connection, depth, le.getResultCode());
if (retryResult != null) {
return retryResult;
}
}
throw le;
}
if (response instanceof IntermediateResponse) {
final IntermediateResponseListener listener = getIntermediateResponseListener();
if (listener != null) {
listener.intermediateResponseReturned((IntermediateResponse) response);
}
} else {
return handleResponse(connection, response, requestTime, depth, allowRetry);
}
}
}
use of com.unboundid.ldap.protocol.LDAPResponse in project ldapsdk by pingidentity.
the class AddRequest method process.
/**
* Sends this add request to the directory server over the provided connection
* and returns the associated response.
*
* @param connection The connection to use to communicate with the directory
* server.
* @param depth The current referral depth for this request. It should
* always be one for the initial request, and should only
* be incremented when following referrals.
*
* @return An LDAP result object that provides information about the result
* of the add processing.
*
* @throws LDAPException If a problem occurs while sending the request or
* reading the response.
*/
@Override()
@NotNull()
protected LDAPResult process(@NotNull final LDAPConnection connection, final int depth) throws LDAPException {
if (connection.synchronousMode()) {
@SuppressWarnings("deprecation") final boolean autoReconnect = connection.getConnectionOptions().autoReconnect();
return processSync(connection, depth, autoReconnect);
}
final long requestTime = System.nanoTime();
processAsync(connection, null);
try {
// Wait for and process the response.
final LDAPResponse response;
try {
final long responseTimeout = getResponseTimeoutMillis(connection);
if (responseTimeout > 0) {
response = responseQueue.poll(responseTimeout, TimeUnit.MILLISECONDS);
} else {
response = responseQueue.take();
}
} catch (final InterruptedException ie) {
Debug.debugException(ie);
Thread.currentThread().interrupt();
throw new LDAPException(ResultCode.LOCAL_ERROR, ERR_ADD_INTERRUPTED.get(connection.getHostPort()), ie);
}
return handleResponse(connection, response, requestTime, depth, false);
} finally {
connection.deregisterResponseAcceptor(messageID);
}
}
Aggregations