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