Search in sources :

Example 1 with LDAPResponse

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);
        }
    }
}
Also used : LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) LDAPResponse(com.unboundid.ldap.protocol.LDAPResponse) NotNull(com.unboundid.util.NotNull)

Example 2 with LDAPResponse

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);
    }
}
Also used : LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) StartTLSExtendedRequest(com.unboundid.ldap.sdk.extensions.StartTLSExtendedRequest) LDAPResponse(com.unboundid.ldap.protocol.LDAPResponse) NotNull(com.unboundid.util.NotNull)

Example 3 with LDAPResponse

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);
}
Also used : Socket(java.net.Socket) LDAPResponse(com.unboundid.ldap.protocol.LDAPResponse) HashSet(java.util.HashSet) NotNull(com.unboundid.util.NotNull)

Example 4 with LDAPResponse

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);
        }
    }
}
Also used : LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) LDAPResponse(com.unboundid.ldap.protocol.LDAPResponse) NotNull(com.unboundid.util.NotNull)

Example 5 with LDAPResponse

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);
    }
}
Also used : LDAPResponse(com.unboundid.ldap.protocol.LDAPResponse) NotNull(com.unboundid.util.NotNull)

Aggregations

LDAPResponse (com.unboundid.ldap.protocol.LDAPResponse)23 NotNull (com.unboundid.util.NotNull)21 LDAPMessage (com.unboundid.ldap.protocol.LDAPMessage)10 ASN1Exception (com.unboundid.asn1.ASN1Exception)2 ASN1OctetString (com.unboundid.asn1.ASN1OctetString)2 NoticeOfDisconnectionExtendedResult (com.unboundid.ldap.sdk.extensions.NoticeOfDisconnectionExtendedResult)2 IOException (java.io.IOException)2 InterruptedIOException (java.io.InterruptedIOException)2 SocketTimeoutException (java.net.SocketTimeoutException)2 Level (java.util.logging.Level)2 ASN1StreamReader (com.unboundid.asn1.ASN1StreamReader)1 StartTLSExtendedRequest (com.unboundid.ldap.sdk.extensions.StartTLSExtendedRequest)1 BufferedInputStream (java.io.BufferedInputStream)1 Socket (java.net.Socket)1 HashSet (java.util.HashSet)1 SSLSocket (javax.net.ssl.SSLSocket)1