send_ok(ssl);
}
+#ifndef THREADS_DISABLED
+/** parse fast reload command options. */
+static int
+fr_parse_options(RES* ssl, char* arg, int* fr_verb, int* fr_nopause)
+{
+ char* argp = arg;
+ while(*argp=='+') {
+ argp++;
+ while(*argp!=0 && *argp!=' ' && *argp!='\t') {
+ if(*argp == 'v') {
+ (*fr_verb)++;
+ } else if(*argp == 'p') {
+ (*fr_nopause) = 1;
+ } else {
+ if(!ssl_printf(ssl,
+ "error: unknown option '+%c'\n",
+ *argp))
+ return 0;
+ return 0;
+ }
+ argp++;
+ }
+ argp = skipwhite(argp);
+ }
+ if(*argp!=0) {
+ if(!ssl_printf(ssl, "error: unknown option '%s'\n", argp))
+ return 0;
+ return 0;
+ }
+ return 1;
+}
+#endif /* !THREADS_DISABLED */
+
/** do the fast_reload command */
static void
do_fast_reload(RES* ssl, struct worker* worker, struct rc_state* s, char* arg)
(void)s;
(void)arg;
#else
- int fr_verb = 0;
- if(arg[0] == '+') {
- int i=1;
- while(arg[i]!=0 && arg[i]!=' ' && arg[i]!='\t') {
- if(arg[i] == 'v')
- fr_verb++;
- else {
- if(!ssl_printf(ssl,
- "error: unknown option '+%c'\n",
- arg[i]))
- return;
- return;
- }
- i++;
- }
- }
+ int fr_verb = 0, fr_nopause = 0;
+ if(!fr_parse_options(ssl, arg, &fr_verb, &fr_nopause))
+ return;
if(fr_verb >= 1) {
if(!ssl_printf(ssl, "start fast_reload\n"))
return;
}
- fast_reload_thread_start(ssl, worker, s, fr_verb);
+ fast_reload_thread_start(ssl, worker, s, fr_verb, fr_nopause);
#endif
}
struct fast_reload_construct* ct)
{
int result = 1;
- fr_send_notification(fr, fast_reload_notification_reload_stop);
- fr_poll_for_ack(fr);
+ if(!fr->fr_nopause) {
+ fr_send_notification(fr, fast_reload_notification_reload_stop);
+ fr_poll_for_ack(fr);
+ }
if(!fr_reload_config(fr, newcfg, ct)) {
result = 0;
}
- fr_send_notification(fr, fast_reload_notification_reload_start);
+ if(!fr->fr_nopause) {
+ fr_send_notification(fr, fast_reload_notification_reload_start);
+ }
return result;
}
/** fast reload thread. setup the thread info */
static int
-fast_reload_thread_setup(struct worker* worker, int fr_verb)
+fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause)
{
struct fast_reload_thread* fr;
int numworkers = worker->daemon->num;
return 0;
fr = worker->daemon->fast_reload_thread;
fr->fr_verb = fr_verb;
+ fr->fr_nopause = fr_nopause;
/* The thread id printed in logs, numworker+1 is the dnstap thread.
* This is numworkers+2. */
fr->threadnum = numworkers+2;
void
fast_reload_thread_start(RES* ssl, struct worker* worker, struct rc_state* s,
- int fr_verb)
+ int fr_verb, int fr_nopause)
{
if(worker->daemon->fast_reload_thread) {
log_err("fast reload thread already running");
return;
}
- if(!fast_reload_thread_setup(worker, fr_verb)) {
+ if(!fast_reload_thread_setup(worker, fr_verb, fr_nopause)) {
if(!ssl_printf(ssl, "error could not setup thread\n"))
return;
return;
int need_to_quit;
/** verbosity of the fast_reload command, the number of +v options */
int fr_verb;
+ /** option to not pause threads during reload */
+ int fr_nopause;
/** the event that listens on the remote service worker to the
* commpair, it receives content from the fast reload thread. */
* while the fast reload is running.
* @param fr_verb: verbosity to print output at. 0 is nothing, 1 is some
* and 2 is more detail.
+ * @param fr_nopause: option to not pause threads during reload.
*/
void fast_reload_thread_start(RES* ssl, struct worker* worker,
- struct rc_state* s, int fr_verb);
+ struct rc_state* s, int fr_verb, int fr_nopause);
/**
* Stop fast reload thread
That means the caches sizes and the number of threads must not change between
reloads.
.TP
-.B fast_reload \fR[\fI+v\fR]
+.B fast_reload \fR[\fI+vp\fR]
Reload the server, but keep downtime to a minimum, so that user queries
keep seeing service. This needs the code compiled with threads. The config
is loaded in a thread, and prepared, then it briefly pauses the existing
the amount of memory that was allocated temporarily to perform the reload,
this amount of memory can be big if the config has large contents. In the
timing output the 'reload' time is the time during which the server was paused.
+.IP
+The '+p' option makes the reload not pause threads, they keep running.
+Locks are acquired, but items are updated in sequence, so it is possible
+for threads to see an inconsistent state with some options from the old
+and some options from the new config, such as cache TTL parameters from the
+old config and forwards from the new config. The stubs and forwards are
+updated at the same time, so that they are viewed consistently, either old
+or new values together. The option makes the reload time take eg. 3
+microseconds instead of 0.3 milliseconds during which the worker threads are
+interrupted. So, the interruption is much shorter, at the expense of some
+inconsistency.
.TP
.B verbosity \fInumber
Change verbosity value for logging. Same values as \fBverbosity\fR keyword in