Merge pull request #2821 from rpv-tomsk/plugin-context-master-2
authorPavel Rochnyak <pavel2000@ngs.ru>
Wed, 20 Jun 2018 10:55:56 +0000 (17:55 +0700)
committerGitHub <noreply@github.com>
Wed, 20 Jun 2018 10:55:56 +0000 (17:55 +0700)
RFE: Add plugin name field into plugin context use it to improve error reporting

src/bind.c
src/daemon/common.c
src/daemon/configfile.c
src/daemon/plugin.c
src/daemon/plugin.h
src/daemon/plugin_mock.c

index 3a5e3c3..b012639 100644 (file)
@@ -73,9 +73,9 @@ typedef int (*list_callback_t)(const char *name, value_t value,
 struct cb_view_s {
   char *name;
 
-  int qtypes;
-  int resolver_stats;
-  int cacherrsets;
+  _Bool qtypes;
+  _Bool resolver_stats;
+  _Bool cacherrsets;
 
   char **zones;
   size_t zones_num;
@@ -107,12 +107,12 @@ typedef struct list_info_ptr_s list_info_ptr_t;
 static bool config_parse_time = true;
 
 static char *url;
-static int global_opcodes = 1;
-static int global_qtypes = 1;
-static int global_server_stats = 1;
-static int global_zone_maint_stats = 1;
-static int global_resolver_stats;
-static int global_memory_stats = 1;
+static _Bool global_opcodes = 1;
+static _Bool global_qtypes = 1;
+static _Bool global_server_stats = 1;
+static _Bool global_zone_maint_stats = 1;
+static _Bool global_resolver_stats;
+static _Bool global_memory_stats = 1;
 static int timeout = -1;
 
 static cb_view_t *views;
@@ -1410,22 +1410,6 @@ static int bind_xml(const char *data) /* {{{ */
   return ret;
 } /* }}} int bind_xml */
 
-static int bind_config_set_bool(const char *name, int *var, /* {{{ */
-                                oconfig_item_t *ci) {
-  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) {
-    WARNING("bind plugin: The `%s' option needs "
-            "exactly one boolean argument.",
-            name);
-    return -1;
-  }
-
-  if (ci->values[0].value.boolean)
-    *var = 1;
-  else
-    *var = 0;
-  return 0;
-} /* }}} int bind_config_set_bool */
-
 static int bind_config_add_view_zone(cb_view_t *view, /* {{{ */
                                      oconfig_item_t *ci) {
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
@@ -1484,11 +1468,11 @@ static int bind_config_add_view(oconfig_item_t *ci) /* {{{ */
     oconfig_item_t *child = ci->children + i;
 
     if (strcasecmp("QTypes", child->key) == 0)
-      bind_config_set_bool("QTypes", &tmp->qtypes, child);
+      cf_util_get_boolean(child, &tmp->qtypes);
     else if (strcasecmp("ResolverStats", child->key) == 0)
-      bind_config_set_bool("ResolverStats", &tmp->resolver_stats, child);
+      cf_util_get_boolean(child, &tmp->resolver_stats);
     else if (strcasecmp("CacheRRSets", child->key) == 0)
-      bind_config_set_bool("CacheRRSets", &tmp->cacherrsets, child);
+      cf_util_get_boolean(child, &tmp->cacherrsets);
     else if (strcasecmp("Zone", child->key) == 0)
       bind_config_add_view_zone(tmp, child);
     else {
@@ -1508,27 +1492,19 @@ static int bind_config(oconfig_item_t *ci) /* {{{ */
     oconfig_item_t *child = ci->children + i;
 
     if (strcasecmp("Url", child->key) == 0) {
-      if ((child->values_num != 1) ||
-          (child->values[0].type != OCONFIG_TYPE_STRING)) {
-        WARNING("bind plugin: The `Url' option needs "
-                "exactly one string argument.");
-        return -1;
-      }
-
-      sfree(url);
-      url = strdup(child->values[0].value.string);
+      cf_util_get_string(child, &url);
     } else if (strcasecmp("OpCodes", child->key) == 0)
-      bind_config_set_bool("OpCodes", &global_opcodes, child);
+      cf_util_get_boolean(child, &global_opcodes);
     else if (strcasecmp("QTypes", child->key) == 0)
-      bind_config_set_bool("QTypes", &global_qtypes, child);
+      cf_util_get_boolean(child, &global_qtypes);
     else if (strcasecmp("ServerStats", child->key) == 0)
-      bind_config_set_bool("ServerStats", &global_server_stats, child);
+      cf_util_get_boolean(child, &global_server_stats);
     else if (strcasecmp("ZoneMaintStats", child->key) == 0)
-      bind_config_set_bool("ZoneMaintStats", &global_zone_maint_stats, child);
+      cf_util_get_boolean(child, &global_zone_maint_stats);
     else if (strcasecmp("ResolverStats", child->key) == 0)
-      bind_config_set_bool("ResolverStats", &global_resolver_stats, child);
+      cf_util_get_boolean(child, &global_resolver_stats);
     else if (strcasecmp("MemoryStats", child->key) == 0)
-      bind_config_set_bool("MemoryStats", &global_memory_stats, child);
+      cf_util_get_boolean(child, &global_memory_stats);
     else if (strcasecmp("View", child->key) == 0)
       bind_config_add_view(child);
     else if (strcasecmp("ParseTime", child->key) == 0)
index 2251d2e..76c7036 100644 (file)
@@ -417,7 +417,7 @@ int strunescape(char *buf, size_t buf_len) {
       continue;
 
     if (((i + 1) >= buf_len) || (buf[i + 1] == 0)) {
-      ERROR("string unescape: backslash found at end of string.");
+      P_ERROR("string unescape: backslash found at end of string.");
       /* Ensure null-byte at the end of the buffer. */
       buf[i] = 0;
       return -1;
@@ -606,9 +606,9 @@ int check_create_dir(const char *file_orig) {
      * behavior.
      */
     if (fields[i][0] == '.') {
-      ERROR("Cowardly refusing to create a directory that "
-            "begins with a `.' (dot): `%s'",
-            file_orig);
+      P_ERROR("Cowardly refusing to create a directory that "
+              "begins with a `.' (dot): `%s'",
+              file_orig);
       return -2;
     }
 
@@ -619,7 +619,7 @@ int check_create_dir(const char *file_orig) {
     if (strjoin(dir + path_is_absolute,
                 (size_t)(sizeof(dir) - path_is_absolute), fields,
                 (size_t)(i + 1), "/") < 0) {
-      ERROR("strjoin failed: `%s', component #%i", file_orig, i);
+      P_ERROR("strjoin failed: `%s', component #%i", file_orig, i);
       return -1;
     }
 
@@ -635,16 +635,16 @@ int check_create_dir(const char *file_orig) {
           if (EEXIST == errno)
             continue;
 
-          ERROR("check_create_dir: mkdir (%s): %s", dir, STRERRNO);
+          P_ERROR("check_create_dir: mkdir (%s): %s", dir, STRERRNO);
           return -1;
         } else {
-          ERROR("check_create_dir: stat (%s): %s", dir, STRERRNO);
+          P_ERROR("check_create_dir: stat (%s): %s", dir, STRERRNO);
           return -1;
         }
       } else if (!S_ISDIR(statbuf.st_mode)) {
-        ERROR("check_create_dir: `%s' exists but is not "
-              "a directory!",
-              dir);
+        P_ERROR("check_create_dir: `%s' exists but is not "
+                "a directory!",
+                dir);
         return -1;
       }
       break;
@@ -667,12 +667,12 @@ int get_kstat(kstat_t **ksp_ptr, char *module, int instance, char *name) {
 
   *ksp_ptr = kstat_lookup(kc, module, instance, name);
   if (*ksp_ptr == NULL) {
-    ERROR("get_kstat: Cound not find kstat %s", ident);
+    P_ERROR("get_kstat: Cound not find kstat %s", ident);
     return -1;
   }
 
   if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) {
-    ERROR("get_kstat: kstat %s has wrong type", ident);
+    P_ERROR("get_kstat: kstat %s has wrong type", ident);
     *ksp_ptr = NULL;
     return -1;
   }
@@ -683,12 +683,12 @@ int get_kstat(kstat_t **ksp_ptr, char *module, int instance, char *name) {
 #endif
 
   if (kstat_read(kc, *ksp_ptr, NULL) == -1) {
-    ERROR("get_kstat: kstat %s could not be read", ident);
+    P_ERROR("get_kstat: kstat %s could not be read", ident);
     return -1;
   }
 
   if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) {
-    ERROR("get_kstat: kstat %s has wrong type", ident);
+    P_ERROR("get_kstat: kstat %s has wrong type", ident);
     return -1;
   }
 
@@ -700,12 +700,12 @@ long long get_kstat_value(kstat_t *ksp, char *name) {
   long long retval = -1LL;
 
   if (ksp == NULL) {
-    ERROR("get_kstat_value (\"%s\"): ksp is NULL.", name);
+    P_ERROR("get_kstat_value (\"%s\"): ksp is NULL.", name);
     return -1LL;
   } else if (ksp->ks_type != KSTAT_TYPE_NAMED) {
-    ERROR("get_kstat_value (\"%s\"): ksp->ks_type (%#x) "
-          "is not KSTAT_TYPE_NAMED (%#x).",
-          name, (unsigned int)ksp->ks_type, (unsigned int)KSTAT_TYPE_NAMED);
+    P_ERROR("get_kstat_value (\"%s\"): ksp->ks_type (%#x) "
+            "is not KSTAT_TYPE_NAMED (%#x).",
+            name, (unsigned int)ksp->ks_type, (unsigned int)KSTAT_TYPE_NAMED);
     return -1LL;
   }
 
@@ -723,7 +723,7 @@ long long get_kstat_value(kstat_t *ksp, char *name) {
   else if (kn->data_type == KSTAT_DATA_UINT64)
     retval = (long long)kn->value.ui64; /* XXX: Might overflow! */
   else
-    WARNING("get_kstat_value: Not a numeric value: %s", name);
+    P_WARNING("get_kstat_value: Not a numeric value: %s", name);
 
   return retval;
 }
@@ -1035,19 +1035,19 @@ int parse_value(const char *value_orig, value_t *ret_value, int ds_type) {
 
   default:
     sfree(value);
-    ERROR("parse_value: Invalid data source type: %i.", ds_type);
+    P_ERROR("parse_value: Invalid data source type: %i.", ds_type);
     return -1;
   }
 
   if (value == endptr) {
-    ERROR("parse_value: Failed to parse string as %s: \"%s\".",
-          DS_TYPE_TO_STRING(ds_type), value);
+    P_ERROR("parse_value: Failed to parse string as %s: \"%s\".",
+            DS_TYPE_TO_STRING(ds_type), value);
     sfree(value);
     return -1;
   } else if ((NULL != endptr) && ('\0' != *endptr))
-    INFO("parse_value: Ignoring trailing garbage \"%s\" after %s value. "
-         "Input string was \"%s\".",
-         endptr, DS_TYPE_TO_STRING(ds_type), value_orig);
+    P_INFO("parse_value: Ignoring trailing garbage \"%s\" after %s value. "
+           "Input string was \"%s\".",
+           endptr, DS_TYPE_TO_STRING(ds_type), value_orig);
 
   sfree(value);
   return 0;
@@ -1212,7 +1212,7 @@ int walk_directory(const char *dir, dirwalk_callback_f callback,
   failure = 0;
 
   if ((dh = opendir(dir)) == NULL) {
-    ERROR("walk_directory: Cannot open '%s': %s", dir, STRERRNO);
+    P_ERROR("walk_directory: Cannot open '%s': %s", dir, STRERRNO);
     return -1;
   }
 
@@ -1252,7 +1252,7 @@ ssize_t read_file_contents(const char *filename, char *buf, size_t bufsize) {
 
   ret = (ssize_t)fread(buf, 1, bufsize, fh);
   if ((ret == 0) && (ferror(fh) != 0)) {
-    ERROR("read_file_contents: Reading file \"%s\" failed.", filename);
+    P_ERROR("read_file_contents: Reading file \"%s\" failed.", filename);
     ret = -1;
   }
 
@@ -1411,8 +1411,8 @@ int service_name_to_port_number(const char *service_name) {
 
   status = getaddrinfo(/* node = */ NULL, service_name, &ai_hints, &ai_list);
   if (status != 0) {
-    ERROR("service_name_to_port_number: getaddrinfo failed: %s",
-          gai_strerror(status));
+    P_ERROR("service_name_to_port_number: getaddrinfo failed: %s",
+            gai_strerror(status));
     return -1;
   }
 
@@ -1450,7 +1450,7 @@ void set_sock_opts(int sockfd) /* {{{ */
   status = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype,
                       &(socklen_t){sizeof(socktype)});
   if (status != 0) {
-    WARNING("set_sock_opts: failed to determine socket type");
+    P_WARNING("set_sock_opts: failed to determine socket type");
     return;
   }
 
@@ -1458,14 +1458,14 @@ void set_sock_opts(int sockfd) /* {{{ */
     status =
         setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &(int){1}, sizeof(int));
     if (status != 0)
-      WARNING("set_sock_opts: failed to set socket keepalive flag");
+      P_WARNING("set_sock_opts: failed to set socket keepalive flag");
 
 #ifdef TCP_KEEPIDLE
     int tcp_keepidle = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 100 + 1);
     status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &tcp_keepidle,
                         sizeof(tcp_keepidle));
     if (status != 0)
-      WARNING("set_sock_opts: failed to set socket tcp keepalive time");
+      P_WARNING("set_sock_opts: failed to set socket tcp keepalive time");
 #endif
 
 #ifdef TCP_KEEPINTVL
@@ -1474,7 +1474,7 @@ void set_sock_opts(int sockfd) /* {{{ */
     status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &tcp_keepintvl,
                         sizeof(tcp_keepintvl));
     if (status != 0)
-      WARNING("set_sock_opts: failed to set socket tcp keepalive interval");
+      P_WARNING("set_sock_opts: failed to set socket tcp keepalive interval");
 #endif
   }
 } /* }}} void set_sock_opts */
@@ -1558,12 +1558,12 @@ int check_capability(int arg) /* {{{ */
     return -1;
 
   if (!(cap = cap_get_proc())) {
-    ERROR("check_capability: cap_get_proc failed.");
+    P_ERROR("check_capability: cap_get_proc failed.");
     return -1;
   }
 
   if (cap_get_flag(cap, cap_value, CAP_EFFECTIVE, &cap_flag_value) < 0) {
-    ERROR("check_capability: cap_get_flag failed.");
+    P_ERROR("check_capability: cap_get_flag failed.");
     cap_free(cap);
     return -1;
   }
@@ -1574,8 +1574,8 @@ int check_capability(int arg) /* {{{ */
 #else
 int check_capability(__attribute__((unused)) int arg) /* {{{ */
 {
-  WARNING("check_capability: unsupported capability implementation. "
-          "Some plugin(s) may require elevated privileges to work properly.");
+  P_WARNING("check_capability: unsupported capability implementation. "
+            "Some plugin(s) may require elevated privileges to work properly.");
   return 0;
 } /* }}} int check_capability */
 #endif /* HAVE_CAPABILITY */
index f88d234..d903800 100644 (file)
@@ -251,11 +251,7 @@ static int dispatch_value_plugindir(oconfig_item_t *ci) {
 }
 
 static int dispatch_loadplugin(oconfig_item_t *ci) {
-  const char *name;
   bool global = false;
-  plugin_ctx_t ctx = {0};
-  plugin_ctx_t old_ctx;
-  int ret_val;
 
   assert(strcasecmp(ci->key, "LoadPlugin") == 0);
 
@@ -265,14 +261,16 @@ static int dispatch_loadplugin(oconfig_item_t *ci) {
     return -1;
   }
 
-  name = ci->values[0].value.string;
+  const char *name = ci->values[0].value.string;
   if (strcmp("libvirt", name) == 0)
     name = "virt";
 
   /* default to the global interval set before loading this plugin */
-  ctx.interval = cf_get_default_interval();
-  ctx.flush_interval = 0;
-  ctx.flush_timeout = 0;
+  plugin_ctx_t ctx = {
+      .interval = cf_get_default_interval(), .name = strdup(name),
+  };
+  if (ctx.name == NULL)
+    return ENOMEM;
 
   for (int i = 0; i < ci->children_num; ++i) {
     oconfig_item_t *child = ci->children + i;
@@ -288,12 +286,12 @@ static int dispatch_loadplugin(oconfig_item_t *ci) {
     else {
       WARNING("Ignoring unknown LoadPlugin option \"%s\" "
               "for plugin \"%s\"",
-              child->key, ci->values[0].value.string);
+              child->key, name);
     }
   }
 
-  old_ctx = plugin_set_ctx(ctx);
-  ret_val = plugin_load(name, global);
+  plugin_ctx_t old_ctx = plugin_set_ctx(ctx);
+  int ret_val = plugin_load(name, global);
   /* reset to the "global" context */
   plugin_set_ctx(old_ctx);
 
@@ -1048,16 +1046,12 @@ int cf_read(const char *filename) {
  * success. */
 int cf_util_get_string(const oconfig_item_t *ci, char **ret_string) /* {{{ */
 {
-  char *string;
-
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
-    ERROR("cf_util_get_string: The %s option requires "
-          "exactly one string argument.",
-          ci->key);
+    P_ERROR("The `%s' option requires exactly one string argument.", ci->key);
     return -1;
   }
 
-  string = strdup(ci->values[0].value.string);
+  char *string = strdup(ci->values[0].value.string);
   if (string == NULL)
     return -1;
 
@@ -1076,9 +1070,7 @@ int cf_util_get_string_buffer(const oconfig_item_t *ci, char *buffer, /* {{{ */
     return EINVAL;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
-    ERROR("cf_util_get_string_buffer: The %s option requires "
-          "exactly one string argument.",
-          ci->key);
+    P_ERROR("The `%s' option requires exactly one string argument.", ci->key);
     return -1;
   }
 
@@ -1095,9 +1087,7 @@ int cf_util_get_int(const oconfig_item_t *ci, int *ret_value) /* {{{ */
     return EINVAL;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
-    ERROR("cf_util_get_int: The %s option requires "
-          "exactly one numeric argument.",
-          ci->key);
+    P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key);
     return -1;
   }
 
@@ -1112,9 +1102,7 @@ int cf_util_get_double(const oconfig_item_t *ci, double *ret_value) /* {{{ */
     return EINVAL;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
-    ERROR("cf_util_get_double: The %s option requires "
-          "exactly one numeric argument.",
-          ci->key);
+    P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key);
     return -1;
   }
 
