1 /*
2 ** Copyright (c) 2018 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
13 ** drh@hwaci.com
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to manage a background processes that
19 ** occur after user interaction with the repository. Examples of
20 ** backoffice processing includes:
21 **
22 ** * Sending alerts and notifications
23 ** * Processing the email queue
24 ** * Handling post-receive hooks
25 ** * Automatically syncing to peer repositories
26 **
27 ** Backoffice processing is automatically started whenever there are
28 ** changes to the repository. The backoffice process dies off after
29 ** a period of inactivity.
30 **
31 ** Steps are taken to ensure that only a single backoffice process is
32 ** running at a time. Otherwise, there could be race conditions that
33 ** cause adverse effects such as multiple alerts for the same changes.
34 **
35 ** At the same time, we do not want a backoffice process to run forever.
36 ** Backoffice processes should die off after doing whatever work they need
37 ** to do. In this way, we avoid having lots of idle processes in the
38 ** process table, doing nothing on rarely accessed repositories, and
39 ** if the Fossil binary is updated on a system, the backoffice processes
40 ** will restart using the new binary automatically.
41 **
42 ** At any point in time there should be at most two backoffice processes.
43 ** There is a main process that is doing the actually work, and there is
44 ** a second stand-by process that is waiting for the main process to finish
45 ** and that will become the main process after a delay.
46 **
47 ** After any successful web page reply, the backoffice_check_if_needed()
48 ** routine is called. That routine checks to see if both one or both of
49 ** the backoffice processes are already running. That routine remembers the
50 ** status in a global variable.
51 **
52 ** Later, after the repository database is closed, the
53 ** backoffice_run_if_needed() routine is called. If the prior call
54 ** to backoffice_check_if_needed() indicated that backoffice processing
55 ** might be required, the run_if_needed() attempts to kick off a backoffice
56 ** process.
57 **
58 ** All work performance by the backoffice is in the backoffice_work()
59 ** routine.
60 */
61 #if defined(_WIN32)
62 # if defined(_WIN32_WINNT)
63 # undef _WIN32_WINNT
64 # endif
65 # define _WIN32_WINNT 0x501
66 #endif
67 #include "config.h"
68 #include "backoffice.h"
69 #include <time.h>
70 #if defined(_WIN32)
71 # include <windows.h>
72 # include <stdio.h>
73 # include <process.h>
74 # if defined(__MINGW32__)
75 # include <wchar.h>
76 # endif
77 # define GETPID (int)GetCurrentProcessId
78 #else
79 # include <unistd.h>
80 # include <sys/types.h>
81 # include <signal.h>
82 # include <errno.h>
83 # include <sys/time.h>
84 # include <sys/resource.h>
85 # include <fcntl.h>
86 # define GETPID getpid
87 #endif
88 #include <time.h>
89
90 /*
91 ** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice
92 ** processing run is valid. Each backoffice run monopolizes the lease for
93 ** at least this amount of time. Hopefully all backoffice processing is
94 ** finished much faster than this - usually in less than a second. But
95 ** regardless of how long each invocation lasts, successive backoffice runs
96 ** must be spaced out by at least this much time.
97 */
98 #define BKOFCE_LEASE_TIME 60 /* Length of lease validity in seconds */
99
100 #if LOCAL_INTERFACE
101 /*
102 ** An instance of the following object describes a lease on the backoffice
103 ** processing timeslot. This lease is used to help ensure that no more than
104 ** one process is running backoffice at a time.
105 */
106 struct Lease {
107 sqlite3_uint64 idCurrent; /* process ID for the current lease holder */
108 sqlite3_uint64 tmCurrent; /* Expiration of the current lease */
109 sqlite3_uint64 idNext; /* process ID for the next lease holder on queue */
110 sqlite3_uint64 tmNext; /* Expiration of the next lease */
111 };
112 #endif
113
114 /***************************************************************************
115 ** Local state variables
116 **
117 ** Set to prevent backoffice processing from ever entering sleep or
118 ** otherwise taking a long time to complete. Set this when a user-visible
119 ** process might need to wait for backoffice to complete.
120 */
121 static int backofficeNoDelay = 0;
122
123 /* This variable is set to the name of a database on which backoffice
124 ** should run if backoffice process is needed. It is set by the
125 ** backoffice_check_if_needed() routine which must be run while the database
126 ** file is open. Later, after the database is closed, the
127 ** backoffice_run_if_needed() will consult this variable to see if it
128 ** should be a no-op.
129 **
130 ** The magic string "x" in this variable means "do not run the backoffice".
131 */
132 static char *backofficeDb = 0;
133
134 /*
135 ** Log backoffice activity to a file named here. If not NULL, this
136 ** overrides the "backoffice-logfile" setting of the database. If NULL,
137 ** the "backoffice-logfile" setting is used instead.
138 */
139 static const char *backofficeLogfile = 0;
140
141 /*
142 ** Write the log message into this open file.
143 */
144 static FILE *backofficeFILE = 0;
145
146 /*
147 ** Write backoffice log messages on this BLOB. to this connection:
148 */
149 static Blob *backofficeBlob = 0;
150
151 /*
152 ** Non-zero for extra logging detail.
153 */
154 static int backofficeLogDetail = 0;
155
156 /* End of state variables
157 ****************************************************************************/
158
159 /*
160 ** This function emits a diagnostic message related to the processing in
161 ** this module.
162 */
163 #if defined(_WIN32)
164 # define BKOFCE_ALWAYS_TRACE (1)
165 extern void sqlite3_win32_write_debug(const char *, int);
166 #else
167 # define BKOFCE_ALWAYS_TRACE (0)
168 #endif
backofficeTrace(const char * zFormat,...)169 static void backofficeTrace(const char *zFormat, ...){
170 char *zMsg = 0;
171 if( BKOFCE_ALWAYS_TRACE || g.fAnyTrace ){
172 va_list ap;
173 va_start(ap, zFormat);
174 zMsg = sqlite3_vmprintf(zFormat, ap);
175 va_end(ap);
176 #if defined(_WIN32)
177 sqlite3_win32_write_debug(zMsg, -1);
178 #endif
179 }
180 if( g.fAnyTrace ) fprintf(stderr, "%s", zMsg);
181 if( zMsg ) sqlite3_free(zMsg);
182 }
183
184 /*
185 ** Do not allow backoffice processes to sleep waiting on a timeslot.
186 ** They must either do their work immediately or exit.
187 **
188 ** In a perfect world, this interface would not exist, as there would
189 ** never be a problem with waiting backoffice threads. But in some cases
190 ** a backoffice will delay a UI thread, so we don't want them to run for
191 ** longer than needed.
192 */
backoffice_no_delay(void)193 void backoffice_no_delay(void){
194 backofficeNoDelay = 1;
195 }
196
197 /*
198 ** Sleeps for the specified number of milliseconds -OR- until interrupted
199 ** by another thread (if supported by the underlying platform). Non-zero
200 ** will be returned if the sleep was interrupted.
201 */
backofficeSleep(int milliseconds)202 static int backofficeSleep(int milliseconds){
203 #if defined(_WIN32)
204 assert( milliseconds>=0 );
205 if( SleepEx((DWORD)milliseconds, TRUE)==WAIT_IO_COMPLETION ){
206 return 1;
207 }
208 #else
209 sqlite3_sleep(milliseconds);
210 #endif
211 return 0;
212 }
213
214 /*
215 ** Parse a unsigned 64-bit integer from a string. Return a pointer
216 ** to the character of z[] that occurs after the integer.
217 */
backofficeParseInt(const char * z,sqlite3_uint64 * pVal)218 static const char *backofficeParseInt(const char *z, sqlite3_uint64 *pVal){
219 *pVal = 0;
220 if( z==0 ) return 0;
221 while( fossil_isspace(z[0]) ){ z++; }
222 while( fossil_isdigit(z[0]) ){
223 *pVal = (*pVal)*10 + z[0] - '0';
224 z++;
225 }
226 return z;
227 }
228
229 /*
230 ** Read the "backoffice" property and parse it into a Lease object.
231 **
232 ** The backoffice property should consist of four integers:
233 **
234 ** (1) Process ID for the active backoffice process.
235 ** (2) Time (seconds since 1970) for when the active backoffice
236 ** lease expires.
237 ** (3) Process ID for the on-deck backoffice process.
238 ** (4) Time when the on-deck process should expire.
239 **
240 ** No other process should start active backoffice processing until
241 ** process (1) no longer exists and the current time exceeds (2).
242 */
backofficeReadLease(Lease * pLease)243 static void backofficeReadLease(Lease *pLease){
244 Stmt q;
245 memset(pLease, 0, sizeof(*pLease));
246 db_unprotect(PROTECT_CONFIG);
247 db_prepare(&q, "SELECT value FROM repository.config"
248 " WHERE name='backoffice'");
249 if( db_step(&q)==SQLITE_ROW ){
250 const char *z = db_column_text(&q,0);
251 z = backofficeParseInt(z, &pLease->idCurrent);
252 z = backofficeParseInt(z, &pLease->tmCurrent);
253 z = backofficeParseInt(z, &pLease->idNext);
254 backofficeParseInt(z, &pLease->tmNext);
255 }
256 db_finalize(&q);
257 db_protect_pop();
258 }
259
260 /*
261 ** Return a string that describes how long it has been since the
262 ** last backoffice run. The string is obtained from fossil_malloc().
263 */
backoffice_last_run(void)264 char *backoffice_last_run(void){
265 Lease x;
266 sqlite3_uint64 tmNow;
267 double rAge;
268 backofficeReadLease(&x);
269 tmNow = time(0);
270 if( x.tmCurrent==0 ){
271 return fossil_strdup("never");
272 }
273 if( tmNow<=(x.tmCurrent-BKOFCE_LEASE_TIME) ){
274 return fossil_strdup("moments ago");
275 }
276 rAge = (tmNow - (x.tmCurrent-BKOFCE_LEASE_TIME))/86400.0;
277 return mprintf("%z ago", human_readable_age(rAge));
278 }
279
280 /*
281 ** Write a lease to the backoffice property
282 */
backofficeWriteLease(Lease * pLease)283 static void backofficeWriteLease(Lease *pLease){
284 db_unprotect(PROTECT_CONFIG);
285 db_multi_exec(
286 "REPLACE INTO repository.config(name,value,mtime)"
287 " VALUES('backoffice','%lld %lld %lld %lld',now())",
288 pLease->idCurrent, pLease->tmCurrent,
289 pLease->idNext, pLease->tmNext);
290 db_protect_pop();
291 }
292
293 /*
294 ** Check to see if the specified Win32 process is still alive. It
295 ** should be noted that even if this function returns non-zero, the
296 ** process may die before another operation on it can be completed.
297 */
298 #if defined(_WIN32)
299 #ifndef PROCESS_QUERY_LIMITED_INFORMATION
300 # define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
301 #endif
backofficeWin32ProcessExists(DWORD dwProcessId)302 static int backofficeWin32ProcessExists(DWORD dwProcessId){
303 HANDLE hProcess;
304 hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,FALSE,dwProcessId);
305 if( hProcess==NULL ) return 0;
306 CloseHandle(hProcess);
307 return 1;
308 }
309 #endif
310
311 /*
312 ** Check to see if the process identified by pid is alive. If
313 ** we cannot prove that the process is dead, return true.
314 */
backofficeProcessExists(sqlite3_uint64 pid)315 static int backofficeProcessExists(sqlite3_uint64 pid){
316 #if defined(_WIN32)
317 return pid>0 && backofficeWin32ProcessExists((DWORD)pid)!=0;
318 #else
319 return pid>0 && kill((pid_t)pid, 0)==0;
320 #endif
321 }
322
323 /*
324 ** Check to see if the process identified by pid has finished. If
325 ** we cannot prove that the process is still running, return true.
326 */
backofficeProcessDone(sqlite3_uint64 pid)327 static int backofficeProcessDone(sqlite3_uint64 pid){
328 #if defined(_WIN32)
329 return pid<=0 || backofficeWin32ProcessExists((DWORD)pid)==0;
330 #else
331 return pid<=0 || kill((pid_t)pid, 0)!=0;
332 #endif
333 }
334
335 /*
336 ** Return a process id number for the current process
337 */
backofficeProcessId(void)338 static sqlite3_uint64 backofficeProcessId(void){
339 return (sqlite3_uint64)GETPID();
340 }
341
342
343 /*
344 ** COMMAND: test-process-id
345 **
346 ** Usage: %fossil [--sleep N] PROCESS-ID ...
347 **
348 ** Show the current process id, and also tell whether or not all other
349 ** processes IDs on the command line are running or not. If the --sleep N
350 ** option is provide, then sleep for N seconds before exiting.
351 */
test_process_id_command(void)352 void test_process_id_command(void){
353 const char *zSleep = find_option("sleep",0,1);
354 int i;
355 verify_all_options();
356 fossil_print("ProcessID for this process: %lld\n", backofficeProcessId());
357 if( zSleep ) sqlite3_sleep(1000*atoi(zSleep));
358 for(i=2; i<g.argc; i++){
359 sqlite3_uint64 x = (sqlite3_uint64)atoi(g.argv[i]);
360 fossil_print("ProcessId %lld: exists %d done %d\n",
361 x, backofficeProcessExists(x),
362 backofficeProcessDone(x));
363 }
364 }
365
366 /*
367 ** COMMAND: test-backoffice-lease
368 **
369 ** Usage: %fossil test-backoffice-lease ?--reset?
370 **
371 ** Print out information about the backoffice "lease" entry in the
372 ** config table that controls whether or not backoffice should run.
373 **
374 ** If the --reset option is given, the backoffice lease is reset.
375 ** The use of the --reset option can be disruptive. It can cause two
376 ** or more backoffice processes to be run simultaneously. Use it with
377 ** caution.
378 */
test_backoffice_lease(void)379 void test_backoffice_lease(void){
380 sqlite3_int64 tmNow = time(0);
381 Lease x;
382 const char *zLease;
383 db_find_and_open_repository(0,0);
384 if( find_option("reset",0,0)!=0 ){
385 db_unprotect(PROTECT_CONFIG);
386 db_multi_exec(
387 "DELETE FROM repository.config WHERE name='backoffice'"
388 );
389 db_protect_pop();
390 }
391 verify_all_options();
392 zLease = db_get("backoffice","");
393 fossil_print("now: %lld\n", tmNow);
394 fossil_print("lease: \"%s\"\n", zLease);
395 backofficeReadLease(&x);
396 fossil_print("idCurrent: %-20lld", x.idCurrent);
397 if( backofficeProcessExists(x.idCurrent) ) fossil_print(" (exists)");
398 if( backofficeProcessDone(x.idCurrent) ) fossil_print(" (done)");
399 fossil_print("\n");
400 fossil_print("tmCurrent: %-20lld", x.tmCurrent);
401 if( x.tmCurrent>0 ){
402 fossil_print(" (now%+d)\n",x.tmCurrent-tmNow);
403 }else{
404 fossil_print("\n");
405 }
406 fossil_print("idNext: %-20lld", x.idNext);
407 if( backofficeProcessExists(x.idNext) ) fossil_print(" (exists)");
408 if( backofficeProcessDone(x.idNext) ) fossil_print(" (done)");
409 fossil_print("\n");
410 fossil_print("tmNext: %-20lld", x.tmNext);
411 if( x.tmNext>0 ){
412 fossil_print(" (now%+d)\n",x.tmNext-tmNow);
413 }else{
414 fossil_print("\n");
415 }
416 }
417
418 /*
419 ** If backoffice processing is needed set the backofficeDb variable to the
420 ** name of the database file. If no backoffice processing is needed,
421 ** this routine makes no changes to state.
422 */
backoffice_check_if_needed(void)423 void backoffice_check_if_needed(void){
424 Lease x;
425 sqlite3_uint64 tmNow;
426
427 if( backofficeDb ) return;
428 if( g.zRepositoryName==0 ) return;
429 if( g.db==0 ) return;
430 if( !db_table_exists("repository","config") ) return;
431 if( db_get_boolean("backoffice-disable",0) ) return;
432 tmNow = time(0);
433 backofficeReadLease(&x);
434 if( x.tmNext>=tmNow && backofficeProcessExists(x.idNext) ){
435 /* Another backoffice process is already queued up to run. This
436 ** process does not need to do any backoffice work. */
437 return;
438 }else{
439 /* We need to run backup to be (at a minimum) on-deck */
440 backofficeDb = fossil_strdup(g.zRepositoryName);
441 }
442 }
443
444 /*
445 ** Call this routine to disable backoffice
446 */
backoffice_disable(void)447 void backoffice_disable(void){
448 backofficeDb = "x";
449 }
450
451 /*
452 ** Check for errors prior to running backoffice_thread() or backoffice_run().
453 */
backoffice_error_check_one(int * pOnce)454 static void backoffice_error_check_one(int *pOnce){
455 if( *pOnce ){
456 fossil_panic("multiple calls to backoffice()");
457 }
458 *pOnce = 1;
459 if( g.db==0 ){
460 fossil_panic("database not open for backoffice processing");
461 }
462 if( db_transaction_nesting_depth()!=0 ){
463 fossil_panic("transaction %s not closed prior to backoffice processing",
464 db_transaction_start_point());
465 }
466 }
467
468 /* This is the main loop for backoffice processing.
469 **
470 ** If another process is already working as the current backoffice and
471 ** the on-deck backoffice, then this routine returns very quickly
472 ** without doing any work.
473 **
474 ** If no backoffice processes are running at all, this routine becomes
475 ** the main backoffice.
476 **
477 ** If a primary backoffice is running, but a on-deck backoffice is
478 ** needed, this routine becomes that on-deck backoffice.
479 */
backoffice_thread(void)480 static void backoffice_thread(void){
481 Lease x;
482 sqlite3_uint64 tmNow;
483 sqlite3_uint64 idSelf;
484 int lastWarning = 0;
485 int warningDelay = 30;
486 static int once = 0;
487
488 if( sqlite3_db_readonly(g.db, 0) ) return;
489 g.zPhase = "backoffice";
490 backoffice_error_check_one(&once);
491 idSelf = backofficeProcessId();
492 while(1){
493 tmNow = time(0);
494 db_begin_write();
495 backofficeReadLease(&x);
496 if( x.tmNext>=tmNow
497 && x.idNext!=idSelf
498 && backofficeProcessExists(x.idNext)
499 ){
500 /* Another backoffice process is already queued up to run. This
501 ** process does not need to do any backoffice work and can stop
502 ** immediately. */
503 db_end_transaction(0);
504 backofficeTrace("/***** Backoffice Processing Not Needed In %d *****/\n",
505 GETPID());
506 break;
507 }
508 if( x.tmCurrent<tmNow && backofficeProcessDone(x.idCurrent) ){
509 /* This process can start doing backoffice work immediately */
510 x.idCurrent = idSelf;
511 x.tmCurrent = tmNow + BKOFCE_LEASE_TIME;
512 x.idNext = 0;
513 x.tmNext = 0;
514 backofficeWriteLease(&x);
515 db_end_transaction(0);
516 backofficeTrace("/***** Begin Backoffice Processing %d *****/\n",
517 GETPID());
518 backoffice_work();
519 break;
520 }
521 if( backofficeNoDelay || db_get_boolean("backoffice-nodelay",0) ){
522 /* If the no-delay flag is set, exit immediately rather than queuing
523 ** up. Assume that some future request will come along and handle any
524 ** necessary backoffice work. */
525 db_end_transaction(0);
526 backofficeTrace(
527 "/***** Backoffice No-Delay Exit For %d *****/\n",
528 GETPID());
529 break;
530 }
531 /* This process needs to queue up and wait for the current lease
532 ** to expire before continuing. */
533 x.idNext = idSelf;
534 x.tmNext = (tmNow>x.tmCurrent ? tmNow : x.tmCurrent) + BKOFCE_LEASE_TIME;
535 backofficeWriteLease(&x);
536 db_end_transaction(0);
537 backofficeTrace("/***** Backoffice On-deck %d *****/\n", GETPID());
538 if( x.tmCurrent >= tmNow ){
539 if( backofficeSleep(1000*(x.tmCurrent - tmNow + 1)) ){
540 /* The sleep was interrupted by a signal from another thread. */
541 backofficeTrace("/***** Backoffice Interrupt %d *****/\n", GETPID());
542 db_end_transaction(0);
543 break;
544 }
545 }else{
546 if( lastWarning+warningDelay < tmNow ){
547 fossil_warning(
548 "backoffice process %lld still running after %d seconds",
549 x.idCurrent, (int)(BKOFCE_LEASE_TIME + tmNow - x.tmCurrent));
550 lastWarning = tmNow;
551 warningDelay *= 2;
552 }
553 if( backofficeSleep(1000) ){
554 /* The sleep was interrupted by a signal from another thread. */
555 backofficeTrace("/***** Backoffice Interrupt %d *****/\n", GETPID());
556 db_end_transaction(0);
557 break;
558 }
559 }
560 }
561 return;
562 }
563
564 /*
565 ** Append to a message to the backoffice log, if the log is open.
566 */
backoffice_log(const char * zFormat,...)567 void backoffice_log(const char *zFormat, ...){
568 va_list ap;
569 if( backofficeBlob==0 ) return;
570 blob_append_char(backofficeBlob, ' ');
571 va_start(ap, zFormat);
572 blob_vappendf(backofficeBlob, zFormat, ap);
573 va_end(ap);
574 }
575
576 #if !defined(_WIN32)
577 /*
578 ** Capture routine for signals while running backoffice.
579 */
backoffice_signal_handler(int sig)580 static void backoffice_signal_handler(int sig){
581 const char *zSig = 0;
582 if( sig==SIGSEGV ) zSig = "SIGSEGV";
583 if( sig==SIGFPE ) zSig = "SIGFPE";
584 if( sig==SIGABRT ) zSig = "SIGABRT";
585 if( sig==SIGILL ) zSig = "SIGILL";
586 if( zSig==0 ){
587 backoffice_log("signal-%d", sig);
588 }else{
589 backoffice_log("%s", zSig);
590 }
591 fprintf(backofficeFILE, "%s\n", blob_str(backofficeBlob));
592 fflush(backofficeFILE);
593 exit(1);
594 }
595 #endif
596
597 #if !defined(_WIN32)
598 /*
599 ** Convert a struct timeval into an integer number of microseconds
600 */
tvms(struct timeval * p)601 static long long int tvms(struct timeval *p){
602 return ((long long int)p->tv_sec)*1000000 + (long long int)p->tv_usec;
603 }
604 #endif
605
606
607 /*
608 ** This routine runs to do the backoffice processing. When adding new
609 ** backoffice processing tasks, add them here.
610 */
backoffice_work(void)611 void backoffice_work(void){
612 /* Log the backoffice run for testing purposes. For production deployments
613 ** the "backoffice-logfile" property should be unset and the following code
614 ** should be a no-op. */
615 const char *zLog = backofficeLogfile;
616 Blob log;
617 int nThis;
618 int nTotal = 0;
619 #if !defined(_WIN32)
620 struct timeval sStart, sEnd;
621 #endif
622 if( zLog==0 ) zLog = db_get("backoffice-logfile",0);
623 if( zLog && zLog[0] && (backofficeFILE = fossil_fopen(zLog,"a"))!=0 ){
624 int i;
625 char *zName = db_get("project-name",0);
626 #if !defined(_WIN32)
627 gettimeofday(&sStart, 0);
628 signal(SIGSEGV, backoffice_signal_handler);
629 signal(SIGABRT, backoffice_signal_handler);
630 signal(SIGFPE, backoffice_signal_handler);
631 signal(SIGILL, backoffice_signal_handler);
632 #endif
633 if( zName==0 ){
634 zName = (char*)file_tail(g.zRepositoryName);
635 if( zName==0 ) zName = "(unnamed)";
636 }else{
637 /* Convert all spaces in the "project-name" into dashes */
638 for(i=0; zName[i]; i++){ if( zName[i]==' ' ) zName[i] = '-'; }
639 }
640 blob_init(&log, 0, 0);
641 backofficeBlob = &log;
642 blob_appendf(&log, "%s %s", db_text(0, "SELECT datetime('now')"), zName);
643 }
644
645 /* Here is where the actual work of the backoffice happens */
646 nThis = alert_backoffice(0);
647 if( nThis ){ backoffice_log("%d alerts", nThis); nTotal += nThis; }
648 nThis = hook_backoffice();
649 if( nThis ){ backoffice_log("%d hooks", nThis); nTotal += nThis; }
650
651 /* Close the log */
652 if( backofficeFILE ){
653 if( nTotal || backofficeLogDetail ){
654 if( nTotal==0 ) backoffice_log("no-op");
655 #if !defined(_WIN32)
656 gettimeofday(&sEnd,0);
657 backoffice_log("elapse-time %d us", tvms(&sEnd) - tvms(&sStart));
658 #endif
659 fprintf(backofficeFILE, "%s\n", blob_str(backofficeBlob));
660 }
661 fclose(backofficeFILE);
662 }
663 }
664
665 /*
666 ** COMMAND: backoffice*
667 **
668 ** Usage: %fossil backoffice [OPTIONS...] [REPOSITORIES...]
669 **
670 ** Run backoffice processing on the repositories listed. If no
671 ** repository is specified, run it on the repository of the local checkout.
672 **
673 ** This might be done by a cron job or similar to make sure backoffice
674 ** processing happens periodically. Or, the --poll option can be used
675 ** to run this command as a daemon that will periodically invoke backoffice
676 ** on a collection of repositories.
677 **
678 ** If only a single repository is named and --poll is omitted, then the
679 ** backoffice work is done in-process. But if there are multiple repositories
680 ** or if --poll is used, a separate sub-process is started for each poll of
681 ** each repository.
682 **
683 ** Standard options:
684 **
685 ** --debug Show what this command is doing.
686 **
687 ** --logfile FILE Append a log of backoffice actions onto FILE.
688 **
689 ** --min N When polling, invoke backoffice at least
690 ** once every N seconds even if the repository
691 ** never changes. 0 or negative means disable
692 ** this feature. Default: 3600 (once per hour).
693 **
694 ** --poll N Repeat backoffice calls for repositories that
695 ** change in appoximately N-second intervals.
696 ** N less than 1 turns polling off (the default).
697 ** Recommended polling interval: 60 seconds.
698 **
699 ** --trace Enable debugging output on stderr
700 **
701 ** Options intended for internal use only which may change or be
702 ** discontinued in future releases:
703 **
704 ** --nodelay Do not queue up or wait for a backoffice job
705 ** to complete. If no work is available or if
706 ** backoffice has run recently, return immediately.
707 **
708 ** --nolease Always run backoffice, even if there is a lease
709 ** conflict. This option implies --nodelay. This
710 ** option is added to secondary backoffice commands
711 ** that are invoked by the --poll option.
712 */
backoffice_command(void)713 void backoffice_command(void){
714 int nPoll;
715 int nMin;
716 const char *zPoll;
717 int bDebug = 0;
718 int bNoLease = 0;
719 unsigned int nCmd = 0;
720 if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1;
721 if( find_option("nodelay",0,0)!=0 ) backofficeNoDelay = 1;
722 backofficeLogfile = find_option("logfile",0,1);
723 zPoll = find_option("poll",0,1);
724 nPoll = zPoll ? atoi(zPoll) : 0;
725 zPoll = find_option("min",0,1);
726 nMin = zPoll ? atoi(zPoll) : 3600;
727 bDebug = find_option("debug",0,0)!=0;
728 bNoLease = find_option("nolease",0,0)!=0;
729
730 /* Silently consume the -R or --repository flag, leaving behind its
731 ** argument. This is for legacy compatibility. Older versions of the
732 ** backoffice command only ran on a single repository that was specified
733 ** using the -R option. */
734 (void)find_option("repository","R",0);
735
736 verify_all_options();
737 if( g.argc>3 || nPoll>0 ){
738 /* Either there are multiple repositories named on the command-line
739 ** or we are polling. In either case, each backoffice should be run
740 ** using a separate sub-process */
741 int i;
742 time_t iNow = 0;
743 time_t ix;
744 i64 *aLastRun = fossil_malloc( sizeof(i64)*g.argc );
745 memset(aLastRun, 0, sizeof(i64)*g.argc );
746 while( 1 /* exit via "break;" */){
747 time_t iNext = time(0);
748 for(i=2; i<g.argc; i++){
749 Blob cmd;
750 if( !file_isfile(g.argv[i], ExtFILE) ){
751 continue; /* Repo no longer exists. Ignore it. */
752 }
753 if( iNow
754 && iNow>file_mtime(g.argv[i], ExtFILE)
755 && (nMin<=0 || aLastRun[i]+nMin>iNow)
756 ){
757 continue; /* Not yet time to run this one */
758 }
759 blob_init(&cmd, 0, 0);
760 blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
761 blob_append(&cmd, " backoffice --nodelay", -1);
762 if( g.fAnyTrace ){
763 blob_append(&cmd, " --trace", -1);
764 }
765 if( bDebug ){
766 blob_append(&cmd, " --debug", -1);
767 }
768 if( nPoll>0 ){
769 blob_append(&cmd, " --nolease", -1);
770 }
771 if( backofficeLogfile ){
772 blob_append(&cmd, " --logfile", -1);
773 blob_append_escaped_arg(&cmd, backofficeLogfile, 1);
774 }
775 blob_append_escaped_arg(&cmd, g.argv[i], 1);
776 nCmd++;
777 if( bDebug ){
778 fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd));
779 }
780 fossil_system(blob_str(&cmd));
781 aLastRun[i] = iNext;
782 blob_reset(&cmd);
783 }
784 if( nPoll<1 ) break;
785 iNow = iNext;
786 ix = time(0);
787 if( ix < iNow+nPoll ){
788 sqlite3_int64 nMS = (iNow + nPoll - ix)*1000;
789 if( bDebug )fossil_print("SLEEP: %lld\n", nMS);
790 sqlite3_sleep((int)nMS);
791 }
792 }
793 }else{
794 /* Not polling and only one repository named. Backoffice is run
795 ** once by this process, which then exits */
796 if( g.argc==3 ){
797 g.zRepositoryOption = g.argv[2];
798 g.argc--;
799 }
800 db_find_and_open_repository(0,0);
801 if( bDebug ){
802 backofficeLogDetail = 1;
803 }
804 if( bNoLease ){
805 backoffice_work();
806 }else{
807 backoffice_thread();
808 }
809 }
810 }
811
812 /*
813 ** This is the main interface to backoffice from the rest of the system.
814 ** This routine launches either backoffice_thread() directly or as a
815 ** subprocess.
816 */
backoffice_run_if_needed(void)817 void backoffice_run_if_needed(void){
818 if( backofficeDb==0 ) return;
819 if( strcmp(backofficeDb,"x")==0 ) return;
820 if( g.db ) return;
821 if( g.repositoryOpen ) return;
822 #if defined(_WIN32)
823 {
824 int i;
825 intptr_t x;
826 char *argv[4];
827 wchar_t *ax[5];
828 argv[0] = g.nameOfExe;
829 argv[1] = "backoffice";
830 argv[2] = "-R";
831 argv[3] = backofficeDb;
832 ax[4] = 0;
833 for(i=0; i<=3; i++) ax[i] = fossil_utf8_to_unicode(argv[i]);
834 x = _wspawnv(_P_NOWAIT, ax[0], (const wchar_t * const *)ax);
835 for(i=0; i<=3; i++) fossil_unicode_free(ax[i]);
836 backofficeTrace(
837 "/***** Subprocess %d creates backoffice child %lu *****/\n",
838 GETPID(), GetProcessId((HANDLE)x));
839 if( x>=0 ) return;
840 }
841 #else /* unix */
842 {
843 pid_t pid = fork();
844 if( pid>0 ){
845 /* This is the parent in a successful fork(). Return immediately. */
846 backofficeTrace(
847 "/***** Subprocess %d creates backoffice child %d *****/\n",
848 GETPID(), (int)pid);
849 return;
850 }
851 if( pid==0 ){
852 /* This is the child of a successful fork(). Run backoffice. */
853 int i;
854 setsid();
855 for(i=0; i<=2; i++){
856 close(i);
857 open("/dev/null", O_RDWR);
858 }
859 for(i=3; i<100; i++){ close(i); }
860 g.fDebug = 0;
861 g.httpIn = 0;
862 g.httpOut = 0;
863 db_open_repository(backofficeDb);
864 backofficeDb = "x";
865 backoffice_thread();
866 db_close(1);
867 backofficeTrace("/***** Backoffice Child %d exits *****/\n", GETPID());
868 exit(0);
869 }
870 fossil_warning("backoffice process %d fork failed, errno %d", GETPID(),
871 errno);
872 }
873 #endif
874 /* Fork() failed or is unavailable. Run backoffice in this process, but
875 ** do so with the no-delay setting.
876 */
877 backofficeNoDelay = 1;
878 db_open_repository(backofficeDb);
879 backofficeDb = "x";
880 backoffice_thread();
881 db_close(1);
882 }
883