From 779e8d65b79e9fada98dd5f070c3359bb963b169 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 17 Sep 2010 22:14:02 +0000
Subject: [PATCH] Implement a new resource limit policy which restricts the number of operations which can be performed during a time interval
---
opends/resource/schema/02-config.ldif | 12 ++
opends/src/admin/messages/ResourceLimitsQOSPolicyCfgDefn.properties | 4 +
opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java | 2
opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyFactory.java | 52 ++++++++++++
opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyTest.java | 63 +++++++++++++++
opends/src/messages/messages/core.properties | 5 +
opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/MockResourceLimitsQOSPolicyCfg.java | 21 +++++
opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicy.java | 2
opends/src/admin/defn/org/opends/server/admin/std/ResourceLimitsQOSPolicyConfiguration.xml | 52 ++++++++++++
9 files changed, 205 insertions(+), 8 deletions(-)
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index 28b8b4d..557ecfc 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -2525,6 +2525,14 @@
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.627
+ NAME 'ds-cfg-max-ops-per-interval'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.628
+ NAME 'ds-cfg-max-ops-interval'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler'
SUP top
@@ -4120,7 +4128,9 @@
ds-cfg-max-concurrent-ops-per-connection $
ds-cfg-size-limit $
ds-cfg-time-limit $
- ds-cfg-min-substring-length)
+ ds-cfg-min-substring-length $
+ ds-cfg-max-ops-per-interval $
+ ds-cfg-max-ops-interval)
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.186
NAME 'ds-cfg-network-group-plugin'
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/ResourceLimitsQOSPolicyConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/ResourceLimitsQOSPolicyConfiguration.xml
index 725a07f..1231da5 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/ResourceLimitsQOSPolicyConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/ResourceLimitsQOSPolicyConfiguration.xml
@@ -23,7 +23,7 @@
! CDDL HEADER END
!
!
- ! Copyright 2009 Sun Microsystems, Inc.
+ ! Copyright 2009-2010 Sun Microsystems, Inc.
! -->
<adm:managed-object name="resource-limits-qos-policy"
plural-name="resource-limits-qos-policies"
@@ -222,4 +222,54 @@
</ldap:attribute>
</adm:profile>
</adm:property>
+ <adm:property name="max-ops-per-interval">
+ <adm:synopsis>
+ Specifies the maximum number of operations that can take place on
+ the same network group during the specified interval.
+ </adm:synopsis>
+ <adm:description>
+ When the maximum number of operations per interval is reached, all
+ subsequent operations on the same network group are refused until the
+ end of the time interval. This parameter allows to limit the throughput
+ on the network group.
+ A value of 0 indicates that no limit is enforced.
+ </adm:description>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>0</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:integer lower-limit="0"/>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:name>ds-cfg-max-ops-per-interval</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="max-ops-interval">
+ <adm:synopsis>
+ Specifies the interval during which the number of operations is limited.
+ </adm:synopsis>
+ <adm:description>
+ When the maximum number of operations per interval is reached, all
+ subsequent operations on the same network group are refused until the
+ end of the time interval. This parameter allows to limit the throughput
+ on the network group.
+ </adm:description>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>1s</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:duration base-unit="ms" lower-limit="1"/>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:name>ds-cfg-max-ops-interval</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
</adm:managed-object>
diff --git a/opends/src/admin/messages/ResourceLimitsQOSPolicyCfgDefn.properties b/opends/src/admin/messages/ResourceLimitsQOSPolicyCfgDefn.properties
index a696060..6ab9ac4 100644
--- a/opends/src/admin/messages/ResourceLimitsQOSPolicyCfgDefn.properties
+++ b/opends/src/admin/messages/ResourceLimitsQOSPolicyCfgDefn.properties
@@ -8,8 +8,12 @@
property.max-connections.description=A value of 0 means that no limit is enforced.
property.max-connections-from-same-ip.synopsis=Specifies the maximum number of client connections from the same source address.
property.max-connections-from-same-ip.description=A value of 0 means that no limit is enforced.
+property.max-ops-interval.synopsis=Specifies the interval during which the number of operations is limited.
+property.max-ops-interval.description=When the maximum number of operations per interval is reached, all subsequent operations on the same network group are refused until the end of the time interval. This parameter allows to limit the throughput on the network group.
property.max-ops-per-connection.synopsis=Specifies the maximum number of operations per client connection.
property.max-ops-per-connection.description=A value of 0 means that no limit is enforced.
+property.max-ops-per-interval.synopsis=Specifies the maximum number of operations that can take place on the same network group during the specified interval.
+property.max-ops-per-interval.description=When the maximum number of operations per interval is reached, all subsequent operations on the same network group are refused until the end of the time interval. This parameter allows to limit the throughput on the network group. A value of 0 indicates that no limit is enforced.
property.min-substring-length.synopsis=Specifies the minimum length for a search filter substring.
property.min-substring-length.description=Search operations with short search filter substring are likely to match a high number of entries and might degrade performance overall. A value of 0 indicates that no limit is enforced.
property.size-limit.synopsis=Specifies the maximum number of entries that can be returned to the client during a single search operation.
diff --git a/opends/src/messages/messages/core.properties b/opends/src/messages/messages/core.properties
index 3dab3bb..55ed59a 100644
--- a/opends/src/messages/messages/core.properties
+++ b/opends/src/messages/messages/core.properties
@@ -1841,3 +1841,8 @@
for directory %s: %s
MILD_ERR_MAX_PSEARCH_LIMIT_EXCEEDED_730=The directory server is not accepting \
a new persistent search request because the server has already reached its limit
+INFO_ERROR_MAX_THROUGHPUT_EXCEEDED_735=Unable to process operation \
+ because the network group has already reached its maximum throughput of %d \
+ operations each %d ms
+SEVERE_ERR_MAX_OPS_PER_INTERVAL_738=The value "%d" is not a valid value for \
+the maximum number of operations per interval (must be positive)
diff --git a/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java b/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
index f6aa131..9634999 100644
--- a/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
+++ b/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2007-2009 Sun Microsystems, Inc.
+ * Copyright 2007-2010 Sun Microsystems, Inc.
*/
package org.opends.server.core.networkgroups;
diff --git a/opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicy.java b/opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicy.java
index 157808b..2c73bb6 100644
--- a/opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicy.java
+++ b/opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicy.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2009 Sun Microsystems, Inc.
+ * Copyright 2009-2010 Sun Microsystems, Inc.
*/
package org.opends.server.core.networkgroups;
diff --git a/opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyFactory.java b/opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyFactory.java
index ed5b347..42d8084 100644
--- a/opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyFactory.java
+++ b/opends/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyFactory.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2009 Sun Microsystems, Inc.
+ * Copyright 2009-2010 Sun Microsystems, Inc.
*/
package org.opends.server.core.networkgroups;
@@ -131,7 +131,13 @@
// The maximum time for a search.
private int timeLimit;
+ // The time interval for throughput limits
+ private long interval;
+ private long intervalStartTime = 0;
+ // The max number of operations during the interval
+ private int maxOperationsPerInterval;
+ private int operationsPerInterval = 0;
/**
* Creates a new resource limits policy.
@@ -306,6 +312,29 @@
}
}
+ // Check the throughput
+ if (operation != null && maxOperationsPerInterval > 0) {
+ synchronized(mutex) {
+ long now = System.currentTimeMillis();
+ // if the start time has never been set, or the interval has already
+ // expired, reset the start time and number of operations
+ if (intervalStartTime == 0 || now > (intervalStartTime + interval)) {
+ intervalStartTime = now;
+ operationsPerInterval = 0;
+ }
+
+ operationsPerInterval++;
+ if (operationsPerInterval > maxOperationsPerInterval) {
+ messages.add(INFO_ERROR_MAX_THROUGHPUT_EXCEEDED.get(
+ maxOperationsPerInterval,interval));
+ result = false;
+ }
+ }
+ if (!result) {
+ return result;
+ }
+ }
+
return true;
}
@@ -438,6 +467,19 @@
}
minSearchSubstringLength = configuration.getMinSubstringLength();
+
+ // Update the Max Ops Per Time Interval parameters
+ long previousInterval = interval;
+ int previousMax = maxOperationsPerInterval;
+
+ interval = configuration.getMaxOpsInterval();
+ maxOperationsPerInterval = configuration.getMaxOpsPerInterval();
+ // If the values have been modified, reset the counters
+ if ((previousInterval != interval)
+ || (previousMax != maxOperationsPerInterval)) {
+ intervalStartTime = 0;
+ operationsPerInterval = 0;
+ }
}
}
@@ -448,7 +490,13 @@
ResourceLimitsQOSPolicyCfg configuration,
List<Message> unacceptableReasons)
{
- // Always valid.
+ // maxOpsPerInterval must be positive
+ long tmpMaxOps = configuration.getMaxOpsInterval();
+ if (tmpMaxOps < 0) {
+ unacceptableReasons.add(ERR_MAX_OPS_PER_INTERVAL.get(tmpMaxOps));
+ return false;
+ }
+
return true;
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/MockResourceLimitsQOSPolicyCfg.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/MockResourceLimitsQOSPolicyCfg.java
index 3485165..3633350 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/MockResourceLimitsQOSPolicyCfg.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/MockResourceLimitsQOSPolicyCfg.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2009 Sun Microsystems, Inc.
+ * Copyright 2009-2010 Sun Microsystems, Inc.
*/
package org.opends.server.core.networkgroups;
@@ -188,4 +188,23 @@
return null;
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getMaxOpsInterval()
+ {
+ return 1;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMaxOpsPerInterval()
+ {
+ return 0;
+ }
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyTest.java
index 1a9e55c..c506257 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/ResourceLimitsPolicyTest.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2006-2009 Sun Microsystems, Inc.
+ * Copyright 2006-2010 Sun Microsystems, Inc.
*/
package org.opends.server.core.networkgroups;
@@ -246,4 +246,65 @@
}
+ /**
+ * Tests the 'max number of operations per interval' resource limit.
+ * @throws Exception If the test failed unexpectedly.
+ */
+ @Test (groups = "virtual")
+ public void testMaxThroughput()
+ throws Exception
+ {
+ ArrayList<Message> messages = new ArrayList<Message>();
+ final long interval = 1000; // Unit is milliseconds
+
+ ResourceLimitsPolicyFactory factory = new ResourceLimitsPolicyFactory();
+ ResourceLimitsPolicy limits = factory.createQOSPolicy(
+ new MockResourceLimitsQOSPolicyCfg() {
+ @Override
+ public int getMaxOpsPerInterval()
+ {
+ return 1;
+ }
+
+ @Override
+ public long getMaxOpsInterval()
+ {
+ return interval;
+ }
+ });
+
+ InternalClientConnection conn = new InternalClientConnection(DN.NULL_DN);
+ limits.addConnection(conn);
+
+ InternalSearchOperation search1 = conn.processSearch(
+ DN.decode("dc=example,dc=com"),
+ SearchScope.BASE_OBJECT,
+ LDAPFilter.decode("(objectclass=*)").toSearchFilter());
+
+ // First operation is allowed
+ boolean check = limits.isAllowed(conn, search1, true, messages);
+ assertTrue(check);
+
+ InternalSearchOperation search2 = conn.processSearch(
+ DN.decode("dc=example,dc=com"),
+ SearchScope.BASE_OBJECT,
+ LDAPFilter.decode("(objectclass=*)").toSearchFilter());
+
+ // Second operation in the same interval is refused
+ check = limits.isAllowed(conn, search2, true, messages);
+ assertFalse(check);
+
+ // Wait for the end of the interval => counters are reset
+ Thread.sleep(interval);
+
+ InternalSearchOperation search3 = conn.processSearch(
+ DN.decode("dc=example,dc=com"),
+ SearchScope.BASE_OBJECT,
+ LDAPFilter.decode("(objectclass=*)").toSearchFilter());
+
+ // The operation is allowed
+ check = limits.isAllowed(conn, search3, true, messages);
+ assertTrue(check);
+ }
+
}
--
Gitblit v1.10.0