Fossil SCM
Use the fork() system call (when available) to start backoffice, in an attempt to avoid unseemly delays in upstream.
Commit
a4b59c320796b31166851b6ea5e3d5505f23ce15bd55f9e87caa2e27e961d4ff
Parent
99fcc43f5d57ee5…
11 files changed
+121
-32
+121
-32
+1
-1
+1
-1
+1
+1
+1
-1
-2
-2
+2
-2
+2
-2
+121
-32
| --- src/backoffice.c | ||
| +++ src/backoffice.c | ||
| @@ -71,23 +71,30 @@ | ||
| 71 | 71 | sqlite3_uint64 idNext; /* ID for the next lease holder on queue */ |
| 72 | 72 | sqlite3_uint64 tmNext; /* Expiration of the next lease */ |
| 73 | 73 | }; |
| 74 | 74 | #endif |
| 75 | 75 | |
| 76 | -/* | |
| 77 | -** Set to prevent backoffice processing from every entering sleep or | |
| 76 | +/*************************************************************************** | |
| 77 | +** Local state variables | |
| 78 | +** | |
| 79 | +** Set to prevent backoffice processing from ever entering sleep or | |
| 78 | 80 | ** otherwise taking a long time to complete. Set this when a user-visible |
| 79 | 81 | ** process might need to wait for backoffice to complete. |
| 80 | 82 | */ |
| 81 | 83 | static int backofficeNoDelay = 0; |
| 82 | 84 | |
| 83 | -/* | |
| 84 | -** Disable the backoffice | |
| 85 | +/* This variable is set to the name of a database on which backoffice | |
| 86 | +** should run if backoffice process is needed. It is set by the | |
| 87 | +** backoffice_check_if_needed() routine which must be run while the database | |
| 88 | +** file is open. Later, after the database is closed, the | |
| 89 | +** backoffice_run_if_needed() will consult this variable to see if it | |
| 90 | +** should be a no-op. | |
| 85 | 91 | */ |
| 86 | -void backoffice_no_delay(void){ | |
| 87 | - backofficeNoDelay = 1; | |
| 88 | -} | |
| 92 | +static char *backofficeDb = 0; | |
| 93 | + | |
| 94 | +/* End of state variables | |
| 95 | +****************************************************************************/ | |
| 89 | 96 | |
| 90 | 97 | /* |
| 91 | 98 | ** Parse a unsigned 64-bit integer from a string. Return a pointer |
| 92 | 99 | ** to the character of z[] that occurs after the integer. |
| 93 | 100 | */ |
| @@ -205,36 +212,72 @@ | ||
| 205 | 212 | x, backofficeProcessExists(x), |
| 206 | 213 | backofficeProcessDone(x)); |
| 207 | 214 | } |
| 208 | 215 | } |
| 209 | 216 | |
| 210 | -/* This is the main public interface to the backoffice. A process invokes this | |
| 211 | -** routine in an attempt to become the backoffice. If another process is | |
| 212 | -** already working as the backoffice, this routine returns very quickly | |
| 213 | -** without doing any work - allowing the other process to continue. But | |
| 214 | -** if no other processes are currently operating as the backoffice, this | |
| 215 | -** routine enters a loop to do background work periodically. | |
| 217 | +/* | |
| 218 | +** If backoffice processing is needed set the backofficeDb value to the | |
| 219 | +** name of the database file. If no backoffice processing is needed, | |
| 220 | +** this routine makes no changes to state. | |
| 216 | 221 | */ |
| 217 | -void backoffice_run(void){ | |
| 222 | +void backoffice_check_if_needed(void){ | |
| 218 | 223 | Lease x; |
| 219 | 224 | sqlite3_uint64 tmNow; |
| 220 | - sqlite3_uint64 idSelf; | |
| 221 | - int lastWarning = 0; | |
| 222 | - int warningDelay = 30; | |
| 223 | - static int once = 0; | |
| 224 | - | |
| 225 | - if( once ){ | |
| 226 | - fossil_panic("multiple calls to backoffice_run()"); | |
| 227 | - } | |
| 228 | - once = 1; | |
| 225 | + | |
| 226 | + if( backofficeDb ) return; | |
| 227 | + if( g.zRepositoryName==0 ) return; | |
| 228 | + if( g.db==0 ) return; | |
| 229 | + tmNow = time(0); | |
| 230 | + backofficeReadLease(&x); | |
| 231 | + if( x.tmNext>=tmNow && backofficeProcessExists(x.idNext) ){ | |
| 232 | + /* Another backoffice process is already queued up to run. This | |
| 233 | + ** process does not need to do any backoffice work. */ | |
| 234 | + return; | |
| 235 | + }else{ | |
| 236 | + /* We need to run backup to be (at a minimum) on-deck */ | |
| 237 | + backofficeDb = fossil_strdup(g.zRepositoryName); | |
| 238 | + } | |
| 239 | +} | |
| 240 | + | |
| 241 | +/* | |
| 242 | +** Check for errors prior to running backoffice_thread() or backoffice_run(). | |
| 243 | +*/ | |
| 244 | +static void backoffice_error_check_one(int *pOnce){ | |
| 245 | + if( *pOnce ){ | |
| 246 | + fossil_panic("multiple calls to backoffice()"); | |
| 247 | + } | |
| 248 | + *pOnce = 1; | |
| 229 | 249 | if( g.db==0 ){ |
| 230 | 250 | fossil_panic("database not open for backoffice processing"); |
| 231 | 251 | } |
| 232 | 252 | if( db_transaction_nesting_depth()!=0 ){ |
| 233 | 253 | fossil_panic("transaction %s not closed prior to backoffice processing", |
| 234 | 254 | db_transaction_start_point()); |
| 235 | 255 | } |
| 256 | +} | |
| 257 | + | |
| 258 | +/* This is the main loop for backoffice processing. | |
| 259 | +** | |
| 260 | +** If others process is already working as the current backoffice and | |
| 261 | +** the on-deck backoffice, then this routine returns very quickly | |
| 262 | +** without doing any work. | |
| 263 | +** | |
| 264 | +** If no backoffice processes are running at all, this routine becomes | |
| 265 | +** the main backoffice. | |
| 266 | +** | |
| 267 | +** If a primary backoffice is running, but a on-deck backoffice is | |
| 268 | +** needed, this routine becomes that backoffice. | |
| 269 | +*/ | |
| 270 | +static void backoffice_thread(void){ | |
| 271 | + Lease x; | |
| 272 | + sqlite3_uint64 tmNow; | |
| 273 | + sqlite3_uint64 idSelf; | |
| 274 | + int lastWarning = 0; | |
| 275 | + int warningDelay = 30; | |
| 276 | + static int once = 0; | |
| 277 | + | |
| 278 | + backoffice_error_check_one(&once); | |
| 236 | 279 | backofficeTimeout(BKOFCE_LEASE_TIME*2); |
| 237 | 280 | idSelf = backofficeProcessId(); |
| 238 | 281 | while(1){ |
| 239 | 282 | tmNow = time(0); |
| 240 | 283 | db_begin_write(); |
| @@ -303,15 +346,61 @@ | ||
| 303 | 346 | void backoffice_work(void){ |
| 304 | 347 | email_backoffice(0); |
| 305 | 348 | } |
| 306 | 349 | |
| 307 | 350 | /* |
| 308 | -** COMMAND: test-backoffice | |
| 309 | -** | |
| 310 | -** Usage: test-backoffice | |
| 311 | -** | |
| 312 | -** Run backoffice processing | |
| 313 | -*/ | |
| 314 | -void test_backoffice_command(void){ | |
| 315 | - db_find_and_open_repository(0,0); | |
| 316 | - backoffice_run(); | |
| 351 | +** COMMAND: backoffice | |
| 352 | +** | |
| 353 | +** Usage: backoffice [-R repository] | |
| 354 | +** | |
| 355 | +** Run backoffice processing. This might be done by a cron job or | |
| 356 | +** similar to make sure backoffice processing happens periodically. | |
| 357 | +*/ | |
| 358 | +void backoffice_command(void){ | |
| 359 | + verify_all_options(); | |
| 360 | + db_find_and_open_repository(0,0); | |
| 361 | + backoffice_thread(); | |
| 362 | +} | |
| 363 | + | |
| 364 | +/* | |
| 365 | +** This is the main interface to backoffice from the rest of the system. | |
| 366 | +** This routine launches either backoffice_thread() directly or as a | |
| 367 | +** subprocess. | |
| 368 | +*/ | |
| 369 | +void backoffice_run_if_needed(void){ | |
| 370 | + if( backofficeDb==0 ) return; | |
| 371 | + if( strcmp(backofficeDb,"x")==0 ) return; | |
| 372 | + if( g.db ) return; | |
| 373 | + if( g.repositoryOpen ) return; | |
| 374 | +#if !defined(_WIN32) | |
| 375 | + { | |
| 376 | + pid_t pid = fork(); | |
| 377 | + if( pid>0 ){ | |
| 378 | + /* This is the parent in a successful fork(). Return immediately. */ | |
| 379 | + if( g.fAnyTrace ){ | |
| 380 | + fprintf(stderr, "/***** Backoffice Child Creates as %d *****/\n", | |
| 381 | + (int)pid); | |
| 382 | + } | |
| 383 | + return; | |
| 384 | + } | |
| 385 | + if( pid==0 ){ | |
| 386 | + /* This is the child of a successful fork(). Run backoffice. */ | |
| 387 | + db_open_repository(backofficeDb); | |
| 388 | + backofficeDb = "x"; | |
| 389 | + backoffice_thread(); | |
| 390 | + db_close(1); | |
| 391 | + if( g.fAnyTrace ){ | |
| 392 | + fprintf(stderr, "/***** Backoffice Child %d exits *****/\n", getpid()); | |
| 393 | + } | |
| 394 | + exit(0); | |
| 395 | + } | |
| 396 | + } | |
| 397 | +#endif | |
| 398 | + /* Fork() failed or is unavailable. Run backoffice in this process, but | |
| 399 | + ** do so with the no-delay setting. | |
| 400 | + */ | |
| 401 | + backofficeNoDelay = 1; | |
| 402 | + db_open_repository(backofficeDb); | |
| 403 | + backofficeDb = "x"; | |
| 404 | + backoffice_thread(); | |
| 405 | + db_close(1); | |
| 317 | 406 | } |
| 318 | 407 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -71,23 +71,30 @@ | |
| 71 | sqlite3_uint64 idNext; /* ID for the next lease holder on queue */ |
| 72 | sqlite3_uint64 tmNext; /* Expiration of the next lease */ |
| 73 | }; |
| 74 | #endif |
| 75 | |
| 76 | /* |
| 77 | ** Set to prevent backoffice processing from every entering sleep or |
| 78 | ** otherwise taking a long time to complete. Set this when a user-visible |
| 79 | ** process might need to wait for backoffice to complete. |
| 80 | */ |
| 81 | static int backofficeNoDelay = 0; |
| 82 | |
| 83 | /* |
| 84 | ** Disable the backoffice |
| 85 | */ |
| 86 | void backoffice_no_delay(void){ |
| 87 | backofficeNoDelay = 1; |
| 88 | } |
| 89 | |
| 90 | /* |
| 91 | ** Parse a unsigned 64-bit integer from a string. Return a pointer |
| 92 | ** to the character of z[] that occurs after the integer. |
| 93 | */ |
| @@ -205,36 +212,72 @@ | |
| 205 | x, backofficeProcessExists(x), |
| 206 | backofficeProcessDone(x)); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | /* This is the main public interface to the backoffice. A process invokes this |
| 211 | ** routine in an attempt to become the backoffice. If another process is |
| 212 | ** already working as the backoffice, this routine returns very quickly |
| 213 | ** without doing any work - allowing the other process to continue. But |
| 214 | ** if no other processes are currently operating as the backoffice, this |
| 215 | ** routine enters a loop to do background work periodically. |
| 216 | */ |
| 217 | void backoffice_run(void){ |
| 218 | Lease x; |
| 219 | sqlite3_uint64 tmNow; |
| 220 | sqlite3_uint64 idSelf; |
| 221 | int lastWarning = 0; |
| 222 | int warningDelay = 30; |
| 223 | static int once = 0; |
| 224 | |
| 225 | if( once ){ |
| 226 | fossil_panic("multiple calls to backoffice_run()"); |
| 227 | } |
| 228 | once = 1; |
| 229 | if( g.db==0 ){ |
| 230 | fossil_panic("database not open for backoffice processing"); |
| 231 | } |
| 232 | if( db_transaction_nesting_depth()!=0 ){ |
| 233 | fossil_panic("transaction %s not closed prior to backoffice processing", |
| 234 | db_transaction_start_point()); |
| 235 | } |
| 236 | backofficeTimeout(BKOFCE_LEASE_TIME*2); |
| 237 | idSelf = backofficeProcessId(); |
| 238 | while(1){ |
| 239 | tmNow = time(0); |
| 240 | db_begin_write(); |
| @@ -303,15 +346,61 @@ | |
| 303 | void backoffice_work(void){ |
| 304 | email_backoffice(0); |
| 305 | } |
| 306 | |
| 307 | /* |
| 308 | ** COMMAND: test-backoffice |
| 309 | ** |
| 310 | ** Usage: test-backoffice |
| 311 | ** |
| 312 | ** Run backoffice processing |
| 313 | */ |
| 314 | void test_backoffice_command(void){ |
| 315 | db_find_and_open_repository(0,0); |
| 316 | backoffice_run(); |
| 317 | } |
| 318 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -71,23 +71,30 @@ | |
| 71 | sqlite3_uint64 idNext; /* ID for the next lease holder on queue */ |
| 72 | sqlite3_uint64 tmNext; /* Expiration of the next lease */ |
| 73 | }; |
| 74 | #endif |
| 75 | |
| 76 | /*************************************************************************** |
| 77 | ** Local state variables |
| 78 | ** |
| 79 | ** Set to prevent backoffice processing from ever entering sleep or |
| 80 | ** otherwise taking a long time to complete. Set this when a user-visible |
| 81 | ** process might need to wait for backoffice to complete. |
| 82 | */ |
| 83 | static int backofficeNoDelay = 0; |
| 84 | |
| 85 | /* This variable is set to the name of a database on which backoffice |
| 86 | ** should run if backoffice process is needed. It is set by the |
| 87 | ** backoffice_check_if_needed() routine which must be run while the database |
| 88 | ** file is open. Later, after the database is closed, the |
| 89 | ** backoffice_run_if_needed() will consult this variable to see if it |
| 90 | ** should be a no-op. |
| 91 | */ |
| 92 | static char *backofficeDb = 0; |
| 93 | |
| 94 | /* End of state variables |
| 95 | ****************************************************************************/ |
| 96 | |
| 97 | /* |
| 98 | ** Parse a unsigned 64-bit integer from a string. Return a pointer |
| 99 | ** to the character of z[] that occurs after the integer. |
| 100 | */ |
| @@ -205,36 +212,72 @@ | |
| 212 | x, backofficeProcessExists(x), |
| 213 | backofficeProcessDone(x)); |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | /* |
| 218 | ** If backoffice processing is needed set the backofficeDb value to the |
| 219 | ** name of the database file. If no backoffice processing is needed, |
| 220 | ** this routine makes no changes to state. |
| 221 | */ |
| 222 | void backoffice_check_if_needed(void){ |
| 223 | Lease x; |
| 224 | sqlite3_uint64 tmNow; |
| 225 | |
| 226 | if( backofficeDb ) return; |
| 227 | if( g.zRepositoryName==0 ) return; |
| 228 | if( g.db==0 ) return; |
| 229 | tmNow = time(0); |
| 230 | backofficeReadLease(&x); |
| 231 | if( x.tmNext>=tmNow && backofficeProcessExists(x.idNext) ){ |
| 232 | /* Another backoffice process is already queued up to run. This |
| 233 | ** process does not need to do any backoffice work. */ |
| 234 | return; |
| 235 | }else{ |
| 236 | /* We need to run backup to be (at a minimum) on-deck */ |
| 237 | backofficeDb = fossil_strdup(g.zRepositoryName); |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | /* |
| 242 | ** Check for errors prior to running backoffice_thread() or backoffice_run(). |
| 243 | */ |
| 244 | static void backoffice_error_check_one(int *pOnce){ |
| 245 | if( *pOnce ){ |
| 246 | fossil_panic("multiple calls to backoffice()"); |
| 247 | } |
| 248 | *pOnce = 1; |
| 249 | if( g.db==0 ){ |
| 250 | fossil_panic("database not open for backoffice processing"); |
| 251 | } |
| 252 | if( db_transaction_nesting_depth()!=0 ){ |
| 253 | fossil_panic("transaction %s not closed prior to backoffice processing", |
| 254 | db_transaction_start_point()); |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | /* This is the main loop for backoffice processing. |
| 259 | ** |
| 260 | ** If others process is already working as the current backoffice and |
| 261 | ** the on-deck backoffice, then this routine returns very quickly |
| 262 | ** without doing any work. |
| 263 | ** |
| 264 | ** If no backoffice processes are running at all, this routine becomes |
| 265 | ** the main backoffice. |
| 266 | ** |
| 267 | ** If a primary backoffice is running, but a on-deck backoffice is |
| 268 | ** needed, this routine becomes that backoffice. |
| 269 | */ |
| 270 | static void backoffice_thread(void){ |
| 271 | Lease x; |
| 272 | sqlite3_uint64 tmNow; |
| 273 | sqlite3_uint64 idSelf; |
| 274 | int lastWarning = 0; |
| 275 | int warningDelay = 30; |
| 276 | static int once = 0; |
| 277 | |
| 278 | backoffice_error_check_one(&once); |
| 279 | backofficeTimeout(BKOFCE_LEASE_TIME*2); |
| 280 | idSelf = backofficeProcessId(); |
| 281 | while(1){ |
| 282 | tmNow = time(0); |
| 283 | db_begin_write(); |
| @@ -303,15 +346,61 @@ | |
| 346 | void backoffice_work(void){ |
| 347 | email_backoffice(0); |
| 348 | } |
| 349 | |
| 350 | /* |
| 351 | ** COMMAND: backoffice |
| 352 | ** |
| 353 | ** Usage: backoffice [-R repository] |
| 354 | ** |
| 355 | ** Run backoffice processing. This might be done by a cron job or |
| 356 | ** similar to make sure backoffice processing happens periodically. |
| 357 | */ |
| 358 | void backoffice_command(void){ |
| 359 | verify_all_options(); |
| 360 | db_find_and_open_repository(0,0); |
| 361 | backoffice_thread(); |
| 362 | } |
| 363 | |
| 364 | /* |
| 365 | ** This is the main interface to backoffice from the rest of the system. |
| 366 | ** This routine launches either backoffice_thread() directly or as a |
| 367 | ** subprocess. |
| 368 | */ |
| 369 | void backoffice_run_if_needed(void){ |
| 370 | if( backofficeDb==0 ) return; |
| 371 | if( strcmp(backofficeDb,"x")==0 ) return; |
| 372 | if( g.db ) return; |
| 373 | if( g.repositoryOpen ) return; |
| 374 | #if !defined(_WIN32) |
| 375 | { |
| 376 | pid_t pid = fork(); |
| 377 | if( pid>0 ){ |
| 378 | /* This is the parent in a successful fork(). Return immediately. */ |
| 379 | if( g.fAnyTrace ){ |
| 380 | fprintf(stderr, "/***** Backoffice Child Creates as %d *****/\n", |
| 381 | (int)pid); |
| 382 | } |
| 383 | return; |
| 384 | } |
| 385 | if( pid==0 ){ |
| 386 | /* This is the child of a successful fork(). Run backoffice. */ |
| 387 | db_open_repository(backofficeDb); |
| 388 | backofficeDb = "x"; |
| 389 | backoffice_thread(); |
| 390 | db_close(1); |
| 391 | if( g.fAnyTrace ){ |
| 392 | fprintf(stderr, "/***** Backoffice Child %d exits *****/\n", getpid()); |
| 393 | } |
| 394 | exit(0); |
| 395 | } |
| 396 | } |
| 397 | #endif |
| 398 | /* Fork() failed or is unavailable. Run backoffice in this process, but |
| 399 | ** do so with the no-delay setting. |
| 400 | */ |
| 401 | backofficeNoDelay = 1; |
| 402 | db_open_repository(backofficeDb); |
| 403 | backofficeDb = "x"; |
| 404 | backoffice_thread(); |
| 405 | db_close(1); |
| 406 | } |
| 407 |
+121
-32
| --- src/backoffice.c | ||
| +++ src/backoffice.c | ||
| @@ -71,23 +71,30 @@ | ||
| 71 | 71 | sqlite3_uint64 idNext; /* ID for the next lease holder on queue */ |
| 72 | 72 | sqlite3_uint64 tmNext; /* Expiration of the next lease */ |
| 73 | 73 | }; |
| 74 | 74 | #endif |
| 75 | 75 | |
| 76 | -/* | |
| 77 | -** Set to prevent backoffice processing from every entering sleep or | |
| 76 | +/*************************************************************************** | |
| 77 | +** Local state variables | |
| 78 | +** | |
| 79 | +** Set to prevent backoffice processing from ever entering sleep or | |
| 78 | 80 | ** otherwise taking a long time to complete. Set this when a user-visible |
| 79 | 81 | ** process might need to wait for backoffice to complete. |
| 80 | 82 | */ |
| 81 | 83 | static int backofficeNoDelay = 0; |
| 82 | 84 | |
| 83 | -/* | |
| 84 | -** Disable the backoffice | |
| 85 | +/* This variable is set to the name of a database on which backoffice | |
| 86 | +** should run if backoffice process is needed. It is set by the | |
| 87 | +** backoffice_check_if_needed() routine which must be run while the database | |
| 88 | +** file is open. Later, after the database is closed, the | |
| 89 | +** backoffice_run_if_needed() will consult this variable to see if it | |
| 90 | +** should be a no-op. | |
| 85 | 91 | */ |
| 86 | -void backoffice_no_delay(void){ | |
| 87 | - backofficeNoDelay = 1; | |
| 88 | -} | |
| 92 | +static char *backofficeDb = 0; | |
| 93 | + | |
| 94 | +/* End of state variables | |
| 95 | +****************************************************************************/ | |
| 89 | 96 | |
| 90 | 97 | /* |
| 91 | 98 | ** Parse a unsigned 64-bit integer from a string. Return a pointer |
| 92 | 99 | ** to the character of z[] that occurs after the integer. |
| 93 | 100 | */ |
| @@ -205,36 +212,72 @@ | ||
| 205 | 212 | x, backofficeProcessExists(x), |
| 206 | 213 | backofficeProcessDone(x)); |
| 207 | 214 | } |
| 208 | 215 | } |
| 209 | 216 | |
| 210 | -/* This is the main public interface to the backoffice. A process invokes this | |
| 211 | -** routine in an attempt to become the backoffice. If another process is | |
| 212 | -** already working as the backoffice, this routine returns very quickly | |
| 213 | -** without doing any work - allowing the other process to continue. But | |
| 214 | -** if no other processes are currently operating as the backoffice, this | |
| 215 | -** routine enters a loop to do background work periodically. | |
| 217 | +/* | |
| 218 | +** If backoffice processing is needed set the backofficeDb value to the | |
| 219 | +** name of the database file. If no backoffice processing is needed, | |
| 220 | +** this routine makes no changes to state. | |
| 216 | 221 | */ |
| 217 | -void backoffice_run(void){ | |
| 222 | +void backoffice_check_if_needed(void){ | |
| 218 | 223 | Lease x; |
| 219 | 224 | sqlite3_uint64 tmNow; |
| 220 | - sqlite3_uint64 idSelf; | |
| 221 | - int lastWarning = 0; | |
| 222 | - int warningDelay = 30; | |
| 223 | - static int once = 0; | |
| 224 | - | |
| 225 | - if( once ){ | |
| 226 | - fossil_panic("multiple calls to backoffice_run()"); | |
| 227 | - } | |
| 228 | - once = 1; | |
| 225 | + | |
| 226 | + if( backofficeDb ) return; | |
| 227 | + if( g.zRepositoryName==0 ) return; | |
| 228 | + if( g.db==0 ) return; | |
| 229 | + tmNow = time(0); | |
| 230 | + backofficeReadLease(&x); | |
| 231 | + if( x.tmNext>=tmNow && backofficeProcessExists(x.idNext) ){ | |
| 232 | + /* Another backoffice process is already queued up to run. This | |
| 233 | + ** process does not need to do any backoffice work. */ | |
| 234 | + return; | |
| 235 | + }else{ | |
| 236 | + /* We need to run backup to be (at a minimum) on-deck */ | |
| 237 | + backofficeDb = fossil_strdup(g.zRepositoryName); | |
| 238 | + } | |
| 239 | +} | |
| 240 | + | |
| 241 | +/* | |
| 242 | +** Check for errors prior to running backoffice_thread() or backoffice_run(). | |
| 243 | +*/ | |
| 244 | +static void backoffice_error_check_one(int *pOnce){ | |
| 245 | + if( *pOnce ){ | |
| 246 | + fossil_panic("multiple calls to backoffice()"); | |
| 247 | + } | |
| 248 | + *pOnce = 1; | |
| 229 | 249 | if( g.db==0 ){ |
| 230 | 250 | fossil_panic("database not open for backoffice processing"); |
| 231 | 251 | } |
| 232 | 252 | if( db_transaction_nesting_depth()!=0 ){ |
| 233 | 253 | fossil_panic("transaction %s not closed prior to backoffice processing", |
| 234 | 254 | db_transaction_start_point()); |
| 235 | 255 | } |
| 256 | +} | |
| 257 | + | |
| 258 | +/* This is the main loop for backoffice processing. | |
| 259 | +** | |
| 260 | +** If others process is already working as the current backoffice and | |
| 261 | +** the on-deck backoffice, then this routine returns very quickly | |
| 262 | +** without doing any work. | |
| 263 | +** | |
| 264 | +** If no backoffice processes are running at all, this routine becomes | |
| 265 | +** the main backoffice. | |
| 266 | +** | |
| 267 | +** If a primary backoffice is running, but a on-deck backoffice is | |
| 268 | +** needed, this routine becomes that backoffice. | |
| 269 | +*/ | |
| 270 | +static void backoffice_thread(void){ | |
| 271 | + Lease x; | |
| 272 | + sqlite3_uint64 tmNow; | |
| 273 | + sqlite3_uint64 idSelf; | |
| 274 | + int lastWarning = 0; | |
| 275 | + int warningDelay = 30; | |
| 276 | + static int once = 0; | |
| 277 | + | |
| 278 | + backoffice_error_check_one(&once); | |
| 236 | 279 | backofficeTimeout(BKOFCE_LEASE_TIME*2); |
| 237 | 280 | idSelf = backofficeProcessId(); |
| 238 | 281 | while(1){ |
| 239 | 282 | tmNow = time(0); |
| 240 | 283 | db_begin_write(); |
| @@ -303,15 +346,61 @@ | ||
| 303 | 346 | void backoffice_work(void){ |
| 304 | 347 | email_backoffice(0); |
| 305 | 348 | } |
| 306 | 349 | |
| 307 | 350 | /* |
| 308 | -** COMMAND: test-backoffice | |
| 309 | -** | |
| 310 | -** Usage: test-backoffice | |
| 311 | -** | |
| 312 | -** Run backoffice processing | |
| 313 | -*/ | |
| 314 | -void test_backoffice_command(void){ | |
| 315 | - db_find_and_open_repository(0,0); | |
| 316 | - backoffice_run(); | |
| 351 | +** COMMAND: backoffice | |
| 352 | +** | |
| 353 | +** Usage: backoffice [-R repository] | |
| 354 | +** | |
| 355 | +** Run backoffice processing. This might be done by a cron job or | |
| 356 | +** similar to make sure backoffice processing happens periodically. | |
| 357 | +*/ | |
| 358 | +void backoffice_command(void){ | |
| 359 | + verify_all_options(); | |
| 360 | + db_find_and_open_repository(0,0); | |
| 361 | + backoffice_thread(); | |
| 362 | +} | |
| 363 | + | |
| 364 | +/* | |
| 365 | +** This is the main interface to backoffice from the rest of the system. | |
| 366 | +** This routine launches either backoffice_thread() directly or as a | |
| 367 | +** subprocess. | |
| 368 | +*/ | |
| 369 | +void backoffice_run_if_needed(void){ | |
| 370 | + if( backofficeDb==0 ) return; | |
| 371 | + if( strcmp(backofficeDb,"x")==0 ) return; | |
| 372 | + if( g.db ) return; | |
| 373 | + if( g.repositoryOpen ) return; | |
| 374 | +#if !defined(_WIN32) | |
| 375 | + { | |
| 376 | + pid_t pid = fork(); | |
| 377 | + if( pid>0 ){ | |
| 378 | + /* This is the parent in a successful fork(). Return immediately. */ | |
| 379 | + if( g.fAnyTrace ){ | |
| 380 | + fprintf(stderr, "/***** Backoffice Child Creates as %d *****/\n", | |
| 381 | + (int)pid); | |
| 382 | + } | |
| 383 | + return; | |
| 384 | + } | |
| 385 | + if( pid==0 ){ | |
| 386 | + /* This is the child of a successful fork(). Run backoffice. */ | |
| 387 | + db_open_repository(backofficeDb); | |
| 388 | + backofficeDb = "x"; | |
| 389 | + backoffice_thread(); | |
| 390 | + db_close(1); | |
| 391 | + if( g.fAnyTrace ){ | |
| 392 | + fprintf(stderr, "/***** Backoffice Child %d exits *****/\n", getpid()); | |
| 393 | + } | |
| 394 | + exit(0); | |
| 395 | + } | |
| 396 | + } | |
| 397 | +#endif | |
| 398 | + /* Fork() failed or is unavailable. Run backoffice in this process, but | |
| 399 | + ** do so with the no-delay setting. | |
| 400 | + */ | |
| 401 | + backofficeNoDelay = 1; | |
| 402 | + db_open_repository(backofficeDb); | |
| 403 | + backofficeDb = "x"; | |
| 404 | + backoffice_thread(); | |
| 405 | + db_close(1); | |
| 317 | 406 | } |
| 318 | 407 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -71,23 +71,30 @@ | |
| 71 | sqlite3_uint64 idNext; /* ID for the next lease holder on queue */ |
| 72 | sqlite3_uint64 tmNext; /* Expiration of the next lease */ |
| 73 | }; |
| 74 | #endif |
| 75 | |
| 76 | /* |
| 77 | ** Set to prevent backoffice processing from every entering sleep or |
| 78 | ** otherwise taking a long time to complete. Set this when a user-visible |
| 79 | ** process might need to wait for backoffice to complete. |
| 80 | */ |
| 81 | static int backofficeNoDelay = 0; |
| 82 | |
| 83 | /* |
| 84 | ** Disable the backoffice |
| 85 | */ |
| 86 | void backoffice_no_delay(void){ |
| 87 | backofficeNoDelay = 1; |
| 88 | } |
| 89 | |
| 90 | /* |
| 91 | ** Parse a unsigned 64-bit integer from a string. Return a pointer |
| 92 | ** to the character of z[] that occurs after the integer. |
| 93 | */ |
| @@ -205,36 +212,72 @@ | |
| 205 | x, backofficeProcessExists(x), |
| 206 | backofficeProcessDone(x)); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | /* This is the main public interface to the backoffice. A process invokes this |
| 211 | ** routine in an attempt to become the backoffice. If another process is |
| 212 | ** already working as the backoffice, this routine returns very quickly |
| 213 | ** without doing any work - allowing the other process to continue. But |
| 214 | ** if no other processes are currently operating as the backoffice, this |
| 215 | ** routine enters a loop to do background work periodically. |
| 216 | */ |
| 217 | void backoffice_run(void){ |
| 218 | Lease x; |
| 219 | sqlite3_uint64 tmNow; |
| 220 | sqlite3_uint64 idSelf; |
| 221 | int lastWarning = 0; |
| 222 | int warningDelay = 30; |
| 223 | static int once = 0; |
| 224 | |
| 225 | if( once ){ |
| 226 | fossil_panic("multiple calls to backoffice_run()"); |
| 227 | } |
| 228 | once = 1; |
| 229 | if( g.db==0 ){ |
| 230 | fossil_panic("database not open for backoffice processing"); |
| 231 | } |
| 232 | if( db_transaction_nesting_depth()!=0 ){ |
| 233 | fossil_panic("transaction %s not closed prior to backoffice processing", |
| 234 | db_transaction_start_point()); |
| 235 | } |
| 236 | backofficeTimeout(BKOFCE_LEASE_TIME*2); |
| 237 | idSelf = backofficeProcessId(); |
| 238 | while(1){ |
| 239 | tmNow = time(0); |
| 240 | db_begin_write(); |
| @@ -303,15 +346,61 @@ | |
| 303 | void backoffice_work(void){ |
| 304 | email_backoffice(0); |
| 305 | } |
| 306 | |
| 307 | /* |
| 308 | ** COMMAND: test-backoffice |
| 309 | ** |
| 310 | ** Usage: test-backoffice |
| 311 | ** |
| 312 | ** Run backoffice processing |
| 313 | */ |
| 314 | void test_backoffice_command(void){ |
| 315 | db_find_and_open_repository(0,0); |
| 316 | backoffice_run(); |
| 317 | } |
| 318 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -71,23 +71,30 @@ | |
| 71 | sqlite3_uint64 idNext; /* ID for the next lease holder on queue */ |
| 72 | sqlite3_uint64 tmNext; /* Expiration of the next lease */ |
| 73 | }; |
| 74 | #endif |
| 75 | |
| 76 | /*************************************************************************** |
| 77 | ** Local state variables |
| 78 | ** |
| 79 | ** Set to prevent backoffice processing from ever entering sleep or |
| 80 | ** otherwise taking a long time to complete. Set this when a user-visible |
| 81 | ** process might need to wait for backoffice to complete. |
| 82 | */ |
| 83 | static int backofficeNoDelay = 0; |
| 84 | |
| 85 | /* This variable is set to the name of a database on which backoffice |
| 86 | ** should run if backoffice process is needed. It is set by the |
| 87 | ** backoffice_check_if_needed() routine which must be run while the database |
| 88 | ** file is open. Later, after the database is closed, the |
| 89 | ** backoffice_run_if_needed() will consult this variable to see if it |
| 90 | ** should be a no-op. |
| 91 | */ |
| 92 | static char *backofficeDb = 0; |
| 93 | |
| 94 | /* End of state variables |
| 95 | ****************************************************************************/ |
| 96 | |
| 97 | /* |
| 98 | ** Parse a unsigned 64-bit integer from a string. Return a pointer |
| 99 | ** to the character of z[] that occurs after the integer. |
| 100 | */ |
| @@ -205,36 +212,72 @@ | |
| 212 | x, backofficeProcessExists(x), |
| 213 | backofficeProcessDone(x)); |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | /* |
| 218 | ** If backoffice processing is needed set the backofficeDb value to the |
| 219 | ** name of the database file. If no backoffice processing is needed, |
| 220 | ** this routine makes no changes to state. |
| 221 | */ |
| 222 | void backoffice_check_if_needed(void){ |
| 223 | Lease x; |
| 224 | sqlite3_uint64 tmNow; |
| 225 | |
| 226 | if( backofficeDb ) return; |
| 227 | if( g.zRepositoryName==0 ) return; |
| 228 | if( g.db==0 ) return; |
| 229 | tmNow = time(0); |
| 230 | backofficeReadLease(&x); |
| 231 | if( x.tmNext>=tmNow && backofficeProcessExists(x.idNext) ){ |
| 232 | /* Another backoffice process is already queued up to run. This |
| 233 | ** process does not need to do any backoffice work. */ |
| 234 | return; |
| 235 | }else{ |
| 236 | /* We need to run backup to be (at a minimum) on-deck */ |
| 237 | backofficeDb = fossil_strdup(g.zRepositoryName); |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | /* |
| 242 | ** Check for errors prior to running backoffice_thread() or backoffice_run(). |
| 243 | */ |
| 244 | static void backoffice_error_check_one(int *pOnce){ |
| 245 | if( *pOnce ){ |
| 246 | fossil_panic("multiple calls to backoffice()"); |
| 247 | } |
| 248 | *pOnce = 1; |
| 249 | if( g.db==0 ){ |
| 250 | fossil_panic("database not open for backoffice processing"); |
| 251 | } |
| 252 | if( db_transaction_nesting_depth()!=0 ){ |
| 253 | fossil_panic("transaction %s not closed prior to backoffice processing", |
| 254 | db_transaction_start_point()); |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | /* This is the main loop for backoffice processing. |
| 259 | ** |
| 260 | ** If others process is already working as the current backoffice and |
| 261 | ** the on-deck backoffice, then this routine returns very quickly |
| 262 | ** without doing any work. |
| 263 | ** |
| 264 | ** If no backoffice processes are running at all, this routine becomes |
| 265 | ** the main backoffice. |
| 266 | ** |
| 267 | ** If a primary backoffice is running, but a on-deck backoffice is |
| 268 | ** needed, this routine becomes that backoffice. |
| 269 | */ |
| 270 | static void backoffice_thread(void){ |
| 271 | Lease x; |
| 272 | sqlite3_uint64 tmNow; |
| 273 | sqlite3_uint64 idSelf; |
| 274 | int lastWarning = 0; |
| 275 | int warningDelay = 30; |
| 276 | static int once = 0; |
| 277 | |
| 278 | backoffice_error_check_one(&once); |
| 279 | backofficeTimeout(BKOFCE_LEASE_TIME*2); |
| 280 | idSelf = backofficeProcessId(); |
| 281 | while(1){ |
| 282 | tmNow = time(0); |
| 283 | db_begin_write(); |
| @@ -303,15 +346,61 @@ | |
| 346 | void backoffice_work(void){ |
| 347 | email_backoffice(0); |
| 348 | } |
| 349 | |
| 350 | /* |
| 351 | ** COMMAND: backoffice |
| 352 | ** |
| 353 | ** Usage: backoffice [-R repository] |
| 354 | ** |
| 355 | ** Run backoffice processing. This might be done by a cron job or |
| 356 | ** similar to make sure backoffice processing happens periodically. |
| 357 | */ |
| 358 | void backoffice_command(void){ |
| 359 | verify_all_options(); |
| 360 | db_find_and_open_repository(0,0); |
| 361 | backoffice_thread(); |
| 362 | } |
| 363 | |
| 364 | /* |
| 365 | ** This is the main interface to backoffice from the rest of the system. |
| 366 | ** This routine launches either backoffice_thread() directly or as a |
| 367 | ** subprocess. |
| 368 | */ |
| 369 | void backoffice_run_if_needed(void){ |
| 370 | if( backofficeDb==0 ) return; |
| 371 | if( strcmp(backofficeDb,"x")==0 ) return; |
| 372 | if( g.db ) return; |
| 373 | if( g.repositoryOpen ) return; |
| 374 | #if !defined(_WIN32) |
| 375 | { |
| 376 | pid_t pid = fork(); |
| 377 | if( pid>0 ){ |
| 378 | /* This is the parent in a successful fork(). Return immediately. */ |
| 379 | if( g.fAnyTrace ){ |
| 380 | fprintf(stderr, "/***** Backoffice Child Creates as %d *****/\n", |
| 381 | (int)pid); |
| 382 | } |
| 383 | return; |
| 384 | } |
| 385 | if( pid==0 ){ |
| 386 | /* This is the child of a successful fork(). Run backoffice. */ |
| 387 | db_open_repository(backofficeDb); |
| 388 | backofficeDb = "x"; |
| 389 | backoffice_thread(); |
| 390 | db_close(1); |
| 391 | if( g.fAnyTrace ){ |
| 392 | fprintf(stderr, "/***** Backoffice Child %d exits *****/\n", getpid()); |
| 393 | } |
| 394 | exit(0); |
| 395 | } |
| 396 | } |
| 397 | #endif |
| 398 | /* Fork() failed or is unavailable. Run backoffice in this process, but |
| 399 | ** do so with the no-delay setting. |
| 400 | */ |
| 401 | backofficeNoDelay = 1; |
| 402 | db_open_repository(backofficeDb); |
| 403 | backofficeDb = "x"; |
| 404 | backoffice_thread(); |
| 405 | db_close(1); |
| 406 | } |
| 407 |
+1
-1
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -354,11 +354,11 @@ | ||
| 354 | 354 | g.httpOut = fossil_fopen("/dev/null", "wb"); |
| 355 | 355 | #endif |
| 356 | 356 | if( g.httpOut==0 ){ |
| 357 | 357 | fossil_warning("failed ot open /dev/null"); |
| 358 | 358 | }else{ |
| 359 | - backoffice_run(); | |
| 359 | + backoffice_check_if_needed(); | |
| 360 | 360 | } |
| 361 | 361 | } |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | 364 | /* |
| 365 | 365 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -354,11 +354,11 @@ | |
| 354 | g.httpOut = fossil_fopen("/dev/null", "wb"); |
| 355 | #endif |
| 356 | if( g.httpOut==0 ){ |
| 357 | fossil_warning("failed ot open /dev/null"); |
| 358 | }else{ |
| 359 | backoffice_run(); |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | /* |
| 365 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -354,11 +354,11 @@ | |
| 354 | g.httpOut = fossil_fopen("/dev/null", "wb"); |
| 355 | #endif |
| 356 | if( g.httpOut==0 ){ |
| 357 | fossil_warning("failed ot open /dev/null"); |
| 358 | }else{ |
| 359 | backoffice_check_if_needed(); |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | /* |
| 365 |
+1
-1
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -354,11 +354,11 @@ | ||
| 354 | 354 | g.httpOut = fossil_fopen("/dev/null", "wb"); |
| 355 | 355 | #endif |
| 356 | 356 | if( g.httpOut==0 ){ |
| 357 | 357 | fossil_warning("failed ot open /dev/null"); |
| 358 | 358 | }else{ |
| 359 | - backoffice_run(); | |
| 359 | + backoffice_check_if_needed(); | |
| 360 | 360 | } |
| 361 | 361 | } |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | 364 | /* |
| 365 | 365 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -354,11 +354,11 @@ | |
| 354 | g.httpOut = fossil_fopen("/dev/null", "wb"); |
| 355 | #endif |
| 356 | if( g.httpOut==0 ){ |
| 357 | fossil_warning("failed ot open /dev/null"); |
| 358 | }else{ |
| 359 | backoffice_run(); |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | /* |
| 365 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -354,11 +354,11 @@ | |
| 354 | g.httpOut = fossil_fopen("/dev/null", "wb"); |
| 355 | #endif |
| 356 | if( g.httpOut==0 ){ |
| 357 | fossil_warning("failed ot open /dev/null"); |
| 358 | }else{ |
| 359 | backoffice_check_if_needed(); |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | /* |
| 365 |
M
src/db.c
+1
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1880,10 +1880,11 @@ | ||
| 1880 | 1880 | } |
| 1881 | 1881 | g.repositoryOpen = 0; |
| 1882 | 1882 | g.localOpen = 0; |
| 1883 | 1883 | assert( g.dbConfig==0 ); |
| 1884 | 1884 | assert( g.zConfigDbName==0 ); |
| 1885 | + backoffice_run_if_needed(); | |
| 1885 | 1886 | } |
| 1886 | 1887 | |
| 1887 | 1888 | /* |
| 1888 | 1889 | ** Close the database as quickly as possible without unnecessary processing. |
| 1889 | 1890 | */ |
| 1890 | 1891 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1880,10 +1880,11 @@ | |
| 1880 | } |
| 1881 | g.repositoryOpen = 0; |
| 1882 | g.localOpen = 0; |
| 1883 | assert( g.dbConfig==0 ); |
| 1884 | assert( g.zConfigDbName==0 ); |
| 1885 | } |
| 1886 | |
| 1887 | /* |
| 1888 | ** Close the database as quickly as possible without unnecessary processing. |
| 1889 | */ |
| 1890 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1880,10 +1880,11 @@ | |
| 1880 | } |
| 1881 | g.repositoryOpen = 0; |
| 1882 | g.localOpen = 0; |
| 1883 | assert( g.dbConfig==0 ); |
| 1884 | assert( g.zConfigDbName==0 ); |
| 1885 | backoffice_run_if_needed(); |
| 1886 | } |
| 1887 | |
| 1888 | /* |
| 1889 | ** Close the database as quickly as possible without unnecessary processing. |
| 1890 | */ |
| 1891 |
M
src/db.c
+1
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1880,10 +1880,11 @@ | ||
| 1880 | 1880 | } |
| 1881 | 1881 | g.repositoryOpen = 0; |
| 1882 | 1882 | g.localOpen = 0; |
| 1883 | 1883 | assert( g.dbConfig==0 ); |
| 1884 | 1884 | assert( g.zConfigDbName==0 ); |
| 1885 | + backoffice_run_if_needed(); | |
| 1885 | 1886 | } |
| 1886 | 1887 | |
| 1887 | 1888 | /* |
| 1888 | 1889 | ** Close the database as quickly as possible without unnecessary processing. |
| 1889 | 1890 | */ |
| 1890 | 1891 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1880,10 +1880,11 @@ | |
| 1880 | } |
| 1881 | g.repositoryOpen = 0; |
| 1882 | g.localOpen = 0; |
| 1883 | assert( g.dbConfig==0 ); |
| 1884 | assert( g.zConfigDbName==0 ); |
| 1885 | } |
| 1886 | |
| 1887 | /* |
| 1888 | ** Close the database as quickly as possible without unnecessary processing. |
| 1889 | */ |
| 1890 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1880,10 +1880,11 @@ | |
| 1880 | } |
| 1881 | g.repositoryOpen = 0; |
| 1882 | g.localOpen = 0; |
| 1883 | assert( g.dbConfig==0 ); |
| 1884 | assert( g.zConfigDbName==0 ); |
| 1885 | backoffice_run_if_needed(); |
| 1886 | } |
| 1887 | |
| 1888 | /* |
| 1889 | ** Close the database as quickly as possible without unnecessary processing. |
| 1890 | */ |
| 1891 |
+1
-1
| --- src/http_transport.c | ||
| +++ src/http_transport.c | ||
| @@ -270,11 +270,11 @@ | ||
| 270 | 270 | void transport_flip(UrlData *pUrlData){ |
| 271 | 271 | if( pUrlData->isFile ){ |
| 272 | 272 | char *zCmd; |
| 273 | 273 | fclose(transport.pFile); |
| 274 | 274 | zCmd = mprintf("\"%s\" http --in \"%s\" --out \"%s\" --ipaddr 127.0.0.1" |
| 275 | - " \"%s\" --localauth --nodelay", | |
| 275 | + " \"%s\" --localauth", | |
| 276 | 276 | g.nameOfExe, transport.zOutFile, transport.zInFile, pUrlData->name |
| 277 | 277 | ); |
| 278 | 278 | fossil_system(zCmd); |
| 279 | 279 | free(zCmd); |
| 280 | 280 | transport.pFile = fossil_fopen(transport.zInFile, "rb"); |
| 281 | 281 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -270,11 +270,11 @@ | |
| 270 | void transport_flip(UrlData *pUrlData){ |
| 271 | if( pUrlData->isFile ){ |
| 272 | char *zCmd; |
| 273 | fclose(transport.pFile); |
| 274 | zCmd = mprintf("\"%s\" http --in \"%s\" --out \"%s\" --ipaddr 127.0.0.1" |
| 275 | " \"%s\" --localauth --nodelay", |
| 276 | g.nameOfExe, transport.zOutFile, transport.zInFile, pUrlData->name |
| 277 | ); |
| 278 | fossil_system(zCmd); |
| 279 | free(zCmd); |
| 280 | transport.pFile = fossil_fopen(transport.zInFile, "rb"); |
| 281 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -270,11 +270,11 @@ | |
| 270 | void transport_flip(UrlData *pUrlData){ |
| 271 | if( pUrlData->isFile ){ |
| 272 | char *zCmd; |
| 273 | fclose(transport.pFile); |
| 274 | zCmd = mprintf("\"%s\" http --in \"%s\" --out \"%s\" --ipaddr 127.0.0.1" |
| 275 | " \"%s\" --localauth", |
| 276 | g.nameOfExe, transport.zOutFile, transport.zInFile, pUrlData->name |
| 277 | ); |
| 278 | fossil_system(zCmd); |
| 279 | free(zCmd); |
| 280 | transport.pFile = fossil_fopen(transport.zInFile, "rb"); |
| 281 |
-2
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -2297,11 +2297,10 @@ | ||
| 2297 | 2297 | ** --host NAME specify hostname of the server |
| 2298 | 2298 | ** --https signal a request coming in via https |
| 2299 | 2299 | ** --in FILE Take input from FILE instead of standard input |
| 2300 | 2300 | ** --ipaddr ADDR Assume the request comes from the given IP address |
| 2301 | 2301 | ** --nocompress do not compress HTTP replies |
| 2302 | -** --nodelay omit backoffice processing if it would delay process exit | |
| 2303 | 2302 | ** --nojail drop root privilege but do not enter the chroot jail |
| 2304 | 2303 | ** --nossl signal that no SSL connections are available |
| 2305 | 2304 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 2306 | 2305 | ** --out FILE write results to FILE instead of to standard output |
| 2307 | 2306 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| @@ -2364,11 +2363,10 @@ | ||
| 2364 | 2363 | g.httpOut = stdout; |
| 2365 | 2364 | } |
| 2366 | 2365 | zIpAddr = find_option("ipaddr",0,1); |
| 2367 | 2366 | useSCGI = find_option("scgi", 0, 0)!=0; |
| 2368 | 2367 | zAltBase = find_option("baseurl", 0, 1); |
| 2369 | - if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay(); | |
| 2370 | 2368 | if( zAltBase ) set_base_url(zAltBase); |
| 2371 | 2369 | if( find_option("https",0,0)!=0 ){ |
| 2372 | 2370 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2373 | 2371 | cgi_replace_parameter("HTTPS","on"); |
| 2374 | 2372 | } |
| 2375 | 2373 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -2297,11 +2297,10 @@ | |
| 2297 | ** --host NAME specify hostname of the server |
| 2298 | ** --https signal a request coming in via https |
| 2299 | ** --in FILE Take input from FILE instead of standard input |
| 2300 | ** --ipaddr ADDR Assume the request comes from the given IP address |
| 2301 | ** --nocompress do not compress HTTP replies |
| 2302 | ** --nodelay omit backoffice processing if it would delay process exit |
| 2303 | ** --nojail drop root privilege but do not enter the chroot jail |
| 2304 | ** --nossl signal that no SSL connections are available |
| 2305 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 2306 | ** --out FILE write results to FILE instead of to standard output |
| 2307 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| @@ -2364,11 +2363,10 @@ | |
| 2364 | g.httpOut = stdout; |
| 2365 | } |
| 2366 | zIpAddr = find_option("ipaddr",0,1); |
| 2367 | useSCGI = find_option("scgi", 0, 0)!=0; |
| 2368 | zAltBase = find_option("baseurl", 0, 1); |
| 2369 | if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay(); |
| 2370 | if( zAltBase ) set_base_url(zAltBase); |
| 2371 | if( find_option("https",0,0)!=0 ){ |
| 2372 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2373 | cgi_replace_parameter("HTTPS","on"); |
| 2374 | } |
| 2375 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -2297,11 +2297,10 @@ | |
| 2297 | ** --host NAME specify hostname of the server |
| 2298 | ** --https signal a request coming in via https |
| 2299 | ** --in FILE Take input from FILE instead of standard input |
| 2300 | ** --ipaddr ADDR Assume the request comes from the given IP address |
| 2301 | ** --nocompress do not compress HTTP replies |
| 2302 | ** --nojail drop root privilege but do not enter the chroot jail |
| 2303 | ** --nossl signal that no SSL connections are available |
| 2304 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 2305 | ** --out FILE write results to FILE instead of to standard output |
| 2306 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| @@ -2364,11 +2363,10 @@ | |
| 2363 | g.httpOut = stdout; |
| 2364 | } |
| 2365 | zIpAddr = find_option("ipaddr",0,1); |
| 2366 | useSCGI = find_option("scgi", 0, 0)!=0; |
| 2367 | zAltBase = find_option("baseurl", 0, 1); |
| 2368 | if( zAltBase ) set_base_url(zAltBase); |
| 2369 | if( find_option("https",0,0)!=0 ){ |
| 2370 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2371 | cgi_replace_parameter("HTTPS","on"); |
| 2372 | } |
| 2373 |
-2
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -2297,11 +2297,10 @@ | ||
| 2297 | 2297 | ** --host NAME specify hostname of the server |
| 2298 | 2298 | ** --https signal a request coming in via https |
| 2299 | 2299 | ** --in FILE Take input from FILE instead of standard input |
| 2300 | 2300 | ** --ipaddr ADDR Assume the request comes from the given IP address |
| 2301 | 2301 | ** --nocompress do not compress HTTP replies |
| 2302 | -** --nodelay omit backoffice processing if it would delay process exit | |
| 2303 | 2302 | ** --nojail drop root privilege but do not enter the chroot jail |
| 2304 | 2303 | ** --nossl signal that no SSL connections are available |
| 2305 | 2304 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 2306 | 2305 | ** --out FILE write results to FILE instead of to standard output |
| 2307 | 2306 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| @@ -2364,11 +2363,10 @@ | ||
| 2364 | 2363 | g.httpOut = stdout; |
| 2365 | 2364 | } |
| 2366 | 2365 | zIpAddr = find_option("ipaddr",0,1); |
| 2367 | 2366 | useSCGI = find_option("scgi", 0, 0)!=0; |
| 2368 | 2367 | zAltBase = find_option("baseurl", 0, 1); |
| 2369 | - if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay(); | |
| 2370 | 2368 | if( zAltBase ) set_base_url(zAltBase); |
| 2371 | 2369 | if( find_option("https",0,0)!=0 ){ |
| 2372 | 2370 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2373 | 2371 | cgi_replace_parameter("HTTPS","on"); |
| 2374 | 2372 | } |
| 2375 | 2373 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -2297,11 +2297,10 @@ | |
| 2297 | ** --host NAME specify hostname of the server |
| 2298 | ** --https signal a request coming in via https |
| 2299 | ** --in FILE Take input from FILE instead of standard input |
| 2300 | ** --ipaddr ADDR Assume the request comes from the given IP address |
| 2301 | ** --nocompress do not compress HTTP replies |
| 2302 | ** --nodelay omit backoffice processing if it would delay process exit |
| 2303 | ** --nojail drop root privilege but do not enter the chroot jail |
| 2304 | ** --nossl signal that no SSL connections are available |
| 2305 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 2306 | ** --out FILE write results to FILE instead of to standard output |
| 2307 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| @@ -2364,11 +2363,10 @@ | |
| 2364 | g.httpOut = stdout; |
| 2365 | } |
| 2366 | zIpAddr = find_option("ipaddr",0,1); |
| 2367 | useSCGI = find_option("scgi", 0, 0)!=0; |
| 2368 | zAltBase = find_option("baseurl", 0, 1); |
| 2369 | if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay(); |
| 2370 | if( zAltBase ) set_base_url(zAltBase); |
| 2371 | if( find_option("https",0,0)!=0 ){ |
| 2372 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2373 | cgi_replace_parameter("HTTPS","on"); |
| 2374 | } |
| 2375 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -2297,11 +2297,10 @@ | |
| 2297 | ** --host NAME specify hostname of the server |
| 2298 | ** --https signal a request coming in via https |
| 2299 | ** --in FILE Take input from FILE instead of standard input |
| 2300 | ** --ipaddr ADDR Assume the request comes from the given IP address |
| 2301 | ** --nocompress do not compress HTTP replies |
| 2302 | ** --nojail drop root privilege but do not enter the chroot jail |
| 2303 | ** --nossl signal that no SSL connections are available |
| 2304 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 2305 | ** --out FILE write results to FILE instead of to standard output |
| 2306 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| @@ -2364,11 +2363,10 @@ | |
| 2363 | g.httpOut = stdout; |
| 2364 | } |
| 2365 | zIpAddr = find_option("ipaddr",0,1); |
| 2366 | useSCGI = find_option("scgi", 0, 0)!=0; |
| 2367 | zAltBase = find_option("baseurl", 0, 1); |
| 2368 | if( zAltBase ) set_base_url(zAltBase); |
| 2369 | if( find_option("https",0,0)!=0 ){ |
| 2370 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2371 | cgi_replace_parameter("HTTPS","on"); |
| 2372 | } |
| 2373 |
+2
-2
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -405,11 +405,11 @@ | ||
| 405 | 405 | aux = fossil_fopen(zCmdFName, "wb"); |
| 406 | 406 | if( aux==0 ) goto end_request; |
| 407 | 407 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| 408 | 408 | |
| 409 | 409 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 410 | - "\"%s\" http -args \"%s\" --nossl --nodelay%s", | |
| 410 | + "\"%s\" http -args \"%s\" --nossl%s", | |
| 411 | 411 | g.nameOfExe, zCmdFName, p->zOptions |
| 412 | 412 | ); |
| 413 | 413 | in = fossil_fopen(zReplyFName, "w+b"); |
| 414 | 414 | fflush(out); |
| 415 | 415 | fflush(aux); |
| @@ -476,11 +476,11 @@ | ||
| 476 | 476 | } |
| 477 | 477 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 478 | 478 | zIp = SocketAddr_toString(&p->addr); |
| 479 | 479 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 480 | 480 | "\"%s\" http --in \"%s\" --out \"%s\" --ipaddr %s \"%s\"" |
| 481 | - " --scgi --nossl --nodelay%s", | |
| 481 | + " --scgi --nossl%s", | |
| 482 | 482 | g.nameOfExe, zRequestFName, zReplyFName, zIp, |
| 483 | 483 | g.zRepositoryName, p->zOptions |
| 484 | 484 | ); |
| 485 | 485 | fossil_free(zIp); |
| 486 | 486 | in = fossil_fopen(zReplyFName, "w+b"); |
| 487 | 487 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -405,11 +405,11 @@ | |
| 405 | aux = fossil_fopen(zCmdFName, "wb"); |
| 406 | if( aux==0 ) goto end_request; |
| 407 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| 408 | |
| 409 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 410 | "\"%s\" http -args \"%s\" --nossl --nodelay%s", |
| 411 | g.nameOfExe, zCmdFName, p->zOptions |
| 412 | ); |
| 413 | in = fossil_fopen(zReplyFName, "w+b"); |
| 414 | fflush(out); |
| 415 | fflush(aux); |
| @@ -476,11 +476,11 @@ | |
| 476 | } |
| 477 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 478 | zIp = SocketAddr_toString(&p->addr); |
| 479 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 480 | "\"%s\" http --in \"%s\" --out \"%s\" --ipaddr %s \"%s\"" |
| 481 | " --scgi --nossl --nodelay%s", |
| 482 | g.nameOfExe, zRequestFName, zReplyFName, zIp, |
| 483 | g.zRepositoryName, p->zOptions |
| 484 | ); |
| 485 | fossil_free(zIp); |
| 486 | in = fossil_fopen(zReplyFName, "w+b"); |
| 487 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -405,11 +405,11 @@ | |
| 405 | aux = fossil_fopen(zCmdFName, "wb"); |
| 406 | if( aux==0 ) goto end_request; |
| 407 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| 408 | |
| 409 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 410 | "\"%s\" http -args \"%s\" --nossl%s", |
| 411 | g.nameOfExe, zCmdFName, p->zOptions |
| 412 | ); |
| 413 | in = fossil_fopen(zReplyFName, "w+b"); |
| 414 | fflush(out); |
| 415 | fflush(aux); |
| @@ -476,11 +476,11 @@ | |
| 476 | } |
| 477 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 478 | zIp = SocketAddr_toString(&p->addr); |
| 479 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 480 | "\"%s\" http --in \"%s\" --out \"%s\" --ipaddr %s \"%s\"" |
| 481 | " --scgi --nossl%s", |
| 482 | g.nameOfExe, zRequestFName, zReplyFName, zIp, |
| 483 | g.zRepositoryName, p->zOptions |
| 484 | ); |
| 485 | fossil_free(zIp); |
| 486 | in = fossil_fopen(zReplyFName, "w+b"); |
| 487 |
+2
-2
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -405,11 +405,11 @@ | ||
| 405 | 405 | aux = fossil_fopen(zCmdFName, "wb"); |
| 406 | 406 | if( aux==0 ) goto end_request; |
| 407 | 407 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| 408 | 408 | |
| 409 | 409 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 410 | - "\"%s\" http -args \"%s\" --nossl --nodelay%s", | |
| 410 | + "\"%s\" http -args \"%s\" --nossl%s", | |
| 411 | 411 | g.nameOfExe, zCmdFName, p->zOptions |
| 412 | 412 | ); |
| 413 | 413 | in = fossil_fopen(zReplyFName, "w+b"); |
| 414 | 414 | fflush(out); |
| 415 | 415 | fflush(aux); |
| @@ -476,11 +476,11 @@ | ||
| 476 | 476 | } |
| 477 | 477 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 478 | 478 | zIp = SocketAddr_toString(&p->addr); |
| 479 | 479 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 480 | 480 | "\"%s\" http --in \"%s\" --out \"%s\" --ipaddr %s \"%s\"" |
| 481 | - " --scgi --nossl --nodelay%s", | |
| 481 | + " --scgi --nossl%s", | |
| 482 | 482 | g.nameOfExe, zRequestFName, zReplyFName, zIp, |
| 483 | 483 | g.zRepositoryName, p->zOptions |
| 484 | 484 | ); |
| 485 | 485 | fossil_free(zIp); |
| 486 | 486 | in = fossil_fopen(zReplyFName, "w+b"); |
| 487 | 487 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -405,11 +405,11 @@ | |
| 405 | aux = fossil_fopen(zCmdFName, "wb"); |
| 406 | if( aux==0 ) goto end_request; |
| 407 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| 408 | |
| 409 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 410 | "\"%s\" http -args \"%s\" --nossl --nodelay%s", |
| 411 | g.nameOfExe, zCmdFName, p->zOptions |
| 412 | ); |
| 413 | in = fossil_fopen(zReplyFName, "w+b"); |
| 414 | fflush(out); |
| 415 | fflush(aux); |
| @@ -476,11 +476,11 @@ | |
| 476 | } |
| 477 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 478 | zIp = SocketAddr_toString(&p->addr); |
| 479 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 480 | "\"%s\" http --in \"%s\" --out \"%s\" --ipaddr %s \"%s\"" |
| 481 | " --scgi --nossl --nodelay%s", |
| 482 | g.nameOfExe, zRequestFName, zReplyFName, zIp, |
| 483 | g.zRepositoryName, p->zOptions |
| 484 | ); |
| 485 | fossil_free(zIp); |
| 486 | in = fossil_fopen(zReplyFName, "w+b"); |
| 487 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -405,11 +405,11 @@ | |
| 405 | aux = fossil_fopen(zCmdFName, "wb"); |
| 406 | if( aux==0 ) goto end_request; |
| 407 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| 408 | |
| 409 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 410 | "\"%s\" http -args \"%s\" --nossl%s", |
| 411 | g.nameOfExe, zCmdFName, p->zOptions |
| 412 | ); |
| 413 | in = fossil_fopen(zReplyFName, "w+b"); |
| 414 | fflush(out); |
| 415 | fflush(aux); |
| @@ -476,11 +476,11 @@ | |
| 476 | } |
| 477 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 478 | zIp = SocketAddr_toString(&p->addr); |
| 479 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 480 | "\"%s\" http --in \"%s\" --out \"%s\" --ipaddr %s \"%s\"" |
| 481 | " --scgi --nossl%s", |
| 482 | g.nameOfExe, zRequestFName, zReplyFName, zIp, |
| 483 | g.zRepositoryName, p->zOptions |
| 484 | ); |
| 485 | fossil_free(zIp); |
| 486 | in = fossil_fopen(zReplyFName, "w+b"); |
| 487 |