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,
228 LWP_NORMAL_PRIORITY, (void *) 2,
229 "cmdDispatch", &dispatchPid);
235 printf("Couldn't create cmdDispatch task\n");
238 if (localTaskFlags & NOREMOVE) {
239 curPollPtr->flags |= STARTING; /* Will ignore on other passes */
240 curPollPtr->flags |= (code?TASK_ERROR:TASK_DONE);
241 curPollPtr->scheduledDump = 0;
243 deleteStatusNode(curPollPtr);
250 if ( localTaskFlags & ABORT_LOCAL )
252 /* kill the local task */
253 if ( (localTaskFlags & CONTACT_LOST) != 0 )
255 printf("Job %d: in contact with butc at port %d\n",
257 printf("Job %d cont: Local kill ignored - use normal kill\n",
262 code = (afs_int32)bc_GetConn(bc_globalConfig, port, &tconn);
265 SET_FLAG(CONTACT_LOST);
269 if ( CheckTCVersion(tconn) )
271 SET_FLAG(CONTACT_LOST);
275 /* Send abort to TC requst if we have to */
276 if ( localTaskFlags & ABORT_REQUEST )
278 code = TC_RequestAbort(tconn, taskId);
281 com_err("statusWatcher", code, "; Can't post abort request");
282 com_err("statusWatcher", 0, "...Deleting job");
283 if (localTaskFlags & NOREMOVE) {
284 curPollPtr->flags |= (STARTING|TASK_ERROR);
285 curPollPtr->scheduledDump = 0;
287 deleteStatusNode(curPollPtr);
295 curPollPtr->flags &= ~ABORT_REQUEST;
296 curPollPtr->flags |= ABORT_SENT;
301 /* otherwise just get the status */
302 code = TC_GetStatus(tconn, taskId, &statusPtr);
305 if (code == TC_NODENOTFOUND)
307 printf("Job %d: %s - no such task on port %d, deleting\n",
308 jobNumber, curPollPtr->taskName, port);
310 if (localTaskFlags & NOREMOVE) {
311 curPollPtr->flags |= (STARTING|TASK_ERROR);
312 curPollPtr->scheduledDump = 0;
314 deleteStatusNode(curPollPtr); /* delete this status node */
320 SET_FLAG(CONTACT_LOST);
324 /* in case we previously lost contact or couldn't find */
325 CLEAR_FLAG(CONTACT_LOST);
327 /* extract useful status */
328 taskFlags = statusPtr.flags;
330 /* update local status */
333 /* remember some status flags in local struct */
334 temp = (DRIVE_WAIT | OPR_WAIT | CALL_WAIT | TASK_DONE | ABORT_DONE | TASK_ERROR);
335 curPollPtr->flags &= ~temp; /* clear */
336 curPollPtr->flags |= (taskFlags & temp); /* update */
338 curPollPtr->dbDumpId = statusPtr.dbDumpId;
339 curPollPtr->nKBytes = statusPtr.nKBytes;
340 strcpy(curPollPtr->volumeName, statusPtr.volumeName);
341 curPollPtr->volsFailed = statusPtr.volsFailed;
342 curPollPtr->lastPolled = statusPtr.lastPolled;
346 if (taskFlags & TASK_DONE)
348 if (taskFlags & ABORT_DONE)
350 if (curPollPtr->dbDumpId)
351 printf("Job %d: %s: DumpID %u Aborted",
352 jobNumber, curPollPtr->taskName, curPollPtr->dbDumpId);
354 printf("Job %d: %s Aborted", jobNumber, curPollPtr->taskName);
356 if ( taskFlags & TASK_ERROR ) printf(" with errors\n");
362 else if (taskFlags & TASK_ERROR)
364 if ( !(localTaskFlags & SILENT) ) {
365 if (curPollPtr->dbDumpId)
366 printf("Job %d: DumpID %u Failed with errors\n",
367 jobNumber, curPollPtr->dbDumpId);
369 printf("Job %d Failed with errors\n", jobNumber);
376 if ( !(localTaskFlags & SILENT) )
378 if (curPollPtr->dbDumpId)
379 printf("Job %d: %s: DumpID %u finished",
380 jobNumber, curPollPtr->taskName, curPollPtr->dbDumpId);
382 printf("Job %d: %s finished", jobNumber, curPollPtr->taskName);
384 if (curPollPtr->volsTotal)
386 printf(". %d volumes dumped", (curPollPtr->volsTotal-
387 curPollPtr->volsFailed));
388 if ( curPollPtr->volsFailed)
389 printf(", %d failed", curPollPtr->volsFailed);
397 /* make call to destroy task on server */
398 code = TC_EndStatus(tconn, taskId);
400 printf("Job %d: %s, error in job termination cleanup\n",
401 jobNumber, curPollPtr->taskName);
403 if (localTaskFlags & NOREMOVE) {
404 curPollPtr->flags |= STARTING;
405 curPollPtr->scheduledDump = 0;
407 deleteStatusNode(curPollPtr); /* unlink and destroy local task */
415 * Allocate a job number. Computes the maximum of all the job numbers
416 * and then returns the maximum+1.
417 * If no jobs are found, returns 1.
423 afs_int32 retval = 0;
426 ptr = statusHead.dlq_next;
427 while ( ptr != &statusHead )
429 /* compute max of all job numbers */
430 if ( ((statusP) ptr)->jobNumber > retval )
431 retval = ((statusP) ptr)->jobNumber;
440 * Wait for a specific task to finish and then return.
441 * Return the task's flags when it's done. If the job
442 * had been cleaned up, then just return 0.
448 afs_int32 done=0, rcode, t;
449 extern statusP findStatus();
451 t = (TASK_DONE | ABORT_DONE | TASK_ERROR);
453 /* Sleep 2 seconds */
454 #ifdef AFS_PTHREAD_ENV
455 struct timespec delaytime;
456 delayTime.tv_sec = 2;
457 delayTime.tv_nsec = 0;
458 pthread_delay_np(&delayTime);
461 #endif /*else AFS_PTHREAD_ENV*/
463 /* Check if we are done */
465 ptr = findStatus(taskId);
466 if (!ptr || (ptr->flags & t)) {
467 rcode = (ptr ? ptr->flags : 0);