Import Upstream version 1.8.5
[hcoop/debian/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 }