Browse Source

MT#61977 add notification failure handling

Change-Id: Ide4d8429d57f53d0f759fa8a1255be9e06d94515
pull/1998/head
Richard Fuchs 4 months ago
parent
commit
bc9fc1e443
4 changed files with 71 additions and 3 deletions
  1. +9
    -0
      recording-daemon/notify.c
  2. +57
    -3
      recording-daemon/output.c
  3. +1
    -0
      recording-daemon/output.h
  4. +4
    -0
      recording-daemon/types.h

+ 9
- 0
recording-daemon/notify.c View File

@ -143,6 +143,11 @@ cleanup:
return success; return success;
} }
static void failed_http(notif_req_t *req) {
if (req->content)
output_content_failure(req->content);
}
static bool do_notify_command(notif_req_t *req) { static bool do_notify_command(notif_req_t *req) {
ilog(LOG_DEBUG, "Executing notification command for '%s%s%s'", FMT_M(req->name)); ilog(LOG_DEBUG, "Executing notification command for '%s%s%s'", FMT_M(req->name));
@ -190,6 +195,9 @@ static void do_notify(void *p, void *u) {
"Giving up", "Giving up",
FMT_M(req->name), FMT_M(req->name),
req->retries); req->retries);
if (req->action->failed)
req->action->failed(req);
} }
req->action->cleanup(req); req->action->cleanup(req);
@ -335,6 +343,7 @@ static const notif_action_t http_action = {
.setup = notify_req_setup_http, .setup = notify_req_setup_http,
.perform = do_notify_http, .perform = do_notify_http,
.cleanup = cleanup_http, .cleanup = cleanup_http,
.failed = failed_http,
}; };


+ 57
- 3
recording-daemon/output.c View File

@ -522,12 +522,15 @@ static bool output_config(sink_t *sink, output_t *output, const format_t *reques
static void content_free(content_t *s) { static void content_free(content_t *s) {
g_string_free(s->s, TRUE); g_string_free(s->s, TRUE);
g_free(s->name);
} }
static content_t *output_make_content(GString *s) {
static content_t *output_make_content(GString *s, output_t *output) {
content_t *ret = obj_alloc0(content_t, content_free); content_t *ret = obj_alloc0(content_t, content_free);
ret->s = s; ret->s = s;
if (output->file_name && output->file_name[0])
ret->name = g_strdup(output->file_name);
return ret; return ret;
} }
@ -557,12 +560,63 @@ content_t *output_get_content(output_t *output) {
return NULL; return NULL;
} }
output->content = output_make_content(content);
output->content = output_make_content(content, output);
return obj_get(output->content); return obj_get(output->content);
} }
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FILE, fclose)
void output_content_failure(content_t *c) {
unsigned int exp = 0;
if (!atomic_compare_exchange(&c->failed, &exp, 1))
return; // already done
// find output file name
const char *prefix;
char buf[33];
if (c->name)
prefix = c->name;
else {
rand_hex_str(buf, 16);
prefix = buf;
}
g_autoptr(char) fn = g_strdup_printf("%s/backup-%s", output_dir, prefix);
if (g_file_test(fn, G_FILE_TEST_EXISTS)) {
char suffix[17];
rand_hex_str(suffix, 8);
g_free(fn);
fn = g_strdup_printf("%s/backup-%s%s", output_dir, prefix, suffix);
if (g_file_test(fn, G_FILE_TEST_EXISTS)) {
ilog(LOG_ERR, "Failed to write emergency backup to '%s': file exists",
fn);
return;
}
}
g_autoptr(FILE) fp = fopen(fn, "wb");
if (!fp) {
ilog(LOG_ERR, "Failed to write emergency backup to '%s': %s",
fn, strerror(errno));
return;
}
ssize_t written = fwrite(c->s->str, 1, c->s->len, fp);
if (written < 0)
ilog(LOG_ERR, "Failed to write emergency backup to '%s': %s",
fn, strerror(errno));
else if (written != c->s->len)
ilog(LOG_ERR, "Failed to write emergency backup to '%s': short write",
fn);
else
ilog(LOG_NOTICE, "Wrote emergency backup to '%s'", fn);
}
static bool output_shutdown(output_t *output) { static bool output_shutdown(output_t *output) {
if (!output) if (!output)
return false; return false;
@ -581,7 +635,7 @@ static bool output_shutdown(output_t *output) {
else if (output->membuf) { else if (output->membuf) {
if (output->membuf->len) { if (output->membuf->len) {
obj_release(output->content); obj_release(output->content);
output->content = output_make_content(output->membuf);
output->content = output_make_content(output->membuf, output);
output->membuf = NULL; output->membuf = NULL;
ret = true; ret = true;
} }


+ 1
- 0
recording-daemon/output.h View File

@ -13,6 +13,7 @@ void output_init(const char *format);
output_t *output_new_ext(metafile_t *, const char *type, const char *kind, const char *label); output_t *output_new_ext(metafile_t *, const char *type, const char *kind, const char *label);
void output_close(metafile_t *, output_t *, tag_t *, bool discard); void output_close(metafile_t *, output_t *, tag_t *, bool discard);
content_t *output_get_content(output_t *); content_t *output_get_content(output_t *);
void output_content_failure(content_t *);
void sink_init(sink_t *); void sink_init(sink_t *);


+ 4
- 0
recording-daemon/types.h View File

@ -228,12 +228,16 @@ struct decode_s {
struct content_s { struct content_s {
struct obj obj; struct obj obj;
GString *s; GString *s;
char *name;
unsigned int failed;
}; };
struct notif_action_s { struct notif_action_s {
const char *name; const char *name;
void (*setup)(notif_req_t *, output_t *o, metafile_t *mf, tag_t *tag); void (*setup)(notif_req_t *, output_t *o, metafile_t *mf, tag_t *tag);
bool (*perform)(notif_req_t *); bool (*perform)(notif_req_t *);
void (*failed)(notif_req_t *);
void (*cleanup)(notif_req_t *); void (*cleanup)(notif_req_t *);
}; };


Loading…
Cancel
Save