]> andersk Git - moira.git/blob - dcm/dcm.c
moved directory definitions
[moira.git] / dcm / dcm.c
1 /*
2  * The Data Control Manager for SMS.
3  *
4  * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
5  * For copying and distribution information, see the file
6  * "mit-copyright.h".
7  *
8  * $Source$
9  * $Author$
10  * $Header$
11  */
12
13 #ifndef lint
14 static char rcsid_dcm_c[] = "$Header$";
15 #endif lint
16
17 #include <stdio.h>
18 #include <update.h>
19 #include <sys/file.h>
20 #include <sys/time.h>
21 #include <sys/wait.h>
22 #include <signal.h>
23 #include <ctype.h>
24 #include <sms.h>
25 #include <sms_app.h>
26 #include "dcm.h"
27 #include "mit-copyright.h"
28
29 extern char *ctime();
30 extern char *getenv();
31 extern int log_flags;
32 extern char *error_message();
33 char *itoa();
34 int gqval();
35 long time();
36
37
38 #define DEADLOCK_WAIT   (3 * 60)        /* number of seconds to wait after
39                                            a deadlock before trying again. */
40
41 /* declared global so that we can get the current time from different places. */
42 struct timeval tv;
43
44
45 main(argc, argv)
46 int argc;
47 char *argv[];
48 {
49         int i;
50         char **arg = argv;
51         char *qargv[3];
52         int status;
53
54         whoami = argv[0];
55         dbg = atoi(getenv("DEBUG"));
56         umask(UMASK);
57         log_flags = 0;
58         setlinebuf(stderr);
59         setlinebuf(stdout);
60         
61         while(++arg - argv < argc) {
62             if (**arg == '-')
63                 switch((*arg)[1]) {
64                 case 'd':
65                     dbg =  atoi((*arg)[2]? *arg+2: *++arg);
66                     break;
67                 }
68         }
69         set_com_err_hook(dcm_com_err_hook);
70         
71         /* if /etc/nodcm exists, punt quietly. */
72         if (!access(NODCMFILE, F_OK)) {
73                 exit(1);
74         } 
75
76         if (status = sms_connect("")) {
77             com_err(whoami, status, " on sms_connect");
78             leave("connect failed");
79         }
80
81         if (status = sms_auth("dcm")) {
82             com_err(whoami, status, " on \"authenticate\"");
83             leave("auth failed");
84         }
85
86         /* if DCM is not enabled, exit after logging */
87         qargv[0] = "dcm_enable";
88         if (status = sms_query("get_value", 1, qargv, gqval, &i)) {
89             com_err(whoami, status, " check dcm_enable");
90             leave("query failed");
91         }
92         if (i == 0) {
93             errno = 0;
94             leave("dcm_enable not set");
95         } 
96
97         /* do it! */
98         do_services();
99         errno = 0;
100         leave("");
101 }
102
103
104 /* Used by the get_value query when checking for dcm_enable. */
105
106 gqval(argc, argv, hint)
107 int argc;
108 char **argv;
109 int *hint;
110 {
111     *hint = atoi(argv[0]);
112     return(UPCALL_STOP);
113 }
114
115
116 /* Used by qualified_get_server to make a list of servers to check */
117
118 qgetsv(argc, argv, sq)
119 int argc;
120 char **argv;
121 struct save_queue *sq;
122 {
123     sq_save_data(sq, strsave(argv[0]));
124     return(UPCALL_CONT);
125 }
126
127
128 /* Used by get_server_info to record all of the returned information */
129
130 getsvinfo(argc, argv, sserv)
131 int argc;
132 char **argv;
133 struct service *sserv;
134 {
135     sserv->service = strsave(argv[0]);
136     sserv->interval = atoi(argv[1]);
137     sserv->target = strsave(argv[2]);
138     sserv->script = strsave(argv[3]);
139     sserv->dfgen = atoi(argv[4]);
140     sserv->dfcheck = atoi(argv[5]);
141     sserv->type = strsave(argv[6]);
142     sserv->enable = atoi(argv[7]);
143     sserv->inprogress = atoi(argv[8]);
144     sserv->harderror = atoi(argv[9]);
145     sserv->errmsg = strsave(argv[10]);
146     return(UPCALL_STOP);
147 }
148
149
150 /* Scan the services and process any that need it. */
151
152 do_services()
153 {
154     char *qargv[6];
155     struct save_queue *sq, *sq_create();
156     char *service, dfgen_prog[64], dfgen_cmd[128];
157     struct service svc;
158     int status, lock_fd, ex, (*cstat)();
159     struct timezone tz;
160     register char *p;
161     union wait waits;
162
163     if (dbg & DBG_VERBOSE)
164         com_err(whoami, 0, "starting pass over services");
165
166     qargv[0] = "true";
167     qargv[1] = "dontcare";
168     qargv[2] = "false";
169     sq = sq_create();
170     if (status = sms_query("qualified_get_server", 3, qargv, qgetsv, sq)) {
171         com_err(whoami, status, " getting services");
172         leave("query failed");
173     }
174     while (sq_get_data(sq, &service)) {
175         for (p = service; *p; p++)
176           if (isupper(*p))
177             *p = tolower(*p);
178         com_err(whoami, 0, "checking %s...", service);
179         qargv[0] = service;
180         sprintf(dfgen_prog, "%s/%s.gen", BIN_DIR, service);
181         if (!file_exists(dfgen_prog)) {
182             com_err(whoami, 0, "prog %s doesn't exist\n", dfgen_prog);
183             free(service);
184             continue;
185         }
186         sprintf(dfgen_cmd, "exec %s %s/%s.out",
187                 dfgen_prog, DCM_DIR, service);
188         gettimeofday(&tv, &tz);
189         if (status = sms_query("get_server_info", 1, qargv, getsvinfo, &svc)) {
190             com_err(whoami, status, " getting service %s info, skipping to next service", service);
191             continue;
192         }
193         svc.service = strsave(service);
194         qargv[0] = strsave(service);
195         qargv[1] = itoa(svc.dfgen);
196         qargv[2] = itoa(svc.dfcheck);
197         qargv[3] = strsave("0");
198         qargv[4] = itoa(svc.harderror);
199         qargv[5] = strsave(svc.errmsg);
200         if (svc.interval != 0) {
201             if (svc.interval * 60 + svc.dfcheck < tv.tv_sec) {
202                 lock_fd = maybe_lock_update("@db@", service, 1);
203                 if (lock_fd < 0)
204                   goto free_service;
205                 free(qargv[3]);
206                 free(qargv[4]);
207                 free(qargv[5]);
208                 qargv[3] = strsave("1");
209                 qargv[4] = strsave("0");
210                 qargv[5] = strsave("");
211                 status = sms_query("set_server_internal_flags", 6, qargv,
212                                    scream, NULL);
213                 if (status != SMS_SUCCESS) {
214                     com_err(whoami, status, " setting server state");
215                     goto free_service;
216                 }
217             
218                 com_err(whoami, status, " running %s", dfgen_prog);
219                 cstat = signal(SIGCHLD, SIG_DFL);
220                 waits.w_status = system(dfgen_cmd);
221                 signal(SIGCHLD, cstat);
222                 if (waits.w_termsig) {
223                     status = SMS_TAR_FAIL;
224                     com_err(whoami, status, " %s exited on signal %d",
225                             dfgen_prog, waits.w_termsig);
226                 } else if (waits.w_retcode) {
227                     /* extract the process's exit value */
228                     status = waits.w_retcode + sms_err_base;
229                     com_err(whoami, status, " %s exited", dfgen_prog);
230                 }
231                 if (SOFT_FAIL(status)) {
232                     free(qargv[5]);
233                     qargv[5] = strsave(error_message(status));
234                 } else if (status == SMS_NO_CHANGE) {
235                     free(qargv[2]);
236                     qargv[2] = itoa(tv.tv_sec);
237                     svc.dfcheck = tv.tv_sec;
238                 } else if (status == SMS_SUCCESS) {
239                     free(qargv[1]);
240                     free(qargv[2]);
241                     qargv[1] = itoa(tv.tv_sec);
242                     qargv[2] = strsave(qargv[1]);
243                     svc.dfcheck = svc.dfgen = tv.tv_sec;
244                 } else { /* HARD_FAIL(status) */
245                     free(qargv[2]);
246                     free(qargv[4]);
247                     free(qargv[5]);
248                     qargv[2] = itoa(tv.tv_sec); 
249                     svc.dfcheck = tv.tv_sec;
250                     qargv[4] = itoa(status);
251                     qargv[5] = strsave(error_message(status));
252                     critical_alert("DCM","DCM building config files for %s: %s",
253                                   service, qargv[5]);
254                 }
255             free_service:
256                 free(qargv[3]);
257                 qargv[3] = strsave("0");
258                 status = sms_query("set_server_internal_flags", 6, qargv,
259                                    scream, NULL);
260                 if (status) {
261                     com_err(whoami, status,
262                             " setting service state, sleeping");
263                     sleep(DEADLOCK_WAIT);
264                     status = sms_query("set_server_internal_flags", 6, qargv,
265                                        scream, NULL);
266                     if (status)
267                       com_err(whoami, status, " setting service state again");
268                 }
269                 close(lock_fd);
270                 free(qargv[0]);
271                 free(qargv[1]);
272                 free(qargv[2]);
273                 free(qargv[3]);
274                 free(qargv[4]);
275                 free(qargv[5]);
276             }
277             if (!strcmp(svc.type, "REPLICAT"))
278               ex = 1;
279             else
280               ex = 0;
281             lock_fd = maybe_lock_update("@db@", service, ex);
282             if (lock_fd >= 0) {
283                 do_hosts(&svc);
284                 close(lock_fd);
285             }
286         }
287         free(svc.service);
288         free(svc.target);
289         free(svc.script);
290         free(svc.type);
291         free(svc.errmsg);
292         free(service);
293     }
294     sq_destroy(sq);
295 }
296
297
298 /* Used by qualified_get_server_host to make a list of hosts to check */
299
300 qgethost(argc, argv, sq)
301 int argc;
302 char **argv;
303 struct save_queue *sq;
304 {
305     sq_save_data(sq, strsave(argv[1]));
306     return(UPCALL_CONT);
307 }
308
309
310 /* Used by get_server_host_info to store all of the info about a host */
311
312 gethostinfo(argc, argv, shost)
313 int argc;
314 char **argv;
315 struct svrhost *shost;
316 {
317     shost->service = strsave(argv[0]);
318     shost->machine = strsave(argv[1]);
319     shost->enable = atoi(argv[2]);
320     shost->override = atoi(argv[3]);
321     shost->success = atoi(argv[4]);
322     shost->inprogress = atoi(argv[5]);
323     shost->hosterror = atoi(argv[6]);
324     shost->errmsg = strsave(argv[7]);
325     shost->lasttry = atoi(argv[8]);
326     shost->lastsuccess = atoi(argv[9]);
327     shost->value1 = atoi(argv[10]);
328     shost->value2 = atoi(argv[11]);
329     shost->value3 = strsave(argv[12]);
330     return(UPCALL_STOP);
331 }
332
333
334 /* Scans all of the hosts for a particular service, and processes them. */
335
336 do_hosts(svc)
337 struct service *svc;
338 {
339     char *argv[9], *machine;
340     int status, lock_fd;
341     struct save_queue *sq;
342     struct svrhost shost;
343
344     sq = sq_create();
345     argv[0] = svc->service;
346     argv[1] = "TRUE";
347     argv[2] = argv[3] = argv[4] = "DONTCARE";
348     argv[5] = "FALSE";
349     status = sms_query("qualified_get_server_host", 6, argv, qgethost, sq);
350     if (status == SMS_NO_MATCH) {
351         return;
352     } else if (status) {
353         com_err(whoami, status, " getting server_hosts for  %s", svc->service);
354         return;
355     }
356     while (sq_get_data(sq, &machine)) {
357         if (dbg & DBG_TRACE)
358           com_err(whoami, 0, "checking %s...", machine);
359         argv[1] = machine;
360         status = sms_query("get_server_host_info", 2, argv,gethostinfo, &shost);
361         if (status) {
362             com_err(whoami,status, " getting server_host_info for %s", machine);
363             goto free_mach;
364         }
365         if (!shost.enable || shost.hosterror ||
366             (shost.success && !shost.override &&
367              shost.lastsuccess >= svc->dfgen)) {
368             if (dbg & DBG_TRACE)
369               com_err(whoami, 0, "not updating %s:%s", svc->service, machine);
370             goto free_mach;
371         }
372
373         lock_fd = maybe_lock_update(machine, svc->service, 1);
374         if (lock_fd < 0)
375           goto free_mach;
376         argv[0] = svc->service;
377         argv[1] = machine;
378         argv[2] = argv[3] = argv[5] = "0";
379         argv[4] = "1";
380         argv[6] = strsave("");
381         argv[7] = itoa(tv.tv_sec);
382         argv[8] = itoa(shost.lastsuccess);
383         status = sms_query("set_server_host_internal", 9, argv,scream,NULL);
384         if (status != SMS_SUCCESS) {
385             com_err(whoami,status," while setting internal state for %s:%s",
386                     svc->service, machine);
387             goto free_mach;
388         }
389         status = sms_update_server(svc->service, machine, svc->target,
390                                    svc->script);
391         if (status == SMS_SUCCESS) {
392             argv[2] = "0";
393             argv[3] = "1";
394             free(argv[8]);
395             argv[8] = itoa(tv.tv_sec);
396         } else if (SOFT_FAIL(status)) {
397             free(argv[6]);
398             argv[6] = strsave(error_message(status));
399         } else { /* HARD_FAIL */
400             argv[2] = itoa(shost.override);
401             argv[5] = itoa(status);
402             free(argv[6]);
403             argv[6] = strsave(error_message(status));
404             critical_alert("DCM", "DCM updating %s:%s: %s",
405                            machine, svc->service, argv[6]);
406             if (!strcmp(svc->type, "REPLICAT")) {
407                 char *qargv[6];
408
409                 svc->harderror = status;
410                 svc->errmsg = strsave(argv[6]);
411                 qargv[0] = strsave(svc->service);
412                 qargv[1] = itoa(svc->dfgen);
413                 qargv[2] = itoa(svc->dfcheck);
414                 qargv[3] = strsave("0");
415                 qargv[4] = itoa(svc->harderror);
416                 qargv[5] = strsave(svc->errmsg);
417                 status = sms_query("set_server_internal_flags",
418                                    6, qargv, scream, NULL);
419                 if (status) {
420                     com_err(whoami, status,
421                             " setting service state, sleeping");
422                     sleep(DEADLOCK_WAIT);
423                     status = sms_query("set_server_internal_flags",
424                                        6, qargv, scream, NULL);
425                     if (status)
426                       com_err(whoami, status, " setting service state again");
427                 }
428                 free(qargv[0]);
429                 free(qargv[1]);
430                 free(qargv[2]);
431                 free(qargv[3]);
432                 free(qargv[4]);
433                 free(qargv[5]);
434                 close(lock_fd);
435                 free(argv[2]);
436                 argv[4] = "0";
437                 free(argv[5]);
438                 status = sms_query("set_server_host_internal",
439                                    9, argv,scream,NULL);
440                 if (status) {
441                     com_err(whoami, status,
442                             " setting host state, sleeping");
443                     sleep(DEADLOCK_WAIT);
444                     status = sms_query("set_server_host_internal",
445                                        9, argv,scream,NULL);
446                     if (status)
447                       com_err(whoami, status, " setting host state again");
448                 }
449                 return(-1);
450             }
451             free(argv[2]);
452             free(argv[5]);
453         }
454         argv[4] = "0";
455         close(lock_fd);
456         status = sms_query("set_server_host_internal", 9, argv,scream,NULL);
457         if (status) {
458             com_err(whoami, status, " setting host state, sleeping");
459             sleep(DEADLOCK_WAIT);
460             status = sms_query("set_server_host_internal", 9, argv,scream,NULL);
461             if (status)
462               com_err(whoami, status, " setting host state again");
463         }
464     free_mach:
465         free(machine);
466         close(lock_fd);
467     }
468     return(0);
469 }
This page took 0.219313 seconds and 5 git commands to generate.