2022-05-26 23:47:10 +02:00
|
|
|
#include "cache.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "fsmonitor.h"
|
|
|
|
#include "fsm-health.h"
|
|
|
|
#include "fsmonitor--daemon.h"
|
|
|
|
|
2022-05-26 23:47:11 +02:00
|
|
|
/*
|
|
|
|
* Every minute wake up and test our health.
|
|
|
|
*/
|
|
|
|
#define WAIT_FREQ_MS (60 * 1000)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* State machine states for each of the interval functions
|
|
|
|
* used for polling our health.
|
|
|
|
*/
|
|
|
|
enum interval_fn_ctx {
|
|
|
|
CTX_INIT = 0,
|
|
|
|
CTX_TERM,
|
|
|
|
CTX_TIMER
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef int (interval_fn)(struct fsmonitor_daemon_state *state,
|
|
|
|
enum interval_fn_ctx ctx);
|
|
|
|
|
2022-05-26 23:47:10 +02:00
|
|
|
struct fsm_health_data
|
|
|
|
{
|
|
|
|
HANDLE hEventShutdown;
|
|
|
|
|
|
|
|
HANDLE hHandles[1]; /* the array does not own these handles */
|
|
|
|
#define HEALTH_SHUTDOWN 0
|
|
|
|
int nr_handles; /* number of active event handles */
|
|
|
|
};
|
|
|
|
|
|
|
|
int fsm_health__ctor(struct fsmonitor_daemon_state *state)
|
|
|
|
{
|
|
|
|
struct fsm_health_data *data;
|
|
|
|
|
|
|
|
CALLOC_ARRAY(data, 1);
|
|
|
|
|
|
|
|
data->hEventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
|
|
|
|
data->hHandles[HEALTH_SHUTDOWN] = data->hEventShutdown;
|
|
|
|
data->nr_handles++;
|
|
|
|
|
|
|
|
state->health_data = data;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fsm_health__dtor(struct fsmonitor_daemon_state *state)
|
|
|
|
{
|
|
|
|
struct fsm_health_data *data;
|
|
|
|
|
|
|
|
if (!state || !state->health_data)
|
|
|
|
return;
|
|
|
|
|
|
|
|
data = state->health_data;
|
|
|
|
|
|
|
|
CloseHandle(data->hEventShutdown);
|
|
|
|
|
|
|
|
FREE_AND_NULL(state->health_data);
|
|
|
|
}
|
|
|
|
|
2022-05-26 23:47:11 +02:00
|
|
|
/*
|
|
|
|
* A table of the polling functions.
|
|
|
|
*/
|
|
|
|
static interval_fn *table[] = {
|
|
|
|
NULL, /* must be last */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call all of the polling functions in the table.
|
|
|
|
* Shortcut and return first error.
|
|
|
|
*
|
|
|
|
* Return 0 if all succeeded.
|
|
|
|
*/
|
|
|
|
static int call_all(struct fsmonitor_daemon_state *state,
|
|
|
|
enum interval_fn_ctx ctx)
|
|
|
|
{
|
|
|
|
int k;
|
|
|
|
|
|
|
|
for (k = 0; table[k]; k++) {
|
|
|
|
int r = table[k](state, ctx);
|
|
|
|
if (r)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-05-26 23:47:10 +02:00
|
|
|
void fsm_health__loop(struct fsmonitor_daemon_state *state)
|
|
|
|
{
|
|
|
|
struct fsm_health_data *data = state->health_data;
|
2022-05-26 23:47:11 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
r = call_all(state, CTX_INIT);
|
|
|
|
if (r < 0)
|
|
|
|
goto force_error_stop;
|
|
|
|
if (r > 0)
|
|
|
|
goto force_shutdown;
|
2022-05-26 23:47:10 +02:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
DWORD dwWait = WaitForMultipleObjects(data->nr_handles,
|
|
|
|
data->hHandles,
|
2022-05-26 23:47:11 +02:00
|
|
|
FALSE, WAIT_FREQ_MS);
|
2022-05-26 23:47:10 +02:00
|
|
|
|
|
|
|
if (dwWait == WAIT_OBJECT_0 + HEALTH_SHUTDOWN)
|
|
|
|
goto clean_shutdown;
|
|
|
|
|
2022-05-26 23:47:11 +02:00
|
|
|
if (dwWait == WAIT_TIMEOUT) {
|
|
|
|
r = call_all(state, CTX_TIMER);
|
|
|
|
if (r < 0)
|
|
|
|
goto force_error_stop;
|
|
|
|
if (r > 0)
|
|
|
|
goto force_shutdown;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-05-26 23:47:10 +02:00
|
|
|
error(_("health thread wait failed [GLE %ld]"),
|
|
|
|
GetLastError());
|
|
|
|
goto force_error_stop;
|
|
|
|
}
|
|
|
|
|
|
|
|
force_error_stop:
|
|
|
|
state->health_error_code = -1;
|
2022-05-26 23:47:11 +02:00
|
|
|
force_shutdown:
|
2022-05-26 23:47:10 +02:00
|
|
|
ipc_server_stop_async(state->ipc_server_data);
|
|
|
|
clean_shutdown:
|
2022-05-26 23:47:11 +02:00
|
|
|
call_all(state, CTX_TERM);
|
2022-05-26 23:47:10 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fsm_health__stop_async(struct fsmonitor_daemon_state *state)
|
|
|
|
{
|
|
|
|
SetEvent(state->health_data->hHandles[HEALTH_SHUTDOWN]);
|
|
|
|
}
|