X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fcore%2Fmemstore.c;h=87f9512745446d0f079ca6792fb12ce40168b1ca;hb=b2d31bc42a7694c671186081ee0cac077a188b99;hp=15c4202829159eee3665b74f7d1654b010d8b602;hpb=637fd9289e84a2eb394d01c4769cbd5276c2b905;p=sysdb.git diff --git a/src/core/memstore.c b/src/core/memstore.c index 15c4202..87f9512 100644 --- a/src/core/memstore.c +++ b/src/core/memstore.c @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -65,10 +66,11 @@ typedef struct { int type; const char *name; sdb_time_t last_update; + sdb_time_t interval; const char * const *backends; size_t backends_num; } store_obj_t; -#define STORE_OBJ_INIT { NULL, NULL, 0, NULL, 0, NULL, 0 } +#define STORE_OBJ_INIT { NULL, NULL, 0, NULL, 0, 0, NULL, 0 } static sdb_type_t host_type; static sdb_type_t service_type; @@ -109,14 +111,7 @@ static int store_obj_init(sdb_object_t *obj, va_list ap) { sdb_memstore_obj_t *sobj = STORE_OBJ(obj); - sobj->type = va_arg(ap, int); - - sobj->last_update = va_arg(ap, sdb_time_t); - sobj->interval = 0; - sobj->backends = NULL; - sobj->backends_num = 0; - sobj->parent = NULL; return 0; } /* store_obj_init */ @@ -221,7 +216,8 @@ metric_init(sdb_object_t *obj, va_list ap) if (! sobj->attributes) return -1; - sobj->store.type = sobj->store.id = NULL; + sobj->stores = NULL; + sobj->stores_num = 0; return 0; } /* metric_init */ @@ -229,17 +225,24 @@ static void metric_destroy(sdb_object_t *obj) { metric_t *sobj = METRIC(obj); - assert(obj); + size_t i; + assert(obj); store_obj_destroy(obj); if (sobj->attributes) sdb_avltree_destroy(sobj->attributes); - if (sobj->store.type) - free(sobj->store.type); - if (sobj->store.id) - free(sobj->store.id); + for (i = 0; i < sobj->stores_num; ++i) { + if (sobj->stores[i].type) + free(sobj->stores[i].type); + if (sobj->stores[i].id) + free(sobj->stores[i].id); + } + if (sobj->stores) + free(sobj->stores); + sobj->stores = NULL; + sobj->stores_num = 0; } /* metric_destroy */ static int @@ -248,8 +251,7 @@ attr_init(sdb_object_t *obj, va_list ap) const sdb_data_t *value; int ret; - /* this will consume the first two arguments - * (type and last_update) of ap */ + /* this will consume the first argument (type) of ap */ ret = store_obj_init(obj, ap); if (ret) return ret; @@ -347,37 +349,8 @@ store_obj(store_obj_t *obj, sdb_memstore_obj_t **updated_obj) assert(obj->parent_tree); - if (obj->last_update <= 0) - obj->last_update = sdb_gettime(); - old = STORE_OBJ(sdb_avltree_lookup(obj->parent_tree, obj->name)); if (old) { - if (old->last_update > obj->last_update) { - sdb_log(SDB_LOG_DEBUG, "memstore: Cannot update %s '%s' - " - "value too old (%"PRIsdbTIME" < %"PRIsdbTIME")", - SDB_STORE_TYPE_TO_NAME(obj->type), obj->name, - obj->last_update, old->last_update); - /* don't report an error; the object may be updated by multiple - * backends */ - status = 1; - } - else if (old->last_update == obj->last_update) { - /* don't report an error and also don't even log this to avoid - * excessive noise on high sampling frequencies */ - status = 1; - } - else { - sdb_time_t interval = obj->last_update - old->last_update; - old->last_update = obj->last_update; - if (interval) { - if (old->interval) - old->interval = (sdb_time_t)((0.9 * (double)old->interval) - + (0.1 * (double)interval)); - else - old->interval = interval; - } - } - new = old; sdb_object_deref(SDB_OBJ(old)); } @@ -385,7 +358,7 @@ store_obj(store_obj_t *obj, sdb_memstore_obj_t **updated_obj) if (obj->type == SDB_ATTRIBUTE) { /* the value will be updated by the caller */ new = STORE_OBJ(sdb_object_create(obj->name, attribute_type, - obj->type, obj->last_update, NULL)); + obj->type, NULL)); } else { sdb_type_t t; @@ -394,8 +367,7 @@ store_obj(store_obj_t *obj, sdb_memstore_obj_t **updated_obj) : obj->type == SDB_SERVICE ? service_type : metric_type; - new = STORE_OBJ(sdb_object_create(obj->name, t, - obj->type, obj->last_update)); + new = STORE_OBJ(sdb_object_create(obj->name, t, obj->type)); } if (new) { @@ -417,6 +389,9 @@ store_obj(store_obj_t *obj, sdb_memstore_obj_t **updated_obj) return status; assert(new); + new->last_update = obj->last_update; + new->interval = obj->interval; + if (new->parent != obj->parent) { // Avoid circular self-references which are not handled // correctly by the ref-count based management layer. @@ -434,35 +409,82 @@ store_obj(store_obj_t *obj, sdb_memstore_obj_t **updated_obj) } /* store_obj */ static int -store_metric_store(metric_t *metric, sdb_store_metric_t *m) +store_metric_update_store(metric_store_t *store, + const sdb_metric_store_t __attribute__((unused)) *s, + sdb_time_t last_update) { - char *type = metric->store.type; - char *id = metric->store.id; + if (last_update <= store->last_update) + return 0; + store->last_update = last_update; + return 0; +} /* store_metric_update_store */ - if ((! metric->store.type) || strcasecmp(metric->store.type, m->store.type)) { - if (! (type = strdup(m->store.type))) - return -1; - } - if ((! metric->store.id) || strcasecmp(metric->store.id, m->store.id)) { - if (! (id = strdup(m->store.id))) { - if (type != metric->store.type) - free(type); - return -1; - } +static int +store_metric_add_store(metric_t *metric, const sdb_metric_store_t *s, + sdb_time_t last_update) +{ + char *type = strdup(s->type); + char *id = strdup(s->id); + + metric_store_t *new; + + if ((! type) || (! id)) { + if (type) + free(type); + if (id) + free(id); + return -1; } - if (type != metric->store.type) { - if (metric->store.type) - free(metric->store.type); - metric->store.type = type; + new = realloc(metric->stores, + (metric->stores_num + 1) * sizeof(*metric->stores)); + if (! new) { + free(type); + free(id); + return -1; } - if (id != metric->store.id) { - if (metric->store.id) - free(metric->store.id); - metric->store.id = id; + + metric->stores = new; + new = metric->stores + metric->stores_num; + metric->stores_num++; + + new->type = type; + new->id = id; + new->last_update = last_update; + return 0; +} /* store_metric_add_store */ + +static int +store_metric_stores(metric_t *metric, sdb_store_metric_t *m) +{ + size_t i; + + if (! m->stores_num) + return 0; + + for (i = 0; i < m->stores_num; ++i) { + sdb_time_t last_update = m->stores[i].last_update; + size_t j; + + if (last_update < m->last_update) + last_update = m->last_update; + + for (j = 0; j < metric->stores_num; ++j) { + if ((! strcasecmp(metric->stores[j].type, m->stores[i].type)) + && (! strcasecmp(metric->stores[j].id, m->stores[i].id))) { + if (store_metric_update_store(metric->stores + j, + m->stores + i, last_update) < 0) + return -1; + break; + } + } + + if (j >= metric->stores_num) + if (store_metric_add_store(metric, m->stores + i, last_update) < 0) + return -1; } return 0; -} /* store_metric_store */ +} /* store_metric_stores */ /* The store's host_lock has to be acquired before calling this function. */ static sdb_avltree_t * @@ -560,6 +582,7 @@ store_attribute(sdb_store_attribute_t *attr, sdb_object_t *user_data) obj.type = SDB_ATTRIBUTE; obj.name = attr->key; obj.last_update = attr->last_update; + obj.interval = attr->interval; obj.backends = attr->backends; obj.backends_num = attr->backends_num; if (! status) @@ -585,7 +608,7 @@ static int store_host(sdb_store_host_t *host, sdb_object_t *user_data) { sdb_memstore_t *st = SDB_MEMSTORE(user_data); - store_obj_t obj = { NULL, st->hosts, SDB_HOST, NULL, 0, NULL, 0 }; + store_obj_t obj = { NULL, st->hosts, SDB_HOST, NULL, 0, 0, NULL, 0 }; int status = 0; if ((! host) || (! host->name)) @@ -593,6 +616,7 @@ store_host(sdb_store_host_t *host, sdb_object_t *user_data) obj.name = host->name; obj.last_update = host->last_update; + obj.interval = host->interval; obj.backends = host->backends; obj.backends_num = host->backends_num; pthread_rwlock_wrlock(&st->host_lock); @@ -627,6 +651,7 @@ store_service(sdb_store_service_t *service, sdb_object_t *user_data) obj.name = service->name; obj.last_update = service->last_update; + obj.interval = service->interval; obj.backends = service->backends; obj.backends_num = service->backends_num; if (! status) @@ -646,12 +671,14 @@ store_metric(sdb_store_metric_t *metric, sdb_object_t *user_data) host_t *host; int status = 0; + size_t i; if ((! metric) || (! metric->hostname) || (! metric->name)) return -1; - if ((metric->store.type != NULL) != (metric->store.id != NULL)) - return -1; + for (i = 0; i < metric->stores_num; ++i) + if ((metric->stores[i].type == NULL) || (metric->stores[i].id == NULL)) + return -1; pthread_rwlock_wrlock(&st->host_lock); host = HOST(sdb_avltree_lookup(st->hosts, metric->hostname)); @@ -666,6 +693,7 @@ store_metric(sdb_store_metric_t *metric, sdb_object_t *user_data) obj.name = metric->name; obj.last_update = metric->last_update; + obj.interval = metric->interval; obj.backends = metric->backends; obj.backends_num = metric->backends_num; if (! status) @@ -678,9 +706,8 @@ store_metric(sdb_store_metric_t *metric, sdb_object_t *user_data) } assert(new); - if (metric->store.type && metric->store.id) - if (store_metric_store(METRIC(new), metric)) - status = -1; + if (store_metric_stores(METRIC(new), metric)) + status = -1; pthread_rwlock_unlock(&st->host_lock); return status; } /* store_metric */ @@ -725,44 +752,53 @@ sdb_memstore_create(void) } /* sdb_memstore_create */ int -sdb_memstore_host(sdb_memstore_t *store, const char *name, sdb_time_t last_update) +sdb_memstore_host(sdb_memstore_t *store, const char *name, + sdb_time_t last_update, sdb_time_t interval) { sdb_store_host_t host = { - name, last_update, 0, NULL, 0, + name, last_update, interval, NULL, 0, }; return store_host(&host, SDB_OBJ(store)); } /* sdb_memstore_host */ int sdb_memstore_service(sdb_memstore_t *store, const char *hostname, const char *name, - sdb_time_t last_update) + sdb_time_t last_update, sdb_time_t interval) { sdb_store_service_t service = { - hostname, name, last_update, 0, NULL, 0, + hostname, name, last_update, interval, NULL, 0, }; return store_service(&service, SDB_OBJ(store)); } /* sdb_memstore_service */ int sdb_memstore_metric(sdb_memstore_t *store, const char *hostname, const char *name, - sdb_metric_store_t *metric_store, sdb_time_t last_update) + sdb_metric_store_t *metric_store, + sdb_time_t last_update, sdb_time_t interval) { sdb_store_metric_t metric = { - hostname, name, { NULL, NULL }, last_update, 0, NULL, 0, + hostname, name, /* stores */ NULL, 0, + last_update, interval, NULL, 0, }; if (metric_store) { - metric.store.type = metric_store->type; - metric.store.id = metric_store->id; + metric.stores = &(const sdb_metric_store_t){ + metric_store->type, + metric_store->id, + metric_store->last_update, + }; + metric.stores_num = 1; } return store_metric(&metric, SDB_OBJ(store)); } /* sdb_memstore_metric */ int sdb_memstore_attribute(sdb_memstore_t *store, const char *hostname, - const char *key, const sdb_data_t *value, sdb_time_t last_update) + const char *key, const sdb_data_t *value, + sdb_time_t last_update, sdb_time_t interval) { sdb_store_attribute_t attr = { - NULL, SDB_HOST, hostname, key, SDB_DATA_INIT, last_update, 0, NULL, 0, + NULL, SDB_HOST, hostname, key, SDB_DATA_INIT, + last_update, interval, NULL, 0, }; if (value) { attr.value = *value; @@ -773,10 +809,11 @@ sdb_memstore_attribute(sdb_memstore_t *store, const char *hostname, int sdb_memstore_service_attr(sdb_memstore_t *store, const char *hostname, const char *service, const char *key, const sdb_data_t *value, - sdb_time_t last_update) + sdb_time_t last_update, sdb_time_t interval) { sdb_store_attribute_t attr = { - hostname, SDB_SERVICE, service, key, SDB_DATA_INIT, last_update, 0, NULL, 0, + hostname, SDB_SERVICE, service, key, SDB_DATA_INIT, + last_update, interval, NULL, 0, }; if (value) { attr.value = *value; @@ -787,10 +824,11 @@ sdb_memstore_service_attr(sdb_memstore_t *store, const char *hostname, int sdb_memstore_metric_attr(sdb_memstore_t *store, const char *hostname, const char *metric, const char *key, const sdb_data_t *value, - sdb_time_t last_update) + sdb_time_t last_update, sdb_time_t interval) { sdb_store_attribute_t attr = { - hostname, SDB_METRIC, metric, key, SDB_DATA_INIT, last_update, 0, NULL, 0, + hostname, SDB_METRIC, metric, key, SDB_DATA_INIT, + last_update, interval, NULL, 0, }; if (value) { attr.value = *value; @@ -874,7 +912,7 @@ sdb_memstore_get_field(sdb_memstore_obj_t *obj, int field, sdb_data_t *res) if (obj->type != SDB_METRIC) return -1; tmp.type = SDB_TYPE_BOOLEAN; - tmp.data.boolean = METRIC(obj)->store.type != NULL; + tmp.data.boolean = METRIC(obj)->stores_num > 0; default: return -1; } @@ -1016,18 +1054,25 @@ sdb_memstore_emit(sdb_memstore_obj_t *obj, sdb_store_writer_t *w, sdb_object_t * } case SDB_METRIC: { + sdb_metric_store_t metric_stores[METRIC(obj)->stores_num]; sdb_store_metric_t metric = { obj->parent ? obj->parent->_name : NULL, obj->_name, - { - METRIC(obj)->store.type, - METRIC(obj)->store.id, - }, + metric_stores, + METRIC(obj)->stores_num, obj->last_update, obj->interval, (const char * const *)obj->backends, obj->backends_num, }; + size_t i; + + for (i = 0; i < METRIC(obj)->stores_num; ++i) { + metric_stores[i].type = METRIC(obj)->stores[i].type; + metric_stores[i].id = METRIC(obj)->stores[i].id; + metric_stores[i].last_update = METRIC(obj)->stores[i].last_update; + } + if (! w->store_metric) return -1; return w->store_metric(&metric, wd);