summaryrefslogtreecommitdiffstats
path: root/sources.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sources.c47
1 files changed, 30 insertions, 17 deletions
diff --git a/sources.c b/sources.c
index e7ec4b8..e292e4d 100644
--- a/sources.c
+++ b/sources.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Miroslav Lichvar 2011-2016, 2018, 2020-2023
+ * Copyright (C) Miroslav Lichvar 2011-2016, 2018, 2020-2024
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -68,8 +68,8 @@ struct SelectInfo {
typedef enum {
SRC_OK, /* OK so far, not a final status! */
SRC_UNSELECTABLE, /* Has noselect option set */
- SRC_UNSYNCHRONISED, /* Provides samples but not unsynchronised */
SRC_BAD_STATS, /* Doesn't have valid stats data */
+ SRC_UNSYNCHRONISED, /* Provides samples, but not synchronised */
SRC_BAD_DISTANCE, /* Has root distance longer than allowed maximum */
SRC_JITTERY, /* Had std dev larger than allowed maximum */
SRC_WAITS_STATS, /* Others have bad stats, selection postponed */
@@ -177,6 +177,8 @@ static int reported_no_majority; /* Flag to avoid repeated log message
static int report_selection_loss; /* Flag to force logging a message if
selection is lost in a transient state
(SRC_WAITS_STATS, SRC_WAITS_UPDATE) */
+static int forced_first_report; /* Flag to allow one failed selection to be
+ logged before a successful selection */
/* Score needed to replace the currently selected source */
#define SCORE_LIMIT 10.0
@@ -524,11 +526,6 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
if (inst->reachability_size < SOURCE_REACH_BITS)
inst->reachability_size++;
- if (!reachable && inst->index == selected_source_index) {
- /* Try to select a better source */
- SRC_SelectSource(NULL);
- }
-
/* Check if special reference update mode failed */
if (REF_GetMode() != REF_ModeNormal && special_mode_end()) {
REF_SetUnsynchronised();
@@ -537,6 +534,10 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
/* Try to replace unreachable NTP sources */
if (inst->reachability == 0 && inst->reachability_size == SOURCE_REACH_BITS)
handle_bad_source(inst);
+
+ /* Source selection can change with unreachable sources */
+ if (inst->reachability == 0)
+ SRC_SelectSource(NULL);
}
/* ================================================== */
@@ -862,7 +863,8 @@ SRC_SelectSource(SRC_Instance updated_inst)
struct SelectInfo *si;
struct timespec now, ref_time;
int i, j, j1, j2, index, sel_prefer, n_endpoints, n_sel_sources, sel_req_source;
- int n_badstats_sources, max_sel_reach, max_sel_reach_size, max_badstat_reach;
+ int max_badstat_reach, max_badstat_reach_size, n_badstats_sources;
+ int max_sel_reach, max_sel_reach_size;
int depth, best_depth, trust_depth, best_trust_depth, n_sel_trust_sources;
int combined, stratum, min_stratum, max_score_index;
int orphan_stratum, orphan_source;
@@ -893,7 +895,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
n_badstats_sources = 0;
sel_req_source = 0;
max_sel_reach = max_badstat_reach = 0;
- max_sel_reach_size = 0;
+ max_sel_reach_size = max_badstat_reach_size = 0;
max_reach_sample_ago = 0.0;
for (i = 0; i < n_sources; i++) {
@@ -913,12 +915,6 @@ SRC_SelectSource(SRC_Instance updated_inst)
continue;
}
- /* Ignore sources which are not synchronised */
- if (sources[i]->leap == LEAP_Unsynchronised) {
- mark_source(sources[i], SRC_UNSYNCHRONISED);
- continue;
- }
-
si = &sources[i]->sel_info;
SST_GetSelectionData(sources[i]->stats, &now,
&si->lo_limit, &si->hi_limit, &si->root_distance,
@@ -930,6 +926,14 @@ SRC_SelectSource(SRC_Instance updated_inst)
mark_source(sources[i], SRC_BAD_STATS);
if (max_badstat_reach < sources[i]->reachability)
max_badstat_reach = sources[i]->reachability;
+ if (max_badstat_reach_size < sources[i]->reachability_size)
+ max_badstat_reach_size = sources[i]->reachability_size;
+ continue;
+ }
+
+ /* Ignore sources which are not synchronised */
+ if (sources[i]->leap == LEAP_Unsynchronised) {
+ mark_source(sources[i], SRC_UNSYNCHRONISED);
continue;
}
@@ -1068,6 +1072,14 @@ SRC_SelectSource(SRC_Instance updated_inst)
return;
}
+ /* Wait for a source to have full reachability register to allow one
+ failed selection to be logged before first successful selection */
+ if (!forced_first_report &&
+ MAX(max_sel_reach_size, max_badstat_reach_size) == SOURCE_REACH_BITS) {
+ report_selection_loss = 1;
+ forced_first_report = 1;
+ }
+
if (n_endpoints == 0) {
/* No sources provided valid endpoints */
unselect_selected_source(LOGS_INFO, "Can't synchronise: no selectable sources", NULL);
@@ -1334,6 +1346,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
reported_no_majority = 0;
report_selection_loss = 0;
+ forced_first_report = 1;
}
mark_source(sources[selected_source_index], SRC_SELECTED);
@@ -1796,10 +1809,10 @@ get_status_char(SRC_Status status)
switch (status) {
case SRC_UNSELECTABLE:
return 'N';
- case SRC_UNSYNCHRONISED:
- return 's';
case SRC_BAD_STATS:
return 'M';
+ case SRC_UNSYNCHRONISED:
+ return 's';
case SRC_BAD_DISTANCE:
return 'd';
case SRC_JITTERY: