redis plugin: fix issue found by master aggregation tests
[collectd.git] / src / redis.c
index 40a311d..5734098 100644 (file)
@@ -36,7 +36,7 @@
 #define REDIS_DEF_PASSWD ""
 #define REDIS_DEF_PORT 6379
 #define REDIS_DEF_TIMEOUT 2000
-#define REDIS_DEF_DB_COUNT 16
+#define REDIS_DEF_DB_COUNT 256
 #define MAX_REDIS_NODE_NAME 64
 #define MAX_REDIS_PASSWD_LENGTH 512
 #define MAX_REDIS_VAL_SIZE 256
@@ -60,6 +60,8 @@ struct redis_query_s {
   char query[MAX_REDIS_QUERY];
   char type[DATA_MAX_NAME_LEN];
   char instance[DATA_MAX_NAME_LEN];
+  int database;
+
   redis_query_t *next;
 };
 
@@ -76,7 +78,7 @@ struct redis_node_s {
   redis_node_t *next;
 };
 
-static redis_node_t *nodes_head = NULL;
+static redis_node_t *nodes_head;
 
 static int redis_node_add(const redis_node_t *rn) /* {{{ */
 {
@@ -90,13 +92,13 @@ static int redis_node_add(const redis_node_t *rn) /* {{{ */
 
   if (rn_ptr != NULL) {
     ERROR("redis plugin: A node with the name `%s' already exists.", rn->name);
-    return (-1);
+    return -1;
   }
 
   rn_copy = malloc(sizeof(*rn_copy));
   if (rn_copy == NULL) {
     ERROR("redis plugin: malloc failed adding redis_node to the tree.");
-    return (-1);
+    return -1;
   }
 
   memcpy(rn_copy, rn, sizeof(*rn_copy));
@@ -113,7 +115,7 @@ static int redis_node_add(const redis_node_t *rn) /* {{{ */
     rn_ptr->next = rn_copy;
   }
 
-  return (0);
+  return 0;
 } /* }}} */
 
 static redis_query_t *redis_config_query(oconfig_item_t *ci) /* {{{ */
@@ -137,6 +139,8 @@ static redis_query_t *redis_config_query(oconfig_item_t *ci) /* {{{ */
   (void)sstrncpy(rq->instance, rq->query, sizeof(rq->instance));
   replace_special(rq->instance, sizeof(rq->instance));
 
+  rq->database = 0;
+
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *option = ci->children + i;
 
@@ -145,6 +149,13 @@ static redis_query_t *redis_config_query(oconfig_item_t *ci) /* {{{ */
     } else if (strcasecmp("Instance", option->key) == 0) {
       status =
           cf_util_get_string_buffer(option, rq->instance, sizeof(rq->instance));
+    } else if (strcasecmp("Database", option->key) == 0) {
+      status = cf_util_get_int(option, &rq->database);
+      if (rq->database < 0) {
+        WARNING("redis plugin: The \"Database\" option must be positive "
+                "integer or zero");
+        status = -1;
+      }
     } else {
       WARNING("redis plugin: unknown configuration option: %s", option->key);
       status = -1;
@@ -171,7 +182,7 @@ static int redis_config_node(oconfig_item_t *ci) /* {{{ */
 
   status = cf_util_get_string_buffer(ci, rn.name, sizeof(rn.name));
   if (status != 0)
-    return (status);
+    return status;
 
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *option = ci->children + i;
@@ -208,9 +219,9 @@ static int redis_config_node(oconfig_item_t *ci) /* {{{ */
   }
 
   if (status != 0)
-    return (status);
+    return status;
 
-  return (redis_node_add(&rn));
+  return redis_node_add(&rn);
 } /* }}} int redis_config_node */
 
 static int redis_config(oconfig_item_t *ci) /* {{{ */
@@ -228,10 +239,10 @@ static int redis_config(oconfig_item_t *ci) /* {{{ */
 
   if (nodes_head == NULL) {
     ERROR("redis plugin: No valid node configuration could be found.");
-    return (ENOENT);
+    return ENOENT;
   }
 
-  return (0);
+  return 0;
 } /* }}} */
 
 __attribute__((nonnull(2))) static void
@@ -264,7 +275,7 @@ static int redis_init(void) /* {{{ */
   if (nodes_head == NULL)
     redis_node_add(&rn);
 
-  return (0);
+  return 0;
 } /* }}} int redis_init */
 
 static int redis_handle_info(char *node, char const *info_line,
@@ -285,13 +296,13 @@ static int redis_handle_info(char *node, char const *info_line,
 
     if (parse_value(buf, &val, ds_type) == -1) {
       WARNING("redis plugin: Unable to parse field `%s'.", field_name);
-      return (-1);
+      return -1;
     }
 
     redis_submit(node, type, type_instance, val);
-    return (0);
+    return 0;
   }
-  return (-1);
+  return -1;
 
 } /* }}} int redis_handle_info */
 
@@ -305,17 +316,23 @@ static int redis_handle_query(redisContext *rh, redis_node_t *rn,
   ds = plugin_get_ds(rq->type);
   if (!ds) {
     ERROR("redis plugin: DataSet `%s' not defined.", rq->type);
-    return (-1);
+    return -1;
   }
 
   if (ds->ds_num != 1) {
     ERROR("redis plugin: DS `%s' has too many types.", rq->type);
-    return (-1);
+    return -1;
+  }
+
+  if ((rr = redisCommand(rh, "SELECT %d", rq->database)) == NULL) {
+    WARNING("redis plugin: unable to switch to database `%d' on node `%s'.",
+            rq->database, rn->name);
+    return -1;
   }
 
   if ((rr = redisCommand(rh, rq->query)) == NULL) {
     WARNING("redis plugin: unable to carry out query `%s'.", rq->query);
-    return (-1);
+    return -1;
   }
 
   switch (rr->type) {
@@ -339,13 +356,13 @@ static int redis_handle_query(redisContext *rh, redis_node_t *rn,
     if (parse_value(rr->str, &val, ds->ds[0].type) == -1) {
       WARNING("redis plugin: Unable to parse field `%s'.", rq->type);
       freeReplyObject(rr);
-      return (-1);
+      return -1;
     }
     break;
   default:
     WARNING("redis plugin: Cannot coerce redis type.");
     freeReplyObject(rr);
-    return (-1);
+    return -1;
   }
 
   redis_submit(rn->name, rq->type,
@@ -364,13 +381,13 @@ static int redis_db_stats(char *node, char const *info_line) /* {{{ */
 
   for (int db = 0; db < REDIS_DEF_DB_COUNT; db++) {
     static char buf[MAX_REDIS_VAL_SIZE];
-    static char field_name[11];
-    static char db_id[3];
+    static char field_name[12];
+    static char db_id[4];
     value_t val;
     char *str;
     int i;
 
-    ssnprintf(field_name, sizeof(field_name), "db%d:keys=", db);
+    snprintf(field_name, sizeof(field_name), "db%d:keys=", db);
 
     str = strstr(info_line, field_name);
     if (!str)
@@ -383,13 +400,13 @@ static int redis_db_stats(char *node, char const *info_line) /* {{{ */
 
     if (parse_value(buf, &val, DS_TYPE_GAUGE) != 0) {
       WARNING("redis plugin: Unable to parse field `%s'.", field_name);
-      return (-1);
+      return -1;
     }
 
-    ssnprintf(db_id, sizeof(db_id), "%d", db);
+    snprintf(db_id, sizeof(db_id), "%d", db);
     redis_submit(node, "records", db_id, val);
   }
-  return (0);
+  return 0;
 
 } /* }}} int redis_db_stats */