@@ -1130,9 +1118,7 @@ int cf_util_get_boolean(const oconfig_item_t *ci, bool *ret_bool) /* {{{ */
 
   if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN) &&
                                 (ci->values[0].type != OCONFIG_TYPE_STRING))) {
-    ERROR("cf_util_get_boolean: The %s option requires "
-          "exactly one boolean argument.",
-          ci->key);
+    P_ERROR("The `%s' option requires exactly one boolean argument.", ci->key);
     return -1;
   }
 
@@ -1141,19 +1127,19 @@ int cf_util_get_boolean(const oconfig_item_t *ci, bool *ret_bool) /* {{{ */
     *ret_bool = ci->values[0].value.boolean ? true : false;
     break;
   case OCONFIG_TYPE_STRING:
-    WARNING("cf_util_get_boolean: Using string value `%s' for boolean option "
-            "`%s' is deprecated and will be removed in future releases. "
-            "Use unquoted true or false instead.",
-            ci->values[0].value.string, ci->key);
+    P_WARNING("Using string value `%s' for boolean option `%s' is deprecated "
+              "and will be removed in future releases. Use unquoted true or "
+              "false instead.",
+              ci->values[0].value.string, ci->key);
 
     if (IS_TRUE(ci->values[0].value.string))
       *ret_bool = true;
     else if (IS_FALSE(ci->values[0].value.string))
       *ret_bool = false;
     else {
-      ERROR("cf_util_get_boolean: Cannot parse string value `%s' of the `%s' "
-            "option as a boolean value.",
-            ci->values[0].value.string, ci->key);
+      P_ERROR("Cannot parse string value `%s' of the `%s' option as a boolean "
+              "value.",
+              ci->values[0].value.string, ci->key);
       return -1;
     }
     break;
