]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Add minsamples and maxsamples directives
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 13 Jun 2013 14:23:32 +0000 (16:23 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 13 Jun 2013 14:23:32 +0000 (16:23 +0200)
Allow configuration of the maximum and minimum number of samples per
source.

chrony.texi.in
conf.c
conf.h
regress.c
regress.h
sourcestats.c

index 108a2637bc5a7e44d0ae33b60694b68a846510dd..5f9120d7b3a9adac60d506ed2adfa988dfade984 100644 (file)
@@ -1195,7 +1195,9 @@ directives can occur in any order in the file.
 * maxchange directive::         Set maximum allowed offset
 * manual directive::            Allow manual entry using chronyc's settime cmd.
 * maxclockerror directive::     Set maximum frequency error of local clock
+* maxsamples directive::        Set maximum number of samples per source
 * maxupdateskew directive::     Stop bad estimates upsetting machine clock
+* minsamples directive::        Set minimum number of samples per source
 * noclientlog directive::       Prevent chronyd from gathering data about clients
 * clientloglimit directive::    Set client log memory limit
 * peer directive::              Specify an NTP peer
@@ -2374,6 +2376,19 @@ Typical values for <error-in-ppm> might be 10 for a low quality clock
 to 0.1 for a high quality clock using a temperature compensated
 crystal oscillator.
 @c }}}
+@c {{{ maxsamples
+@node maxsamples directive
+@subsection maxsamples
+The @code{maxsamples} directive sets the maximum number of samples
+@code{chronyd} should keep for each source. The default is 0, which
+disables the configurable limit, and the useful range is 4 to 64.
+
+The syntax is
+
+@example
+maxsamples <samples>
+@end example
+@c }}}
 @c {{{ maxupdateskew
 @node maxupdateskew directive
 @subsection maxupdateskew
@@ -2408,6 +2423,19 @@ highly-reliable master estimate and a new estimate is generated which
 has large error bounds, the existing master estimate will dominate in
 the new master estimate.
 @c }}}
