d640d4edd3258d80f3dd37036103343a6e211489
[openafs.git] / src / bozo / ezbnodeops.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <afs/procmgmt.h>
14 #include <roken.h>
15
16 #include <lwp.h>
17 #include <rx/rx.h>
18
19 #include <afs/afsutil.h>
20 #include "bnode.h"
21 #include "bnode_internal.h"
22 #include "bosprototypes.h"
23
24 extern char *DoPidFiles;
25
26 struct bnode *ez_create(char *, char *, char *, char *, char *, char *);
27 static int ez_hascore(struct bnode *bnode);
28 static int ez_restartp(struct bnode *bnode);
29 static int ez_delete(struct bnode *bnode);
30 static int ez_timeout(struct bnode *bnode);
31 static int ez_getstat(struct bnode *bnode, afs_int32 *status);
32 static int ez_setstat(struct bnode *bnode, afs_int32 status);
33 static int ez_procexit(struct bnode *bnode, struct bnode_proc *proc);
34 static int ez_getstring(struct bnode *bnode, char *abuffer, afs_int32 alen);
35 static int ez_getparm(struct bnode *bnode, afs_int32, char *, afs_int32);
36 static int ez_procstarted(struct bnode *bnode, struct bnode_proc *proc);
37
38 #define SDTIME          60      /* time in seconds given to a process to evaporate */
39 #define ERROR_RESET_TIME 60     /* time in seconds to wait before resetting error count state */
40
41 struct bnode_ops ezbnode_ops = {
42     ez_create,
43     ez_timeout,
44     ez_getstat,
45     ez_setstat,
46     ez_delete,
47     ez_procexit,
48     ez_getstring,
49     ez_getparm,
50     ez_restartp,
51     ez_hascore,
52     ez_procstarted
53 };
54
55 static int
56 ez_hascore(struct bnode *abnode)
57 {
58     char tbuffer[256];
59
60     bnode_CoreName(abnode, NULL, tbuffer);
61     if (access(tbuffer, 0) == 0)
62         return 1;
63     else
64         return 0;
65 }
66
67 static int
68 ez_restartp(struct bnode *bn)
69 {
70     struct ezbnode *abnode = (struct ezbnode *)bn;
71     struct bnode_token *tt;
72     afs_int32 code;
73     struct stat tstat;
74
75     code = bnode_ParseLine(abnode->command, &tt);
76     if (code)
77         return 0;
78     if (!tt)
79         return 0;
80     code = stat(tt->key, &tstat);
81     if (code) {
82         bnode_FreeTokens(tt);
83         return 0;
84     }
85     if (tstat.st_ctime > abnode->lastStart)
86         code = 1;
87     else
88         code = 0;
89     bnode_FreeTokens(tt);
90     return code;
91 }
92
93 static int
94 ez_delete(struct bnode *bn)
95 {
96     struct ezbnode *abnode = (struct ezbnode *)bn;
97
98     free(abnode->command);
99     free(abnode);
100     return 0;
101 }
102
103 struct bnode *
104 ez_create(char *ainstance, char *acommand, char *unused1, char *unused2,
105           char *unused3, char *unused4)
106 {
107     struct ezbnode *te;
108     char *cmdpath;
109
110     if (ConstructLocalBinPath(acommand, &cmdpath)) {
111         bozo_Log("BNODE: command path invalid '%s'\n", acommand);
112         return NULL;
113     }
114
115     te = calloc(1, sizeof(struct ezbnode));
116     if (bnode_InitBnode((struct bnode *)te, &ezbnode_ops, ainstance) != 0) {
117         free(te);
118         return NULL;
119     }
120     te->command = cmdpath;
121     return (struct bnode *)te;
122 }
123
124 /* called to SIGKILL a process if it doesn't terminate normally
125  * or to retry start after an error stop. */
126 static int
127 ez_timeout(struct bnode *bn)
128 {
129     struct ezbnode *abnode = (struct ezbnode *)bn;
130
131     if (abnode->waitingForShutdown) {
132         /* send kill and turn off timer */
133         bnode_StopProc(abnode->proc, SIGKILL);
134         abnode->killSent = 1;
135         bnode_SetTimeout((struct bnode *)abnode, 0);
136     } else if (!abnode->running && abnode->b.flags & BNODE_ERRORSTOP) {
137         /* was stopped for too many errors, retrying */
138         /* reset error count after running for a bit */
139         bnode_SetTimeout(bn, ERROR_RESET_TIME);
140         bnode_SetStat(bn, BSTAT_NORMAL);
141     } else {
142         bnode_SetTimeout(bn, 0); /* one shot timer */
143         bnode_ResetErrorCount(bn);
144     }
145     return 0;
146 }
147
148 static int
149 ez_getstat(struct bnode *bn, afs_int32 * astatus)
150 {
151     struct ezbnode *abnode = (struct ezbnode *)bn;
152
153     afs_int32 temp;
154     if (abnode->waitingForShutdown)
155         temp = BSTAT_SHUTTINGDOWN;
156     else if (abnode->running)
157         temp = BSTAT_NORMAL;
158     else if (abnode->b.flags & BNODE_ERRORSTOP)
159         temp = BSTAT_STARTINGUP;
160     else
161         temp = BSTAT_SHUTDOWN;
162     *astatus = temp;
163     return 0;
164 }
165
166 static int
167 ez_setstat(struct bnode *bn, afs_int32 astatus)
168 {
169     struct ezbnode *abnode = (struct ezbnode *)bn;
170
171     struct bnode_proc *tp;
172     afs_int32 code;
173
174     if (abnode->waitingForShutdown)
175         return BZBUSY;
176     if (astatus == BSTAT_NORMAL && !abnode->running) {
177         /* start up */
178         abnode->lastStart = FT_ApproxTime();
179         code = bnode_NewProc((struct bnode *)abnode, abnode->command, NULL, &tp);
180         if (code)
181             return code;
182         abnode->running = 1;
183         abnode->proc = tp;
184         return 0;
185     } else if (astatus == BSTAT_SHUTDOWN && abnode->running) {
186         /* start shutdown */
187         bnode_StopProc(abnode->proc, SIGTERM);
188         abnode->waitingForShutdown = 1;
189         bnode_SetTimeout((struct bnode *)abnode, SDTIME);
190         return 0;
191     }
192     return 0;
193 }
194
195 static int
196 ez_procstarted(struct bnode *bn, struct bnode_proc *aproc)
197 {
198     int code = 0;
199
200     if (DoPidFiles) {
201         code = bozo_CreatePidFile(bn->name, NULL, aproc->pid);
202     }
203     return code;;
204 }
205
206 static int
207 ez_procexit(struct bnode *bn, struct bnode_proc *aproc)
208 {
209     struct ezbnode *abnode = (struct ezbnode *)bn;
210
211     /* process has exited */
212     afs_int32 code = 0;
213
214     if (DoPidFiles) {
215         bozo_DeletePidFile(bn->name, NULL);
216     }
217
218     abnode->waitingForShutdown = 0;
219     abnode->running = 0;
220     abnode->killSent = 0;
221     abnode->proc = NULL;
222     bnode_SetTimeout((struct bnode *) abnode, 0);       /* clear timer */
223     if (abnode->b.goal)
224         code = ez_setstat((struct bnode *) abnode, BSTAT_NORMAL);
225     else if (abnode->b.flags & BNODE_ERRORSTOP && abnode->b.errorStopDelay) {
226         bozo_Log("%s will retry start in %d seconds\n", abnode->b.name,
227                  abnode->b.errorStopDelay);
228         bnode_SetTimeout(bn, abnode->b.errorStopDelay);
229     }
230     return code;
231 }
232
233 static int
234 ez_getstring(struct bnode *abnode, char *abuffer, afs_int32 alen)
235 {
236     return -1;                  /* don't have much to add */
237 }
238
239 static int
240 ez_getparm(struct bnode *bn, afs_int32 aindex, char *abuffer,
241            afs_int32 alen)
242 {
243     struct ezbnode *abnode = (struct ezbnode *) bn;
244     if (aindex > 0)
245         return BZDOM;
246     strcpy(abuffer, abnode->command);
247     return 0;
248 }