@@ -1194,9 +1180,7 @@ int cf_util_get_port_number(const oconfig_item_t *ci) /* {{{ */
 
   if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) &&
                                 (ci->values[0].type != OCONFIG_TYPE_NUMBER))) {
-    ERROR("cf_util_get_port_number: The \"%s\" option requires "
-          "exactly one string argument.",
-          ci->key);
+    P_ERROR("The `%s' option requires exactly one string argument.", ci->key);
     return -1;
   }
 
@@ -1206,11 +1190,9 @@ int cf_util_get_port_number(const oconfig_item_t *ci) /* {{{ */
   assert(ci->values[0].type == OCONFIG_TYPE_NUMBER);
   tmp = (int)(ci->values[0].value.number + 0.5);
   if ((tmp < 1) || (tmp > 65535)) {
-    ERROR("cf_util_get_port_number: The \"%s\" option requires "
-          "a service name or a port number. The number "
-          "you specified, %i, is not in the valid "
-          "range of 1-65535.",
-          ci->key, tmp);
+    P_ERROR("The `%s' option requires a service name or a port number. The "
+            "number you specified, %i, is not in the valid range of 1-65535.",
+            ci->key, tmp);
     return -1;
   }
 
@@ -1224,18 +1206,15 @@ int cf_util_get_service(const oconfig_item_t *ci, char **ret_string) /* {{{ */
   int status;
 
   if (ci->values_num != 1) {
-    ERROR("cf_util_get_service: The %s option requires exactly "
-          "one argument.",
-          ci->key);
+    P_ERROR("The `%s` option requires exactly one argument.", ci->key);
     return -1;
   }
 
   if (ci->values[0].type == OCONFIG_TYPE_STRING)
     return cf_util_get_string(ci, ret_string);
   if (ci->values[0].type != OCONFIG_TYPE_NUMBER) {
-    ERROR("cf_util_get_service: The %s option requires "
-          "exactly one string or numeric argument.",
-          ci->key);
+    P_ERROR("The `%s` option requires exactly one string or numeric argument.",
+            ci->key);
   }
 
   port = 0;
