diff options
author | Stelios Fragkakis <52996999+stelfrag@users.noreply.github.com> | 2020-09-24 13:05:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-24 13:05:15 +0300 |
commit | 80676423617d2587632eb69c9ea5a0ef0cb49d0c (patch) | |
tree | 960b8a1b7583801e13887d21ed456f46cbb851bd /web | |
parent | b2ac03cf4bf6bf19783ff726585dc5b62bb55520 (diff) |
Improved the data query when using the context parameter (#9978)
Diffstat (limited to 'web')
-rw-r--r-- | web/api/formatters/rrd2json.c | 97 | ||||
-rw-r--r-- | web/api/formatters/rrd2json.h | 11 | ||||
-rw-r--r-- | web/api/queries/query.c | 36 | ||||
-rw-r--r-- | web/api/queries/rrdr.c | 3 | ||||
-rw-r--r-- | web/api/queries/rrdr.h | 7 | ||||
-rw-r--r-- | web/api/web_api_v1.c | 41 |
6 files changed, 116 insertions, 79 deletions
diff --git a/web/api/formatters/rrd2json.c b/web/api/formatters/rrd2json.c index 00fe0c9480..7bb7544cfe 100644 --- a/web/api/formatters/rrd2json.c +++ b/web/api/formatters/rrd2json.c @@ -22,6 +22,57 @@ static inline void free_temp_rrddim(RRDDIM *temp_rd) } } +void free_context_param_list(struct context_param **param_list) +{ + if (unlikely(!param_list || !*param_list)) + return; + + free_temp_rrddim(((*param_list)->rd)); + freez((*param_list)); + *param_list = NULL; +} + +void build_context_param_list(struct context_param **param_list, RRDSET *st) +{ + if (unlikely(!param_list || !st)) + return; + + if (unlikely(!(*param_list))) { + *param_list = mallocz(sizeof(struct context_param)); + (*param_list)->first_entry_t = LONG_MAX; + (*param_list)->last_entry_t = 0; + (*param_list)->rd = NULL; + } + + RRDDIM *rd1; + rrdset_rdlock(st); + + st->last_accessed_time = now_realtime_sec(); + (*param_list)->first_entry_t = MIN((*param_list)->first_entry_t, rrdset_first_entry_t(st)); + (*param_list)->last_entry_t = MAX((*param_list)->last_entry_t, rrdset_last_entry_t(st)); + + rrddim_foreach_read(rd1, st) { + RRDDIM *rd = mallocz(rd1->memsize); + memcpy(rd, rd1, rd1->memsize); + rd->id = strdupz(rd1->id); + rd->name = strdupz(rd1->name); + rd->state = mallocz(sizeof(*rd->state)); + memcpy(rd->state, rd1->state, sizeof(*rd->state)); + memcpy(&rd->state->collect_ops, &rd1->state->collect_ops, sizeof(struct rrddim_collect_ops)); + memcpy(&rd->state->query_ops, &rd1->state->query_ops, sizeof(struct rrddim_query_ops)); +#ifdef ENABLE_DBENGINE + if (rd->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) { + rd->state->metric_uuid = mallocz(sizeof(uuid_t)); + uuid_copy(*rd->state->metric_uuid, *rd1->state->metric_uuid); + } +#endif + rd->next = (*param_list)->rd; + (*param_list)->rd = rd; + } + + rrdset_unlock(st); +} + void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb) { rrdset2json(st, wb, NULL, NULL, 0); } @@ -89,9 +140,8 @@ int rrdset2value_api_v1( , time_t *db_before , int *value_is_null ) { - RRDDIM *temp_rd = NULL; - RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions, temp_rd); + RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions, NULL); if(!r) { if(value_is_null) *value_is_null = 1; @@ -121,8 +171,6 @@ int rrdset2value_api_v1( long i = (!(options & RRDR_OPTION_REVERSED))?rrdr_rows(r) - 1:0; *n = rrdr2value(r, i, options, value_is_null); - free_temp_rrddim(temp_rd); - rrdr_free(r); return HTTP_RESP_OK; } @@ -139,47 +187,14 @@ int rrdset2anything_api_v1( , long group_time , uint32_t options , time_t *latest_timestamp - , char *context + , struct context_param *context_param_list ) { time_t last_accessed_time = now_realtime_sec(); st->last_accessed_time = last_accessed_time; - RRDDIM *temp_rd = NULL; - - if (context) { - rrdhost_rdlock(st->rrdhost); - RRDSET *st1; - rrdset_foreach_read(st1, st->rrdhost) { - if (strcmp(st1->context, context) == 0) { - // Loop the dimensions of the chart - RRDDIM *rd1; - rrdset_rdlock(st1); - st1->last_accessed_time = last_accessed_time; - rrddim_foreach_read(rd1, st1) { - RRDDIM *rd = mallocz(rd1->memsize); - memcpy(rd, rd1, rd1->memsize); - rd->id = strdupz(rd1->id); - rd->name = strdupz(rd1->name); - rd->state = mallocz(sizeof(*rd->state)); - memcpy(rd->state, rd1->state, sizeof(*rd->state)); - memcpy(&rd->state->collect_ops, &rd1->state->collect_ops, sizeof(struct rrddim_collect_ops)); - memcpy(&rd->state->query_ops, &rd1->state->query_ops, sizeof(struct rrddim_query_ops)); -#ifdef ENABLE_DBENGINE - if (rd->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) { - rd->state->metric_uuid = mallocz(sizeof(uuid_t)); - uuid_copy(*rd->state->metric_uuid, *rd1->state->metric_uuid); - } -#endif - rd->next = temp_rd; - temp_rd = rd; - } - rrdset_unlock(st1); - } - } - rrdhost_unlock(st->rrdhost); - } + RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL; - RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions?buffer_tostring(dimensions):NULL, temp_rd); + RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions?buffer_tostring(dimensions):NULL, context_param_list); if(!r) { buffer_strcat(wb, "Cannot generate output with these parameters on this chart."); return HTTP_RESP_INTERNAL_SERVER_ERROR; @@ -355,8 +370,6 @@ int rrdset2anything_api_v1( break; } - free_temp_rrddim(temp_rd); - rrdr_free(r); return HTTP_RESP_OK; } diff --git a/web/api/formatters/rrd2json.h b/web/api/formatters/rrd2json.h index f235113480..eb0b5e6045 100644 --- a/web/api/formatters/rrd2json.h +++ b/web/api/formatters/rrd2json.h @@ -53,6 +53,12 @@ extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb); extern void rrdr_buffer_print_format(BUFFER *wb, uint32_t format); +typedef struct context_param { + RRDDIM *rd; + time_t first_entry_t; + time_t last_entry_t; +} CONTEXT_PARAM; + extern int rrdset2anything_api_v1( RRDSET *st , BUFFER *wb @@ -65,7 +71,7 @@ extern int rrdset2anything_api_v1( , long group_time , uint32_t options , time_t *latest_timestamp - , char *context + , struct context_param *context_param_list ); extern int rrdset2value_api_v1( @@ -84,4 +90,7 @@ extern int rrdset2value_api_v1( , int *value_is_null ); +extern void build_context_param_list(struct context_param **param_list, RRDSET *st); +extern void free_context_param_list(struct context_param **param_list); + #endif /* NETDATA_RRD2JSON_H */ diff --git a/web/api/queries/query.c b/web/api/queries/query.c index 6b46cc6bd2..73779a6134 100644 --- a/web/api/queries/query.c +++ b/web/api/queries/query.c @@ -815,8 +815,8 @@ static RRDR *rrd2rrdr_fixedstep( , int update_every , time_t first_entry_t , time_t last_entry_t - , int absolute_period_requested, - RRDDIM *temp_rd + , int absolute_period_requested + , struct context_param *context_param_list ) { int aligned = !(options & RRDR_OPTION_NOT_ALIGNED); @@ -824,8 +824,10 @@ static RRDR *rrd2rrdr_fixedstep( time_t duration = before_requested - after_requested; long available_points = duration / update_every; + RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL; + if(duration <= 0 || available_points <= 0) - return rrdr_create(st, 1, temp_rd); + return rrdr_create(st, 1, context_param_list); // check the number of wanted points in the result if(unlikely(points_requested < 0)) points_requested = -points_requested; @@ -983,7 +985,7 @@ static RRDR *rrd2rrdr_fixedstep( // initialize our result set // this also locks the chart for us - RRDR *r = rrdr_create(st, points_wanted, temp_rd); + RRDR *r = rrdr_create(st, points_wanted, context_param_list); if(unlikely(!r)) { #ifdef NETDATA_INTERNAL_CHECKS error("INTERNAL CHECK: Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after_wanted, (uint32_t)before_wanted, (uint32_t)duration, points_wanted); @@ -1185,7 +1187,7 @@ static RRDR *rrd2rrdr_variablestep( , time_t last_entry_t , int absolute_period_requested , struct rrdeng_region_info *region_info_array - , RRDDIM *temp_rd + , struct context_param *context_param_list ) { int aligned = !(options & RRDR_OPTION_NOT_ALIGNED); @@ -1193,9 +1195,11 @@ static RRDR *rrd2rrdr_variablestep( time_t duration = before_requested - after_requested; long available_points = duration / update_every; + RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL; + if(duration <= 0 || available_points <= 0) { freez(region_info_array); - return rrdr_create(st, 1, temp_rd); + return rrdr_create(st, 1, context_param_list); } // check the number of wanted points in the result @@ -1354,7 +1358,7 @@ static RRDR *rrd2rrdr_variablestep( // initialize our result set // this also locks the chart for us - RRDR *r = rrdr_create(st, points_wanted, temp_rd); + RRDR *r = rrdr_create(st, points_wanted, context_param_list); if(unlikely(!r)) { #ifdef NETDATA_INTERNAL_CHECKS error("INTERNAL CHECK: Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after_wanted, (uint32_t)before_wanted, (uint32_t)duration, points_wanted); @@ -1556,17 +1560,19 @@ RRDR *rrd2rrdr( , long resampling_time_requested , RRDR_OPTIONS options , const char *dimensions - , RRDDIM *temp_rd + , struct context_param *context_param_list ) { int rrd_update_every; int absolute_period_requested; +// RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL; + time_t first_entry_t; time_t last_entry_t; - if (temp_rd) { - first_entry_t = rrddim_first_entry_t(temp_rd); - last_entry_t = rrddim_last_entry_t(temp_rd); + if (context_param_list) { + first_entry_t = context_param_list->first_entry_t; + last_entry_t = context_param_list->last_entry_t; } else { first_entry_t = rrdset_first_entry_t(st); last_entry_t = rrdset_last_entry_t(st); @@ -1583,7 +1589,7 @@ RRDR *rrd2rrdr( /* This call takes the chart read-lock */ regions = rrdeng_variable_step_boundaries(st, after_requested, before_requested, - ®ion_info_array, &max_interval, temp_rd); + ®ion_info_array, &max_interval, context_param_list); if (1 == regions) { if (region_info_array) { if (rrd_update_every != region_info_array[0].update_every) { @@ -1597,7 +1603,7 @@ RRDR *rrd2rrdr( } return rrd2rrdr_fixedstep(st, points_requested, after_requested, before_requested, group_method, resampling_time_requested, options, dimensions, rrd_update_every, - first_entry_t, last_entry_t, absolute_period_requested, temp_rd); + first_entry_t, last_entry_t, absolute_period_requested, context_param_list); } else { if (rrd_update_every != (uint16_t)max_interval) { rrd_update_every = (uint16_t) max_interval; @@ -1608,11 +1614,11 @@ RRDR *rrd2rrdr( } return rrd2rrdr_variablestep(st, points_requested, after_requested, before_requested, group_method, resampling_time_requested, options, dimensions, rrd_update_every, - first_entry_t, last_entry_t, absolute_period_requested, region_info_array, temp_rd); + first_entry_t, last_entry_t, absolute_period_requested, region_info_array, context_param_list); } } #endif return rrd2rrdr_fixedstep(st, points_requested, after_requested, before_requested, group_method, resampling_time_requested, options, dimensions, - rrd_update_every, first_entry_t, last_entry_t, absolute_period_requested, temp_rd); + rrd_update_every, first_entry_t, last_entry_t, absolute_period_requested, context_param_list); }
\ No newline at end of file diff --git a/web/api/queries/rrdr.c b/web/api/queries/rrdr.c index b3e04d48c5..6cd0c0b142 100644 --- a/web/api/queries/rrdr.c +++ b/web/api/queries/rrdr.c @@ -98,7 +98,7 @@ inline void rrdr_free(RRDR *r) freez(r); } -RRDR *rrdr_create(struct rrdset *st, long n, struct rrddim *temp_rd) +RRDR *rrdr_create(struct rrdset *st, long n, struct context_param *context_param_list) { if(unlikely(!st)) { error("NULL value given!"); @@ -110,6 +110,7 @@ RRDR *rrdr_create(struct rrdset *st, long n, struct rrddim *temp_rd) rrdr_lock_rrdset(r); + RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL; RRDDIM *rd; if (temp_rd) { RRDDIM *t = temp_rd; diff --git a/web/api/queries/rrdr.h b/web/api/queries/rrdr.h index a4e8c44d15..2ed96cac46 100644 --- a/web/api/queries/rrdr.h +++ b/web/api/queries/rrdr.h @@ -99,12 +99,15 @@ typedef struct rrdresult { #include "../../../database/rrd.h" extern void rrdr_free(RRDR *r); -extern RRDR *rrdr_create(struct rrdset *st, long n, struct rrddim *id); +extern RRDR *rrdr_create(struct rrdset *st, long n, struct context_param *context_param_list); #include "../web_api_v1.h" #include "web/api/queries/query.h" -extern RRDR *rrd2rrdr(RRDSET *st, long points_requested, long long after_requested, long long before_requested, RRDR_GROUPING group_method, long resampling_time_requested, RRDR_OPTIONS options, const char *dimensions, RRDDIM *temp_rd); +extern RRDR *rrd2rrdr( + RRDSET *st, long points_requested, long long after_requested, long long before_requested, + RRDR_GROUPING group_method, long resampling_time_requested, RRDR_OPTIONS options, const char *dimensions, + struct context_param *context_param_list); #include "query.h" diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c index b6bf60f58a..ecedf4bc2c 100644 --- a/web/api/web_api_v1.c +++ b/web/api/web_api_v1.c @@ -491,36 +491,39 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c goto cleanup; } + struct context_param *context_param_list = NULL; if (context) { - st = NULL; - // TODO: Scan all charts of host - rrdhost_rdlock(localhost); RRDSET *st1; + uint32_t context_hash = simple_hash(context); + rrdhost_rdlock(localhost); rrdset_foreach_read(st1, localhost) { - if (strcmp(st1->context, context) == 0) { - st = st1; - break; - } + if (st1->hash_context == context_hash && !strcmp(st1->context, context)) + build_context_param_list(&context_param_list, st1); } rrdhost_unlock(localhost); + if (likely(context_param_list && context_param_list->rd)) // Just set the first one + st = context_param_list->rd->rrdset; } - - if (!st) { - if (!chart || !*chart) { - buffer_sprintf(w->response.data, "No chart id is given at the request."); - goto cleanup; - } + else { st = rrdset_find(host, chart); if (!st) st = rrdset_find_byname(host, chart); - if (!st) { + if (likely(st)) + st->last_accessed_time = now_realtime_sec(); + } + + if (!st && !context_param_list) { + if (context) { + buffer_strcat(w->response.data, "Context is not found: "); + buffer_strcat_htmlescape(w->response.data, context); + } + else { buffer_strcat(w->response.data, "Chart is not found: "); buffer_strcat_htmlescape(w->response.data, chart); - ret = HTTP_RESP_NOT_FOUND; - goto cleanup; } + ret = HTTP_RESP_NOT_FOUND; + goto cleanup; } - st->last_accessed_time = now_realtime_sec(); long long before = (before_str && *before_str)?str2l(before_str):0; long long after = (after_str && *after_str) ?str2l(after_str):-600; @@ -565,7 +568,9 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c } ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format, points, after, before, group, group_time - , options, &last_timestamp_in_data, context); + , options, &last_timestamp_in_data, context_param_list); + + free_context_param_list(&context_param_list); if(format == DATASOURCE_DATATABLE_JSONP) { if(google_timestamp < last_timestamp_in_data) |