Fossil

Diff
Login

Diff

Differences From Artifact [d2cf5ceb44]:

To Artifact [c4b4d4095a]:


69
70
71
72
73
74
75


76
77


78
79
80
81
82
83
84






85
86
87
88




89
90
91
92
93
94
95
69
70
71
72
73
74
75
76
77


78
79
80
81
82
83
84


85
86
87
88
89
90
91



92
93
94
95
96
97
98
99
100
101
102







+
+
-
-
+
+





-
-
+
+
+
+
+
+

-
-
-
+
+
+
+







  sqlite3_uint64 idCurrent;   /* ID for the current lease holder */
  sqlite3_uint64 tmCurrent;   /* Expiration of the current lease */
  sqlite3_uint64 idNext;      /* ID for the next lease holder on queue */
  sqlite3_uint64 tmNext;      /* Expiration of the next lease */
};
#endif

/***************************************************************************
** Local state variables
/*
** Set to prevent backoffice processing from every entering sleep or
**
** Set to prevent backoffice processing from ever entering sleep or
** otherwise taking a long time to complete.  Set this when a user-visible
** process might need to wait for backoffice to complete.
*/
static int backofficeNoDelay = 0;

/*
** Disable the backoffice
/* This variable is set to the name of a database on which backoffice
** should run if backoffice process is needed.  It is set by the
** backoffice_check_if_needed() routine which must be run while the database
** file is open.  Later, after the database is closed, the
** backoffice_run_if_needed() will consult this variable to see if it
** should be a no-op.
*/
void backoffice_no_delay(void){
  backofficeNoDelay = 1;
}
static char *backofficeDb = 0;

/* End of state variables
****************************************************************************/

/*
** Parse a unsigned 64-bit integer from a string.  Return a pointer
** to the character of z[] that occurs after the integer.
*/
static const char *backofficeParseInt(const char *z, sqlite3_uint64 *pVal){
  *pVal = 0;
203
204
205
206
207
208
209

210
211
212



213
214
215
216
217

218
219
220
221
222
223
224
225
226






















227
228

229
230
231
232
233
234
235























236
237
238
239
240
241
242
210
211
212
213
214
215
216
217



218
219
220



221

222
223
224







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285







+
-
-
-
+
+
+
-
-
-

-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    sqlite3_uint64 x = (sqlite3_uint64)atoi(g.argv[i]);
    fossil_print("ProcessId %lld: exists %d done %d\n",
                 x, backofficeProcessExists(x),
                    backofficeProcessDone(x));
  }
}

/*
/* This is the main public interface to the backoffice.  A process invokes this
** routine in an attempt to become the backoffice.  If another process is
** already working as the backoffice, this routine returns very quickly
** If backoffice processing is needed set the backofficeDb value to the
** name of the database file.  If no backoffice processing is needed,
** this routine makes no changes to state.
** without doing any work - allowing the other process to continue.  But
** if no other processes are currently operating as the backoffice, this
** routine enters a loop to do background work periodically.
*/
void backoffice_run(void){
void backoffice_check_if_needed(void){
  Lease x;
  sqlite3_uint64 tmNow;
  sqlite3_uint64 idSelf;
  int lastWarning = 0;
  int warningDelay = 30;
  static int once = 0;

  if( once ){
    fossil_panic("multiple calls to backoffice_run()");

  if( backofficeDb ) return;
  if( g.zRepositoryName==0 ) return;
  if( g.db==0 ) return;
  tmNow = time(0);
  backofficeReadLease(&x);
  if( x.tmNext>=tmNow && backofficeProcessExists(x.idNext) ){
    /* Another backoffice process is already queued up to run.  This
    ** process does not need to do any backoffice work. */
    return;
  }else{
    /* We need to run backup to be (at a minimum) on-deck */
    backofficeDb = fossil_strdup(g.zRepositoryName);
  }
}

/*
** Check for errors prior to running backoffice_thread() or backoffice_run().
*/
static void backoffice_error_check_one(int *pOnce){
  if( *pOnce ){
    fossil_panic("multiple calls to backoffice()");
  }
  once = 1;
  *pOnce = 1;
  if( g.db==0 ){
    fossil_panic("database not open for backoffice processing");
  }
  if( db_transaction_nesting_depth()!=0 ){
    fossil_panic("transaction %s not closed prior to backoffice processing",
                 db_transaction_start_point());
  }
}

/* This is the main loop for backoffice processing.
**
** If others process is already working as the current backoffice and
** the on-deck backoffice, then this routine returns very quickly
** without doing any work.
**
** If no backoffice processes are running at all, this routine becomes
** the main backoffice.
**
** If a primary backoffice is running, but a on-deck backoffice is
** needed, this routine becomes that backoffice.
*/
static void backoffice_thread(void){
  Lease x;
  sqlite3_uint64 tmNow;
  sqlite3_uint64 idSelf;
  int lastWarning = 0;
  int warningDelay = 30;
  static int once = 0;

  backoffice_error_check_one(&once);
  backofficeTimeout(BKOFCE_LEASE_TIME*2);
  idSelf = backofficeProcessId();
  while(1){
    tmNow = time(0);
    db_begin_write();
    backofficeReadLease(&x);
    if( x.tmNext>=tmNow
301
302
303
304
305
306
307
308

309
310

311
312


313
314


315
316

317












































344
345
346
347
348
349
350

351
352

353
354

355
356
357

358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406







-
+

-
+

-
+
+

-
+
+

-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
** backoffice processing tasks, add them here.
*/
void backoffice_work(void){
  email_backoffice(0);
}

/*
** COMMAND: test-backoffice
** COMMAND: backoffice
**
** Usage: test-backoffice
** Usage: backoffice [-R repository]
**
** Run backoffice processing
** Run backoffice processing.  This might be done by a cron job or
** similar to make sure backoffice processing happens periodically.
*/
void test_backoffice_command(void){
void backoffice_command(void){
  verify_all_options();
  db_find_and_open_repository(0,0);
  backoffice_run();
  backoffice_thread();
}

/*
** This is the main interface to backoffice from the rest of the system.
** This routine launches either backoffice_thread() directly or as a
** subprocess.
*/
void backoffice_run_if_needed(void){
  if( backofficeDb==0 ) return;
  if( strcmp(backofficeDb,"x")==0 ) return;
  if( g.db ) return;
  if( g.repositoryOpen ) return;
#if !defined(_WIN32)
  {
    pid_t pid = fork();
    if( pid>0 ){
      /* This is the parent in a successful fork().  Return immediately. */
      if( g.fAnyTrace ){
        fprintf(stderr, "/***** Backoffice Child Creates as %d *****/\n",
                        (int)pid);
      }
      return;
    }
    if( pid==0 ){
      /* This is the child of a successful fork().  Run backoffice. */
      db_open_repository(backofficeDb);
      backofficeDb = "x";
      backoffice_thread();
      db_close(1);
      if( g.fAnyTrace ){
        fprintf(stderr, "/***** Backoffice Child %d exits *****/\n", getpid());
      }
      exit(0);
    }
  }
#endif
  /* Fork() failed or is unavailable.  Run backoffice in this process, but
  ** do so with the no-delay setting.
  */
  backofficeNoDelay = 1;
  db_open_repository(backofficeDb);
  backofficeDb = "x";
  backoffice_thread();
  db_close(1);
}