X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fceph.c;h=04a397434d1b7c228fc5a885a424ebbb9101c230;hb=43aca8ed8b22a7a5a14f8c740948d6ce06efbc95;hp=5b83adc798c3d58cd37f92ed75d9c09c77440f79;hpb=380959068f87619143e98c52399847eb761fb222;p=collectd.git diff --git a/src/ceph.c b/src/ceph.c index 5b83adc7..04a39743 100644 --- a/src/ceph.c +++ b/src/ceph.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -97,7 +96,7 @@ enum ceph_dset_type_d }; /** Valid types for ceph defined in types.db */ -const char * ceph_dset_types [CEPH_DSET_TYPES_NUM] = +static const char * const ceph_dset_types [CEPH_DSET_TYPES_NUM] = {"ceph_latency", "ceph_bytes", "ceph_rate"}; /******* ceph_daemon *******/ @@ -135,11 +134,10 @@ struct yajl_struct { node_handler_t handler; void * handler_arg; - struct { - char key[DATA_MAX_NAME_LEN]; - int key_len; - } state[YAJL_MAX_DEPTH]; - int depth; + + char *key; + char *stack[YAJL_MAX_DEPTH]; + size_t depth; }; typedef struct yajl_struct yajl_struct; @@ -267,69 +265,72 @@ static int ceph_cb_boolean(void *ctx, int bool_val) static int ceph_cb_number(void *ctx, const char *number_val, yajl_len_t number_len) { - yajl_struct *yajl = (yajl_struct*)ctx; + yajl_struct *state = (yajl_struct*) ctx; char buffer[number_len+1]; - int i, status; char key[2 * DATA_MAX_NAME_LEN]; _Bool latency_type = 0; + size_t i; + int status; memcpy(buffer, number_val, number_len); buffer[sizeof(buffer) - 1] = 0; - sstrncpy (key, yajl->state[0].key, sizeof (key)); - for (i = 1; i < yajl->depth; i++) + memset (key, 0, sizeof (key)); + for (i = 0; i < state->depth; i++) { - /* Special case for latency metrics. */ - if ((i == yajl->depth-1) - && ((strcmp(yajl->state[i].key,"avgcount") == 0) - || (strcmp(yajl->state[i].key,"sum") == 0))) - { - /* Super-special case for filestore:JournalWrBytes. For some - * reason, Ceph schema encodes this as a count/sum pair while all - * other "Bytes" data (excluding used/capacity bytes for OSD space) - * uses a single "Derive" type. To spare further confusion, keep - * this KPI as the same type of other "Bytes". Instead of keeping - * an "average" or "rate", use the "sum" in the pair and assign - * that to the derive value. */ - if (convert_special_metrics && (i >= 2) - && (strcmp("filestore", yajl->state[i-2].key) == 0) - && (strcmp("journal_wr_bytes", yajl->state[i-1].key) == 0) - && (strcmp("avgcount", yajl->state[i].key) == 0)) - { - DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes"); - yajl->depth -= 1; - return CEPH_CB_CONTINUE; - } + if (state->stack[i] == NULL) + continue; - /* Don't add "avgcount" or "sum" to the key just yet. If the - * handler function signals RETRY_AVGCOUNT, we'll add it and try - * again. */ - latency_type = 1; - break; - } + if (strlen (key) != 0) + BUFFER_ADD (key, "."); + BUFFER_ADD (key, state->stack[i]); + } + + /* Special case for latency metrics. */ + if ((strcmp ("avgcount", state->key) == 0) + || (strcmp ("sum", state->key) == 0)) + { + latency_type = 1; + /* Super-special case for filestore.journal_wr_bytes.avgcount: For + * some reason, Ceph schema encodes this as a count/sum pair while all + * other "Bytes" data (excluding used/capacity bytes for OSD space) uses + * a single "Derive" type. To spare further confusion, keep this KPI as + * the same type of other "Bytes". Instead of keeping an "average" or + * "rate", use the "sum" in the pair and assign that to the derive + * value. */ + if (convert_special_metrics && (state->depth >= 2) + && (strcmp("filestore", state->stack[state->depth - 2]) == 0) + && (strcmp("journal_wr_bytes", state->stack[state->depth - 1]) == 0) + && (strcmp("avgcount", state->key) == 0)) + { + DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes"); + return CEPH_CB_CONTINUE; + } + } + else /* not a latency type */ + { BUFFER_ADD (key, "."); - BUFFER_ADD (key, yajl->state[i].key); + BUFFER_ADD (key, state->key); } - status = yajl->handler(yajl->handler_arg, buffer, key); + status = state->handler(state->handler_arg, buffer, key); if((status == RETRY_AVGCOUNT) && latency_type) { /* Add previously skipped part of the key, either "avgcount" or "sum", * and try again. */ BUFFER_ADD (key, "."); - BUFFER_ADD (key, yajl->state[yajl->depth-1].key); + BUFFER_ADD (key, state->key); - status = yajl->handler(yajl->handler_arg, buffer, key); + status = state->handler(state->handler_arg, buffer, key); } - if(status == -ENOMEM) + if (status != 0) { - ERROR("ceph plugin: memory allocation failed"); + ERROR("ceph plugin: JSON handler failed with status %d.", status); return CEPH_CB_ABORT; } - yajl->depth -= 1; return CEPH_CB_CONTINUE; } @@ -341,37 +342,52 @@ static int ceph_cb_string(void *ctx, const unsigned char *string_val, static int ceph_cb_start_map(void *ctx) { + yajl_struct *state = (yajl_struct*) ctx; + + /* Push key to the stack */ + if (state->depth == YAJL_MAX_DEPTH) + return CEPH_CB_ABORT; + + state->stack[state->depth] = state->key; + state->depth++; + state->key = NULL; + return CEPH_CB_CONTINUE; } -static int -ceph_cb_map_key(void *ctx, const unsigned char *key, yajl_len_t string_len) +static int ceph_cb_end_map(void *ctx) { - yajl_struct *yajl = (yajl_struct*)ctx; + yajl_struct *state = (yajl_struct*) ctx; - if((yajl->depth+1) >= YAJL_MAX_DEPTH) - { - ERROR("ceph plugin: depth exceeds max, aborting."); + /* Pop key from the stack */ + if (state->depth == 0) return CEPH_CB_ABORT; - } - char buffer[string_len+1]; - - memcpy(buffer, key, string_len); - buffer[sizeof(buffer) - 1] = 0; - - snprintf(yajl->state[yajl->depth].key, sizeof(buffer), "%s", buffer); - yajl->state[yajl->depth].key_len = sizeof(buffer); - yajl->depth = (yajl->depth + 1); + sfree (state->key); + state->depth--; + state->key = state->stack[state->depth]; + state->stack[state->depth] = NULL; return CEPH_CB_CONTINUE; } -static int ceph_cb_end_map(void *ctx) +static int +ceph_cb_map_key(void *ctx, const unsigned char *key, yajl_len_t string_len) { - yajl_struct *yajl = (yajl_struct*)ctx; + yajl_struct *state = (yajl_struct*) ctx; + size_t sz = ((size_t) string_len) + 1; + + sfree (state->key); + state->key = malloc (sz); + if (state->key == NULL) + { + ERROR ("ceph plugin: malloc failed."); + return CEPH_CB_ABORT; + } + + memmove (state->key, key, sz - 1); + state->key[sz - 1] = 0; - yajl->depth = (yajl->depth - 1); return CEPH_CB_CONTINUE; } @@ -607,7 +623,7 @@ static int ceph_daemon_add_ds_entry(struct ceph_daemon *d, const char *name, return -ENOMEM; } - d->ds_names[d->ds_num] = malloc(sizeof(char) * DATA_MAX_NAME_LEN); + d->ds_names[d->ds_num] = malloc(DATA_MAX_NAME_LEN); if(!d->ds_names[d->ds_num]) { return -ENOMEM; @@ -731,7 +747,7 @@ static int cc_add_daemon_config(oconfig_item_t *ci) } g_daemons = tmp; - nd = malloc(sizeof(*nd)); + nd = malloc(sizeof (*nd)); if(!nd) { return ENOMEM; @@ -829,7 +845,7 @@ node_handler_define_schema(void *arg, const char *val, const char *key) static int add_last(struct ceph_daemon *d, const char *ds_n, double cur_sum, uint64_t cur_count) { - d->last_poll_data[d->last_idx] = malloc(1 * sizeof(struct last_data)); + d->last_poll_data[d->last_idx] = malloc(sizeof (*d->last_poll_data[d->last_idx])); if(!d->last_poll_data[d->last_idx]) { return -ENOMEM; @@ -857,7 +873,7 @@ static int update_last(struct ceph_daemon *d, const char *ds_n, int index, if(!d->last_poll_data) { - d->last_poll_data = malloc(1 * sizeof(struct last_data *)); + d->last_poll_data = malloc(sizeof (*d->last_poll_data)); if(!d->last_poll_data) { return -ENOMEM; @@ -1080,7 +1096,7 @@ static int cconn_connect(struct cconn *io) fd = socket(PF_UNIX, SOCK_STREAM, 0); if(fd < 0) { - int err = -errno; + err = -errno; ERROR("ceph plugin: cconn_connect: socket(PF_UNIX, SOCK_STREAM, 0) " "failed: error %d", err); return err; @@ -1529,7 +1545,7 @@ static int cconn_main_loop(uint32_t request_type) } else { - int ret = cconn_handle_event(io); + ret = cconn_handle_event(io); if(ret) { WARNING("ceph plugin: cconn_handle_event(name=%s,"