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