Skip to content

Instantly share code, notes, and snippets.

@mnot
Created September 8, 2010 03:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mnot/569583 to your computer and use it in GitHub Desktop.
Save mnot/569583 to your computer and use it in GitHub Desktop.
mod_loadshed.c
/**
* \file mod_loadshed.c
* \author Mark Nottingham, <mnot@mnot.net>
*
* mod_loadshed, when enabled, will refuse the request with a 503 if
* no additional Apache children are currently available. This should
* prevent requests from going to the listen queue.
*/
#include "httpd.h"
#include "http_core.h"
#include "http_config.h"
#include "http_log.h"
#include "scoreboard.h"
#include <stdio.h>
MODULE_VAR_EXPORT module loadshed_module;
typedef struct {
int enabled;
} loadshed_cfg;
static void *mkconfig(pool *p)
{
loadshed_cfg *cfg = ap_pcalloc(p, sizeof(loadshed_cfg));
cfg->enabled = 0;
return cfg;
}
/*
* Respond to a callback to create configuration record for a server or
* vhost environment.
*/
static void *create_mconfig_for_server(pool *p, server_rec *s)
{
return mkconfig(p);
}
/*
* Respond to a callback to create a config record for a specific directory.
*/
static void *create_mconfig_for_directory(pool *p, char *dir)
{
return mkconfig(p);
}
/*
* Handler for the LoadShed directive, which is FLAG.
*/
static const char *set_loadshed(cmd_parms *cmd, void *mconfig, int arg)
{
loadshed_cfg *cfg = (loadshed_cfg *) mconfig;
cfg->enabled = arg;
return NULL;
}
static int check_loadshed(request_rec *r)
{
loadshed_cfg *cfg;
int i, res;
short_score score_record;
int ready = 0;
cfg = ap_get_module_config(r->per_dir_config, &loadshed_module);
if (cfg->enabled) {
// ap_sync_scoreboard_image();
for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
score_record = ap_scoreboard_image->servers[i];
res = score_record.status;
if (res == SERVER_READY)
ready++;
}
if (ready < 1) {
ap_log_error(__FILE__, __LINE__, APLOG_NOERRNO, r->server, "shed request from %s.", r->connection->remote_ip);
return HTTP_SERVICE_UNAVAILABLE;
}
}
return DECLINED;
}
static const command_rec loadshed_cmds[] = {
{"LoadShed", set_loadshed, NULL, OR_OPTIONS, FLAG, "set mod_loadshed on or off"},
{NULL}
};
module MODULE_VAR_EXPORT loadshed_module =
{
STANDARD_MODULE_STUFF,
NULL, /* initializer */
create_mconfig_for_directory, /* create per-dir config */
NULL, /* merge per-dir config */
create_mconfig_for_server, /* server config */
NULL, /* merge server config */
loadshed_cmds, /* command table */
NULL, /* handlers */
NULL, /* filename translation */
NULL, /* check_user_id */
NULL, /* check auth */
NULL, /* check access */
NULL, /* type_checker */
NULL, /* fixups */
NULL, /* logger */
NULL, /* header parser */
NULL, /* child_init */
NULL, /* child_exit */
check_loadshed /* post read-request */
};
/* eof */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment