Commit 8abe06b2 authored by Mark Andrews's avatar Mark Andrews
Browse files

1905. [bug] Recursive clients soft quota support wasn't working

                        as expected. [RT #15103]
parent 0992797c
1905. [bug] Recursive clients soft quota support wasn't working
as expected. [RT #15103]
1904. [bug] A escaped character is, potentially, converted to
the output character set too early. [RT #14666]
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.c,v 1.228 2005/06/07 00:15:59 marka Exp $ */
/* $Id: client.c,v 1.229 2005/07/27 02:28:58 marka Exp $ */
#include <config.h>
......@@ -181,26 +181,32 @@ static void client_request(isc_task_t *task, isc_event_t *event);
static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
void
ns_client_recursing(ns_client_t *client, isc_boolean_t killoldest) {
ns_client_t *oldest;
ns_client_recursing(ns_client_t *client) {
REQUIRE(NS_CLIENT_VALID(client));
LOCK(&client->manager->lock);
if (killoldest) {
oldest = ISC_LIST_HEAD(client->manager->recursing);
if (oldest != NULL) {
ns_query_cancel(oldest);
ISC_LIST_UNLINK(*oldest->list, oldest, link);
ISC_LIST_APPEND(client->manager->active, oldest, link);
oldest->list = &client->manager->active;
}
}
ISC_LIST_UNLINK(*client->list, client, link);
ISC_LIST_APPEND(client->manager->recursing, client, link);
client->list = &client->manager->recursing;
UNLOCK(&client->manager->lock);
}
void
ns_client_killoldestquery(ns_client_t *client) {
ns_client_t *oldest;
REQUIRE(NS_CLIENT_VALID(client));
LOCK(&client->manager->lock);
oldest = ISC_LIST_HEAD(client->manager->recursing);
if (oldest != NULL) {
ns_query_cancel(oldest);
ISC_LIST_UNLINK(*oldest->list, oldest, link);
ISC_LIST_APPEND(client->manager->active, oldest, link);
oldest->list = &client->manager->active;
}
UNLOCK(&client->manager->lock);
}
void
ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
isc_result_t result;
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.h,v 1.75 2005/07/18 05:58:57 marka Exp $ */
/* $Id: client.h,v 1.76 2005/07/27 02:28:59 marka Exp $ */
#ifndef NAMED_CLIENT_H
#define NAMED_CLIENT_H 1
......@@ -326,10 +326,15 @@ ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
DNS_RDATACLASS_FORMATSIZE + sizeof(x) + sizeof("'/'"))
void
ns_client_recursing(ns_client_t *client, isc_boolean_t killoldest);
ns_client_recursing(ns_client_t *client);
/*%
* Add client to end of recursing list. If 'killoldest' is true
* kill the oldest recursive client (list head).
* Add client to end of th recursing list.
*/
void
ns_client_killoldestquery(ns_client_t *client);
/*%
* Kill the oldest recursive query (recursing list head).
*/
void
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.268 2005/06/27 00:15:42 marka Exp $ */
/* $Id: query.c,v 1.269 2005/07/27 02:28:58 marka Exp $ */
/*! \file */
......@@ -2701,33 +2701,37 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
* connection was accepted (if allowed by the TCP quota).
*/
if (client->recursionquota == NULL) {
isc_boolean_t killoldest = ISC_FALSE;
result = isc_quota_attach(&ns_g_server->recursionquota,
&client->recursionquota);
if (result == ISC_R_SOFTQUOTA) {
if (result == ISC_R_SOFTQUOTA) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
"recursive-clients limit exceeded, "
"recursive-clients soft limit exceeded, "
"aborting oldest query");
killoldest = ISC_TRUE;
result = ISC_R_SUCCESS;
}
if (dns_resolver_nrunning(client->view->resolver) >
(unsigned int)ns_g_server->recursionquota.max)
result = ISC_R_QUOTA;
if (result == ISC_R_SUCCESS && !client->mortal &&
(client->attributes & NS_CLIENTATTR_TCP) == 0)
result = ns_client_replace(client);
if (result != ISC_R_SUCCESS) {
ns_client_killoldestquery(client);
result == ISC_R_SUCCESS;
} else if (result == ISC_R_QUOTA) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
"no more recursive clients: %s",
isc_result_totext(result));
if (client->recursionquota != NULL)
ns_client_killoldestquery(client);
}
if (result == ISC_R_SUCCESS && !client->mortal &&
(client->attributes & NS_CLIENTATTR_TCP) == 0) {
result = ns_client_replace(client);
if (result != ISC_R_SUCCESS) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY,
ISC_LOG_WARNING,
"ns_client_replace() failed: %s",
isc_result_totext(result));
isc_quota_detach(&client->recursionquota);
return (result);
}
}
ns_client_recursing(client, killoldest);
if (result != ISC_R_SUCCESS)
return (result);
ns_client_recursing(client);
}
/*
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.445 2005/06/27 00:15:42 marka Exp $ */
/* $Id: server.c,v 1.446 2005/07/27 02:28:58 marka Exp $ */
/*! \file */
......@@ -1882,7 +1882,7 @@ configure_server_quota(cfg_obj_t **maps, const char *name, isc_quota_t *quota)
result = ns_config_get(maps, name, &obj);
INSIST(result == ISC_R_SUCCESS);
quota->max = cfg_obj_asuint32(obj);
isc_quota_max(quota, cfg_obj_asuint32(obj));
}
/*
......@@ -2309,6 +2309,11 @@ load_configuration(const char *filename, ns_server_t *server,
configure_server_quota(maps, "tcp-clients", &server->tcpquota);
configure_server_quota(maps, "recursive-clients",
&server->recursionquota);
if (server->recursionquota.max > 1000)
isc_quota_soft(&server->recursionquota,
server->recursionquota.max - 100);
else
isc_quota_soft(&server->recursionquota, 0);
CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
ns_g_mctx, &server->blackholeacl));
......@@ -3036,7 +3041,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = isc_quota_init(&server->recursionquota, 100);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
isc_quota_soft(&server->recursionquota, ISC_FALSE);
result = dns_aclenv_init(mctx, &server->aclenv);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
......@@ -4147,12 +4151,13 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) {
"xfers deferred: %u\n"
"soa queries in progress: %u\n"
"query logging is %s\n"
"recursive clients: %d/%d\n"
"recursive clients: %d/%d/%d\n"
"tcp clients: %d/%d\n"
"server is up and running",
zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
soaqueries, server->log_queries ? "ON" : "OFF",
server->recursionquota.used, server->recursionquota.max,
server->recursionquota.used, server->recursionquota.soft,
server->recursionquota.max,
server->tcpquota.used, server->tcpquota.max);
if (n >= isc_buffer_availablelength(text))
return (ISC_R_NOSPACE);
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: quota.h,v 1.12 2005/04/29 00:23:42 marka Exp $ */
/* $Id: quota.h,v 1.13 2005/07/27 02:29:01 marka Exp $ */
#ifndef ISC_QUOTA_H
#define ISC_QUOTA_H 1
......@@ -72,9 +72,15 @@ isc_quota_destroy(isc_quota_t *quota);
*/
void
isc_quota_soft(isc_quota_t *quota, isc_boolean_t soft);
isc_quota_soft(isc_quota_t *quota, int soft);
/*%<
* Turn on/off soft quotas.
* Set a soft quota.
*/
void
isc_quota_max(isc_quota_t *quota, int max);
/*%<
* Re-set a maximum quota.
*/
isc_result_t
......@@ -83,9 +89,9 @@ isc_quota_reserve(isc_quota_t *quota);
* Attempt to reserve one unit of 'quota'.
*
* Returns:
*\li #ISC_R_SUCCESS Success
*\li #ISC_R_SOFTQUOTA Success soft quota reached
*\li #ISC_R_QUOTA Quota is full
* \li #ISC_R_SUCCESS Success
* \li #ISC_R_SOFTQUOTA Success soft quota reached
* \li #ISC_R_QUOTA Quota is full
*/
void
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: quota.c,v 1.15 2005/04/29 00:23:29 marka Exp $ */
/* $Id: quota.c,v 1.16 2005/07/27 02:29:00 marka Exp $ */
/*! \file */
......@@ -30,38 +30,45 @@ isc_result_t
isc_quota_init(isc_quota_t *quota, int max) {
quota->max = max;
quota->used = 0;
quota->soft = ISC_FALSE;
quota->soft = 0;
return (isc_mutex_init(&quota->lock));
}
void
isc_quota_destroy(isc_quota_t *quota) {
INSIST(quota->used == 0);
quota->max = -1;
quota->used = -1;
quota->soft = ISC_FALSE;
quota->max = 0;
quota->used = 0;
quota->soft = 0;
DESTROYLOCK(&quota->lock);
}
void
isc_quota_soft(isc_quota_t *quota, isc_boolean_t soft) {
isc_quota_soft(isc_quota_t *quota, int soft) {
LOCK(&quota->lock);
quota->soft = soft;
UNLOCK(&quota->lock);
}
void
isc_quota_max(isc_quota_t *quota, int max) {
LOCK(&quota->lock);
quota->max = max;
UNLOCK(&quota->lock);
}
isc_result_t
isc_quota_reserve(isc_quota_t *quota) {
isc_result_t result;
LOCK(&quota->lock);
if (quota->used < quota->max) {
quota->used++;
result = ISC_R_SUCCESS;
} else {
if (quota->soft) {
quota->used++;
if (quota->max == 0 || quota->used < quota->max) {
if (quota->soft == 0 || quota->used < quota->soft)
result = ISC_R_SUCCESS;
else
result = ISC_R_SOFTQUOTA;
} else
result = ISC_R_QUOTA;
}
quota->used++;
} else
result = ISC_R_QUOTA;
UNLOCK(&quota->lock);
return (result);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment