2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
26 #include <afs/com_err.h>
27 #include <afs/bubasics.h>
29 #include <afs/tcdata.h>
31 #include "error_macros.h"
33 #define SET_FLAG(set) \
35 curPollPtr->flags |= (set); \
38 #define CLEAR_FLAG(clear) \
40 curPollPtr->flags &= ~(clear); \
43 /* globals for backup coordinator status management */
45 dlqlinkT statusHead; /* chain of status blocks */
46 struct Lock statusQueueLock; /* access control for status chain */
47 struct Lock cmdLineLock; /* lock on the cmdLine */
49 afs_int32 lastTaskCode; /* Error code from task that last finished */
52 * get next item for status interrogation, if any.
60 ptr = (dlqlinkP) linkPtr;
62 /* if last known item has terminated, reset ptr */
72 /* if we're back at the head again */
73 if ( ptr == &statusHead )
75 return((statusP) ptr);
85 ptr = (dlqlinkP) linkPtr;
87 /* if last known item has terminated, reset ptr */
97 /* if we're back at the head again */
98 if ( ptr == &statusHead )
102 return((statusP) ptr);
111 char **targv[MAXV]; /*Ptr to parsed argv stuff*/
112 afs_int32 targc; /*Num parsed arguments*/
114 char *internalCmdLine;
116 internalCmdLine = cmdLine;
119 code = cmd_ParseLine(internalCmdLine, targv, &targc, MAXV);
121 printf("Couldn't parse line: '%s'", error_message(code));
124 free(internalCmdLine);
127 * Because the "-at" option cannot be wildcarded, we cannot fall
128 * into recusive loop here by setting dispatchCount to 1.
130 doDispatch(targc, targv, 1);
136 struct rx_connection *tconn = (struct rc_connection *)0;
137 statusP curPollPtr = 0;
139 struct tciStatusS statusPtr;
141 /* task information */
142 afs_uint32 taskFlags;
143 afs_uint32 localTaskFlags;
144 afs_uint32 temp; /* for flag manipulation */
152 extern struct bc_config *bc_globalConfig;
153 extern struct rx_connection *bc_GetConn();
159 if (tconn) rx_DestroyConnection(tconn);
160 tconn = (struct rc_connection *)0;
163 curPollPtr = nextItem(curPollPtr);
165 if ( curPollPtr == 0 )
167 #ifdef AFS_PTHREAD_ENV
168 struct timespec delaytime;
170 delayTime.tv_sec = 5;
171 delayTime.tv_nsec = 0;
172 pthread_delay_np(&delayTime);
175 IOMGR_Sleep(5); /* wait a while */
176 #endif /*else AFS_PTHREAD_ENV*/
180 /* save useful information */
181 localTaskFlags = curPollPtr->flags;
182 taskId = curPollPtr->taskId;
183 port = curPollPtr->port;
184 atTime = curPollPtr->scheduledDump;
185 jobNumber = curPollPtr->jobNumber;
188 /* reset certain flags; local kill; */
189 CLEAR_FLAG(ABORT_LOCAL);
191 /* An abort request before the command even started */
192 if ( atTime && (localTaskFlags & ABORT_REQUEST) )
194 if (localTaskFlags & NOREMOVE) {
195 curPollPtr->flags |= (STARTING|ABORT_DONE); /* Will ignore on other passes */
196 curPollPtr->scheduledDump = 0;
198 deleteStatusNode(curPollPtr);
204 /* A task not started yet - check its start time */
205 if ( localTaskFlags & STARTING || atTime )
208 * Start a timed dump if its time has come. When the job is
209 * started, it will allocate its own status structure so this
210 * one is no longer needed: delete it.
212 * Avoid multiple processes trouncing the cmdLine by placing
215 if ( atTime && (atTime <= time(0)) )
217 lock_cmdLine(); /* Will unlock in cmdDispatch */
219 cmdLine = curPollPtr->cmdLine;
221 curPollPtr->cmdLine = 0;
224 printf("Starting scheduled dump: job %d\n", jobNumber);
225 printf("schedD> %s\n", cmdLine);
227 code = LWP_CreateProcess(cmdDispatch, 16384, LWP_NORMAL_PRIORITY, 2,
228 "cmdDispatch", &dispatchPid);
234 printf("Couldn't create cmdDispatch task\n");
237 if (localTaskFlags & NOREMOVE) {
238 curPollPtr->flags |= STARTING; /* Will ignore on other passes */
239 curPollPtr->flags |= (code?TASK_ERROR:TASK_DONE);
240 curPollPtr->scheduledDump = 0;
242 deleteStatusNode(curPollPtr);
249 if ( localTaskFlags & ABORT_LOCAL )
251 /* kill the local task */
252 if ( (localTaskFlags & CONTACT_LOST) != 0 )
254 printf("Job %d: in contact with butc at port %d\n",
256 printf("Job %d cont: Local kill ignored - use normal kill\n",
261 code = (afs_int32)bc_GetConn(bc_globalConfig, port, &tconn);
264 SET_FLAG(CONTACT_LOST);
268 if ( CheckTCVersion(tconn) )
270 SET_FLAG(CONTACT_LOST);
274 /* Send abort to TC requst if we have to */
275 if ( localTaskFlags & ABORT_REQUEST )
277 code = TC_RequestAbort(tconn, taskId);
280 com_err("statusWatcher", code, "; Can't post abort request");
281 com_err("statusWatcher", 0, "...Deleting job");
282 if (localTaskFlags & NOREMOVE) {
283 curPollPtr->flags |= (STARTING|TASK_ERROR);
284 curPollPtr->scheduledDump = 0;
286 deleteStatusNode(curPollPtr);
294 curPollPtr->flags &= ~ABORT_REQUEST;
295 curPollPtr->flags |= ABORT_SENT;
300 /* otherwise just get the status */
301 code = TC_GetStatus(tconn, taskId, &statusPtr);
304 if (code == TC_NODENOTFOUND)
306 printf("Job %d: %s - no such task on port %d, deleting\n",
307 jobNumber, curPollPtr->taskName, port);
309 if (localTaskFlags & NOREMOVE) {
310 curPollPtr->flags |= (STARTING|TASK_ERROR);
311 curPollPtr->scheduledDump = 0;
313 deleteStatusNode(curPollPtr); /* delete this status node */
319 SET_FLAG(CONTACT_LOST);
323 /* in case we previously lost contact or couldn't find */
324 CLEAR_FLAG(CONTACT_LOST);
326 /* extract useful status */
327 taskFlags = statusPtr.flags;
329 /* update local status */
332 /* remember some status flags in local struct */
333 temp = (DRIVE_WAIT | OPR_WAIT | CALL_WAIT | TASK_DONE | ABORT_DONE | TASK_ERROR);
334 curPollPtr->flags &= ~temp; /* clear */
335 curPollPtr->flags |= (taskFlags & temp); /* update */
337 curPollPtr->dbDumpId = statusPtr.dbDumpId;
338 curPollPtr->nKBytes = statusPtr.nKBytes;
339 strcpy(curPollPtr->volumeName, statusPtr.volumeName);
340 curPollPtr->volsFailed = statusPtr.volsFailed;
341 curPollPtr->lastPolled = statusPtr.lastPolled;
345 if (taskFlags & TASK_DONE)
347 if (taskFlags & ABORT_DONE)
349 if (curPollPtr->dbDumpId)
350 printf("Job %d: %s: DumpID %u Aborted",
351 jobNumber, curPollPtr->taskName, curPollPtr->dbDumpId);
353 printf("Job %d: %s Aborted", jobNumber, curPollPtr->taskName);
355 if ( taskFlags & TASK_ERROR ) printf(" with errors\n");
361 else if (taskFlags & TASK_ERROR)
363 if ( !(localTaskFlags & SILENT) ) {
364 if (curPollPtr->dbDumpId)
365 printf("Job %d: DumpID %u Failed with errors\n",
366 jobNumber, curPollPtr->dbDumpId);
368 printf("Job %d Failed with errors\n", jobNumber);
375 if ( !(localTaskFlags & SILENT) )
377 if (curPollPtr->dbDumpId)
378 printf("Job %d: %s: DumpID %u finished",
379 jobNumber, curPollPtr->taskName, curPollPtr->dbDumpId);
381 printf("Job %d: %s finished", jobNumber, curPollPtr->taskName);
383 if (curPollPtr->volsTotal)
385 printf(". %d volumes dumped", (curPollPtr->volsTotal-
386 curPollPtr->volsFailed));
387 if ( curPollPtr->volsFailed)
388 printf(", %d failed", curPollPtr->volsFailed);
396 /* make call to destroy task on server */
397 code = TC_EndStatus(tconn, taskId);
399 printf("Job %d: %s, error in job termination cleanup\n",
400 jobNumber, curPollPtr->taskName);
402 if (localTaskFlags & NOREMOVE) {
403 curPollPtr->flags |= STARTING;
404 curPollPtr->scheduledDump = 0;
406 deleteStatusNode(curPollPtr); /* unlink and destroy local task */
414 * Allocate a job number. Computes the maximum of all the job numbers
415 * and then returns the maximum+1.
416 * If no jobs are found, returns 1.
422 afs_int32 retval = 0;
425 ptr = statusHead.dlq_next;
426 while ( ptr != &statusHead )
428 /* compute max of all job numbers */
429 if ( ((statusP) ptr)->jobNumber > retval )
430 retval = ((statusP) ptr)->jobNumber;
439 * Wait for a specific task to finish and then return.
440 * Return the task's flags when it's done. If the job
441 * had been cleaned up, then just return 0.
447 afs_int32 done=0, rcode, t;
448 extern statusP findStatus();
450 t = (TASK_DONE | ABORT_DONE | TASK_ERROR);
452 /* Sleep 2 seconds */
453 #ifdef AFS_PTHREAD_ENV
454 struct timespec delaytime;
455 delayTime.tv_sec = 2;
456 delayTime.tv_nsec = 0;
457 pthread_delay_np(&delayTime);
460 #endif /*else AFS_PTHREAD_ENV*/
462 /* Check if we are done */
464 ptr = findStatus(taskId);
465 if (!ptr || (ptr->flags & t)) {
466 rcode = (ptr ? ptr->flags : 0);