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