@@ -1243,16 +1222,14 @@ int cf_util_get_service(const oconfig_item_t *ci, char **ret_string) /* {{{ */
   if (status != 0)
     return status;
   else if ((port < 1) || (port > 65535)) {
-    ERROR("cf_util_get_service: The port number given "
-          "for the %s option is out of "
-          "range (%i).",
-          ci->key, port);
+    P_ERROR("The port number given for the `%s` option is out of range (%i).",
+            ci->key, port);
     return -1;
   }
 
   service = malloc(6);
   if (service == NULL) {
-    ERROR("cf_util_get_service: Out of memory.");
+    P_ERROR("cf_util_get_service: Out of memory.");
     return -1;
   }
   snprintf(service, 6, "%i", port);
@@ -1269,16 +1246,13 @@ int cf_util_get_cdtime(const oconfig_item_t *ci, cdtime_t *ret_value) /* {{{ */
     return EINVAL;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
-    ERROR("cf_util_get_cdtime: The %s option requires "
-          "exactly one numeric argument.",
-          ci->key);
+    P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key);
     return -1;
   }
 
   if (ci->values[0].value.number < 0.0) {
-    ERROR("cf_util_get_cdtime: The numeric argument of the %s "
-          "option must not be negative.",
-          ci->key);
+    P_ERROR("The numeric argument of the `%s' option must not be negative.",
+            ci->key);
     return -1;
   }
 
