/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include #include #include #include #include #include #include #include "bnode.h" #include "bnode_internal.h" #include "bosprototypes.h" extern char *DoPidFiles; struct bnode *ez_create(char *, char *, char *, char *, char *, char *); static int ez_hascore(struct bnode *bnode); static int ez_restartp(struct bnode *bnode); static int ez_delete(struct bnode *bnode); static int ez_timeout(struct bnode *bnode); static int ez_getstat(struct bnode *bnode, afs_int32 *status); static int ez_setstat(struct bnode *bnode, afs_int32 status); static int ez_procexit(struct bnode *bnode, struct bnode_proc *proc); static int ez_getstring(struct bnode *bnode, char *abuffer, afs_int32 alen); static int ez_getparm(struct bnode *bnode, afs_int32, char *, afs_int32); static int ez_procstarted(struct bnode *bnode, struct bnode_proc *proc); #define SDTIME 60 /* time in seconds given to a process to evaporate */ #define ERROR_RESET_TIME 60 /* time in seconds to wait before resetting error count state */ struct bnode_ops ezbnode_ops = { ez_create, ez_timeout, ez_getstat, ez_setstat, ez_delete, ez_procexit, ez_getstring, ez_getparm, ez_restartp, ez_hascore, ez_procstarted }; static int ez_hascore(struct bnode *abnode) { char tbuffer[256]; bnode_CoreName(abnode, NULL, tbuffer); if (access(tbuffer, 0) == 0) return 1; else return 0; } static int ez_restartp(struct bnode *bn) { struct ezbnode *abnode = (struct ezbnode *)bn; struct bnode_token *tt; afs_int32 code; struct stat tstat; code = bnode_ParseLine(abnode->command, &tt); if (code) return 0; if (!tt) return 0; code = stat(tt->key, &tstat); if (code) { bnode_FreeTokens(tt); return 0; } if (tstat.st_ctime > abnode->lastStart) code = 1; else code = 0; bnode_FreeTokens(tt); return code; } static int ez_delete(struct bnode *bn) { struct ezbnode *abnode = (struct ezbnode *)bn; free(abnode->command); free(abnode); return 0; } struct bnode * ez_create(char *ainstance, char *acommand, char *unused1, char *unused2, char *unused3, char *unused4) { struct ezbnode *te; char *cmdpath; if (ConstructLocalBinPath(acommand, &cmdpath)) { bozo_Log("BNODE: command path invalid '%s'\n", acommand); return NULL; } te = calloc(1, sizeof(struct ezbnode)); if (bnode_InitBnode((struct bnode *)te, &ezbnode_ops, ainstance) != 0) { free(te); return NULL; } te->command = cmdpath; return (struct bnode *)te; } /* called to SIGKILL a process if it doesn't terminate normally * or to retry start after an error stop. */ static int ez_timeout(struct bnode *bn) { struct ezbnode *abnode = (struct ezbnode *)bn; if (abnode->waitingForShutdown) { /* send kill and turn off timer */ bnode_StopProc(abnode->proc, SIGKILL); abnode->killSent = 1; bnode_SetTimeout((struct bnode *)abnode, 0); } else if (!abnode->running && abnode->b.flags & BNODE_ERRORSTOP) { /* was stopped for too many errors, retrying */ /* reset error count after running for a bit */ bnode_SetTimeout(bn, ERROR_RESET_TIME); bnode_SetStat(bn, BSTAT_NORMAL); } else { bnode_SetTimeout(bn, 0); /* one shot timer */ bnode_ResetErrorCount(bn); } return 0; } static int ez_getstat(struct bnode *bn, afs_int32 * astatus) { struct ezbnode *abnode = (struct ezbnode *)bn; afs_int32 temp; if (abnode->waitingForShutdown) temp = BSTAT_SHUTTINGDOWN; else if (abnode->running) temp = BSTAT_NORMAL; else if (abnode->b.flags & BNODE_ERRORSTOP) temp = BSTAT_STARTINGUP; else temp = BSTAT_SHUTDOWN; *astatus = temp; return 0; } static int ez_setstat(struct bnode *bn, afs_int32 astatus) { struct ezbnode *abnode = (struct ezbnode *)bn; struct bnode_proc *tp; afs_int32 code; if (abnode->waitingForShutdown) return BZBUSY; if (astatus == BSTAT_NORMAL && !abnode->running) { /* start up */ abnode->lastStart = FT_ApproxTime(); code = bnode_NewProc((struct bnode *)abnode, abnode->command, NULL, &tp); if (code) return code; abnode->running = 1; abnode->proc = tp; return 0; } else if (astatus == BSTAT_SHUTDOWN && abnode->running) { /* start shutdown */ bnode_StopProc(abnode->proc, SIGTERM); abnode->waitingForShutdown = 1; bnode_SetTimeout((struct bnode *)abnode, SDTIME); return 0; } return 0; } static int ez_procstarted(struct bnode *bn, struct bnode_proc *aproc) { int code = 0; if (DoPidFiles) { code = bozo_CreatePidFile(bn->name, NULL, aproc->pid); } return code;; } static int ez_procexit(struct bnode *bn, struct bnode_proc *aproc) { struct ezbnode *abnode = (struct ezbnode *)bn; /* process has exited */ afs_int32 code = 0; if (DoPidFiles) { bozo_DeletePidFile(bn->name, NULL); } abnode->waitingForShutdown = 0; abnode->running = 0; abnode->killSent = 0; abnode->proc = NULL; bnode_SetTimeout((struct bnode *) abnode, 0); /* clear timer */ if (abnode->b.goal) code = ez_setstat((struct bnode *) abnode, BSTAT_NORMAL); else if (abnode->b.flags & BNODE_ERRORSTOP && abnode->b.errorStopDelay) { bozo_Log("%s will retry start in %d seconds\n", abnode->b.name, abnode->b.errorStopDelay); bnode_SetTimeout(bn, abnode->b.errorStopDelay); } return code; } static int ez_getstring(struct bnode *abnode, char *abuffer, afs_int32 alen) { return -1; /* don't have much to add */ } static int ez_getparm(struct bnode *bn, afs_int32 aindex, char *abuffer, afs_int32 alen) { struct ezbnode *abnode = (struct ezbnode *) bn; if (aindex > 0) return BZDOM; strcpy(abuffer, abnode->command); return 0; }