2 * The Data Control Manager for SMS.
4 * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
5 * For copying and distribution information, see the file
14 static char rcsid_dcm_c[] = "$Header$";
26 #include "mit-copyright.h"
29 extern char *getenv();
31 extern char *error_message();
37 /* declared global so that we can get the current time from different places. */
51 dbg = atoi(getenv("DEBUG"));
57 while(++arg - argv < argc) {
61 dbg = atoi((*arg)[2]? *arg+2: *++arg);
65 set_com_err_hook(dcm_com_err_hook);
67 /* if /etc/nodcm exists, punt quietly. */
68 if (!access("/etc/nodcm", F_OK)) {
72 if (status = sms_connect()) {
73 com_err(whoami, status, " on sms_connect");
74 leave("connect failed");
77 if (status = sms_auth("dcm")) {
78 com_err(whoami, status, " on \"authenticate\"");
82 /* if DCM is not enabled, exit after logging */
83 qargv[0] = "dcm_enable";
84 if (status = sms_query("get_value", 1, qargv, gqval, &i)) {
85 com_err(whoami, status, " check dcm_enable");
86 leave("query failed");
90 leave("dcm_enable not set");
100 /* Used by the get_value query when checking for dcm_enable. */
102 gqval(argc, argv, hint)
107 *hint = atoi(argv[0]);
112 /* Used by qualified_get_server to make a list of servers to check */
114 qgetsv(argc, argv, sq)
117 struct save_queue *sq;
119 sq_save_data(sq, strsave(argv[0]));
124 /* Used by get_server_info to record all of the returned information */
126 getsvinfo(argc, argv, sserv)
129 struct service *sserv;
131 sserv->service = strsave(argv[0]);
132 sserv->interval = atoi(argv[1]);
133 sserv->target = strsave(argv[2]);
134 sserv->script = strsave(argv[3]);
135 sserv->dfgen = atoi(argv[4]);
136 sserv->dfcheck = atoi(argv[5]);
137 sserv->type = strsave(argv[6]);
138 sserv->enable = atoi(argv[7]);
139 sserv->inprogress = atoi(argv[8]);
140 sserv->harderror = atoi(argv[9]);
141 sserv->errmsg = strsave(argv[10]);
146 /* Scan the services and process any that need it. */
151 struct save_queue *sq, *sq_create();
152 char *service, dfgen_prog[64], dfgen_cmd[128];
154 int status, lock_fd, ex;
159 if (dbg & DBG_VERBOSE)
160 com_err(whoami, 0, "starting pass over services");
163 qargv[1] = "dontcare";
166 if (status = sms_query("qualified_get_server", 3, qargv, qgetsv, sq)) {
167 com_err(whoami, status, " getting services");
168 leave("query failed");
170 while (sq_get_data(sq, &service)) {
171 for (p = service; *p; p++)
174 com_err(whoami, 0, "checking %s...", service);
176 sprintf(dfgen_prog, "%s/bin/%s.gen", SMS_DIR, service);
177 if (!file_exists(dfgen_prog)) {
178 com_err(whoami, 0, "prog %s doesn't exist\n", dfgen_prog);
182 sprintf(dfgen_cmd, "exec %s %s/dcm/%s.out",
183 dfgen_prog, SMS_DIR, service);
184 gettimeofday(&tv, &tz);
185 if (status = sms_query("get_server_info", 1, qargv, getsvinfo, &svc)) {
186 com_err(whoami, status, " getting service %s info", service);
188 svc.service = strsave(service);
189 qargv[0] = strsave(service);
190 qargv[1] = itoa(svc.dfgen);
191 qargv[2] = itoa(svc.dfcheck);
192 qargv[3] = strsave("0");
193 qargv[4] = itoa(svc.harderror);
194 qargv[5] = strsave(svc.errmsg);
195 if (svc.interval != 0) {
196 if (svc.interval * 60 + svc.dfcheck < tv.tv_sec) {
197 lock_fd = maybe_lock_update(SMS_DIR, "@db@", service, 1);
203 qargv[3] = strsave("1");
204 qargv[4] = strsave("0");
205 qargv[5] = strsave("");
206 status = sms_query("set_server_internal_flags", 6, qargv,
208 if (status != SMS_SUCCESS) {
209 com_err(whoami, status, " setting server state");
213 com_err(whoami, status, " running %s", dfgen_prog);
214 waits.w_status = system(dfgen_cmd);
215 if (waits.w_termsig) {
216 status = SMS_TAR_FAIL;
217 com_err(whoami, status, " %s exited on signal %d",
218 dfgen_prog, waits.w_termsig);
219 } else if (waits.w_retcode) {
220 /* extract the process's exit value */
221 status = waits.w_retcode + sms_err_base;
222 com_err(whoami, status, " %s exited", dfgen_prog);
224 if (SOFT_FAIL(status)) {
226 qargv[5] = strsave(error_message(status));
227 } else if (status == SMS_NO_CHANGE) {
229 qargv[2] = itoa(tv.tv_sec);
230 svc.dfcheck = tv.tv_sec;
231 } else if (status == SMS_SUCCESS) {
234 qargv[1] = itoa(tv.tv_sec);
235 qargv[2] = strsave(qargv[1]);
236 svc.dfcheck = svc.dfgen = tv.tv_sec;
237 } else { /* HARD_FAIL(status) */
241 qargv[2] = itoa(tv.tv_sec);
242 svc.dfcheck = tv.tv_sec;
243 qargv[4] = itoa(status);
244 qargv[5] = strsave(error_message(status));
245 critical_alert("DCM","DCM building config files for %s: %s",
250 qargv[3] = strsave("0");
251 status = sms_query("set_server_internal_flags", 6, qargv,
261 if (!strcmp(svc.type, "REPLICAT"))
265 lock_fd = maybe_lock_update(SMS_DIR, "@db@", service, ex);
282 /* Used by qualified_get_server_host to make a list of hosts to check */
284 qgethost(argc, argv, sq)
287 struct save_queue *sq;
289 sq_save_data(sq, strsave(argv[1]));
294 /* Used by get_server_host_info to store all of the info about a host */
296 gethostinfo(argc, argv, shost)
299 struct svrhost *shost;
301 shost->service = strsave(argv[0]);
302 shost->machine = strsave(argv[1]);
303 shost->enable = atoi(argv[2]);
304 shost->override = atoi(argv[3]);
305 shost->success = atoi(argv[4]);
306 shost->inprogress = atoi(argv[5]);
307 shost->hosterror = atoi(argv[6]);
308 shost->errmsg = strsave(argv[7]);
309 shost->lasttry = atoi(argv[8]);
310 shost->lastsuccess = atoi(argv[9]);
311 shost->value1 = atoi(argv[10]);
312 shost->value2 = atoi(argv[11]);
313 shost->value3 = strsave(argv[12]);
318 /* Scans all of the hosts for a particular service, and processes them. */
323 char *argv[9], *machine;
325 struct save_queue *sq;
326 struct svrhost shost;
329 argv[0] = svc->service;
331 argv[2] = argv[3] = argv[4] = "DONTCARE";
333 status = sms_query("qualified_get_server_host", 6, argv, qgethost, sq);
334 if (status == SMS_NO_MATCH) {
337 com_err(whoami, status, " getting server_hosts for %s", svc->service);
340 while (sq_get_data(sq, &machine)) {
342 com_err(whoami, 0, "checking %s...", machine);
344 status = sms_query("get_server_host_info", 2, argv,gethostinfo, &shost);
346 com_err(whoami,status, " getting server_host_info for %s", machine);
349 if (!shost.enable || shost.hosterror ||
350 (shost.success && !shost.override &&
351 shost.lastsuccess > svc->dfgen)) {
353 com_err(whoami, 0, "not updating %s:%s", svc->service, machine);
356 if (!shost.success || shost.override ||
357 shost.lasttry + svc->interval < tv.tv_sec) {
358 lock_fd = maybe_lock_update(SMS_DIR, machine, svc->service, 1);
361 argv[0] = svc->service;
363 argv[2] = argv[3] = argv[5] = "0";
365 argv[6] = strsave("");
366 argv[7] = itoa(tv.tv_sec);
367 argv[8] = itoa(shost.lastsuccess);
368 status = sms_query("set_server_host_internal", 9, argv,scream,NULL);
369 if (status != SMS_SUCCESS) {
370 com_err(whoami,status," while setting internal state for %s:%s",
371 svc->service, machine);
374 status = sms_update_server(svc->service, machine, svc->target,
376 if (status == SMS_SUCCESS) {
380 argv[8] = itoa(tv.tv_sec);
381 } else if (SOFT_FAIL(status)) {
383 argv[6] = strsave(error_message(status));
384 } else { /* HARD_FAIL */
385 argv[2] = itoa(shost.override);
386 argv[5] = itoa(status);
388 argv[6] = strsave(error_message(status));
389 critical_alert("DCM", "DCM updating %s:%s: %s",
390 machine, svc->service, argv[6]);
391 if (!strcmp(svc->type, "REPLICAT")) {
394 svc->harderror = status;
395 svc->errmsg = strsave(argv[6]);
396 qargv[0] = strsave(svc->service);
397 qargv[1] = itoa(svc->dfgen);
398 qargv[2] = itoa(svc->dfcheck);
399 qargv[3] = strsave("0");
400 qargv[4] = itoa(svc->harderror);
401 qargv[5] = strsave(svc->errmsg);
402 status = sms_query("set_server_internal_flags",
403 6, qargv, scream, NULL);
414 status = sms_query("set_server_host_internal",
415 9, argv,scream,NULL);
423 status = sms_query("set_server_host_internal", 9, argv,scream,NULL);
426 com_err(whoami, 0, "not updating %s", machine);