diff --git a/config.c b/config.c index c7365114..e61cd3e7 100644 --- a/config.c +++ b/config.c @@ -24,6 +24,7 @@ #include "strutil.h" #include "repmgr.h" +static void parse_event_notifications_list(t_configuration_options *options, const char *arg); static void tablespace_list_append(t_configuration_options *options, const char *arg); @@ -220,6 +221,8 @@ parse_config(const char *config_file, t_configuration_options *options) options->ignore_external_config_files = atoi(value); else if (strcmp(name, "event_notification_command") == 0) strncpy(options->event_notification_command, value, MAXLEN); + else if (strcmp(name, "event_notifications") == 0) + parse_event_notifications_list(options, value); else if (strcmp(name, "tablespace_mapping") == 0) tablespace_list_append(options, value); else @@ -648,3 +651,69 @@ tablespace_list_append(t_configuration_options *options, const char *arg) options->tablespace_mapping.tail = cell; } + +/* + * parse_event_notifications_list() + * + * + */ + +static void +parse_event_notifications_list(t_configuration_options *options, const char *arg) +{ + const char *arg_ptr; + char event_type_buf[MAXLEN] = ""; + char *dst_ptr = event_type_buf; + + + for (arg_ptr = arg; arg_ptr <= (arg + strlen(arg)); arg_ptr++) + { + /* ignore whitespace */ + if(*arg_ptr == ' ' || *arg_ptr == '\t') + { + continue; + } + + /* + * comma (or end-of-string) should mark the end of an event type - + * just as long as there was something preceding it + */ + if((*arg_ptr == ',' || *arg_ptr == '\0') && event_type_buf[0] != '\0') + { + EventNotificationListCell *cell; + + cell = (EventNotificationListCell *) pg_malloc0(sizeof(EventNotificationListCell)); + + if(cell == NULL) + { + log_err(_("unable to allocate memory. Terminating.\n")); + exit(ERR_BAD_CONFIG); + } + + strncpy(cell->event_type, event_type_buf, MAXLEN); + + if (options->event_notifications.tail) + { + options->event_notifications.tail->next = cell; + } + else + { + options->event_notifications.head = cell; + } + + options->event_notifications.tail = cell; + + memset(event_type_buf, 0, MAXLEN); + dst_ptr = event_type_buf; + } + /* ignore duplicated commas */ + else if(*arg_ptr == ',') + { + continue; + } + else + { + *dst_ptr++ = *arg_ptr; + } + } +} diff --git a/config.h b/config.h index d8e36ecc..0160c3fe 100644 --- a/config.h +++ b/config.h @@ -25,6 +25,19 @@ #include "strutil.h" +typedef struct EventNotificationListCell +{ + struct EventNotificationListCell *next; + char event_type[MAXLEN]; +} EventNotificationListCell; + + +typedef struct EventNotificationList +{ + EventNotificationListCell *head; + EventNotificationListCell *tail; +} EventNotificationList; + typedef struct TablespaceListCell { struct TablespaceListCell *next; @@ -63,12 +76,13 @@ typedef struct int monitor_interval_secs; int retry_promote_interval_secs; int use_replication_slots; - int ignore_external_config_files; + int ignore_external_config_files; char event_notification_command[MAXLEN]; + EventNotificationList event_notifications; TablespaceList tablespace_mapping; } t_configuration_options; -#define T_CONFIGURATION_OPTIONS_INITIALIZER { "", -1, NO_UPSTREAM_NODE, "", MANUAL_FAILOVER, -1, "", "", "", "", "", "", "", -1, -1, -1, "", "", "", "", 0, 0, 0, 0, "", {NULL, NULL} } +#define T_CONFIGURATION_OPTIONS_INITIALIZER { "", -1, NO_UPSTREAM_NODE, "", MANUAL_FAILOVER, -1, "", "", "", "", "", "", "", -1, -1, -1, "", "", "", "", 0, 0, 0, 0, "", { NULL, NULL }, {NULL, NULL} } bool parse_config(const char *config_file, t_configuration_options *options); diff --git a/dbutils.c b/dbutils.c index 0727839c..281baf10 100644 --- a/dbutils.c +++ b/dbutils.c @@ -1191,7 +1191,39 @@ create_event_record(PGconn *conn, t_configuration_options *options, int node_id, const char *src_ptr; char *dst_ptr; char *end_ptr; - int r; + int r; + + /* + * If configuration option 'event_notifications' was provided, + * check if this event is one of the ones listed; if not listed, + * don't execute the notification script. + * + * (If 'event_notifications' was not provided, we assume the script + * should be executed for all events). + */ + if(options->event_notifications.head != NULL) + { + EventNotificationListCell *cell; + bool notify_ok = false; + + for (cell = options->event_notifications.head; cell; cell = cell->next) + { + if(strcmp(event, cell->event_type) == 0) + { + notify_ok = true; + break; + } + } + + /* + * Event type not found in the 'event_notifications' list - return early + */ + if(notify_ok == false) + { + log_debug(_("Not executing notification script for event type '%s'\n"), event); + return success; + } + } dst_ptr = parsed_command; end_ptr = parsed_command + MAXPGPATH - 1;