index 427a813..92e1ab2 100644 (file)
@@ -346,19 +346,22 @@ static void log_list_callbacks(llist_t **list, /* {{{ */
 static int create_register_callback(llist_t **list, /* {{{ */
                                     const char *name, void *callback,
                                     user_data_t const *ud) {
-  callback_func_t *cf;
 
-  cf = calloc(1, sizeof(*cf));
+  if (name == NULL || callback == NULL)
+    return EINVAL;
+
+  callback_func_t *cf = calloc(1, sizeof(*cf));
   if (cf == NULL) {
     free_userdata(ud);
     ERROR("plugin: create_register_callback: calloc failed.");
-    return -1;
+    return ENOMEM;
   }
 
   cf->cf_callback = callback;
   if (ud == NULL) {
-    cf->cf_udata.data = NULL;
-    cf->cf_udata.free_func = NULL;
+    cf->cf_udata = (user_data_t){
+        .data = NULL, .free_func = NULL,
+    };
   } else {
     cf->cf_udata = *ud;
   }
@@ -1714,8 +1717,12 @@ int plugin_write(const char *plugin, /* {{{ */
       callback_func_t *cf = le->value;
       plugin_write_cb callback;
 
-      /* do not switch plugin context; rather keep the context (interval)
-       * information of the calling read plugin */
+      /* Keep the read plugin's interval and flush information but update the
+       * plugin name. */
+      plugin_ctx_t old_ctx = plugin_get_ctx();
+      plugin_ctx_t ctx = old_ctx;
+      ctx.name = cf->cf_ctx.name;
+      plugin_set_ctx(ctx);
 
       DEBUG("plugin: plugin_write: Writing values via %s.", le->key);
       callback = cf->cf_callback;
@@ -1725,6 +1732,7 @@ int plugin_write(const char *plugin, /* {{{ */
       else
         success++;
 
+      plugin_set_ctx(old_ctx);
       le = le->next;
     }
 
@@ -2236,6 +2244,21 @@ void plugin_log(int level, const char *format, ...) {
   }
 } /* void plugin_log */
 
+void daemon_log(int level, const char *format, ...) {
+  char msg[1024] = ""; // Size inherits from plugin_log()
+
+  char const *name = plugin_get_ctx().name;
+  if (name == NULL)
+    name = "UNKNOWN";
+
+  va_list ap;
+  va_start(ap, format);
+  vsnprintf(msg, sizeof(msg), format, ap);
+  va_end(ap);
+
+  plugin_log(level, "%s plugin: %s", name, msg);
+} /* void daemon_log */
+
 int parse_log_severity(const char *severity) {
   int log_level = -1;
 
index 0369067..871eccd 100644 (file)
@@ -171,6 +171,7 @@ struct user_data_s {
 typedef struct user_data_s user_data_t;
 
 struct plugin_ctx_s {
+  char *name;
   cdtime_t interval;
   cdtime_t flush_interval;
   cdtime_t flush_timeout;
@@ -398,6 +399,15 @@ int parse_notif_severity(const char *severity);
 #define DEBUG(...) /* noop */
 #endif             /* ! COLLECT_DEBUG */
 
+/* This will log messages, prefixed by plugin name */
+void daemon_log(int level, const char *format, ...)
+    __attribute__((format(printf, 2, 3)));
+
+#define P_ERROR(...) daemon_log(LOG_ERR, __VA_ARGS__)
+#define P_WARNING(...) daemon_log(LOG_WARNING, __VA_ARGS__)
+#define P_NOTICE(...) daemon_log(LOG_NOTICE, __VA_ARGS__)
+#define P_INFO(...) daemon_log(LOG_INFO, __VA_ARGS__)
+
 const data_set_t *plugin_get_ds(const char *name);
 
 int plugin_notification_meta_add_string(notification_t *n, const char *name,
index a11d4f5..1624f0e 100644 (file)
@@ -170,6 +170,17 @@ void plugin_log(int level, char const *format, ...) {
   printf("plugin_log (%i, \"%s\");\n", level, buffer);
 }
 
+void daemon_log(int level, char const *format, ...) {
+  char buffer[1024];
+  va_list ap;
+
+  va_start(ap, format);
+  vsnprintf(buffer, sizeof(buffer), format, ap);
+  va_end(ap);
+
+  printf("daemon_log (%i, \"%s\");\n", level, buffer);
+}
+
 void plugin_init_ctx(void) { /* nop */
 }