From: Dave Hart Date: Thu, 13 Oct 2011 18:13:58 +0000 (+0000) Subject: ntpq mrulist shows intermediate counts every five seconds while X-Git-Tag: NTP_4_2_7P224~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2cf256bbbbd64d1f82676a3b9e520032b8d7ec2f;p=thirdparty%2Fntp.git ntpq mrulist shows intermediate counts every five seconds while retrieving list, and allows Ctrl-C interruption of the retrieval, showing the incomplete list as retrieved. Reduce delay between successive mrulist retrieval queries from 30 to 5 msec. Do not give up mrulist retrieval when a single query times out. bk: 4e972a66ne0ahGB5OMdVfV3THZDFlQ --- diff --git a/ChangeLog b/ChangeLog index 7d9142452..2ee41b2e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +* ntpq mrulist shows intermediate counts every five seconds while + retrieving list, and allows Ctrl-C interruption of the retrieval, + showing the incomplete list as retrieved. Reduce delay between + successive mrulist retrieval queries from 30 to 5 msec. Do not + give up mrulist retrieval when a single query times out. (4.2.7p223) 2011/10/12 Released by Harlan Stenn * Documentation updates from Dave Mills. (4.2.7p222) 2011/10/11 Released by Harlan Stenn diff --git a/include/ntp_stdlib.h b/include/ntp_stdlib.h index 7669e298f..0a4a32f88 100644 --- a/include/ntp_stdlib.h +++ b/include/ntp_stdlib.h @@ -77,6 +77,8 @@ extern void errno_to_str(int, char *, size_t); errno = preserved_errno; \ } +typedef void (*ctrl_c_fn)(void); + /* authkeys.c */ extern void auth_delkeys (void); extern int auth_havekey (keyid_t); @@ -175,6 +177,7 @@ extern int decodenetnum (const char *, sockaddr_u *); extern const char * FindConfig (const char *); extern void signal_no_reset (int, RETSIGTYPE (*func)(int)); +extern void set_ctrl_c_hook (ctrl_c_fn); extern void getauthkeys (const char *); extern void auth_agekeys (void); diff --git a/libntp/syssignal.c b/libntp/syssignal.c index 3f1848135..5e496a95f 100644 --- a/libntp/syssignal.c +++ b/libntp/syssignal.c @@ -9,6 +9,13 @@ #include "ntp_syslog.h" #include "ntp_stdlib.h" +static ctrl_c_fn ctrl_c_hook; +#ifndef SYS_WINNT +RETSIGTYPE sigint_handler(int); +#else +BOOL WINAPI console_event_handler(DWORD); +#endif + #ifdef HAVE_SIGACTION @@ -107,3 +114,75 @@ signal_no_reset( } #endif + +#ifndef SYS_WINNT +/* + * POSIX implementation of set_ctrl_c_hook() + */ +RETSIGTYPE +sigint_handler( + int signum + ) +{ + UNUSED_ARG(signum); + if (ctrl_c_hook != NULL) + (*ctrl_c_hook)(); +} + +void +set_ctrl_c_hook( + ctrl_c_fn c_hook + ) +{ + RETSIGTYPE (*handler)(int); + + if (NULL == c_hook) { + handler = SIG_DFL; + ctrl_c_hook = NULL; + } else { + handler = &sigint_handler; + ctrl_c_hook = c_hook; + } + signal_no_reset(SIGINT, handler); +} +#else /* SYS_WINNT follows */ +/* + * Windows implementation of set_ctrl_c_hook() + */ +BOOL WINAPI +console_event_handler( + DWORD dwCtrlType + ) +{ + BOOL handled; + + if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) { + (*ctrl_c_hook)(); + handled = TRUE; + } else { + handled = FALSE; + } + + return handled; +} +void +set_ctrl_c_hook( + ctrl_c_fn c_hook + ) +{ + BOOL install; + + if (NULL == c_hook) { + ctrl_c_hook = NULL; + install = FALSE; + } else { + ctrl_c_hook = c_hook; + install = TRUE; + } + if (!SetConsoleCtrlHandler(&console_event_handler, install)) + msyslog(LOG_ERR, "Can't %s console control handler: %m", + (install) + ? "add" + : "remove"); +} +#endif /* SYS_WINNT */ diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index 1bc8b13e1..d5e403584 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -319,8 +319,9 @@ typedef struct var_display_collection_tag { } vdc; /* - * other static function prototypes + * other local function prototypes */ +void mrulist_ctrl_c_hook(void); static mru * add_mru(mru *); static int collect_mru_list(const char *, l_fp *); static int fetch_nonce(char *, size_t); @@ -339,6 +340,8 @@ static void collect_display_vdc(associd_t as, vdc *table, * static globals */ static u_int mru_count; +static u_int mru_dupes; +volatile int mrulist_interrupted; static mru mru_list; /* listhead */ static mru ** hash_table; @@ -2175,11 +2178,11 @@ add_mru( add->last.l_uf, mon->last.l_ui, mon->last.l_uf); exit(1); - } UNLINK_DLIST(mon, mlink); UNLINK_SLIST(unlinked, hash_table[hash], mon, hlink, mru); NTP_INSIST(unlinked == mon); + mru_dupes++; if (debug) fprintf(stderr, "(updated from %08x.%08x) ", mon->last.l_ui, mon->last.l_uf); @@ -2216,16 +2219,24 @@ add_mru( } while (0) +void +mrulist_ctrl_c_hook(void) +{ + mrulist_interrupted = TRUE; +} + + static int collect_mru_list( - const char *parms, - l_fp * pnow + const char * parms, + l_fp * pnow ) { - const u_int sleep_msecs = 30; + const u_int sleep_msecs = 5; static int ntpd_row_limit = MRU_ROW_LIMIT; int c_mru_l_rc; /* this function's return code */ u_char got; /* MRU_GOT_* bits */ + time_t next_report; size_t cb; mru *mon; mru *head; @@ -2279,6 +2290,12 @@ collect_mru_list( mon = emalloc_zero(cb); ZERO(*pnow); ZERO(last_older); + mrulist_interrupted = FALSE; + set_ctrl_c_hook(&mrulist_ctrl_c_hook); + fprintf(stderr, + "Ctrl-C will stop MRU retrieval and display partial results.\n"); + fflush(stderr); + next_report = time(NULL) + MRU_REPORT_SECS; limit = min(3 * MAXFRAGS, ntpd_row_limit); snprintf(req_buf, sizeof(req_buf), "nonce=%s, limit=%d%s", @@ -2343,7 +2360,8 @@ collect_mru_list( fprintf(stderr, "Row limit reduced to %d following CERR_BADVALUE.\n", limit); - } else if (ERR_INCOMPLETE == qres) { + } else if (ERR_INCOMPLETE == qres || + ERR_TIMEOUT == qres) { /* * Reduce the number of rows to minimize effect * of single lost packets. @@ -2466,10 +2484,18 @@ collect_mru_list( } else if (1 != sscanf(tag, "last.%d", &si) || si != ci || '0' != val[0] || 'x' != val[1] || - !hextolfp(val + 2, &mon->last)) + !hextolfp(val + 2, &mon->last)) { goto nomatch; - else + } else { MGOT(MRU_GOT_LAST); + /* + * allow interrupted retrieval, + * using most recent retrieved + * entry's last seen timestamp + * as the end of operation. + */ + *pnow = mon->last; + } break; case 'f': @@ -2531,8 +2557,26 @@ collect_mru_list( list_complete = TRUE; if (list_complete) { NTP_INSIST(0 == ri || have_addr_older); + } + if (mrulist_interrupted) { + printf("mrulist retrieval interrupted by operator.\n" + "Displaying partial client list.\n"); + fflush(stdout); + } + if (list_complete || mrulist_interrupted) { + fprintf(stderr, + "\rRetrieved %u unique MRU entries and %u updates.\n", + mru_count, mru_dupes); + fflush(stderr); break; } + if (time(NULL) >= next_report) { + next_report += MRU_REPORT_SECS; + fprintf(stderr, "\r%u (%u updates) ", mru_count, + mru_dupes); + fflush(stderr); + } + /* * Snooze for a bit between queries to let ntpd catch * up with other duties. @@ -2592,6 +2636,7 @@ collect_mru_list( } } + set_ctrl_c_hook(NULL); c_mru_l_rc = TRUE; goto retain_hash_table; diff --git a/ntpq/ntpq.h b/ntpq/ntpq.h index 6398ec6ce..243a54afe 100644 --- a/ntpq/ntpq.h +++ b/ntpq/ntpq.h @@ -104,6 +104,11 @@ struct association { #define MAXASSOC 1024 +/* + * mrulist terminal status interval + */ +#define MRU_REPORT_SECS 5 + /* * var_format is used to override cooked formatting for selected vars. */