Move last_poll_data to inside ceph_daemon struct
authordaryder <daryder@cisco.com>
Wed, 7 Jan 2015 15:14:10 +0000 (10:14 -0500)
committerdaryder <daryder@cisco.com>
Wed, 7 Jan 2015 15:14:10 +0000 (10:14 -0500)
Also add backup search for last poll data

src/ceph.c

index e8bde9b..4f68e5b 100644 (file)
@@ -114,6 +114,14 @@ struct ceph_daemon
     uint32_t *ds_types;
     /** Track ds names to match with types */
     char **ds_names;
+    
+    /**
+     * Keep track of last data for latency values so we can calculate rate
+     * since last poll.
+     */
+    struct last_data **last_poll_data;
+    /** index of last poll data */
+    int last_idx;
 };
 
 /******* JSON parsing *******/
@@ -132,14 +140,6 @@ struct yajl_struct
 };
 typedef struct yajl_struct yajl_struct;
 
-/**
- * Keep track of last data for latency values so we can calculate rate
- * since last poll.
- */
-struct last_data **last_poll_data = NULL;
-/** index of last poll data */
-int last_idx = 0;
-
 enum perfcounter_type_d
 {
     PERFCOUNTER_LATENCY = 0x4, PERFCOUNTER_DERIVE = 0x8,
@@ -200,7 +200,6 @@ struct last_data
     uint64_t last_count;
 };
 
-
 /******* network I/O *******/
 enum cstate_t
 {
@@ -404,7 +403,14 @@ static void ceph_daemons_print(void)
 static void ceph_daemon_free(struct ceph_daemon *d)
 {
     int i = 0;
-    for(; i < d->ds_num; i++)
+    for(; i < d->last_idx; i++)
+    {
+        sfree(d->last_poll_data[i]);
+    }
+    sfree(d->last_poll_data);
+    d->last_poll_data = NULL;
+    d->last_idx = 0;
+    for(i = 0; i < d->ds_num; i++)
     {
         sfree(d->ds_names[i]);
     }
@@ -533,6 +539,7 @@ static int parse_keys(const char *key_str, char *ds_name)
         memcpy(tmp_ds_name, key_str, max_str_len - 1);
         goto compact;
     }
+    
     ds_name_len = (rptr - ptr) > max_str_len ? max_str_len : (rptr - ptr);
     if((ds_name_len == 0) || strncmp(rptr + 1, "type", 4))
     { /** copy whole key **/
@@ -700,6 +707,7 @@ static int cc_add_daemon_config(oconfig_item_t *ci)
                 "with '/' or './' Can't parse: '%s'\n", cd.name, cd.asok_path);
         return -EINVAL;
     }
+    
     array = realloc(g_daemons,
                     sizeof(struct ceph_daemon *) * (g_num_daemons + 1));
     if(array == NULL)
@@ -806,78 +814,112 @@ node_handler_define_schema(void *arg, const char *val, const char *key)
 /**
  * Latency counter does not yet have an entry in last poll data - add it.
  */
-static int add_last(const char *ds_n, double cur_sum, uint64_t cur_count)
+static int add_last(struct ceph_daemon *d, const char *ds_n, double cur_sum, 
+        uint64_t cur_count)
 {
-    last_poll_data[last_idx] = malloc(1 * sizeof(struct last_data));
-    if(!last_poll_data[last_idx])
+    d->last_poll_data[d->last_idx] = malloc(1 * sizeof(struct last_data));
+    if(!d->last_poll_data[d->last_idx])
     {
         return -ENOMEM;
     }
-    sstrncpy(last_poll_data[last_idx]->ds_name,ds_n,
-            sizeof(last_poll_data[last_idx]->ds_name));
-    last_poll_data[last_idx]->last_sum = cur_sum;
-    last_poll_data[last_idx]->last_count = cur_count;
-    last_idx++;
+    sstrncpy(d->last_poll_data[d->last_idx]->ds_name,ds_n,
+            sizeof(d->last_poll_data[d->last_idx]->ds_name));
+    d->last_poll_data[d->last_idx]->last_sum = cur_sum;
+    d->last_poll_data[d->last_idx]->last_count = cur_count;
+    d->last_idx = (d->last_idx + 1);
     return 0;
 }
 
 /**
  * Update latency counter or add new entry if it doesn't exist
  */
