]> andersk Git - moira.git/blame - server/increment.pc
Add queries for creating, deleting, and modifying containers, as well as
[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
88 char *name;
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, "
97 "u.clearid, u.type FROM users u WHERE %s", qual);
5eaef520 98 dosql(before);
d6759517 99 beforec = 10;
5eaef520 100 break;
101 case MACHINE_TABLE:
102 sprintf(stmt_buf, "SELECT m.name, m.vendor FROM machine m "
103 "WHERE %s", qual);
104 dosql(before);
105 beforec = 2;
106 break;
e688520a 107 case CLUSTERS_TABLE:
5eaef520 108 sprintf(stmt_buf, "SELECT c.name, c.description, c.location "
109 "FROM clusters c WHERE %s", qual);
110 dosql(before);
111 beforec = 3;
112 break;
113 case MCMAP_TABLE:
114 strcpy(before[0], argv[0]);
115 strcpy(before[1], argv[1]);
116 beforec = 2;
117 break;
118 case SVC_TABLE:
119 strcpy(before[0], argv[0]);
120 strcpy(before[1], argv[1]);
121 strcpy(before[2], argv[2]);
122 beforec = 3;
123 break;
124 case FILESYS_TABLE:
125 sprintf(stmt_buf, "SELECT fs.label, fs.type, fs.mach_id, fs.name, "
126 "fs.mount, fs.rwaccess, fs.comments, fs.owner, fs.owners, "
127 "fs.createflg, fs.lockertype FROM filesys fs WHERE %s", qual);
128 dosql(before);
129 name = malloc(0);
130 id = atoi(before[2]);
131 id_to_name(id, MACHINE_TABLE, &name);
132 strcpy(before[2], name);
133 id = atoi(before[7]);
134 id_to_name(id, USERS_TABLE, &name);
135 strcpy(before[7], name);
136 id = atoi(before[8]);
137 id_to_name(id, LIST_TABLE, &name);
138 strcpy(before[8], name);
139 free(name);
140 beforec = 11;
141 break;
142 case QUOTA_TABLE:
143 strcpy(before[0], "?");
144 strcpy(before[1], argv[1]);
145 strcpy(before[2], "?");
146 sprintf(stmt_buf, "SELECT q.quota, fs.name FROM quota q, filesys fs "
147 "WHERE %s AND fs.filsys_id = q.filsys_id", qual);
148 dosql(&(before[3]));
149 strcpy(before[2], argv[1]);
150 beforec = 5;
151 break;
152 case LIST_TABLE:
153 sprintf(stmt_buf, "SELECT l.name, l.active, l.publicflg, l.hidden, "
154 "l.maillist, l.grouplist, l.gid, l.acl_type, l.acl_id, "
155 "l.description FROM list l WHERE %s", qual);
156 dosql(before);
157 beforec = 10;
158 break;
159 case IMEMBERS_TABLE:
160 id = (int) argv[0];
161 sprintf(stmt_buf, "SELECT active, publicflg, hidden, maillist, "
162 "grouplist, gid FROM list WHERE list_id = %d", id);
163 dosql(&(before[3]));
164 name = malloc(0);
165 id_to_name(id, LIST_TABLE, &name);
166 strcpy(before[0], name);
167 strcpy(before[1], argv[1]);
168 id = (int) argv[2];
169 beforec = 9;
170 if (!strcmp(before[1], "USER"))
171 {
172 id_to_name(id, USERS_TABLE, &name);
173 EXEC SQL SELECT status INTO :before[9] FROM users
174 WHERE users_id = :id;
175 beforec = 10;
176 }
177 else if (!strcmp(before[1], "LIST"))
03c05291 178 id_to_name(id, LIST_TABLE, &name);
5eaef520 179 else if (!strcmp(before[1], "STRING") || !strcmp(before[1], "KERBEROS"))
180 id_to_name(id, STRINGS_TABLE, &name);
181 strcpy(before[2], name);
182 free(name);
183 break;
184 default:
03c05291 185 /*
186 com_err(whoami, 0, "requested incremental on unexpected table `%s'",
187 table_name[table]);
188 */
5eaef520 189 break;
190 }
a313cad2 191}
32cfe906 192
193
03c05291 194void incremental_clear_before(void)
32cfe906 195{
5eaef520 196 beforec = 0;
32cfe906 197}
198
32cfe906 199
03c05291 200/* add an element to the incremental queue for the changed row */
32cfe906 201
5eaef520 202void incremental_after(enum tables table, char *qual, char **argv)
a313cad2 203{
5eaef520 204 char *name;
205 EXEC SQL BEGIN DECLARE SECTION;
206 int id;
207 EXEC SQL END DECLARE SECTION;
208 struct iupdate *iu;
209
210 switch (table)
211 {
212 case USERS_TABLE:
d6759517 213 sprintf(stmt_buf, "SELECT u.login, u.unix_uid, u.shell, "
214 "u.winconsoleshell, u.last, u.first, u.middle, u.status, "
215 "u.clearid, u.type FROM users u WHERE %s", qual);
5eaef520 216 dosql(after);
d6759517 217 afterc = 10;
5eaef520 218 break;
219 case MACHINE_TABLE:
220 sprintf(stmt_buf, "SELECT m.name, m.vendor FROM machine m "
221 "WHERE %s", qual);
222 dosql(after);
223 afterc = 2;
224 break;
e688520a 225 case CLUSTERS_TABLE:
5eaef520 226 sprintf(stmt_buf, "SELECT c.name, c.description, c.location "
227 "FROM clusters c WHERE %s", qual);
228 dosql(after);
229 afterc = 3;
230 break;
231 case MCMAP_TABLE:
232 strcpy(after[0], argv[0]);
233 strcpy(after[1], argv[1]);
234 afterc = 2;
235 break;
236 case SVC_TABLE:
237 strcpy(after[0], argv[0]);
238 strcpy(after[1], argv[1]);
239 strcpy(after[2], argv[2]);
240 afterc = 3;
241 break;
242 case FILESYS_TABLE:
243 sprintf(stmt_buf, "SELECT fs.label, fs.type, fs.mach_id, fs.name, "
244 "fs.mount, fs.rwaccess, fs.comments, fs.owner, fs.owners, "
245 "fs.createflg, fs.lockertype FROM filesys fs WHERE %s", qual);
246 dosql(after);
247 name = malloc(0);
248 id = atoi(after[2]);
249 id_to_name(id, MACHINE_TABLE, &name);
250 strcpy(after[2], name);
251 id = atoi(after[7]);
252 id_to_name(id, USERS_TABLE, &name);
253 strcpy(after[7], name);
254 id = atoi(after[8]);
255 id_to_name(id, LIST_TABLE, &name);
256 strcpy(after[8], name);
257 free(name);
258 afterc = 11;
259 break;
260 case QUOTA_TABLE:
261 strcpy(after[0], "?");
262 strcpy(after[1], argv[1]);
263 strcpy(after[2], "?");
264 sprintf(stmt_buf, "SELECT q.quota, fs.name FROM quota q, filesys fs "
265 "WHERE %s and fs.filsys_id = q.filsys_id and q.type = '%s'",
266 qual, argv[1]);
267 dosql(&(after[3]));
268 afterc = 5;
269 break;
270 case LIST_TABLE:
271 sprintf(stmt_buf, "SELECT l.name, l.active, l.publicflg, l.hidden, "
272 "l.maillist, l.grouplist, l.gid, l.acl_type, l.acl_id, "
273 "l.description FROM list l WHERE %s", qual);
274 dosql(after);
275 afterc = 10;
276 break;
277 case IMEMBERS_TABLE:
278 id = (int) argv[0];
279 sprintf(stmt_buf, "SELECT active, publicflg, hidden, maillist, "
280 "grouplist, gid FROM list WHERE list_id = %d", id);
281 dosql(&(after[3]));
282 name = malloc(0);
283 id_to_name(id, LIST_TABLE, &name);
284 strcpy(after[0], name);
285 strcpy(after[1], argv[1]);
286 id = (int) argv[2];
287 afterc = 9;
288 if (!strcmp(after[1], "USER"))
289 {
290 id_to_name(id, USERS_TABLE, &name);
291 EXEC SQL SELECT status INTO :after[9] FROM users
292 WHERE users_id = :id;
293 afterc = 10;
32cfe906 294 }
5eaef520 295 else if (!strcmp(after[1], "LIST"))
296 id_to_name(id, LIST_TABLE, &name);
297 else if (!strcmp(after[1], "STRING") || !strcmp(after[1], "KERBEROS"))
298 id_to_name(id, STRINGS_TABLE, &name);
299 strcpy(after[2], name);
300 free(name);
301 break;
302 case NO_TABLE:
303 afterc = 0;
304 table = beforetable;
305 break;
306 default:
03c05291 307 /*
308 com_err(whoami, 0, "requested incremental on unexpected table `%s'",
309 table_name[table]);
310 */
5eaef520 311 break;
32cfe906 312 }
5eaef520 313
e688520a 314 iu = xmalloc(sizeof(struct iupdate));
5eaef520 315 iu->table = table_name[table];
316 iu->beforec = beforec;
fc053494 317 iu->before = copy_argv(before, beforec);
5eaef520 318 iu->afterc = afterc;
fc053494 319 iu->after = copy_argv(after, afterc);
5eaef520 320 sq_save_data(incremental_sq, iu);
a313cad2 321}
32cfe906 322
03c05291 323void incremental_clear_after(void)
324{
5eaef520 325 incremental_after(NO_TABLE, NULL, NULL);
03c05291 326}
327
32cfe906 328
329/* Called when the current transaction is committed to start any queued
330 * incremental updates. This caches the update table the first time it
331 * is called.
332 */
333
334struct inc_cache {
5eaef520 335 struct inc_cache *next;
336 char *table, *service;
32cfe906 337};
338
339
03c05291 340void incremental_update(void)
32cfe906 341{
5eaef520 342 static int inited = 0;
343 static struct inc_cache *cache;
344 struct inc_cache *c;
345 EXEC SQL BEGIN DECLARE SECTION;
e688520a 346 char tab[INCREMENTAL_TABLE_NAME_SIZE], serv[INCREMENTAL_SERVICE_SIZE];
5eaef520 347 EXEC SQL END DECLARE SECTION;
772c26b3 348 struct iupdate *iu, *iu_save;
5eaef520 349
350 if (!inited)
351 {
352 inited++;
353
354 EXEC SQL DECLARE inc CURSOR FOR SELECT table_name, service
355 FROM incremental;
356 EXEC SQL OPEN inc;
357 while (1)
358 {
359 EXEC SQL FETCH inc INTO :tab, :serv;
360 if (sqlca.sqlcode)
361 break;
e688520a 362 c = xmalloc(sizeof(struct inc_cache));
5eaef520 363 c->next = cache;
e688520a 364 c->table = xstrdup(strtrim(tab));
365 c->service = xstrdup(strtrim(serv));
5eaef520 366 cache = c;
32cfe906 367 }
5eaef520 368 EXEC SQL CLOSE inc;
369 EXEC SQL COMMIT WORK;
32cfe906 370 }
371
5eaef520 372 while (sq_remove_data(incremental_sq, &iu))
373 {
374 for (c = cache; c; c = c->next)
375 {
376 if (!strcmp(c->table, iu->table))
377 {
378 iu->service = c->service;
772c26b3 379 iu_save = xmalloc(sizeof(struct iupdate));
380 iu_save->service = iu->service;
381 iu_save->table = iu->table;
382 iu_save->beforec = iu->beforec;
383 iu_save->afterc = iu->afterc;
384 iu_save->before = copy_argv(iu->before, iu->beforec);
385 iu_save->after = copy_argv(iu->after, iu->afterc);
386 sq_save_data(incremental_exec, iu_save);
32cfe906 387 }
388 }
e688520a 389 if (!c)
390 {
391 free_argv(iu->before, iu->beforec);
392 free_argv(iu->after, iu->afterc);
393 free(iu);
394 }
32cfe906 395 }
5eaef520 396 if (inc_running == 0)
397 next_incremental();
32cfe906 398}
399
f18a32ee 400/* Pro*C 2.2.4 can't cope with the sigset_t below, at least in Solaris 2.6.
401 We add DEFINE=_PROC_ to the proc invocation and then #ifndef that around
402 this function so proc will pass it through without reading it. */
32cfe906 403
f18a32ee 404#ifndef _PROC_
03c05291 405void next_incremental(void)
32cfe906 406{
5eaef520 407 struct iupdate *iu;
e688520a 408 char *argv[MAXARGC * 2 + 4], cafter[3], cbefore[3], prog[MAXPATHLEN];
5eaef520 409 int i;
410 sigset_t sigs;
411
412 if (!incremental_exec)
413 incremental_init();
414
415 if (sq_empty(incremental_exec) ||
416 (inc_running && now - inc_started < INC_TIMEOUT))
417 return;
418
419 if (inc_running)
420 com_err(whoami, 0, "incremental timeout on pid %d", inc_pid);
421
422 sq_remove_data(incremental_exec, &iu);
423 argv[1] = iu->table;
424 sprintf(cbefore, "%d", iu->beforec);
425 argv[2] = cbefore;
426 sprintf(cafter, "%d", iu->afterc);
427 argv[3] = cafter;
428 for (i = 0; i < iu->beforec; i++)
429 argv[4 + i] = iu->before[i];
430 for (i = 0; i < iu->afterc; i++)
431 argv[4 + iu->beforec + i] = iu->after[i];
432
433 sprintf(prog, "%s/%s.incr", BIN_DIR, iu->service);
434 argv[0] = prog;
435 argv[4 + iu->beforec + iu->afterc] = 0;
436
437 sigemptyset(&sigs);
438 sigaddset(&sigs, SIGCHLD);
439 sigprocmask(SIG_BLOCK, &sigs, NULL);
440 inc_pid = vfork();
441 switch (inc_pid)
442 {
32cfe906 443 case 0:
5eaef520 444 execv(prog, argv);
445 _exit(1);
32cfe906 446 case -1:
5eaef520 447 com_err(whoami, 0, "Failed to start incremental update");
448 break;
32cfe906 449 default:
5eaef520 450 inc_running = 1;
451 inc_started = now;
32cfe906 452 }
5eaef520 453 sigprocmask(SIG_UNBLOCK, &sigs, NULL);
32cfe906 454
5eaef520 455 free_argv(iu->before, iu->beforec);
456 free_argv(iu->after, iu->afterc);
457 free(iu);
32cfe906 458}
f18a32ee 459#endif
32cfe906 460
461/* Called when the current transaction is aborted to throw away any queued
462 * incremental updates
463 */
464
03c05291 465void incremental_flush(void)
32cfe906 466{
5eaef520 467 struct iupdate *iu;
32cfe906 468
5eaef520 469 while (sq_get_data(incremental_sq, &iu))
470 {
471 free_argv(iu->before, iu->beforec);
472 free_argv(iu->after, iu->afterc);
473 free(iu);
32cfe906 474 }
5eaef520 475 sq_destroy(incremental_sq);
476 incremental_sq = sq_create();
32cfe906 477}
478
479
fc053494 480char **copy_argv(char **argv, int argc)
481{
482 char **ret = xmalloc(sizeof(char *) * argc);
483 while (--argc >= 0)
484 ret[argc] = xstrdup(strtrim(argv[argc]));
485 return ret;
486}
487
5eaef520 488void free_argv(char **argv, int argc)
32cfe906 489{
5eaef520 490 while (--argc >= 0)
491 free(argv[argc]);
492 free(argv);
32cfe906 493}
03c05291 494
495int table_num(char *name)
496{
497 int i;
498
5eaef520 499 for (i = num_tables - 1; i; i--)
500 {
501 if (!strcmp(table_name[i], name))
502 break;
503 }
03c05291 504
505 return i; /* 0 = "none" if no match */
506}
This page took 0.158032 seconds and 5 git commands to generate.