size_t values_len;
char *instance_prefix;
char *instance;
+ char *plugin_instance_from;
int is_table;
unsigned long magic;
};
struct cx_s /* {{{ */
{
char *instance;
+ char *plugin_name;
char *host;
char *url;
sfree(xpath->path);
sfree(xpath->type);
sfree(xpath->instance_prefix);
+ sfree(xpath->plugin_instance_from);
sfree(xpath->instance);
sfree(xpath->values);
sfree(xpath);
sfree(db->buffer);
sfree(db->instance);
+ sfree(db->plugin_name);
sfree(db->host);
sfree(db->url);
sfree(db);
} /* }}} void cx_free */
-static const char *cx_host(cx_t *db) /* {{{ */
+static const char *cx_host(const cx_t *db) /* {{{ */
{
if (db->host == NULL)
return hostname_g;
} /* }}} int cx_handle_all_value_xpaths */
static int cx_handle_instance_xpath(xmlXPathContextPtr xpath_ctx, /* {{{ */
- cx_xpath_t *xpath, value_list_t *vl,
- _Bool is_table) {
+ cx_xpath_t *xpath, value_list_t *vl) {
+
xmlXPathObjectPtr instance_node_obj = NULL;
xmlNodeSetPtr instance_node = NULL;
memset(vl->type_instance, 0, sizeof(vl->type_instance));
- /* If the base xpath returns more than one block, the result is assumed to be
- * a table. The `Instance' option is not optional in this case. Check for the
- * condition and inform the user. */
- if (is_table && (xpath->instance == NULL)) {
- WARNING("curl_xml plugin: "
- "Base-XPath %s is a table (more than one result was returned), "
- "but no instance-XPath has been defined.",
- xpath->path);
- return -1;
- }
-
/* instance has to be an xpath expression */
if (xpath->instance != NULL) {
int tmp_size;
* somewhere inside this structure. */
xmlXPathFreeObject(instance_node_obj);
+ /* Part 2, handle PluginInstanceFrom */
+ instance_node_obj = NULL;
+ instance_node = NULL;
+
+ /* plugin_instance_from has to be an xpath expression */
+ if (xpath->plugin_instance_from != NULL) {
+ int tmp_size;
+
+ instance_node_obj = cx_evaluate_xpath(xpath_ctx,
+ BAD_CAST xpath->plugin_instance_from);
+ if (instance_node_obj == NULL)
+ return -1; /* error is already logged */
+
+ instance_node = instance_node_obj->nodesetval;
+ tmp_size = (instance_node) ? instance_node->nodeNr : 0;
+
+ if (tmp_size <= 0) {
+ WARNING("curl_xml plugin: "
+ "relative xpath expression for 'PluginInstanceFrom' \"%s\" "
+ "doesn't match any of the nodes. Skipping the node.",
+ xpath->plugin_instance_from);
+ xmlXPathFreeObject(instance_node_obj);
+ return -1;
+ }
+
+ if (tmp_size > 1) {
+ WARNING("curl_xml plugin: "
+ "relative xpath expression for 'PluginInstanceFrom' \"%s\" "
+ "is expected to return only one text node. Skipping the node.",
+ xpath->plugin_instance_from);
+ xmlXPathFreeObject(instance_node_obj);
+ return -1;
+ }
+
+ /* ignoring the element if other than textnode/attribute */
+ if (cx_if_not_text_node(instance_node->nodeTab[0])) {
+ WARNING("curl_xml plugin: "
+ "relative xpath expression \"%s\" is expected to return only "
+ "text node which is not the case. Skipping the node.",
+ xpath->plugin_instance_from);
+ xmlXPathFreeObject(instance_node_obj);
+ return -1;
+ }
+
+ if (instance_node != NULL) {
+ char *node_value = (char *)xmlNodeGetContent(instance_node->nodeTab[0]);
+ sstrncpy (vl->plugin_instance, node_value, sizeof(vl->plugin_instance));
+ sfree(node_value);
+ }
+
+ /* Free `instance_node_obj' this late, because `instance_node' points to
+ * somewhere inside this structure. */
+ xmlXPathFreeObject(instance_node_obj);
+ } /* if (xpath->plugin_instance_from != NULL) */
+
return 0;
} /* }}} int cx_handle_instance_xpath */
-static int cx_handle_base_xpath(char const *plugin_instance, /* {{{ */
- char const *host, xmlXPathContextPtr xpath_ctx,
+static int cx_handle_base_xpath(const cx_t *db, /* {{{ */
+ xmlXPathContextPtr xpath_ctx,
const data_set_t *ds, char *base_xpath,
cx_xpath_t *xpath) {
int total_nodes;
}
/* If base_xpath returned multiple results, then */
- /* Instance in the xpath block is required */
- if (total_nodes > 1 && xpath->instance == NULL) {
+ /* InstanceFrom or PluginInstanceFrom in the xpath block is required */
+ if (total_nodes > 1 && xpath->instance == NULL
+ && xpath->plugin_instance_from == NULL) {
ERROR("curl_xml plugin: "
- "InstanceFrom is must in xpath block since the base xpath expression "
- "\"%s\" "
+ "InstanceFrom or PluginInstanceFrom is must in xpath block "
+ "since the base xpath expression \"%s\" "
"returned multiple results. Skipping the xpath block...",
base_xpath);
return -1;
/* set the values for the value_list */
vl.values_len = ds->ds_num;
sstrncpy(vl.type, xpath->type, sizeof(vl.type));
- sstrncpy(vl.plugin, "curl_xml", sizeof(vl.plugin));
- sstrncpy(vl.host, host, sizeof(vl.host));
- if (plugin_instance != NULL)
- sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
+ sstrncpy(vl.plugin, (db->plugin_name != NULL) ? db->plugin_name : "curl_xml",
+ sizeof(vl.plugin));
+ sstrncpy(vl.host, cx_host(db), sizeof(vl.host));
for (int i = 0; i < total_nodes; i++) {
int status;
xpath_ctx->node = base_nodes->nodeTab[i];
- status = cx_handle_instance_xpath(xpath_ctx, xpath, &vl,
- /* is_table = */ (total_nodes > 1));
+ if (db->instance != NULL)
+ sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
+
+ status = cx_handle_instance_xpath(xpath_ctx, xpath, &vl);
if (status != 0)
continue; /* An error has already been reported. */
ds = plugin_get_ds(xpath->type);
if ((cx_check_type(ds, xpath) == 0) &&
- (cx_handle_base_xpath(db->instance, cx_host(db), xpath_ctx, ds, le->key,
- xpath) == 0))
+ (cx_handle_base_xpath(db, xpath_ctx, ds, le->key, xpath) == 0))
status = 0; /* we got atleast one success */
le = le->next;
long rc;
char *ptr;
char *url;
- url = db->url;
db->buffer_fill = 0;
+
+ curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
+
status = curl_easy_perform(curl);
if (status != CURLE_OK) {
ERROR("curl_xml plugin: curl_easy_perform failed with status %i: %s (%s)",
- status, db->curl_errbuf, url);
+ status, db->curl_errbuf, db->url);
return -1;
}
if (db->stats != NULL)
status = cf_util_get_string(child, &xpath->instance_prefix);
else if (strcasecmp("InstanceFrom", child->key) == 0)
status = cf_util_get_string(child, &xpath->instance);
+ else if (strcasecmp("PluginInstanceFrom", child->key) == 0)
+ status = cf_util_get_string(child, &xpath->plugin_instance_from);
else if (strcasecmp("ValuesFrom", child->key) == 0)
status = cx_config_add_values("ValuesFrom", xpath, child);
else {
curl_easy_setopt(db->curl, CURLOPT_WRITEDATA, db);
curl_easy_setopt(db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt(db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
- curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
curl_easy_setopt(db->curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(db->curl, CURLOPT_MAXREDIRS, 50L);
if (strcasecmp("Instance", child->key) == 0)
status = cf_util_get_string(child, &db->instance);
+ else if (strcasecmp("PluginName", child->key) == 0)
+ status = cf_util_get_string(child, &db->plugin_name);
else if (strcasecmp("Host", child->key) == 0)
status = cf_util_get_string(child, &db->host);
else if (strcasecmp("User", child->key) == 0)