Fixed usage of Tcl_GetIndexFromObj.
/*
* The contents of this file are subject to the AOLserver Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://aolserver.com/.
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is AOLserver Code and related documentation
* distributed by AOL.
*
* The Initial Developer of the Original Code is America Online,
* Inc. Portions created by AOL are Copyright (C) 1999 America Online,
* Inc. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the terms
* of the GNU General Public License (the "GPL"), in which case the
* provisions of GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the
* GPL and not to allow others to use your version of this file under the
* License, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the GPL.
* If you do not delete the provisions above, a recipient may use your
* version of this file under either the License or the GPL.
*/
/*
* limits.c --
*
* Routines to manage resource limits.
*/
static const char *RCSID = "@(#) $Header: /cvsroot/aolserver/aolserver/nsd/limits.c,v 1.10 2005/03/28 00:06:44 jgdavidson Exp $, compiled: " __DATE__ " " __TIME__;
#include "nsd.h"
/*
* Static functions defined in this file.
*/
static int LimitsResult(Tcl_Interp *interp, Limits *limitsPtr);
static int AppendLimit(Tcl_Interp *interp, char *limit, unsigned int val);
static int GetLimits(Tcl_Interp *interp, Tcl_Obj *objPtr,
Limits **limitsPtrPtr, int create);
static Limits *FindLimits(char *limits, int create);
/*
* Static variables defined in this file.
*/
static int limid;
static Limits *defLimitsPtr;
static Tcl_HashTable limtable;
/*
*----------------------------------------------------------------------
*
* NsInitLimits --
*
* Initialize request limits.
*
* Results:
* None.
*
* Side effects:
* Will create the default limits.
*
*----------------------------------------------------------------------
*/
void
NsInitLimits(void)
{
limid = Ns_UrlSpecificAlloc();
Tcl_InitHashTable(&limtable, TCL_STRING_KEYS);
defLimitsPtr = FindLimits("default", 1);
}
/*
*----------------------------------------------------------------------
*
*NsTclLimitsObjCmd --
*
* Implements ns_limits command to create and query request limit
* structures.
*
* Results:
* Standard Tcl result.
*
* Side effects:
* May create a new limit structure.
*
*----------------------------------------------------------------------
*/
int
NsTclLimitsObjCmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj **objv)
{
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
Limits *limitsPtr, saveLimits;
char *limits, *pattern;
int i, val;
static CONST char *opts[] = {
"get", "set", "list", "register", NULL
};
enum {
LGetIdx, LSetIdx, LListIdx, LRegisterIdx
} opt;
static CONST char *cfgs[] = {
"-maxrun", "-maxwait", "-maxupload", "-timeout", NULL
};
enum {
LCRunIdx, LCWaitIdx, LCUploadIdx, LCTimeoutIdx
} cfg;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], opts, "option", 0,
(int *) &opt) != TCL_OK) {
return TCL_ERROR;
}
switch (opt) {
case LListIdx:
if (objc != 2 && objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
return TCL_ERROR;
}
if (objc == 2) {
pattern = NULL;
} else {
pattern = Tcl_GetString(objv[2]);
}
hPtr = Tcl_FirstHashEntry(&limtable, &search);
while (hPtr != NULL) {
limits = Tcl_GetHashKey(&limtable, hPtr);
if (pattern == NULL || Tcl_StringMatch(limits, pattern)) {
Tcl_AppendElement(interp, limits);
}
hPtr = Tcl_NextHashEntry(&search);
}
break;
case LGetIdx:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "limit");
return TCL_ERROR;
}
if (GetLimits(interp, objv[2], &limitsPtr, 0) != TCL_OK ||
LimitsResult(interp, limitsPtr) != TCL_OK) {
return TCL_ERROR;
}
break;
case LSetIdx:
if (objc < 3 || (((objc - 3) % 2) != 0)) {
Tcl_WrongNumArgs(interp, 2, objv, "limit ?opt val opt val...?");
return TCL_ERROR;
}
(void) GetLimits(interp, objv[2], &limitsPtr, 1);
saveLimits = *limitsPtr;
for (i = 3; i < objc; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], cfgs, "cfg", 0,
(int *) &cfg) != TCL_OK ||
Tcl_GetIntFromObj(interp, objv[i+1], &val) != TCL_OK) {
*limitsPtr = saveLimits;
return TCL_ERROR;
}
switch (cfg) {
case LCRunIdx:
limitsPtr->maxrun = val;
break;
case LCWaitIdx:
limitsPtr->maxwait = val;
break;
case LCUploadIdx:
limitsPtr->maxupload = val;
break;
case LCTimeoutIdx:
limitsPtr->timeout = val;
break;
}
}
if (LimitsResult(interp, limitsPtr) != TCL_OK) {
return TCL_ERROR;
}
break;
case LRegisterIdx:
if (objc != 6) {
Tcl_WrongNumArgs(interp, 2, objv, "limit server method url");
return TCL_ERROR;
}
if (GetLimits(interp, objv[2], &limitsPtr, 0) != TCL_OK) {
return TCL_ERROR;
}
Ns_UrlSpecificSet(Tcl_GetString(objv[3]),
Tcl_GetString(objv[4]),
Tcl_GetString(objv[5]), limid, limitsPtr, 0, NULL);
break;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* NsGetRequestLimits --
*
* Return the limits structure for a given request.
*
* Results:
* Pointer to limits.
*
* Side effects:
* May return the default limits if no more specific limits
* have been created.
*
*----------------------------------------------------------------------
*/
Limits *
NsGetRequestLimits(char *server, char *method, char *url)
{
Limits *limitsPtr;
limitsPtr = Ns_UrlSpecificGet(server, method, url, limid);
return (limitsPtr ? limitsPtr : defLimitsPtr);
}
/*
*----------------------------------------------------------------------
*
* FindLimits --
*
* Return the limits by name.
*
* Results:
* Pointer to Limits or NULL if no such limits and create is zero.
*
* Side effects:
* If create is not zero, will create new default limits.
*
*----------------------------------------------------------------------
*/
static Limits *
FindLimits(char *limits, int create)
{
Limits *limitsPtr;
Tcl_HashEntry *hPtr;
int new;
if (!create) {
hPtr = Tcl_FindHashEntry(&limtable, limits);
} else {
hPtr = Tcl_CreateHashEntry(&limtable, limits, &new);
if (new) {
limitsPtr = ns_malloc(sizeof(Limits));
limitsPtr->name = Tcl_GetHashKey(&limtable, hPtr);
Ns_MutexInit(&limitsPtr->lock);
limitsPtr->nrunning = limitsPtr->nwaiting = 0;
limitsPtr->ntimeout = limitsPtr->ndropped = limitsPtr->noverflow = 0;
limitsPtr->maxrun = limitsPtr->maxwait = 100;
limitsPtr->maxupload = 10 * 1024 * 1000; /* NB: 10meg limit. */
limitsPtr->timeout = 60;
Tcl_SetHashValue(hPtr, limitsPtr);
}
}
return (hPtr ? Tcl_GetHashValue(hPtr) : NULL);
}
/*
*----------------------------------------------------------------------
*
* GetLimits --
*
* Utility routing to find Limits by Tcl_Obj for Tcl.
*
* Results:
* Standard Tcl result.
*
* Side effects:
* Will update limitsPtrPtr with pointer to Limits or leave
* an error message in given interp if no limits found and
* create is zero.
*
*----------------------------------------------------------------------
*/
static int
GetLimits(Tcl_Interp *interp, Tcl_Obj *objPtr, Limits **limitsPtrPtr,
int create)
{
char *limits = Tcl_GetString(objPtr);
Limits *limitsPtr;
limitsPtr = FindLimits(limits, create);
if (limitsPtr == NULL) {
Tcl_AppendResult(interp, "no such limits: ", limits, NULL);
return TCL_ERROR;
}
*limitsPtrPtr = limitsPtr;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* LimitsResult --
*
* Return a list of info about a given limits.
*
* Results:
* TCL_ERROR if list could not be appended, TCL_OK otherwise.
*
* Side effects:
* Will leave list in given interp result.
*
*----------------------------------------------------------------------
*/
static int
LimitsResult(Tcl_Interp *interp, Limits *limitsPtr)
{
if (!AppendLimit(interp, "nrunning", limitsPtr->nrunning) ||
!AppendLimit(interp, "nwaiting", limitsPtr->nwaiting) ||
!AppendLimit(interp, "ntimeout", limitsPtr->ntimeout) ||
!AppendLimit(interp, "ndropped", limitsPtr->ndropped) ||
!AppendLimit(interp, "noverflow", limitsPtr->noverflow) ||
!AppendLimit(interp, "maxwait", limitsPtr->maxwait) ||
!AppendLimit(interp, "maxupload", limitsPtr->maxupload) ||
!AppendLimit(interp, "timeout", limitsPtr->timeout) ||
!AppendLimit(interp, "maxrun", limitsPtr->maxrun)) {
return TCL_ERROR;
}
return TCL_OK;
}
static int
AppendLimit(Tcl_Interp *interp, char *limit, unsigned int val)
{
Tcl_Obj *result = Tcl_GetObjResult(interp);
if (Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(limit, -1))
!= TCL_OK ||
Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj((int) val))
!= TCL_OK) {
return 0;
}
return 1;
}
|
Back to SourceForge.net Powered by ViewCVS 1.0-dev |