@cryptotaxi247 / netdata-1 / commits / 46fe76afa

fix crash on query plan switch (#13920)

fix https://github.com/netdata/netdata/issues/13918

Costa Tsaousis committed Oct 31, 2022 at 22:26 UTC 46fe76afa9e0369bf56495dbfb2f7c8fe89f360b
1 file changed +18 -10
web/api/queries/query.c
+18 -10
@@ -933,15 +933,10 @@ typedef struct query_engine_ops {
933
934 #define query_plan_should_switch_plan(ops, now) ((now) >= (ops).current_plan_expire_time)
935
936 -static bool query_planer_activate_plan(QUERY_ENGINE_OPS *ops, size_t plan_id, time_t overwrite_after) {
936 +static void query_planer_activate_plan(QUERY_ENGINE_OPS *ops, size_t plan_id, time_t overwrite_after) {
937 if(unlikely(plan_id >= ops->plan.entries))
938 plan_id = ops->plan.entries - 1;
939
940 - if(!query_metric_is_valid_tier(ops->qm, ops->plan.data[plan_id].tier)) {
941 - ops->current_plan_expire_time = ops->plan.data[plan_id].before;
942 - return false;
943 - }
944 -
940 time_t after = ops->plan.data[plan_id].after;
941 time_t before = ops->plan.data[plan_id].before;
942
@@ -956,20 +951,21 @@ static bool query_planer_activate_plan(QUERY_ENGINE_OPS *ops, size_t plan_id, ti
951 ops->finalize = ops->tier_ptr->eng->api.query_ops.finalize;
952 ops->current_plan = plan_id;
953 ops->current_plan_expire_time = ops->plan.data[plan_id].before;
959 -
960 - return true;
954 }
955
956 static void query_planer_next_plan(QUERY_ENGINE_OPS *ops, time_t now, time_t last_point_end_time) {
957 internal_error(now < ops->current_plan_expire_time && now < ops->plan.data[ops->current_plan].before,
958 "QUERY: switching query plan too early!");
959
960 + size_t old_plan = ops->current_plan;
961 +
962 time_t next_plan_before_time;
963 do {
964 ops->current_plan++;
965
966 if (ops->current_plan >= ops->plan.entries) {
972 - ops->current_plan = ops->plan.entries - 1;
967 + ops->current_plan = old_plan;
968 + ops->current_plan_expire_time = ops->r->internal.qt->window.before;
969 // let the query run with current plan
970 // we will not switch it
971 return;
@@ -978,9 +974,16 @@ static void query_planer_next_plan(QUERY_ENGINE_OPS *ops, time_t now, time_t las
974 next_plan_before_time = ops->plan.data[ops->current_plan].before;
975 } while(now >= next_plan_before_time || last_point_end_time >= next_plan_before_time);
976
977 + if(!query_metric_is_valid_tier(ops->qm, ops->plan.data[ops->current_plan].tier)) {
978 + ops->current_plan = old_plan;
979 + ops->current_plan_expire_time = ops->r->internal.qt->window.before;
980 + return;
981 + }
982 +
983 if(ops->finalize) {
984 ops->finalize(&ops->handle);
985 ops->finalize = NULL;
986 + ops->is_finished = NULL;
987 }
988
989 // internal_error(true, "QUERY: switched plan to %zu (all is %zu), previous expiration was %ld, this starts at %ld, now is %ld, last_point_end_time %ld", ops->current_plan, ops->plan.entries, ops->plan.data[ops->current_plan-1].before, ops->plan.data[ops->current_plan].after, now, last_point_end_time);
@@ -1101,7 +1104,12 @@ static bool query_plan(QUERY_ENGINE_OPS *ops, time_t after_wanted, time_t before
1104
1105 //internal_error(true, "%s", buffer_tostring(wb));
1106
1104 - return query_planer_activate_plan(ops, 0, 0);
1107 + if(!query_metric_is_valid_tier(ops->qm, ops->plan.data[0].tier))
1108 + return false;
1109 +
1110 + query_planer_activate_plan(ops, 0, 0);
1111 +
1112 + return true;
1113 }
1114
1115