sources: update reference leap status early
When a leap second status is updated by a source, don't wait for the next source selection and full update of the reference. Count votes from sources that passed the previous selection and update the reference leap status directly. This should allow leap seconds to spread quickly even when the samples are dropped or delayed by the filters.
This commit is contained in:
parent
2582be8754
commit
4883086fc1
3 changed files with 61 additions and 16 deletions
15
reference.c
15
reference.c
|
@ -1130,6 +1130,21 @@ REF_SetUnsynchronised(void)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
REF_UpdateLeapStatus(NTP_Leap leap)
|
||||
{
|
||||
struct timespec raw_now;
|
||||
|
||||
/* Wait for a full reference update if not already synchronised */
|
||||
if (!are_we_synchronised)
|
||||
return;
|
||||
|
||||
SCH_GetLastEventTime(NULL, NULL, &raw_now);
|
||||
update_leap_status(leap, raw_now.tv_sec, 0);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
REF_GetReferenceParams
|
||||
(
|
||||
|
|
|
@ -162,6 +162,9 @@ extern void REF_SetManualReference
|
|||
extern void
|
||||
REF_SetUnsynchronised(void);
|
||||
|
||||
/* Announce a leap second before the full reference update */
|
||||
extern void REF_UpdateLeapStatus(NTP_Leap leap);
|
||||
|
||||
/* Return the current stratum of this host or 16 if the host is not
|
||||
synchronised */
|
||||
extern int REF_GetOurStratum(void);
|
||||
|
|
59
sources.c
59
sources.c
|
@ -128,6 +128,9 @@ struct SRC_Instance_Record {
|
|||
|
||||
/* Latest leap status */
|
||||
NTP_Leap leap;
|
||||
|
||||
/* Flag indicating the source has a leap second vote */
|
||||
int leap_vote;
|
||||
};
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -301,6 +304,7 @@ SRC_ResetInstance(SRC_Instance instance)
|
|||
instance->status = SRC_BAD_STATS;
|
||||
instance->sel_score = 1.0;
|
||||
instance->leap = LEAP_Unsynchronised;
|
||||
instance->leap_vote = 0;
|
||||
|
||||
SST_ResetInstance(instance->stats);
|
||||
}
|
||||
|
@ -326,6 +330,34 @@ SRC_GetSourcestats(SRC_Instance instance)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static NTP_Leap
|
||||
get_leap_status(void)
|
||||
{
|
||||
int i, leap_votes, leap_ins, leap_del;
|
||||
|
||||
/* Accept a leap second if more than half of the sources with a vote agree */
|
||||
|
||||
for (i = leap_ins = leap_del = leap_votes = 0; i < n_sources; i++) {
|
||||
if (!sources[i]->leap_vote)
|
||||
continue;
|
||||
|
||||
leap_votes++;
|
||||
if (sources[i]->leap == LEAP_InsertSecond)
|
||||
leap_ins++;
|
||||
else if (sources[i]->leap == LEAP_DeleteSecond)
|
||||
leap_del++;
|
||||
}
|
||||
|
||||
if (leap_ins > leap_votes / 2)
|
||||
return LEAP_InsertSecond;
|
||||
else if (leap_del > leap_votes / 2)
|
||||
return LEAP_DeleteSecond;
|
||||
else
|
||||
return LEAP_Normal;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
SRC_SetLeapStatus(SRC_Instance inst, NTP_Leap leap)
|
||||
{
|
||||
|
@ -333,6 +365,9 @@ SRC_SetLeapStatus(SRC_Instance inst, NTP_Leap leap)
|
|||
return;
|
||||
|
||||
inst->leap = leap;
|
||||
|
||||
if (inst->leap_vote)
|
||||
REF_UpdateLeapStatus(get_leap_status());
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -609,7 +644,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||
int n_badstats_sources, max_sel_reach, max_sel_reach_size, max_badstat_reach;
|
||||
int depth, best_depth, trust_depth, best_trust_depth;
|
||||
int combined, stratum, min_stratum, max_score_index;
|
||||
int orphan_stratum, orphan_source, leap_votes, leap_ins, leap_del;
|
||||
int orphan_stratum, orphan_source;
|
||||
double src_offset, src_offset_sd, src_frequency, src_frequency_sd, src_skew;
|
||||
double src_root_delay, src_root_dispersion;
|
||||
double best_lo, best_hi, distance, sel_src_distance, max_score;
|
||||
|
@ -692,6 +727,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||
}
|
||||
|
||||
sources[i]->status = SRC_OK; /* For now */
|
||||
sources[i]->leap_vote = 0;
|
||||
|
||||
if (sources[i]->reachability && max_reach_sample_ago < first_sample_ago)
|
||||
max_reach_sample_ago = first_sample_ago;
|
||||
|
@ -928,26 +964,15 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Accept leap second status if more than half of selectable (and trusted
|
||||
if there are any) sources agree */
|
||||
for (i = leap_ins = leap_del = leap_votes = 0; i < n_sel_sources; i++) {
|
||||
/* Enable the selectable sources (and trusted if there are any) to
|
||||
vote on leap seconds */
|
||||
for (i = 0; i < n_sel_sources; i++) {
|
||||
index = sel_sources[i];
|
||||
if (best_trust_depth && !(sources[index]->sel_options & SRC_SELECT_TRUST))
|
||||
continue;
|
||||
leap_votes++;
|
||||
if (sources[index]->leap == LEAP_InsertSecond)
|
||||
leap_ins++;
|
||||
else if (sources[index]->leap == LEAP_DeleteSecond)
|
||||
leap_del++;
|
||||
sources[index]->leap_vote = 1;
|
||||
}
|
||||
|
||||
if (leap_ins > leap_votes / 2)
|
||||
leap_status = LEAP_InsertSecond;
|
||||
else if (leap_del > leap_votes / 2)
|
||||
leap_status = LEAP_DeleteSecond;
|
||||
else
|
||||
leap_status = LEAP_Normal;
|
||||
|
||||
/* If there are any sources with prefer option, reduce the list again
|
||||
only to the preferred sources */
|
||||
for (i = 0; i < n_sel_sources; i++) {
|
||||
|
@ -1079,6 +1104,8 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||
for (i = 0; i < n_sources; i++)
|
||||
sources[i]->updates = 0;
|
||||
|
||||
leap_status = get_leap_status();
|
||||
|
||||
/* Now just use the statistics of the selected source combined with
|
||||
the other selectable sources for trimming the local clock */
|
||||
|
||||
|
|
Loading…
Reference in a new issue