Fossil SCM
Add the --poll option to "fossil backoffice" to allow it to act as a backoffice launch daemon.
Commit
1021afc6aa3ea77c9d242b948f306e02c47f5769e76f22cc2b4348ee5e5404b4
Parent
96fc48487662e52…
1 file changed
+52
-19
+52
-19
| --- src/backoffice.c | ||
| +++ src/backoffice.c | ||
| @@ -80,10 +80,11 @@ | ||
| 80 | 80 | # include <signal.h> |
| 81 | 81 | # include <errno.h> |
| 82 | 82 | # include <fcntl.h> |
| 83 | 83 | # define GETPID getpid |
| 84 | 84 | #endif |
| 85 | +#include <time.h> | |
| 85 | 86 | |
| 86 | 87 | /* |
| 87 | 88 | ** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice |
| 88 | 89 | ** processing run is valid. Each backoffice run monopolizes the lease for |
| 89 | 90 | ** at least this amount of time. Hopefully all backoffice processing is |
| @@ -546,51 +547,83 @@ | ||
| 546 | 547 | ** |
| 547 | 548 | ** Run backoffice processing on the repositories listed. If no |
| 548 | 549 | ** repository is specified, run it on the repository of the local checkout. |
| 549 | 550 | ** |
| 550 | 551 | ** This might be done by a cron job or similar to make sure backoffice |
| 551 | -** processing happens periodically. | |
| 552 | +** processing happens periodically. Or, the --poll option can be used | |
| 553 | +** to run this command as a daemon that will periodically invoke backoffice | |
| 554 | +** on collection of repositories. | |
| 555 | +** | |
| 556 | +** OPTIONS: | |
| 552 | 557 | ** |
| 553 | -** Options: | |
| 558 | +** --debug Show what this command is doing. | |
| 554 | 559 | ** |
| 555 | 560 | ** --nodelay Do not queue up or wait for a backoffice job |
| 556 | 561 | ** to complete. If no work is available or if |
| 557 | 562 | ** backoffice has run recently, return immediately. |
| 558 | 563 | ** The --nodelay option is implied if more than |
| 559 | 564 | ** one repository is listed on the command-line. |
| 560 | 565 | ** |
| 566 | +** --poll N Repeat backoffice calls for repositories that | |
| 567 | +** change in appoximately N-second intervals. | |
| 568 | +** N less than 1 turns polling off (the default). | |
| 569 | +** | |
| 561 | 570 | ** --trace Enable debugging output on stderr |
| 562 | 571 | */ |
| 563 | 572 | void backoffice_command(void){ |
| 573 | + int nPoll; | |
| 574 | + const char *zPoll; | |
| 575 | + int bDebug = 0; | |
| 576 | + unsigned int nCmd = 0; | |
| 564 | 577 | if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1; |
| 565 | 578 | if( find_option("nodelay",0,0)!=0 ) backofficeNoDelay = 1; |
| 579 | + zPoll = find_option("poll",0,1); | |
| 580 | + nPoll = zPoll ? atoi(zPoll) : 0; | |
| 581 | + bDebug = find_option("debug",0,0)!=0; | |
| 566 | 582 | |
| 567 | 583 | /* Silently consume the -R or --repository flag, leaving behind its |
| 568 | 584 | ** argument. This is for legacy compatibility. Older versions of the |
| 569 | 585 | ** backoffice command only ran on a single repository that was specified |
| 570 | 586 | ** using the -R option. */ |
| 571 | 587 | (void)find_option("repository","R",0); |
| 572 | 588 | |
| 573 | 589 | verify_all_options(); |
| 574 | - if( g.argc>3 ){ | |
| 575 | - /* Multiple repositories named on the command-line. Run each in a | |
| 576 | - ** separate sub-process */ | |
| 590 | + if( g.argc>3 || nPoll>0 ){ | |
| 591 | + /* Either there are multiple repositories named on the command-line | |
| 592 | + ** or we are polling. In either case, each backoffice should be run | |
| 593 | + ** using a separate sub-process */ | |
| 577 | 594 | int i; |
| 578 | - for(i=2; i<g.argc; i++){ | |
| 579 | - Blob cmd; | |
| 580 | - blob_init(&cmd, 0, 0); | |
| 581 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 582 | - blob_append(&cmd, " backoffice --nodelay", -1); | |
| 583 | - if( g.fAnyTrace ){ | |
| 584 | - blob_append(&cmd, " --trace", -1); | |
| 585 | - } | |
| 586 | - blob_append_escaped_arg(&cmd, g.argv[i]); | |
| 587 | - if( g.fAnyTrace ){ | |
| 588 | - fossil_print("-- %s\n", blob_str(&cmd)); | |
| 589 | - } | |
| 590 | - fossil_system(blob_str(&cmd)); | |
| 591 | - blob_reset(&cmd); | |
| 595 | + time_t iNow = 0; | |
| 596 | + time_t ix; | |
| 597 | + while( 1 /* exit via "break;" */){ | |
| 598 | + time_t iNext = time(0); | |
| 599 | + for(i=2; i<g.argc; i++){ | |
| 600 | + Blob cmd; | |
| 601 | + if( !file_isfile(g.argv[i], ExtFILE) ) continue; | |
| 602 | + if( iNow && iNow>file_mtime(g.argv[i],ExtFILE) ) continue; | |
| 603 | + blob_init(&cmd, 0, 0); | |
| 604 | + blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 605 | + blob_append(&cmd, " backoffice --nodelay", -1); | |
| 606 | + if( g.fAnyTrace ){ | |
| 607 | + blob_append(&cmd, " --trace", -1); | |
| 608 | + } | |
| 609 | + blob_append_escaped_arg(&cmd, g.argv[i]); | |
| 610 | + nCmd++; | |
| 611 | + if( bDebug ){ | |
| 612 | + fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd)); | |
| 613 | + } | |
| 614 | + fossil_system(blob_str(&cmd)); | |
| 615 | + blob_reset(&cmd); | |
| 616 | + } | |
| 617 | + if( nPoll<1 ) break; | |
| 618 | + iNow = iNext; | |
| 619 | + ix = time(0); | |
| 620 | + if( ix < iNow+nPoll ){ | |
| 621 | + sqlite3_int64 nMS = (iNow + nPoll - ix)*1000; | |
| 622 | + if( bDebug )fossil_print("SLEEP: %lld\n", nMS); | |
| 623 | + sqlite3_sleep((int)nMS); | |
| 624 | + } | |
| 592 | 625 | } |
| 593 | 626 | }else{ |
| 594 | 627 | if( g.argc==3 ){ |
| 595 | 628 | g.zRepositoryOption = g.argv[2]; |
| 596 | 629 | g.argc--; |
| 597 | 630 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -80,10 +80,11 @@ | |
| 80 | # include <signal.h> |
| 81 | # include <errno.h> |
| 82 | # include <fcntl.h> |
| 83 | # define GETPID getpid |
| 84 | #endif |
| 85 | |
| 86 | /* |
| 87 | ** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice |
| 88 | ** processing run is valid. Each backoffice run monopolizes the lease for |
| 89 | ** at least this amount of time. Hopefully all backoffice processing is |
| @@ -546,51 +547,83 @@ | |
| 546 | ** |
| 547 | ** Run backoffice processing on the repositories listed. If no |
| 548 | ** repository is specified, run it on the repository of the local checkout. |
| 549 | ** |
| 550 | ** This might be done by a cron job or similar to make sure backoffice |
| 551 | ** processing happens periodically. |
| 552 | ** |
| 553 | ** Options: |
| 554 | ** |
| 555 | ** --nodelay Do not queue up or wait for a backoffice job |
| 556 | ** to complete. If no work is available or if |
| 557 | ** backoffice has run recently, return immediately. |
| 558 | ** The --nodelay option is implied if more than |
| 559 | ** one repository is listed on the command-line. |
| 560 | ** |
| 561 | ** --trace Enable debugging output on stderr |
| 562 | */ |
| 563 | void backoffice_command(void){ |
| 564 | if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1; |
| 565 | if( find_option("nodelay",0,0)!=0 ) backofficeNoDelay = 1; |
| 566 | |
| 567 | /* Silently consume the -R or --repository flag, leaving behind its |
| 568 | ** argument. This is for legacy compatibility. Older versions of the |
| 569 | ** backoffice command only ran on a single repository that was specified |
| 570 | ** using the -R option. */ |
| 571 | (void)find_option("repository","R",0); |
| 572 | |
| 573 | verify_all_options(); |
| 574 | if( g.argc>3 ){ |
| 575 | /* Multiple repositories named on the command-line. Run each in a |
| 576 | ** separate sub-process */ |
| 577 | int i; |
| 578 | for(i=2; i<g.argc; i++){ |
| 579 | Blob cmd; |
| 580 | blob_init(&cmd, 0, 0); |
| 581 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 582 | blob_append(&cmd, " backoffice --nodelay", -1); |
| 583 | if( g.fAnyTrace ){ |
| 584 | blob_append(&cmd, " --trace", -1); |
| 585 | } |
| 586 | blob_append_escaped_arg(&cmd, g.argv[i]); |
| 587 | if( g.fAnyTrace ){ |
| 588 | fossil_print("-- %s\n", blob_str(&cmd)); |
| 589 | } |
| 590 | fossil_system(blob_str(&cmd)); |
| 591 | blob_reset(&cmd); |
| 592 | } |
| 593 | }else{ |
| 594 | if( g.argc==3 ){ |
| 595 | g.zRepositoryOption = g.argv[2]; |
| 596 | g.argc--; |
| 597 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -80,10 +80,11 @@ | |
| 80 | # include <signal.h> |
| 81 | # include <errno.h> |
| 82 | # include <fcntl.h> |
| 83 | # define GETPID getpid |
| 84 | #endif |
| 85 | #include <time.h> |
| 86 | |
| 87 | /* |
| 88 | ** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice |
| 89 | ** processing run is valid. Each backoffice run monopolizes the lease for |
| 90 | ** at least this amount of time. Hopefully all backoffice processing is |
| @@ -546,51 +547,83 @@ | |
| 547 | ** |
| 548 | ** Run backoffice processing on the repositories listed. If no |
| 549 | ** repository is specified, run it on the repository of the local checkout. |
| 550 | ** |
| 551 | ** This might be done by a cron job or similar to make sure backoffice |
| 552 | ** processing happens periodically. Or, the --poll option can be used |
| 553 | ** to run this command as a daemon that will periodically invoke backoffice |
| 554 | ** on collection of repositories. |
| 555 | ** |
| 556 | ** OPTIONS: |
| 557 | ** |
| 558 | ** --debug Show what this command is doing. |
| 559 | ** |
| 560 | ** --nodelay Do not queue up or wait for a backoffice job |
| 561 | ** to complete. If no work is available or if |
| 562 | ** backoffice has run recently, return immediately. |
| 563 | ** The --nodelay option is implied if more than |
| 564 | ** one repository is listed on the command-line. |
| 565 | ** |
| 566 | ** --poll N Repeat backoffice calls for repositories that |
| 567 | ** change in appoximately N-second intervals. |
| 568 | ** N less than 1 turns polling off (the default). |
| 569 | ** |
| 570 | ** --trace Enable debugging output on stderr |
| 571 | */ |
| 572 | void backoffice_command(void){ |
| 573 | int nPoll; |
| 574 | const char *zPoll; |
| 575 | int bDebug = 0; |
| 576 | unsigned int nCmd = 0; |
| 577 | if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1; |
| 578 | if( find_option("nodelay",0,0)!=0 ) backofficeNoDelay = 1; |
| 579 | zPoll = find_option("poll",0,1); |
| 580 | nPoll = zPoll ? atoi(zPoll) : 0; |
| 581 | bDebug = find_option("debug",0,0)!=0; |
| 582 | |
| 583 | /* Silently consume the -R or --repository flag, leaving behind its |
| 584 | ** argument. This is for legacy compatibility. Older versions of the |
| 585 | ** backoffice command only ran on a single repository that was specified |
| 586 | ** using the -R option. */ |
| 587 | (void)find_option("repository","R",0); |
| 588 | |
| 589 | verify_all_options(); |
| 590 | if( g.argc>3 || nPoll>0 ){ |
| 591 | /* Either there are multiple repositories named on the command-line |
| 592 | ** or we are polling. In either case, each backoffice should be run |
| 593 | ** using a separate sub-process */ |
| 594 | int i; |
| 595 | time_t iNow = 0; |
| 596 | time_t ix; |
| 597 | while( 1 /* exit via "break;" */){ |
| 598 | time_t iNext = time(0); |
| 599 | for(i=2; i<g.argc; i++){ |
| 600 | Blob cmd; |
| 601 | if( !file_isfile(g.argv[i], ExtFILE) ) continue; |
| 602 | if( iNow && iNow>file_mtime(g.argv[i],ExtFILE) ) continue; |
| 603 | blob_init(&cmd, 0, 0); |
| 604 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 605 | blob_append(&cmd, " backoffice --nodelay", -1); |
| 606 | if( g.fAnyTrace ){ |
| 607 | blob_append(&cmd, " --trace", -1); |
| 608 | } |
| 609 | blob_append_escaped_arg(&cmd, g.argv[i]); |
| 610 | nCmd++; |
| 611 | if( bDebug ){ |
| 612 | fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd)); |
| 613 | } |
| 614 | fossil_system(blob_str(&cmd)); |
| 615 | blob_reset(&cmd); |
| 616 | } |
| 617 | if( nPoll<1 ) break; |
| 618 | iNow = iNext; |
| 619 | ix = time(0); |
| 620 | if( ix < iNow+nPoll ){ |
| 621 | sqlite3_int64 nMS = (iNow + nPoll - ix)*1000; |
| 622 | if( bDebug )fossil_print("SLEEP: %lld\n", nMS); |
| 623 | sqlite3_sleep((int)nMS); |
| 624 | } |
| 625 | } |
| 626 | }else{ |
| 627 | if( g.argc==3 ){ |
| 628 | g.zRepositoryOption = g.argv[2]; |
| 629 | g.argc--; |
| 630 |