@@ -35,10 +35,29 @@
35 35 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Backoffice processes should die off after doing whatever work they need
36 36 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** to do. In this way, we avoid having lots of idle processes in the
37 37 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** process table, doing nothing on rarely accessed repositories, and
38 38 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** if the Fossil binary is updated on a system, the backoffice processes
39 39 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** will restart using the new binary automatically.
40 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
41 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** At any point in time there should be at most two backoffice processes.
42 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** There is a main process that is doing the actually work, and there is
43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** a second stand-by process that is waiting for the main process to finish
44 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** and that will become the main process after a delay.
45 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
46 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** After any successful web page reply, the backoffice_check_if_needed()
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** routine is called. That routine checks to see if both one or both of
48 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** the backoffice processes are already running. That routine remembers the
49 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** status in a global variable.
50 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
51 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Later, after the repository database is closed, the
52 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** backoffice_run_if_needed() routine is called. If the prior call
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** to backoffice_check_if_needed() indicated that backoffice processing
54 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** might be required, the run_if_needed() attempts to kick off a backoffice
55 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** process.
56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** All work performance by the backoffice is in the backoffice_work()
58 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** routine.
40 59 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
41 60 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#include "config.h"
42 61 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#include "backoffice.h"
43 62 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#include <time.h>
44 63 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#if defined(_WIN32)
@@ -52,38 +71,58 @@
52 71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
53 72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice
54 73 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** processing run is valid. Each backoffice run monopolizes the lease for
55 74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** at least this amount of time. Hopefully all backoffice processing is
56 75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** finished much faster than this - usually in less than a second. But
57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** regardless of how fast each invocations run, successive backoffice runs
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** regardless of how long each invocation lasts, successive backoffice runs
58 77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** must be spaced out by at least this much time.
59 78 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
60 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- #define BKOFCE_LEASE_TIME 60 /* Length of lease validity */
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #define BKOFCE_LEASE_TIME 60 /* Length of lease validity in seconds */
61 80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
62 81 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#if LOCAL_INTERFACE
63 82 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
64 83 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** An instance of the following object describes a lease on the backoffice
65 84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** processing timeslot. This lease is used to help ensure that no more than
66 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** one processing is running backoffice at a time.
85 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** one process is running backoffice at a time.
67 86 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
68 87 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
struct Lease {
69 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sqlite3_uint64 idCurrent; /* ID for the current lease holder */
70 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sqlite3_uint64 tmCurrent; /* Expiration of the current lease */
71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sqlite3_uint64 idNext; /* ID for the next lease holder on queue */
72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sqlite3_uint64 tmNext; /* Expiration of the next lease */
88 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_uint64 idCurrent; /* process ID for the current lease holder */
89 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_uint64 tmCurrent; /* Expiration of the current lease */
90 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_uint64 idNext; /* process ID for the next lease holder on queue */
91 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_uint64 tmNext; /* Expiration of the next lease */
73 92 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
};
74 93 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#endif
75 94 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- /*
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** Set to prevent backoffice processing from every entering sleep or
95 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /***************************************************************************
96 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Local state variables
97 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
98 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Set to prevent backoffice processing from ever entering sleep or
78 99 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** otherwise taking a long time to complete. Set this when a user-visible
79 100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** process might need to wait for backoffice to complete.
80 101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
81 102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
static int backofficeNoDelay = 0;
82 103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* This variable is set to the name of a database on which backoffice
105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** should run if backoffice process is needed. It is set by the
106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** backoffice_check_if_needed() routine which must be run while the database
107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** file is open. Later, after the database is closed, the
108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** backoffice_run_if_needed() will consult this variable to see if it
109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** should be a no-op.
110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static char *backofficeDb = 0;
112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* End of state variables
114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ****************************************************************************/
115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
83 116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** Disable the backoffice
117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Do not allow backoffice processes to sleep waiting on a timeslot.
118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** They must either do their work immediately or exit.
119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** In a perfect world, this interface would not exist, as there would
121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** never be a problem with waiting backoffice threads. But in some cases
122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** a backoffice will delay a UI thread, so we don't want them to run for
123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** longer than needed.
85 124 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
86 125 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
void backoffice_no_delay(void){
87 126 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
backofficeNoDelay = 1;
88 127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
89 128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@@ -130,11 +169,11 @@
130 169 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
pLease->idCurrent, pLease->tmCurrent,
131 170 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
pLease->idNext, pLease->tmNext);
132 171 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
133 172 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
134 173 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
135 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** Check to see if the process identified by selfId is alive. If
174 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Check to see if the process identified by pid is alive. If
136 175 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** we cannot prove the the process is dead, return true.
137 176 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
138 177 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
static int backofficeProcessExists(sqlite3_uint64 pid){
139 178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#if defined(_WIN32)
140 179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return 1;
@@ -142,11 +181,11 @@
142 181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return pid>0 && kill((pid_t)pid, 0)==0;
143 182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#endif
144 183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
145 184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
146 185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
147 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** Check to see if the process identified by selfId has finished. If
186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Check to see if the process identified by pid has finished. If
148 187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** we cannot prove the the process is still running, return true.
149 188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
150 189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
static int backofficeProcessDone(sqlite3_uint64 pid){
151 190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#if defined(_WIN32)
152 191 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return 1;
@@ -205,36 +244,72 @@
205 244 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
x, backofficeProcessExists(x),
206 245 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
backofficeProcessDone(x));
207 246 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
208 247 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
209 248 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
210 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- /* This is the main public interface to the backoffice. A process invokes this
211 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** routine in an attempt to become the backoffice. If another process is
212 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** already working as the backoffice, this routine returns very quickly
213 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** without doing any work - allowing the other process to continue. But
214 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** if no other processes are currently operating as the backoffice, this
215 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** routine enters a loop to do background work periodically.
249 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
250 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If backoffice processing is needed set the backofficeDb variable to the
251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** name of the database file. If no backoffice processing is needed,
252 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** this routine makes no changes to state.
216 253 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
217 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- void backoffice_run(void){
254 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void backoffice_check_if_needed(void){
218 255 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Lease x;
219 256 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
sqlite3_uint64 tmNow;
220 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sqlite3_uint64 idSelf;
221 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int lastWarning = 0;
222 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int warningDelay = 30;
223 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- static int once = 0;
224 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
225 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( once ){
226 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- fossil_panic("multiple calls to backoffice_run()");
227 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }
228 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- once = 1;
257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( backofficeDb ) return;
259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.zRepositoryName==0 ) return;
260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.db==0 ) return;
261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tmNow = time(0);
262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backofficeReadLease(&x);
263 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( x.tmNext>=tmNow && backofficeProcessExists(x.idNext) ){
264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Another backoffice process is already queued up to run. This
265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** process does not need to do any backoffice work. */
266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* We need to run backup to be (at a minimum) on-deck */
269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backofficeDb = fossil_strdup(g.zRepositoryName);
270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Check for errors prior to running backoffice_thread() or backoffice_run().
275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static void backoffice_error_check_one(int *pOnce){
277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( *pOnce ){
278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_panic("multiple calls to backoffice()");
279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ *pOnce = 1;
229 281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.db==0 ){
230 282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_panic("database not open for backoffice processing");
231 283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
232 284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( db_transaction_nesting_depth()!=0 ){
233 285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_panic("transaction %s not closed prior to backoffice processing",
234 286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_transaction_start_point());
235 287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* This is the main loop for backoffice processing.
291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If another process is already working as the current backoffice and
293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** the on-deck backoffice, then this routine returns very quickly
294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** without doing any work.
295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If no backoffice processes are running at all, this routine becomes
297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** the main backoffice.
298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If a primary backoffice is running, but a on-deck backoffice is
300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** needed, this routine becomes that on-desk backoffice.
301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static void backoffice_thread(void){
303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Lease x;
304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_uint64 tmNow;
305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_uint64 idSelf;
306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int lastWarning = 0;
307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int warningDelay = 30;
308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static int once = 0;
309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backoffice_error_check_one(&once);
236 311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
backofficeTimeout(BKOFCE_LEASE_TIME*2);
237 312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
idSelf = backofficeProcessId();
238 313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
while(1){
239 314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
tmNow = time(0);
240 315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_begin_write();
@@ -303,15 +378,62 @@
303 378 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
void backoffice_work(void){
304 379 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
email_backoffice(0);
305 380 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
306 381 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
307 382 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** COMMAND: test-backoffice
309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- **
310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** Usage: test-backoffice
311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- **
312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** Run backoffice processing
313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- */
314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- void test_backoffice_command(void){
315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- db_find_and_open_repository(0,0);
316 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- backoffice_run();
383 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** COMMAND: backoffice
384 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
385 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Usage: backoffice [-R repository]
386 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
387 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Run backoffice processing. This might be done by a cron job or
388 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** similar to make sure backoffice processing happens periodically.
389 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
390 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void backoffice_command(void){
391 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ verify_all_options();
392 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_find_and_open_repository(0,0);
393 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backoffice_thread();
394 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
395 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
396 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
397 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** This is the main interface to backoffice from the rest of the system.
398 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** This routine launches either backoffice_thread() directly or as a
399 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** subprocess.
400 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
401 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void backoffice_run_if_needed(void){
402 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( backofficeDb==0 ) return;
403 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( strcmp(backofficeDb,"x")==0 ) return;
404 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.db ) return;
405 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.repositoryOpen ) return;
406 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #if !defined(_WIN32)
407 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ {
408 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pid_t pid = fork();
409 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( pid>0 ){
410 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* This is the parent in a successful fork(). Return immediately. */
411 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.fAnyTrace ){
412 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fprintf(stderr,
413 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "/***** Subprocess %d creates backoffice child %d *****/\n",
414 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ getpid(), (int)pid);
415 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
416 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
417 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
418 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( pid==0 ){
419 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* This is the child of a successful fork(). Run backoffice. */
420 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_open_repository(backofficeDb);
421 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backofficeDb = "x";
422 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backoffice_thread();
423 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_close(1);
424 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.fAnyTrace ){
425 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fprintf(stderr, "/***** Backoffice Child %d exits *****/\n", getpid());
426 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
427 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ exit(0);
428 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
429 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
430 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #endif
431 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Fork() failed or is unavailable. Run backoffice in this process, but
432 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** do so with the no-delay setting.
433 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
434 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backofficeNoDelay = 1;
435 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_open_repository(backofficeDb);
436 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backofficeDb = "x";
437 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ backoffice_thread();
438 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_close(1);
317 439 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
318 440 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!