-static int update_last(const char *ds_n, int index, double cur_sum,
-        uint64_t cur_count)
+static int update_last(struct ceph_daemon *d, const char *ds_n, int index,
+        double cur_sum, uint64_t cur_count)
 {
-    if((last_idx > index) && (strcmp(last_poll_data[index]->ds_name, ds_n) == 0))
+    if((d->last_idx > index) && (strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0))
     {
-        last_poll_data[index]->last_sum = cur_sum;
-        last_poll_data[index]->last_count = cur_count;
+        d->last_poll_data[index]->last_sum = cur_sum;
+        d->last_poll_data[index]->last_count = cur_count;
         return 0;
     }
 
-    if(!last_poll_data)
+    if(!d->last_poll_data)
     {
-        last_poll_data = malloc(1 * sizeof(struct last_data *));
-        if(!last_poll_data)
+        d->last_poll_data = malloc(1 * sizeof(struct last_data *));
+        if(!d->last_poll_data)
         {
             return -ENOMEM;
         }
     }
     else
     {
-        struct last_data **tmp_last = realloc(last_poll_data,
-                ((last_idx+1) * sizeof(struct last_data *)));
+        struct last_data **tmp_last = realloc(d->last_poll_data,
+                ((d->last_idx+1) * sizeof(struct last_data *)));
         if(!tmp_last)
         {
             return -ENOMEM;
         }
-        last_poll_data = tmp_last;
+        d->last_poll_data = tmp_last;
     }
-    return add_last(ds_n, cur_sum, cur_count);
+    return add_last(d, ds_n, cur_sum, cur_count);
+}
+
+/**
+ * If using index guess failed (shouldn't happen, but possible if counters
+ * get rearranged), resort to searching for counter name
+ */
+static int backup_search_for_last_avg(struct ceph_daemon *d, const char *ds_n)
+{
+    int i = 0;
+    for(; i < d->last_idx; i++)
+    {
+        if(strcmp(d->last_poll_data[i]->ds_name, ds_n) == 0)
+        {
+            return i;
+        }
+    }
+    return -1;
 }
 
 /**
  * Calculate average b/t current data and last poll data
  * if last poll data exists
  */
-static double get_last_avg(const char *ds_n, int index,
+static double get_last_avg(struct ceph_daemon *d, const char *ds_n, int index,
         double cur_sum, uint64_t cur_count)
 {
     double result = -1.1, sum_delt = 0.0;
     uint64_t count_delt = 0;
-    if((last_idx > index) &&
-            (strcmp(last_poll_data[index]->ds_name, ds_n) == 0) &&
-            (cur_count > last_poll_data[index]->last_count))
+    int tmp_index = 0;
+    if(d->last_idx > index)
     {
-        sum_delt = (cur_sum - last_poll_data[index]->last_sum);
-        count_delt = (cur_count - last_poll_data[index]->last_count);
-        result = (sum_delt / count_delt);
+        if(strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0)
+        {
+            tmp_index = index;
+        }
+        //test previous index
+        else if((index > 0) && (strcmp(d->last_poll_data[index-1]->ds_name, ds_n) == 0))
+        {
+            tmp_index = (index - 1);
+        }
+        else
+        {
+            tmp_index = backup_search_for_last_avg(d, ds_n);
+        }
+
+        if((tmp_index > -1) && (cur_count > d->last_poll_data[tmp_index]->last_count))
+        {
+            sum_delt = (cur_sum - d->last_poll_data[tmp_index]->last_sum);
+            count_delt = (cur_count - d->last_poll_data[tmp_index]->last_count);
+            result = (sum_delt / count_delt);
+        }
     }
 
     if(result == -1.1)
     {
         result = NAN;
     }
-    if(update_last(ds_n, index, cur_sum, cur_count) == -ENOMEM)
+    if(update_last(d, ds_n, tmp_index, cur_sum, cur_count) == -ENOMEM)
     {
         return -ENOMEM;
     }
@@ -980,7 +1022,7 @@ static int node_handler_fetch_data(void *arg, const char *val, const char *key)
                 }
                 else
                 {
-                    result = get_last_avg(ds_name, vtmp->latency_index, sum, vtmp->avgcount);
+                    result = get_last_avg(vtmp->d, ds_name, vtmp->latency_index, sum, vtmp->avgcount);
                     if(result == -ENOMEM)
                     {
                         return -ENOMEM;
@@ -1147,6 +1189,10 @@ static int cconn_process_json(struct cconn *io)
             result = cconn_process_data(io, &io->yajl, hand);
             break;
         case ASOK_REQ_SCHEMA:
+            //init daemon specific variables
+            io->d->ds_num = 0;
+            io->d->last_idx = 0;
+            io->d->last_poll_data = NULL;
             io->yajl.handler = node_handler_define_schema;
             io->yajl.handler_arg = io->d;
             result = traverse_json(io->json, io->json_len, hand);
@@ -1196,7 +1242,6 @@ static int cconn_validate_revents(struct cconn *io, int revents)
         case CSTATE_READ_AMT:
         case CSTATE_READ_JSON:
             return (revents & POLLIN) ? 0 : -EINVAL;
-            return (revents & POLLIN) ? 0 : -EINVAL;
         default:
             ERROR("ceph plugin: cconn_validate_revents(name=%s) got to "
                 "illegal state on line %d", io->d->name, __LINE__);
@@ -1535,13 +1580,6 @@ static int ceph_shutdown(void)
     sfree(g_daemons);
     g_daemons = NULL;
     g_num_daemons = 0;
-    for(i = 0; i < last_idx; i++)
-    {
-        sfree(last_poll_data[i]);
-    }
-    sfree(last_poll_data);
-    last_poll_data = NULL;
-    last_idx = 0;
     DEBUG("ceph plugin: finished ceph_shutdown");
     return 0;
 }