]> andersk Git - moira.git/blame - server/increment.pc
cant_fix takes an argument
[moira.git] / server / increment.pc
CommitLineData
32cfe906 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1989 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
9 *
10 */
11
12#ifndef lint
13static char *rcsid_increment_dc = "$Header$";
14#endif lint
15
16#include <mit-copyright.h>
17#include <moira.h>
03c05291 18#include <fcntl.h>
19#include <unistd.h>
20#include <signal.h>
32cfe906 21#include "mr_server.h"
03c05291 22#include "query.h"
23#include "qrtn.h"
45bf7573 24EXEC SQL INCLUDE sqlca;
32cfe906 25
26extern char *whoami;
03c05291 27extern char *table_name[];
28extern int num_tables;
32cfe906 29
30int inc_pid = 0;
31int inc_running = 0;
32time_t inc_started;
33
34#define MAXARGC 15
35
03c05291 36EXEC SQL WHENEVER SQLERROR DO dbmserr();
45bf7573 37
32cfe906 38/* structures to save before args */
32cfe906 39static char *before[MAXARGC];
32cfe906 40static int beforec;
03c05291 41static enum tables beforetable;
32cfe906 42
43/* structures to save after args */
32cfe906 44static char *after[MAXARGC];
32cfe906 45static int afterc;
46
47/* structures to save entire sets of incremental changes */
48struct save_queue *incremental_sq = NULL;
49struct save_queue *incremental_exec = NULL;
50struct iupdate {
51 char *table;
52 int beforec;
53 char **before;
54 int afterc;
55 char **after;
56 char *service;
57};
58
03c05291 59void next_incremental(void);
60char **copy_argv(char **argv, int argc);
61void free_argv(char **argv, int argc);
62int table_num(char *table);
32cfe906 63
03c05291 64void incremental_init(void)
32cfe906 65{
66 int i;
67
32cfe906 68 if (incremental_sq == NULL)
69 incremental_sq = sq_create();
70 if (incremental_exec == NULL)
71 incremental_exec = sq_create();
03c05291 72
73 for(i=0; i<MAXARGC; i++) {
74 before[i]=malloc(ARGLEN);
75 after[i]=malloc(ARGLEN);
76 }
32cfe906 77}
78
79
03c05291 80/* record the state of a table row before it is changed */
81
82void incremental_before(table, qual, argv)
83 enum tables table;
84EXEC SQL BEGIN DECLARE SECTION;
85 char *qual, **argv;
86EXEC SQL END DECLARE SECTION;
32cfe906 87{
88 EXEC SQL BEGIN DECLARE SECTION;
89 int id;
90 EXEC SQL END DECLARE SECTION;
91
03c05291 92 char *name;
32cfe906 93
94 beforetable = table;
95
03c05291 96 switch(table)
97 {
98 case USERS_TABLE:
99 sprintf(stmt_buf, "SELECT u.login, u.unix_uid, u.shell, u.last, "
100 "u.first, u.middle, u.status, u.clearid, u.type "
101 "FROM users u WHERE %s", qual);
102 dosql(before);
32cfe906 103 beforec = 9;
03c05291 104 break;
105 case MACHINE_TABLE:
106 sprintf(stmt_buf, "SELECT m.name, m.vendor FROM machine m "
107 "WHERE %s", qual);
108 dosql(before);
32cfe906 109 beforec = 2;
03c05291 110 break;
111 case CLUSTER_TABLE:
112 sprintf(stmt_buf, "SELECT c.name, c.description, c.location "
113 "FROM clusters c WHERE %s", qual);
114 dosql(before);
32cfe906 115 beforec = 3;
03c05291 116 break;
117 case MCMAP_TABLE:
118 strcpy(before[0], argv[0]);
119 strcpy(before[1], argv[1]);
32cfe906 120 beforec = 2;
03c05291 121 break;
122 case SVC_TABLE:
123 strcpy(before[0], argv[0]);
124 strcpy(before[1], argv[1]);
125 strcpy(before[2], argv[2]);
32cfe906 126 beforec = 3;
03c05291 127 break;
128 case FILESYS_TABLE:
129 sprintf(stmt_buf, "SELECT fs.label, fs.type, fs.mach_id, fs.name, "
130 "fs.mount, fs.rwaccess, fs.comments, fs.owner, fs.owners, "
131 "fs.createflg, fs.lockertype FROM filesys fs WHERE %s", qual);
132 dosql(before);
bc5e9d66 133 name = malloc(0);
03c05291 134 id = atoi(before[2]);
135 id_to_name(id, MACHINE_TABLE, &name);
136 strcpy(before[2], name);
137 id = atoi(before[7]);
138 id_to_name(id, USERS_TABLE, &name);
139 strcpy(before[7], name);
140 id = atoi(before[8]);
141 id_to_name(id, LIST_TABLE, &name);
142 strcpy(before[8], name);
bc5e9d66 143 free(name);
32cfe906 144 beforec = 11;
03c05291 145 break;
146 case QUOTA_TABLE:
147 strcpy(before[0], "?");
148 strcpy(before[1], argv[1]);
149 strcpy(before[2], "?");
150 sprintf(stmt_buf, "SELECT q.quota, fs.name FROM quota q, filesys fs "
151 "WHERE %s AND fs.filsys_id = q.filsys_id", qual);
152 dosql(&(before[3]));
153 strcpy(before[2], argv[1]);
32cfe906 154 beforec = 5;
03c05291 155 break;
156 case LIST_TABLE:
157 sprintf(stmt_buf, "SELECT l.name, l.active, l.publicflg, l.hidden, "
158 "l.maillist, l.grouplist, l.gid, l.acl_type, l.acl_id, "
159 "l.description FROM list l WHERE %s", qual);
160 dosql(before);
32cfe906 161 beforec = 10;
03c05291 162 break;
163 case IMEMBERS_TABLE:
32cfe906 164 id = (int) argv[0];
03c05291 165 sprintf(stmt_buf, "SELECT active, publicflg, hidden, maillist, "
166 "grouplist, gid FROM list WHERE list_id = %d", id);
167 dosql(&(before[3]));
32cfe906 168 name = malloc(0);
03c05291 169 id_to_name(id, LIST_TABLE, &name);
170 strcpy(before[0], name);
171 strcpy(before[1], argv[1]);
32cfe906 172 id = (int) argv[2];
edf38460 173 beforec = 9;
03c05291 174 if (!strcmp(before[1], "USER")) {
175 id_to_name(id, USERS_TABLE, &name);
176 EXEC SQL SELECT status INTO :before[9] FROM users
edf38460 177 WHERE users_id=:id;
178 beforec = 10;
03c05291 179 } else if (!strcmp(before[1], "LIST")) {
180 id_to_name(id, LIST_TABLE, &name);
181 } else if (!strcmp(before[1], "STRING") || !strcmp(before[1], "KERBEROS")) {
182 id_to_name(id, STRINGS_TABLE, &name);
32cfe906 183 }
03c05291 184 strcpy(before[2], name);
32cfe906 185 free(name);
03c05291 186 break;
187 default:
188 /*
189 com_err(whoami, 0, "requested incremental on unexpected table `%s'",
190 table_name[table]);
191 */
192 break;
193 }
a313cad2 194}
32cfe906 195
196
03c05291 197void incremental_clear_before(void)
32cfe906 198{
199 beforec = 0;
200}
201
32cfe906 202
03c05291 203/* add an element to the incremental queue for the changed row */
32cfe906 204
03c05291 205void incremental_after(table, qual, argv)
206 enum tables table;
207EXEC SQL BEGIN DECLARE SECTION;
208 char *qual, **argv;
209EXEC SQL END DECLARE SECTION;
a313cad2 210{
03c05291 211#ifdef DEBUG
212 char buffer[2048];
213#endif
214 char *name;
a313cad2 215EXEC SQL BEGIN DECLARE SECTION;
03c05291 216 int id;
a313cad2 217EXEC SQL END DECLARE SECTION;
32cfe906 218 struct iupdate *iu;
03c05291 219
220 switch(table)
221 {
222 case USERS_TABLE:
223 sprintf(stmt_buf, "SELECT u.login, u.unix_uid, u.shell, u.last, "
224 "u.first, u.middle, u.status, u.clearid, u.type "
225 "FROM users u WHERE %s", qual);
226 dosql(after);
32cfe906 227 afterc = 9;
03c05291 228 break;
229 case MACHINE_TABLE:
230 sprintf(stmt_buf, "SELECT m.name, m.vendor FROM machine m "
231 "WHERE %s", qual);
232 dosql(after);
32cfe906 233 afterc = 2;
03c05291 234 break;
235 case CLUSTER_TABLE:
236 sprintf(stmt_buf, "SELECT c.name, c.description, c.location "
237 "FROM clusters c WHERE %s", qual);
238 dosql(after);
32cfe906 239 afterc = 3;
03c05291 240 break;
241 case MCMAP_TABLE:
242 strcpy(after[0], argv[0]);
243 strcpy(after[1], argv[1]);
32cfe906 244 afterc = 2;
03c05291 245 break;
246 case SVC_TABLE:
247 strcpy(after[0], argv[0]);
248 strcpy(after[1], argv[1]);
249 strcpy(after[2], argv[2]);
32cfe906 250 afterc = 3;
03c05291 251 break;
252 case FILESYS_TABLE:
253 sprintf(stmt_buf, "SELECT fs.label, fs.type, fs.mach_id, fs.name, "
254 "fs.mount, fs.rwaccess, fs.comments, fs.owner, fs.owners, "
255 "fs.createflg, fs.lockertype FROM filesys fs WHERE %s", qual);
256 dosql(after);
bc5e9d66 257 name = malloc(0);
03c05291 258 id = atoi(after[2]);
259 id_to_name(id, MACHINE_TABLE, &name);
260 strcpy(after[2], name);
261 id = atoi(after[7]);
262 id_to_name(id, USERS_TABLE, &name);
263 strcpy(after[7], name);
264 id = atoi(after[8]);
265 id_to_name(id, LIST_TABLE, &name);
266 strcpy(after[8], name);
bc5e9d66 267 free(name);
32cfe906 268 afterc = 11;
03c05291 269 break;
270 case QUOTA_TABLE:
271 strcpy(after[0], "?");
272 strcpy(after[1], argv[1]);
273 strcpy(after[2], "?");
274 sprintf(stmt_buf, "SELECT q.quota, fs.name FROM quota q, filesys fs "
275 "WHERE %s and fs.filsys_id = q.filsys_id and q.type = '%s'",
962364ec 276 qual, argv[1]);
03c05291 277 dosql(&(after[3]));
32cfe906 278 afterc = 5;
03c05291 279 break;
280 case LIST_TABLE:
281 sprintf(stmt_buf, "SELECT l.name, l.active, l.publicflg, l.hidden, "
282 "l.maillist, l.grouplist, l.gid, l.acl_type, l.acl_id, "
283 "l.description FROM list l WHERE %s", qual);
284 dosql(after);
32cfe906 285 afterc = 10;
03c05291 286 break;
287 case IMEMBERS_TABLE:
32cfe906 288 id = (int) argv[0];
03c05291 289 sprintf(stmt_buf, "SELECT active, publicflg, hidden, maillist, "
290 "grouplist, gid FROM list WHERE list_id = %d", id);
291 dosql(&(after[3]));
32cfe906 292 name = malloc(0);
03c05291 293 id_to_name(id, LIST_TABLE, &name);
294 strcpy(after[0], name);
295 strcpy(after[1], argv[1]);
32cfe906 296 id = (int) argv[2];
edf38460 297 afterc = 9;
03c05291 298 if (!strcmp(after[1], "USER")) {
299 id_to_name(id, USERS_TABLE, &name);
300 EXEC SQL SELECT status INTO :after[9] FROM users
edf38460 301 WHERE users_id=:id;
302 afterc = 10;
03c05291 303 } else if (!strcmp(after[1], "LIST")) {
304 id_to_name(id, LIST_TABLE, &name);
305 } else if (!strcmp(after[1], "STRING") || !strcmp(after[1], "KERBEROS")) {
306 id_to_name(id, STRINGS_TABLE, &name);
32cfe906 307 }
03c05291 308 strcpy(after[2], name);
32cfe906 309 free(name);
03c05291 310 break;
311 case NO_TABLE:
32cfe906 312 afterc = 0;
313 table = beforetable;
03c05291 314 break;
315 default:
316 /*
317 com_err(whoami, 0, "requested incremental on unexpected table `%s'",
318 table_name[table]);
319 */
320 break;
321 }
32cfe906 322
323 iu = (struct iupdate *) malloc(sizeof(struct iupdate));
03c05291 324 iu->table = table_name[table];
32cfe906 325 iu->beforec = beforec;
326 iu->before = copy_argv(before, beforec);
327 iu->afterc = afterc;
328 iu->after = copy_argv(after, afterc);
329 sq_save_data(incremental_sq, iu);
330
331#ifdef DEBUG
03c05291 332 sprintf(buffer, "INCREMENTAL(%s, [", table_name[table]);
32cfe906 333 for (i = 0; i < beforec; i++) {
334 if (i == 0)
335 strcat(buffer, strtrim(before[0]));
336 else {
337 strcat(buffer, ", ");
338 strcat(buffer, strtrim(before[i]));
339 }
340 }
341 strcat(buffer, "], [");
342 for (i = 0; i < afterc; i++) {
343 if (i == 0)
344 strcat(buffer, strtrim(after[0]));
345 else {
346 strcat(buffer, ", ");
347 strcat(buffer, strtrim(after[i]));
348 }
349 }
350 strcat(buffer, "])");
351 com_err(whoami, 0, buffer);
352#endif DEBUG
a313cad2 353}
32cfe906 354
03c05291 355void incremental_clear_after(void)
356{
357 incremental_after(NO_TABLE, NULL, NULL);
358}
359
32cfe906 360
361/* Called when the current transaction is committed to start any queued
362 * incremental updates. This caches the update table the first time it
363 * is called.
364 */
365
366struct inc_cache {
367 struct inc_cache *next;
03c05291 368 char *table, *service;
32cfe906 369};
370
371
03c05291 372void incremental_update(void)
32cfe906 373{
374 static int inited = 0;
375 static struct inc_cache *cache;
376 struct inc_cache *c;
377 EXEC SQL BEGIN DECLARE SECTION;
378 char tab[17], serv[17];
379 EXEC SQL END DECLARE SECTION;
380 struct iupdate *iu;
381
382 if (!inited) {
383 inited++;
384
03c05291 385 EXEC SQL DECLARE inc CURSOR FOR SELECT table_name, service FROM incremental;
32cfe906 386 EXEC SQL OPEN inc;
387 while (1) {
388 EXEC SQL FETCH inc INTO :tab, :serv;
389 if (sqlca.sqlcode != 0) break;
390 c = (struct inc_cache *)malloc(sizeof(struct inc_cache));
391 c->next = cache;
392 c->table = strsave(strtrim(tab));
393 c->service = strsave(strtrim(serv));
394 cache = c;
395 }
396 EXEC SQL CLOSE inc;
de0954da 397 EXEC SQL COMMIT WORK;
32cfe906 398 }
399
400 while (sq_remove_data(incremental_sq, &iu)) {
401 for (c = cache; c; c = c->next) {
402 if (!strcmp(c->table, iu->table)) {
403 iu->service = c->service;
404 sq_save_data(incremental_exec, iu);
405 }
406 }
407 }
408 if (inc_running == 0)
409 next_incremental();
410}
411
412
03c05291 413void next_incremental(void)
32cfe906 414{
415 struct iupdate *iu;
416 char *argv[MAXARGC * 2 + 4], cafter[3], cbefore[3], prog[BUFSIZ];
417 int i;
03c05291 418 sigset_t sigs;
32cfe906 419
420 if (incremental_exec == NULL)
421 incremental_init();
422
423 if (sq_empty(incremental_exec) ||
424 (inc_running && now - inc_started < INC_TIMEOUT))
425 return;
426
427 if (inc_running)
428 com_err(whoami, 0, "incremental timeout on pid %d", inc_pid);
429
430 sq_remove_data(incremental_exec, &iu);
431 argv[1] = iu->table;
432 sprintf(cbefore, "%d", iu->beforec);
433 argv[2] = cbefore;
434 sprintf(cafter, "%d", iu->afterc);
435 argv[3] = cafter;
436 for (i = 0; i < iu->beforec; i++)
437 argv[4 + i] = iu->before[i];
438 for (i = 0; i < iu->afterc; i++)
439 argv[4 + iu->beforec + i] = iu->after[i];
440
441 sprintf(prog, "%s/%s.incr", BIN_DIR, iu->service);
442#ifdef DEBUG
443 com_err(whoami, 0, "forking %s", prog);
444#endif
445 argv[0] = prog;
446 argv[4 + iu->beforec + iu->afterc] = 0;
03c05291 447
448 sigemptyset(&sigs);
449 sigaddset(&sigs, SIGCHLD);
450 sigprocmask(SIG_BLOCK, &sigs, NULL);
32cfe906 451 inc_pid = vfork();
452 switch (inc_pid) {
453 case 0:
454 execv(prog, argv);
af0171d9 455 _exit(1);
32cfe906 456 case -1:
457 com_err(whoami, 0, "Failed to start incremental update");
458 break;
459 default:
460 inc_running = 1;
461 inc_started = now;
462 }
03c05291 463 sigprocmask(SIG_UNBLOCK, &sigs, NULL);
32cfe906 464
465 free_argv(iu->before, iu->beforec);
466 free_argv(iu->after, iu->afterc);
32cfe906 467 free(iu);
468
469}
470
471
472/* Called when the current transaction is aborted to throw away any queued
473 * incremental updates
474 */
475
03c05291 476void incremental_flush(void)
32cfe906 477{
478 struct iupdate *iu;
479
480 while (sq_get_data(incremental_sq, &iu)) {
481 free_argv(iu->before, iu->beforec);
482 free_argv(iu->after, iu->afterc);
32cfe906 483 free(iu);
484 }
485 sq_destroy(incremental_sq);
486 incremental_sq = sq_create();
487}
488
489
490char **copy_argv(argv, argc)
03c05291 491 char **argv;
492 int argc;
32cfe906 493{
494 char **ret = (char **)malloc(sizeof(char *) * argc);
495 while (--argc >= 0)
496 ret[argc] = strsave(strtrim(argv[argc]));
497 return(ret);
498}
499
03c05291 500void free_argv(argv, argc)
501 char **argv;
502 int argc;
32cfe906 503{
504 while (--argc >= 0)
505 free(argv[argc]);
506 free(argv);
507}
03c05291 508
509int table_num(char *name)
510{
511 int i;
512
513 for(i = num_tables-1; i; i--)
514 if(!strcmp(table_name[i], name)) break;
515
516 return i; /* 0 = "none" if no match */
517}
This page took 0.14906 seconds and 5 git commands to generate.