+@c {{{ minsamples
+@node minsamples directive
+@subsection minsamples
+The @code{minsamples} directive sets the minimum number of samples
+@code{chronyd} should try to keep for each source. The default is 0 and the
+useful range is 4 to 64.
+
+The syntax is
+
+@example
+minsamples <samples>
+@end example
+@c }}}
 @c {{{ noclientlog
 @node noclientlog directive
 @subsection noclientlog
diff --git a/conf.c b/conf.c
index 76db3e66ecc41bc6864e4c112e5c44cd64b87ada..72af3dd051e0a227e5948dc9fb27d9023c7def5a 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -92,7 +92,9 @@ static void parse_makestep(char *);
 static void parse_manual(char *);
 static void parse_maxchange(char *);
 static void parse_maxclockerror(char *);
+static void parse_maxsamples(char *line);
 static void parse_maxupdateskew(char *);
+static void parse_minsamples(char *line);
 static void parse_noclientlog(char *);
 static void parse_peer(char *);
 static void parse_pidfile(char *);
@@ -173,6 +175,10 @@ static int max_offset_delay = -1;
 static int max_offset_ignore;
 static double max_offset;
 
+/* Maximum and minimum number of samples per source */
+static int max_samples = 0; /* no limit */
+static int min_samples = 0;
+
 /* Flag set if we should log to syslog when a time adjustment
    exceeding the threshold is initiated */
 static int do_log_change = 0;
@@ -428,8 +434,12 @@ CNF_ReadFile(const char *filename)
         parse_maxchange(p);
       } else if (!strcasecmp(command, "maxclockerror")) {
         parse_maxclockerror(p);
+      } else if (!strcasecmp(command, "maxsamples")) {
+        parse_maxsamples(p);
       } else if (!strcasecmp(command, "maxupdateskew")) {
         parse_maxupdateskew(p);
+      } else if (!strcasecmp(command, "minsamples")) {
+        parse_minsamples(p);
       } else if (!strcasecmp(command, "noclientlog")) {
         parse_noclientlog(p);
       } else if (!strcasecmp(command, "peer")) {
@@ -828,6 +838,28 @@ parse_logdir(char *line)
 
 /* ================================================== */
 
+static void
+parse_maxsamples(char *line)
+{
+  check_number_of_args(line, 1);
+  if (sscanf(line, "%d", &max_samples) != 1) {
+    command_parse_error();
+  }
+}
+
+/* ================================================== */
+
+static void
+parse_minsamples(char *line)
+{
+  check_number_of_args(line, 1);
+  if (sscanf(line, "%d", &min_samples) != 1) {
+    command_parse_error();
+  }
+}
+
+/* ================================================== */
+
 static void
 parse_dumpdir(char *line)
 {
@@ -1883,3 +1915,19 @@ CNF_GetUser(void)
 {
   return user;
 }
+
+/* ================================================== */
+
+int
+CNF_GetMaxSamples(void)
+{
+  return max_samples;
+}
+
+/* ================================================== */
+
+int
+CNF_GetMinSamples(void)
+{
+  return min_samples;
+}
diff --git a/conf.h b/conf.h
index 2d986e672b5a8b7b2eacff9ecb65a67055844bec..d03406be36a2945096e15d3bc62de55afb97f09f 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -96,4 +96,7 @@ extern void CNF_GetTempComp(char **file, double *interval, double *T0, double *k
 
 extern char *CNF_GetUser(void);
 
+extern int CNF_GetMaxSamples(void);
+extern int CNF_GetMinSamples(void);
+
 #endif /* GOT_CONF_H */
index a0196c18677a65d14d8a874041b2a03b952b581d..60e589a8a6a54facf1fb8488da783e7f8d7a5fd1 100644 (file)
--- a/regress.c
+++ b/regress.c
@@ -226,6 +226,9 @@ RGR_FindBestRegression
  int m,                         /* number of extra samples in x and y arrays
                                    (negative index) which can be used to
                                    extend runs test */
+ int min_samples,               /* minimum number of samples to be kept after
+                                   changing the starting index to pass the runs
+                                   test */
 
  /* And now the results */
 
@@ -297,7 +300,9 @@ RGR_FindBestRegression
     /* Count number of runs */
     nruns = n_runs_from_residuals(resid, n - resid_start); 
 
-    if (nruns > critical_runs[n - resid_start] || n - start <= MIN_SAMPLES_FOR_REGRESS) {
+    if (nruns > critical_runs[n - resid_start] ||
+        n - start <= MIN_SAMPLES_FOR_REGRESS ||
+        n - start <= min_samples) {
       if (start != resid_start) {
         /* Ignore extra samples in returned nruns */
         nruns = n_runs_from_residuals(resid - resid_start + start, n - start);
index 4c11ca578f5a04d9968f06ee1ecb6a95415276dc..b8d0d506f7a07bebd2ab41165b29b0e22ebacc71 100644 (file)
--- a/regress.h
+++ b/regress.h
@@ -80,6 +80,9 @@ RGR_FindBestRegression
  int m,                         /* number of extra samples in x and y arrays
                                    (negative index) which can be used to
                                    extend runs test */
+ int min_samples,               /* minimum number of samples to be kept after
+                                   changing the starting index to pass the runs
+                                   test */
 
  /* And now the results */
 
index fa25ab655cce3fae40e3586a58ce8503484ad161..616b32629d540722c5ef32b335db4bc05b4a4977 100644 (file)
    to store per source */
 #define MAX_SAMPLES 64
 
+/* User defined maximum and minimum number of samples */
+int max_samples;
+int min_samples;
+
 /* This is the assumed worst case bound on an unknown frequency,
    2000ppm, which would be pretty bad */
 #define WORST_CASE_FREQ_BOUND (2000.0/1.0e6)
@@ -160,6 +164,8 @@ SST_Initialise(void)
   logfileid = CNF_GetLogStatistics() ? LOG_FileOpen("statistics",
       "   Date (UTC) Time     IP Address    Std dev'n Est offset  Offset sd  Diff freq   Est skew  Stress  Ns  Bs  Nr")
     : -1;
+  max_samples = CNF_GetMaxSamples();
+  min_samples = CNF_GetMinSamples();
 }
 
 /* ================================================== */
@@ -239,7 +245,8 @@ SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time,
   int n, m;
 
   /* Make room for the new sample */
-  if (inst->n_samples == MAX_SAMPLES) {
+  if (inst->n_samples > 0 &&
+      (inst->n_samples == MAX_SAMPLES || inst->n_samples == max_samples)) {
     prune_register(inst, 1);
   }
 
@@ -428,6 +435,7 @@ SST_DoNewRegression(SST_Stats inst)
   inst->regression_ok = RGR_FindBestRegression(times_back + inst->runs_samples,
                                          offsets + inst->runs_samples, weights,
                                          inst->n_samples, inst->runs_samples,
+                                         min_samples,
                                          &est_intercept, &est_slope, &est_var,
                                          &est_intercept_sd, &est_slope_sd,
                                          &best_start, &nruns, &degrees_of_freedom);