The code for the qos-handler (AuthTrans) and qos-error (Error) SAFs is provided as an example in case you want to define your own SAFs for quality of service handling.
For more information about predefined SAFs, see the Sun Java System Web Server 6.1 SP11 Administrator’s Configuration File Reference.
Inside the default object in obj.conf, add the following AuthTrans and Error directives:
AuthTrans fn=qos-handler ... Error fn=qos-error code=503
The source code for this example is in the qos.c file in the plugins/nsapi/examples subdirectory of the server root directory.
#include "nspr.h" #include "base/pblock.h" #include "frame/log.h" #include "frame/http.h" /*----------------------------------------------------------------- decode : internal function used for parsing of QOS values in pblock ------------------------------------------------------------------- void decode(const char* val, PRInt32* var, pblock* pb) { char* pbval; if ( (!var) || (!val) || (!pb) ) return; pbval = pblock_findval(val, pb); if (!pbval) return; *var = atoi(pbval); } /*---------------------------------------------------------------- qos_error_sample This function is meant to be an error handler for an HTTP 503 error code, which is returned by qos_handler when QOS limits are exceeded and enforced. This sample function just prints out a message about which limits were exceeded. ------------------------------------------------------------------ NSAPI_PUBLIC int qos_error_sample(pblock *pb, Session *sn, Request *rq) { char error[1024] = ""; char* err_header = "<HTML><HEAD><TITLE>Unable to service request </TITLE></HEAD><BODY>"; char* err_footer = "</BODY></HTML>"; PRBool ours = PR_FALSE; PRInt32 vs_bw = 0, vs_bwlim = 0, vs_bw_ef = 0, vs_conn = 0, vs_connlim = 0, vs_conn_ef = 0, vsc_bw = 0, vsc_bwlim = 0, vsc_bw_ef = 0, vsc_conn = 0, vsc_connlim = 0, vsc_conn_ef = 0, srv_bw = 0, srv_bwlim = 0, srv_bw_ef = 0, srv_conn = 0, srv_connlim = 0, srv_conn_ef = 0; pblock* apb = rq->vars; decode("vs_bandwidth", &vs_bw, apb); decode("vs_connections", &vs_conn, apb); decode("vs_bandwidth_limit", &vs_bwlim, apb); decode("vs_bandwidth_enforced", &vs_bw_ef, apb); decode("vs_connections_limit", &vs_connlim, apb); decode("vs_connections_enforced", &vs_conn_ef, apb); decode("vsclass_bandwidth", &vsc_bw, apb); decode("vsclass_connections", &vsc_conn, apb); decode("vsclass_bandwidth_limit", &vsc_bwlim, apb); decode("vsclass_bandwidth_enforced", &vsc_bw_ef, apb); decode("vsclass_connections_limit", &vsc_connlim, apb); decode("vsclass_connections_enforced", &vsc_conn_ef, apb); decode("server_bandwidth", &srv_bw, apb); decode("server_connections", &srv_conn, apb); decode("server_bandwidth_limit", &srv_bwlim, apb); decode("server_bandwidth_enforced", &srv_bw_ef, apb); decode("server_connections_limit", &srv_connlim, apb); decode("server_connections_enforced", &srv_conn_ef, apb); if ((vs_bwlim) && (vs_bw>vs_bwlim)) { /* VS bandwidth limit was exceeded, display it */ ours = PR_TRUE; sprintf(error, "<P>Virtual server bandwidth limit of %d . Current VS bandwidth : %d . <P>", vs_bwlim, vs_bw); }; if ((vs_connlim) && (vs_conn>vs_connlim)) { /* VS connection limit was exceeded, display it */ ours = PR_TRUE; sprintf(error, "<P>Virtual server connection limit of %d . Current VS connections : %d . <P>", vs_connlim, vs_conn); }; if ((vsc_bwlim) && (vsc_bw>vsc_bwlim)) { /* VSCLASS bandwidth limit was exceeded, display it */ ours = PR_TRUE; sprintf(error, "<P>Virtual server class bandwidth limit of %d . Current VSCLASS bandwidth : %d . <P>", vsc_bwlim, vsc_bw); }; if ((vsc_connlim) && (vsc_conn>vsc_connlim)) { /* VSCLASS connection limit was exceeded, display it */ ours = PR_TRUE; sprintf(error, "<P>Virtual server class connection limit of %d . Current VSCLASS connections : %d . <P>", vsc_connlim, vsc_conn); }; if ((srv_bwlim) && (srv_bw>srv_bwlim)) { /* SERVER bandwidth limit was exceeded, display it */ ours = PR_TRUE; sprintf(error, "<P>Global bandwidth limit of %d . Current bandwidth : %d . <P>", srv_bwlim, srv_bw); }; if ((srv_connlim) && (srv_conn>srv_connlim)) { /* SERVER connection limit was exceeded, display it */ ours = PR_TRUE; sprintf(error, "<P>Global connection limit of %d . Current connections : %d . <P>", srv_connlim, srv_conn); }; if (ours) { /* this was really a QOS failure, therefore send the error page */ pb_param *pp = pblock_remove ("content-type", rq->srvhdrs); if (pp != NULL) param_free (pp); pblock_nvinsert ("content-type", "text/html", rq->srvhdrs); protocol_start_response(sn, rq); net_write(sn->csd, err_header, strlen(err_header)); net_write(sn->csd, error, strlen(error)); net_write(sn->csd, err_footer, strlen(err_footer)); return REQ_PROCEED; } else { /* this 503 didn't come from a QOS SAF failure, let someone else handle it */ return REQ_PROCEED; }; } /*--------------------------------------------------------------- qos_handler_sample This is an NSAPI AuthTrans function. It examines the QOS values in the request and compares them to the QOS limits. It does several things: 1) It will log errors if the QOS limits are exceeded. 2) It will return REQ_ABORTED with a 503 error code if the QOS limits are exceeded, and the QOS limits are set to be enforced. Otherwise it will return REQ_PROCEED. ------------------------------------------------------------------ NSAPI_PUBLIC int qos_handler_sample(pblock *pb, Session *sn, Request *rq) { PRBool ok = PR_TRUE; PRInt32 vs_bw = 0, vs_bwlim = 0, vs_bw_ef = 0, vs_conn = 0, vs_connlim = 0, vs_conn_ef = 0, vsc_bw = 0, vsc_bwlim = 0, vsc_bw_ef = 0, vsc_conn = 0, vsc_connlim = 0, vsc_conn_ef = 0, srv_bw = 0, srv_bwlim = 0, srv_bw_ef = 0, srv_conn = 0, srv_connlim = 0, srv_conn_ef = 0; pblock* apb = rq->vars; decode("vs_bandwidth", &vs_bw, apb); decode("vs_connections", &vs_conn, apb); decode("vs_bandwidth_limit", &vs_bwlim, apb); decode("vs_bandwidth_enforced", &vs_bw_ef, apb); decode("vs_connections_limit", &vs_connlim, apb); decode("vs_connections_enforced", &vs_conn_ef, apb); decode("vsclass_bandwidth", &vsc_bw, apb); decode("vsclass_connections", &vsc_conn, apb); decode("vsclass_bandwidth_limit", &vsc_bwlim, apb); decode("vsclass_bandwidth_enforced", &vsc_bw_ef, apb); decode("vsclass_connections_limit", &vsc_connlim, apb); decode("vsclass_connections_enforced", &vsc_conn_ef, apb); decode("server_bandwidth", &srv_bw, apb); decode("server_connections", &srv_conn, apb); decode("server_bandwidth_limit", &srv_bwlim, apb); decode("server_bandwidth_enforced", &srv_bw_ef, apb); decode("server_connections_limit", &srv_connlim, apb); decode("server_connections_enforced", &srv_conn_ef, apb); if ((vs_bwlim) && (vs_bw>vs_bwlim)) { /* bandwidth limit was exceeded, log it */ ereport(LOG_FAILURE, "Virtual server bandwidth limit of %d exceeded. Current VS bandwidth : %d", &vs_bwlim, vs_bw); if (vs_bw_ef) { /* and enforce it */ ok = PR_FALSE; }; }; if ((vs_connlim) && (vs_conn>vs_connlim)) { /* connection limit was exceeded, log it */ ereport(LOG_FAILURE, "Virtual server connection limit of %d exceeded. Current VS connections : %d", &vs_connlim, vs_conn); if (vs_conn_ef) { /* and enforce it */ ok = PR_FALSE; }; }; if ((vsc_bwlim) && (vsc_bw>vsc_bwlim)) { /* bandwidth limit was exceeded, log it */ ereport(LOG_FAILURE, "Virtual server class bandwidth limit of %d exceeded. Current VSCLASS bandwidth : %d", &vsc_bwlim, vsc_bw); if (vsc_bw_ef) { /* and enforce it */ ok = PR_FALSE; }; }; if ((vsc_connlim) && (vsc_conn>vsc_connlim)) { /* connection limit was exceeded, log it */ ereport(LOG_FAILURE, "Virtual server class connection limit of %d exceeded. Current VSCLASS connections : %d", &vsc_connlim, vsc_conn); if (vsc_conn_ef) { /* and enforce it */ ok = PR_FALSE; }; }; if ((srv_bwlim) && (srv_bw>srv_bwlim)) { /* bandwidth limit was exceeded, log it */ ereport(LOG_FAILURE, "Global bandwidth limit of %d exceeded. Current global bandwidth : %d", &srv_bwlim, srv_bw); if (srv_bw_ef) { /* and enforce it */ ok = PR_FALSE; }; }; if ((srv_connlim) && (srv_conn>srv_connlim)) { /* connection limit was exceeded, log it */ ereport(LOG_FAILURE, "Global connection limit of %d exceeded. Current global connections : %d", &srv_connlim, srv_conn); if (srv_conn_ef) { /* and enforce it */ ok = PR_FALSE; }; }; if (ok) { return REQ_PROCEED; } else { /* one of the limits was exceeded therefore, we set HTTP error 503 "server too busy" */ protocol_status(sn, rq, PROTOCOL_SERVICE_UNAVAILABLE, NULL); return REQ_ABORTED; }; }