Fix issue 2850.
Modify the LDAPClientConnection.cancelAllOperations(...) method to pre-emptively set a CancelResult in pending operations thus preventing the subsequent cancel request from blocking (this can cause very slow LDAP disconnects and potentially freeze the server). Fix a similar problem that can occur while shutting down the work queue.
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2007-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.core; |
| | | import org.opends.messages.Message; |
| | |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | // Before calling clientConnection.disconnect, we need to mark this |
| | | // operation as cancelled so that the attempt to cancel it later won't cause |
| | | // an unnecessary delay. |
| | | setCancelResult(CancelResult.CANCELED); |
| | | |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2007-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.core; |
| | | import org.opends.messages.Message; |
| | |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | // Since bind operations can't be cancelled, we don't need to do anything |
| | | // but forward the request on to the client connection. |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2007-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.core; |
| | | import org.opends.messages.Message; |
| | |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | // Before calling clientConnection.disconnect, we need to mark this |
| | | // operation as cancelled so that the attempt to cancel it later won't cause |
| | | // an unnecessary delay. |
| | | setCancelResult(CancelResult.CANCELED); |
| | | |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2007-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.core; |
| | | import org.opends.messages.Message; |
| | |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | // Before calling clientConnection.disconnect, we need to mark this |
| | | // operation as cancelled so that the attempt to cancel it later won't cause |
| | | // an unnecessary delay. |
| | | setCancelResult(CancelResult.CANCELED); |
| | | |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006-2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.core; |
| | | import org.opends.messages.Message; |
| | |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | // Before calling clientConnection.disconnect, we need to mark this |
| | | // operation as cancelled so that the attempt to cancel it later won't cause |
| | | // an unnecessary delay. |
| | | setCancelResult(CancelResult.CANCELED); |
| | | |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006-2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.core; |
| | | import org.opends.messages.Message; |
| | |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | // Before calling clientConnection.disconnect, we need to mark this |
| | | // operation as cancelled so that the attempt to cancel it later won't cause |
| | | // an unnecessary delay. |
| | | setCancelResult(CancelResult.CANCELED); |
| | | |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2007-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.core; |
| | | |
| | |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | // Before calling clientConnection.disconnect, we need to mark this |
| | | // operation as cancelled so that the attempt to cancel it later won't cause |
| | | // an unnecessary delay. |
| | | setCancelResult(CancelResult.CANCELED); |
| | | |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | // Before calling clientConnection.disconnect, we need to mark this |
| | | // operation as cancelled so that the attempt to cancel it later won't cause |
| | | // an unnecessary delay. |
| | | setCancelResult(CancelResult.CANCELED); |
| | | |
| | | clientConnection.disconnect(disconnectReason, sendNotification, message); |
| | | } |
| | | |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006-2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.core; |
| | | import org.opends.messages.Message; |
| | |
| | | public final void disconnectClient(DisconnectReason disconnectReason, |
| | | boolean sendNotification, Message message) |
| | | { |
| | | // Since unbind operations can't be cancelled, we don't need to do anything |
| | | // but forward the request on to the client connection. |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006-2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | |
| | | import org.opends.server.monitors.TraditionalWorkQueueMonitor; |
| | | import org.opends.server.types.AbstractOperation; |
| | | import org.opends.server.types.CancelRequest; |
| | | import org.opends.server.types.CancelResult; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | |
| | | { |
| | | try |
| | | { |
| | | o.cancel(cancelRequest); |
| | | // The operation has no chance of responding to the cancel |
| | | // request so avoid waiting for a cancel response. |
| | | if (o.getCancelResult() == null) { |
| | | o.setCancelResult(CancelResult.CANCELED); |
| | | o.cancel(cancelRequest); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006-2007 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.protocols.ldap; |
| | | |
| | |
| | | boolean sendNotification, |
| | | Message message) |
| | | { |
| | | // If we are already in the middle of a disconnect, then don't do anything. |
| | | if (disconnectRequested) |
| | | // Set a flag indicating that the connection is being terminated so that no |
| | | // new requests will be accepted. Also cancel all operations in progress. |
| | | synchronized (opsInProgressLock) |
| | | { |
| | | return; |
| | | // If we are already in the middle of a disconnect, then don't |
| | | // do anything. |
| | | if (disconnectRequested) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | disconnectRequested = true; |
| | | } |
| | | |
| | | |
| | |
| | | connectionValid = false; |
| | | |
| | | |
| | | // Set a flag indicating that the connection is being terminated so that no |
| | | // new requests will be accepted. Also cancel all operations in progress. |
| | | synchronized (opsInProgressLock) |
| | | { |
| | | try |
| | | { |
| | | disconnectRequested = true; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | cancelAllOperations(new CancelRequest(true, message)); |
| | | finalizeConnectionInternal(); |
| | | |
| | |
| | | { |
| | | try |
| | | { |
| | | CancelResult cancelResult = o.cancel(cancelRequest); |
| | | CancelResult cancelResult = o.getCancelResult(); |
| | | if (cancelResult == null) { |
| | | // Before calling cancelling the operation, we need to |
| | | // mark this operation as cancelled so that the attempt to |
| | | // cancel it later won't cause an unnecessary delay. |
| | | o.setCancelResult(CancelResult.CANCELED); |
| | | cancelResult = o.cancel(cancelRequest); |
| | | } |
| | | |
| | | if (keepStats && (cancelResult == CancelResult.CANCELED)) |
| | | { |
| | | statTracker.updateAbandonedOperation(); |