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;
}
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) {
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",
FMT_M(req->name),
req->retries);
if (req->action->failed)
req->action->failed(req);
}
req->action->cleanup(req);
@ -335,6 +343,7 @@ static const notif_action_t http_action = {
.setup = notify_req_setup_http,
.perform = do_notify_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) {
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);
ret->s = s;
if (output->file_name && output->file_name[0])
ret->name = g_strdup(output->file_name);
return ret;
}
@ -557,12 +560,63 @@ content_t *output_get_content(output_t *output) {
return NULL;
}
output->content = output_make_content(content);
output->content = output_make_content(content, output);
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) {
if (!output)
return false;
@ -581,7 +635,7 @@ static bool output_shutdown(output_t *output) {
else if (output->membuf) {
if (output->membuf->len) {
obj_release(output->content);
output->content = output_make_content(output->membuf);
output->content = output_make_content(output->membuf, output);
output->membuf = NULL;
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);
void output_close(metafile_t *, output_t *, tag_t *, bool discard);
content_t *output_get_content(output_t *);
void output_content_failure(content_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 obj obj;
GString *s;
char *name;
unsigned int failed;
};
struct notif_action_s {
const char *name;
void (*setup)(notif_req_t *, output_t *o, metafile_t *mf, tag_t *tag);
bool (*perform)(notif_req_t *);
void (*failed)(notif_req_t *);
void (*cleanup)(notif_req_t *);
};


Loading…
Cancel
Save