local: reset daemon after unexpected time jump

Add a new change type and use it when an unexpected time jump is
detected in the scheduler to reset reference times, offset and slewing,
NCR instances (with their polling interval), synchronization status, and
drop all sourcestats, manual, refclock and RTC samples.

This should make the recovery more graceful if the estimated jump has a
large error (e.g. select didn't timeout, or after system suspend).
This commit is contained in:
Miroslav Lichvar 2014-06-02 17:14:28 +02:00
parent a3e60c93da
commit a33a955163
10 changed files with 48 additions and 11 deletions

View file

@ -479,7 +479,7 @@ LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
double offset, double dispersion)
{
/* Dispatch to all handlers */
invoke_parameter_change_handlers(raw, cooked, 0.0, offset, LCL_ChangeStep);
invoke_parameter_change_handlers(raw, cooked, 0.0, offset, LCL_ChangeUnknownStep);
lcl_InvokeDispersionNotifyHandlers(dispersion);
}

View file

@ -74,7 +74,8 @@ extern void LCL_GetOffsetCorrection(struct timeval *raw, double *correction, dou
typedef enum {
LCL_ChangeAdjust,
LCL_ChangeStep
LCL_ChangeStep,
LCL_ChangeUnknownStep
} LCL_ChangeType;
typedef void (*LCL_ParameterChangeHandler)

View file

@ -221,6 +221,11 @@ slew_samples(struct timeval *raw,
{
double delta_time;
int i;
if (change_type == LCL_ChangeUnknownStep) {
MNL_Reset();
}
for (i=0; i<n_samples; i++) {
UTI_AdjustTimeval(&samples[i].when, cooked, &samples[i].when, &delta_time,
dfreq, doffset);

View file

@ -491,9 +491,13 @@ slew_sources(struct timeval *raw,
UTI_IPToString(&records[i].remote_addr->ip_addr), dfreq, doffset);
#endif
if (change_type == LCL_ChangeUnknownStep) {
NCR_ResetInstance(records[i].data);
} else {
NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
}
}
}
}

View file

@ -581,9 +581,13 @@ slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
{
int i;
for (i = 0; i < n_sources; i++)
for (i = 0; i < n_sources; i++) {
if (change_type == LCL_ChangeUnknownStep)
filter_reset(&refclocks[i].filter);
else
filter_slew_samples(&refclocks[i].filter, cooked, dfreq, doffset);
}
}
static void
add_dispersion(double dispersion, void *anything)

View file

@ -147,7 +147,10 @@ handle_slew(struct timeval *raw,
LCL_ChangeType change_type,
void *anything)
{
if (change_type == LCL_ChangeStep) {
if (change_type == LCL_ChangeUnknownStep) {
last_ref_update.tv_sec = 0;
last_ref_update.tv_usec = 0;
} else if (change_type == LCL_ChangeStep) {
UTI_AddDoubleToTimeval(&last_ref_update, -doffset, &last_ref_update);
}
}

View file

@ -273,6 +273,11 @@ slew_samples
double delta_time;
double old_seconds_fast, old_gain_rate;
if (change_type == LCL_ChangeUnknownStep) {
/* Drop all samples. */
n_samples = 0;
}
for (i=0; i<n_samples; i++) {
UTI_AdjustTimeval(system_times + i, cooked, system_times + i, &delta_time,
dfreq, doffset);

View file

@ -1093,9 +1093,17 @@ slew_sources(struct timeval *raw,
int i;
for (i=0; i<n_sources; i++) {
if (change_type == LCL_ChangeUnknownStep) {
SST_ResetInstance(sources[i]->stats);
} else {
SST_SlewSamples(sources[i]->stats, cooked, dfreq, doffset);
}
}
if (change_type == LCL_ChangeUnknownStep) {
/* After resetting no source is selectable, set reference unsynchronised */
SRC_SelectSource(NULL);
}
}
/* ================================================== */

View file

@ -87,6 +87,7 @@ static double slew_error;
/* ================================================== */
static void handle_end_of_slew(void *anything);
static void update_slew(void);
/* ================================================== */
/* Adjust slew_start on clock step */
@ -95,9 +96,15 @@ static void
handle_step(struct timeval *raw, struct timeval *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything)
{
if (change_type == LCL_ChangeStep)
if (change_type == LCL_ChangeUnknownStep) {
/* Reset offset and slewing */
slew_start = *raw;
offset_register = 0.0;
update_slew();
} else if (change_type == LCL_ChangeStep) {
UTI_AddDoubleToTimeval(&slew_start, -doffset, &slew_start);
}
}
/* ================================================== */
/* End currently running slew and start a new one */

View file

@ -4,8 +4,8 @@
test_start "external time step"
min_sync_time=1300
max_sync_time=1500
min_sync_time=1500
max_sync_time=1550
for step in -1e2 1e2; do
# Make one step in 150th second