Allow to execute specified program on various HAST events.

MFC after:	2 weeks
Obtained from:	Wheel Systems Sp. z o.o. http://www.wheelsystems.com
This commit is contained in:
Pawel Jakub Dawidek 2010-08-27 15:16:52 +00:00
parent 1cdaf10c45
commit 0becad39a7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=211886
6 changed files with 68 additions and 4 deletions

View File

@ -127,6 +127,8 @@ struct hast_resource {
int hr_extentsize;
/* Maximum number of extents that are kept dirty. */
int hr_keepdirty;
/* Path to a program to execute on various events. */
char hr_exec[PATH_MAX];
/* Path to local component. */
char hr_localpath[PATH_MAX];

View File

@ -62,7 +62,7 @@ const char *cfgpath = HAST_CONFIG;
/* Hastd configuration. */
static struct hastd_config *cfg;
/* Was SIGCHLD signal received? */
static bool sigchld_received = false;
bool sigchld_received = false;
/* Was SIGHUP signal received? */
bool sighup_received = false;
/* Was SIGINT or SIGTERM signal received? */
@ -189,6 +189,8 @@ resource_needs_restart(const struct hast_resource *res0,
return (true);
if (res0->hr_timeout != res1->hr_timeout)
return (true);
if (strcmp(res0->hr_exec, res1->hr_exec) != 0)
return (true);
}
return (false);
}
@ -211,6 +213,8 @@ resource_needs_reload(const struct hast_resource *res0,
return (true);
if (res0->hr_timeout != res1->hr_timeout)
return (true);
if (strcmp(res0->hr_exec, res1->hr_exec) != 0)
return (true);
return (false);
}

View File

@ -40,7 +40,7 @@
#include "hast.h"
extern const char *cfgpath;
extern bool sigexit_received, sighup_received;
extern bool sigchld_received, sigexit_received, sighup_received;
extern struct pidfh *pfh;
void hastd_primary(struct hast_resource *res);

View File

@ -61,6 +61,7 @@ static char depth0_control[HAST_ADDRSIZE];
static char depth0_listen[HAST_ADDRSIZE];
static int depth0_replication;
static int depth0_timeout;
static char depth0_exec[PATH_MAX];
static char depth1_provname[PATH_MAX];
static char depth1_localpath[PATH_MAX];
@ -130,6 +131,7 @@ yy_config_parse(const char *config, bool exitonerror)
depth0_replication = HAST_REPLICATION_MEMSYNC;
strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control));
strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen));
depth0_exec[0] = '\0';
lconfig = calloc(1, sizeof(*lconfig));
if (lconfig == NULL) {
@ -190,6 +192,14 @@ yy_config_parse(const char *config, bool exitonerror)
*/
curres->hr_timeout = depth0_timeout;
}
if (curres->hr_exec[0] == '\0') {
/*
* Exec is not set at resource-level.
* Use global or default setting.
*/
strlcpy(curres->hr_exec, depth0_exec,
sizeof(curres->hr_exec));
}
}
return (lconfig);
@ -208,7 +218,7 @@ yy_config_free(struct hastd_config *config)
}
%}
%token CONTROL LISTEN PORT REPLICATION TIMEOUT EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON
%token CONTROL LISTEN PORT REPLICATION TIMEOUT EXEC EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON
%token FULLSYNC MEMSYNC ASYNC
%token NUM STR OB CB
@ -239,6 +249,8 @@ statement:
|
timeout_statement
|
exec_statement
|
node_statement
|
resource_statement
@ -338,6 +350,32 @@ timeout_statement: TIMEOUT NUM
}
;
exec_statement: EXEC STR
{
switch (depth) {
case 0:
if (strlcpy(depth0_exec, $2, sizeof(depth0_exec)) >=
sizeof(depth0_exec)) {
pjdlog_error("Exec path is too long.");
return (1);
}
break;
case 1:
if (curres == NULL)
break;
if (strlcpy(curres->hr_exec, $2,
sizeof(curres->hr_exec)) >=
sizeof(curres->hr_exec)) {
pjdlog_error("Exec path is too long.");
return (1);
}
break;
default:
assert(!"exec at wrong depth level");
}
}
;
node_statement: ON node_start OB node_entries CB
{
mynode = false;
@ -456,6 +494,7 @@ resource_start: STR
curres->hr_previous_role = HAST_ROLE_INIT;
curres->hr_replication = -1;
curres->hr_timeout = -1;
curres->hr_exec[0] = '\0';
curres->hr_provname[0] = '\0';
curres->hr_localpath[0] = '\0';
curres->hr_localfd = -1;
@ -474,6 +513,8 @@ resource_entry:
|
timeout_statement
|
exec_statement
|
name_statement
|
local_statement

View File

@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include "hast.h"
#include "hast_proto.h"
#include "hastd.h"
#include "hooks.h"
#include "metadata.h"
#include "proto.h"
#include "pjdlog.h"
@ -433,6 +434,7 @@ init_environment(struct hast_resource *res __unused)
signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);
signal(SIGHUP, sighandler);
signal(SIGCHLD, sighandler);
}
static void
@ -791,6 +793,7 @@ hastd_primary(struct hast_resource *res)
signal(SIGHUP, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
hook_init();
init_local(res);
if (real_remote(res) && init_remote(res, NULL, NULL))
sync_start();
@ -1737,6 +1740,9 @@ sighandler(int sig)
case SIGHUP:
sighup_received = true;
break;
case SIGCHLD:
sigchld_received = true;
break;
default:
assert(!"invalid condition");
}
@ -1788,6 +1794,7 @@ config_reload(void)
#define MODIFIED_REMOTEADDR 0x1
#define MODIFIED_REPLICATION 0x2
#define MODIFIED_TIMEOUT 0x4
#define MODIFIED_EXEC 0x8
modified = 0;
if (strcmp(gres->hr_remoteaddr, res->hr_remoteaddr) != 0) {
/*
@ -1805,6 +1812,10 @@ config_reload(void)
gres->hr_timeout = res->hr_timeout;
modified |= MODIFIED_TIMEOUT;
}
if (strcmp(gres->hr_exec, res->hr_exec) != 0) {
strlcpy(gres->hr_exec, res->hr_exec, sizeof(gres->hr_exec));
modified |= MODIFIED_EXEC;
}
/*
* If only timeout was modified we only need to change it without
* reconnecting.
@ -1830,7 +1841,8 @@ config_reload(void)
"Unable to set connection timeout");
}
}
} else {
} else if ((modified &
(MODIFIED_REMOTEADDR | MODIFIED_REPLICATION)) != 0) {
for (ii = 0; ii < ncomps; ii++) {
if (!ISREMOTE(ii))
continue;
@ -1844,6 +1856,7 @@ config_reload(void)
#undef MODIFIED_REMOTEADDR
#undef MODIFIED_REPLICATION
#undef MODIFIED_TIMEOUT
#undef MODIFIED_EXEC
pjdlog_info("Configuration reloaded successfully.");
return;
@ -1907,6 +1920,9 @@ guard_thread(void *arg)
sighup_received = false;
config_reload();
}
hook_check(sigchld_received);
if (sigchld_received)
sigchld_received = false;
timeout = KEEPALIVE_SLEEP;
pjdlog_debug(2, "remote_guard: Checking connections.");

View File

@ -49,6 +49,7 @@ listen { DP; return LISTEN; }
port { DP; return PORT; }
replication { DP; return REPLICATION; }
timeout { DP; return TIMEOUT; }
exec { DP; return EXEC; }
resource { DP; return RESOURCE; }
name { DP; return NAME; }
local { DP; return LOCAL; }