From dc50d3e793098123cf7417713f2790e862e13bbb Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 13 May 2013 12:35:26 +0000
Subject: [PATCH] OPENDJ-858 (CR-1651) Add stats tracking to HTTP client connections
---
opends/src/server/org/opends/server/protocols/http/HTTPClientConnection.java | 151 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 145 insertions(+), 6 deletions(-)
diff --git a/opends/src/server/org/opends/server/protocols/http/HTTPClientConnection.java b/opends/src/server/org/opends/server/protocols/http/HTTPClientConnection.java
index 1b0244c..97d1854 100644
--- a/opends/src/server/org/opends/server/protocols/http/HTTPClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/http/HTTPClientConnection.java
@@ -48,9 +48,28 @@
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import org.opends.server.api.ClientConnection;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.BindOperation;
+import org.opends.server.core.CompareOperation;
+import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ExtendedOperation;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
import org.opends.server.core.SearchOperation;
import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.ldap.AddResponseProtocolOp;
+import org.opends.server.protocols.ldap.BindResponseProtocolOp;
+import org.opends.server.protocols.ldap.CompareResponseProtocolOp;
+import org.opends.server.protocols.ldap.DeleteResponseProtocolOp;
+import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
+import org.opends.server.protocols.ldap.LDAPMessage;
+import org.opends.server.protocols.ldap.ModifyDNResponseProtocolOp;
+import org.opends.server.protocols.ldap.ModifyResponseProtocolOp;
+import org.opends.server.protocols.ldap.ProtocolOp;
+import org.opends.server.protocols.ldap.SearchResultDoneProtocolOp;
+import org.opends.server.protocols.ldap.SearchResultEntryProtocolOp;
+import org.opends.server.protocols.ldap.SearchResultReferenceProtocolOp;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.DN;
@@ -59,6 +78,7 @@
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.IntermediateResponse;
import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SearchResultReference;
@@ -76,7 +96,6 @@
// TODO JNR Confirm with Matt that persistent searches are inapplicable to
// Rest2LDAP.
// TODO JNR Should I override getIdleTime()?
- // TODO JNR Implement stats
/**
* Class grouping together an {@link Operation} and its associated
@@ -128,6 +147,12 @@
private boolean disconnectRequested;
/**
+ * Indicates whether the connection should keep statistics regarding the
+ * operations that it is performing.
+ */
+ private final boolean keepStats;
+
+ /**
* The Map (messageID => {@link OperationWithFutureResult}) of all operations
* currently in progress on this connection.
*/
@@ -153,6 +178,10 @@
/** The reference to the connection handler that accepted this connection. */
private final HTTPConnectionHandler connectionHandler;
+ /** The statistics tracker associated with this client connection. */
+ private final HTTPStatistics statTracker;
+ private boolean useNanoTime = false;
+
/** The protocol in use for this client connection. */
private String protocol;
@@ -206,6 +235,15 @@
this.securityStrengthFactor =
calcSSF(request.getAttribute(SERVLET_SSF_CONSTANT));
+ this.statTracker = this.connectionHandler.getStatTracker();
+
+ this.keepStats = connectionHandler.keepStats();
+ if (this.keepStats)
+ {
+ this.statTracker.updateConnect();
+ this.useNanoTime = DirectoryServer.getUseNanoTime();
+ }
+
this.connectionID = DirectoryServer.newConnectionAccepted(this);
}
@@ -283,6 +321,21 @@
@Override
public void sendResponse(Operation operation)
{
+ if (keepStats)
+ {
+ long time;
+ if (useNanoTime)
+ {
+ time = operation.getProcessingNanoTime();
+ }
+ else
+ {
+ time = operation.getProcessingTime();
+ }
+ this.statTracker.updateOperationMonitoringData(operation
+ .getOperationType(), time);
+ }
+
OperationWithFutureResult op =
this.operationsInProgress.get(operation.getMessageID());
if (op != null)
@@ -290,6 +343,12 @@
try
{
op.futureResult.handleResult(getResponseResult(operation));
+
+ if (keepStats)
+ {
+ this.statTracker.updateMessageWritten(new LDAPMessage(operation
+ .getMessageID(), toResponseProtocolOp(operation)));
+ }
}
catch (ErrorResultException e)
{
@@ -298,6 +357,44 @@
}
}
+ private ProtocolOp toResponseProtocolOp(Operation operation)
+ {
+ final int resultCode = operation.getResultCode().getIntValue();
+ if (operation instanceof AddOperation)
+ {
+ return new AddResponseProtocolOp(resultCode);
+ }
+ else if (operation instanceof BindOperation)
+ {
+ return new BindResponseProtocolOp(resultCode);
+ }
+ else if (operation instanceof CompareOperation)
+ {
+ return new CompareResponseProtocolOp(resultCode);
+ }
+ else if (operation instanceof DeleteOperation)
+ {
+ return new DeleteResponseProtocolOp(resultCode);
+ }
+ else if (operation instanceof ExtendedOperation)
+ {
+ return new ExtendedResponseProtocolOp(resultCode);
+ }
+ else if (operation instanceof ModifyDNOperation)
+ {
+ return new ModifyDNResponseProtocolOp(resultCode);
+ }
+ else if (operation instanceof ModifyOperation)
+ {
+ return new ModifyResponseProtocolOp(resultCode);
+ }
+ else if (operation instanceof SearchOperation)
+ {
+ return new SearchResultDoneProtocolOp(resultCode);
+ }
+ throw new RuntimeException("Not implemented for operation " + operation);
+ }
+
/** {@inheritDoc} */
@Override
public void sendSearchEntry(SearchOperation operation,
@@ -309,6 +406,12 @@
{
((SearchResultHandler) op.futureResult.getResultHandler())
.handleEntry(from(searchEntry));
+
+ if (keepStats)
+ {
+ this.statTracker.updateMessageWritten(new LDAPMessage(operation
+ .getMessageID(), new SearchResultEntryProtocolOp(searchEntry)));
+ }
}
}
@@ -323,6 +426,13 @@
{
((SearchResultHandler) op.futureResult.getResultHandler())
.handleReference(from(searchReference));
+
+ if (keepStats)
+ {
+ this.statTracker.updateMessageWritten(new LDAPMessage(operation
+ .getMessageID(), new SearchResultReferenceProtocolOp(
+ searchReference)));
+ }
}
return connectionValid;
}
@@ -332,6 +442,12 @@
protected boolean sendIntermediateResponseMessage(
IntermediateResponse intermediateResponse)
{
+ // if (keepStats)
+ // {
+ // this.statTracker.updateMessageWritten(new LDAPMessage(
+ // intermediateResponse.getOperation().getMessageID(),
+ // new IntermediateResponseProtocolOp(intermediateResponse.getOID())));
+ // }
throw new RuntimeException("Not implemented");
}
@@ -360,11 +476,10 @@
disconnectRequested = true;
}
- // TODO JNR
- // if (keepStats)
- // {
- // statTracker.updateDisconnect();
- // }
+ if (keepStats)
+ {
+ statTracker.updateDisconnect();
+ }
if (connectionID >= 0)
{
@@ -459,6 +574,15 @@
if (previousValue != null)
{
operationsPerformed.incrementAndGet();
+
+ final Operation operation = previousValue.operation;
+ if (operation.getOperationType() == OperationType.ABANDON)
+ {
+ if (keepStats && operation.getResultCode() == ResultCode.CANCELED)
+ {
+ statTracker.updateAbandonedOperation();
+ }
+ }
}
return previousValue != null;
}
@@ -517,6 +641,11 @@
op.futureResult.handleErrorResult(ErrorResultException
.newErrorResult(org.forgerock.opendj.ldap.ResultCode.CANCELLED));
op.operation.abort(cancelRequest);
+
+ if (keepStats)
+ {
+ statTracker.updateAbandonedOperation();
+ }
}
catch (Exception e)
{ // make sure all operations are cancelled, no matter what
@@ -613,6 +742,16 @@
buffer.append(getServerAddress()).append(":").append(getServerPort());
}
+ /**
+ * Returns the statTracker for this connection handler.
+ *
+ * @return the statTracker for this connection handler
+ */
+ public HTTPStatistics getStatTracker()
+ {
+ return statTracker;
+ }
+
/** {@inheritDoc} */
@Override
public int getSSF()
--
Gitblit v1.10.0