]> andersk Git - moira.git/blob - server/increment.qc
fixed multiple incremental updates bug
[moira.git] / server / increment.qc
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
13 static char *rcsid_qrtn_qc = "$Header$";
14 #endif lint
15
16 #include <mit-copyright.h>
17 #include <sms.h>
18 #include "query.h"
19 #include "sms_server.h"
20
21 extern char *whoami;
22
23 #define MAXARGC 15
24
25 /* structures to save before args */
26 static char beforeb[MAXARGC][ARGLEN];
27 static char *before[MAXARGC];
28 ##char *barg0, *barg1, *barg2, *barg3, *barg4;
29 ##char *barg5, *barg6, *barg7, *barg8, *barg9;
30 ##char *barg10, *barg11, *barg12, *barg13, *barg14;
31 static int beforec;
32 static char *beforetable;
33
34 /* structures to save after args */
35 static char afterb[MAXARGC][ARGLEN];
36 static char *after[MAXARGC];
37 ##char *aarg0, *aarg1, *aarg2, *aarg3, *aarg4;
38 ##char *aarg5, *aarg6, *aarg7, *aarg8, *aarg9;
39 ##char *aarg10, *aarg11, *aarg12, *aarg13, *aarg14;
40 static int afterc;
41
42 /* structures to save entire sets of incremental changes */
43 struct save_queue *incremental_sq = NULL;
44 struct iupdate {
45     char *table;
46     int beforec;
47     char **before;
48     int afterc;
49     char **after;
50 };
51
52
53 incremental_init()
54 {
55     int i;
56
57     for (i = 0; i < MAXARGC; i++) {
58         before[i] = &beforeb[i][0];
59         after[i] = &afterb[i][0];
60     }
61     barg0 = before[0];
62     barg1 = before[1];
63     barg2 = before[2];
64     barg3 = before[3];
65     barg4 = before[4];
66     barg5 = before[5];
67     barg6 = before[6];
68     barg7 = before[7];
69     barg8 = before[8];
70     barg9 = before[9];
71     barg10 = before[10];
72     barg11 = before[11];
73     barg12 = before[12];
74     barg13 = before[13];
75     barg14 = before[14];
76     aarg0 = after[0];
77     aarg1 = after[1];
78     aarg2 = after[2];
79     aarg3 = after[3];
80     aarg4 = after[4];
81     aarg5 = after[5];
82     aarg6 = after[6];
83     aarg7 = after[7];
84     aarg8 = after[8];
85     aarg9 = after[9];
86     aarg10 = after[10];
87     aarg11 = after[11];
88     aarg12 = after[12];
89     aarg13 = after[13];
90     aarg14 = after[14];
91     if (incremental_sq == NULL)
92       incremental_sq = sq_create();
93 }
94
95
96 ##incremental_before(table, qual, argv)
97 ##char *table;
98 ##char *qual;
99 char **argv;
100 ##{
101 ##  int id;
102     char buffer[512];
103
104     beforetable = table;
105
106     if (!strcmp(table, "users")) {
107 ##      retrieve (barg0 = u.login, barg1 = text(u.uid),
108 ##                barg2 = u.shell, barg3 = u.last, barg4 = u.first,
109 ##                barg5 = u.middle, barg6 = text(u.status),
110 ##                barg7 = u.mit_id, barg8 = u.mit_year)
111 ##              where qual
112         beforec = 9;
113     } else if (!strcmp(table, "machine")) {
114 ##      retrieve (barg0 = m.name, barg1 = m.type) where qual
115         beforec = 2;
116     } else if (!strcmp(table, "cluster")) {
117 ##      retrieve (barg0 = c.name, barg1 = c.desc, barg2 = c.location)
118 ##              where qual
119         beforec = 3;
120     } else if (!strcmp(table, "mcmap")) {
121         strcpy(barg0, argv[0]);
122         strcpy(barg1, argv[1]);
123         beforec = 2;
124     } else if (!strcmp(table, "svc")) {
125         strcpy(barg0, argv[0]);
126         strcpy(barg1, argv[1]);
127         strcpy(barg2, argv[2]);
128         beforec = 3;
129     } else if (!strcmp(table, "filesys")) {
130 ##      range of fs is filesys
131 ##      retrieve (barg0 = fs.label, barg1 = fs.type, barg2 = text(fs.mach_id),
132 ##                barg3 = fs.name, barg4 = fs.mount, barg5 = fs.access,
133 ##                barg6 = fs.comments, barg7 = text(fs.owner),
134 ##                barg8 = text(fs.owners), barg9 = text(fs.createflg),
135 ##                barg10 = fs.lockertype)
136 ##        where qual
137         beforec = 11;
138     } else if (!strcmp(table, "nfsquota")) {
139         strcpy(barg0, argv[0]);
140         strcpy(barg1, argv[1]);
141         sprintf(buffer, "%s and filesys.filsys_id = nq.filsys_id", qual);
142         qual = buffer;
143 ##      range of nq is nfsquota
144 ##      retrieve (barg2 = text(nq.quota), barg3 = filesys.name) where qual
145         beforec = 4;
146     } else if (!strcmp(table, "list")) {
147 ##      retrieve (barg0 = l.name, barg1 = text(l.active),
148 ##                barg2 = text(l.public), barg3 = text(l.hidden),
149 ##                barg4 = text(l.maillist), barg5 = text(l.group),
150 ##                barg6 = text(l.gid), barg7 = l.acl_type,
151 ##                barg8 = text(l.acl_id), barg9 = l.desc)
152 ##        where qual
153         beforec = 10;
154     } else if (!strcmp(table, "members")) {
155         id = (int) argv[0];
156 ##      repeat retrieve (barg0 = list.name) where list.list_id = @id
157         strcpy(barg1, argv[1]);
158         id = (int) argv[2];
159         if (!strcmp(barg1, "USER")) {
160 ##          repeat retrieve (barg2 = users.login) where users.users_id = @id
161         } else if (!strcmp(barg1, "LIST")) {
162 ##          repeat retrieve (barg2 = list.name) where list.list_id = @id
163         } else if (!strcmp(barg1, "STRING")) {
164 ##          repeat retrieve (barg2 = strings.string)
165 ##              where strings.string_id = @id
166         } else if (!strcmp(barg1, "KERBEROS")) {
167 ##          repeat retrieve (barg2 = strings.string)
168 ##              where strings.string_id = @id
169         }
170         beforec = 3;
171     } /* else
172       com_err(whoami, 0, "unknown table in incremental_before"); */
173 ##}
174
175
176 incremental_clear_before()
177 {
178     beforec = 0;
179 }
180
181 incremental_clear_after()
182 {
183     incremental_after("clear", 0);
184 }
185
186
187
188 ##incremental_after(table, qual, argv)
189 ##char *table;
190 ##char *qual;
191 char **argv;
192 ##{
193     char buffer[2048];
194 ##  int id, i;
195     struct iupdate *iu;
196     char **copy_argv();
197
198     if (!strcmp(table, "users")) {
199 ##      retrieve (aarg0 = u.login, aarg1 = text(u.uid),
200 ##                aarg2 = u.shell, aarg3 = u.last, aarg4 = u.first,
201 ##                aarg5 = u.middle, aarg6 = text(u.status),
202 ##                aarg7 = u.mit_id, aarg8 = u.mit_year)
203 ##              where qual
204         afterc = 9;
205     } else if (!strcmp(table, "machine")) {
206 ##      retrieve (aarg0 = m.name, aarg1 = m.type) where qual
207         afterc = 2;
208     } else if (!strcmp(table, "cluster")) {
209 ##      retrieve (aarg0 = c.name, aarg1 = c.desc, aarg2 = c.location)
210 ##              where qual
211         afterc = 3;
212     } else if (!strcmp(table, "mcmap")) {
213         strcpy(aarg0, argv[0]);
214         strcpy(aarg1, argv[1]);
215         afterc = 2;
216     } else if (!strcmp(table, "svc")) {
217         strcpy(aarg0, argv[0]);
218         strcpy(aarg1, argv[1]);
219         strcpy(aarg2, argv[2]);
220         afterc = 3;
221     } else if (!strcmp(table, "filesys")) {
222 ##      range of fs is filesys
223 ##      retrieve (aarg0 = fs.label, aarg1 = fs.type,
224 ##                aarg2 = text(fs.mach_id),
225 ##                aarg3 = fs.name, aarg4 = fs.mount, aarg5 = fs.access,
226 ##                aarg6 = fs.comments, aarg7 = text(fs.owner),
227 ##                aarg8 = text(fs.owners), aarg9 = text(fs.createflg),
228 ##                aarg10 = fs.lockertype)
229 ##        where qual
230         afterc = 11;
231     } else if (!strcmp(table, "nfsquota")) {
232         strcpy(aarg0, argv[0]);
233         strcpy(aarg1, argv[1]);
234         sprintf(buffer, "%s and filesys.filsys_id = nq.filsys_id", qual);
235         qual = buffer;
236 ##      range of nq is nfsquota
237 ##      retrieve (aarg2 = text(nq.quota), aarg3 = filesys.name) where qual
238         afterc = 4;
239     } else if (!strcmp(table, "list")) {
240 ##      retrieve (aarg0 = l.name, aarg1 = text(l.active),
241 ##                aarg2 = text(l.public), aarg3 = text(l.hidden),
242 ##                aarg4 = text(l.maillist), aarg5 = text(l.group),
243 ##                aarg6 = text(l.gid), aarg7 = l.acl_type,
244 ##                aarg8 = text(l.acl_id), aarg9 = l.desc)
245 ##        where qual
246         afterc = 10;
247     } else if (!strcmp(table, "members")) {
248         id = (int) argv[0];
249 ##      repeat retrieve (aarg0 = list.name) where list.list_id = @id
250         strcpy(aarg1, argv[1]);
251         id = (int) argv[2];
252         if (!strcmp(aarg1, "USER")) {
253 ##          repeat retrieve (aarg2 = users.login) where users.users_id = @id
254         } else if (!strcmp(aarg1, "LIST")) {
255 ##          repeat retrieve (aarg2 = list.name) where list.list_id = @id
256         } else if (!strcmp(aarg1, "STRING")) {
257 ##          repeat retrieve (aarg2 = strings.string)
258 ##              where strings.string_id = @id
259         } else if (!strcmp(aarg1, "KERBEROS")) {
260 ##          repeat retrieve (aarg2 = strings.string)
261 ##              where strings.string_id = @id
262         }
263         afterc = 3;
264     } else if (!strcmp(table, "clear")) {
265         afterc = 0;
266         table = beforetable;
267     } /* else
268       com_err(whoami, 0, "unknown table in incremental_after"); */
269
270     iu = (struct iupdate *) malloc(sizeof(struct iupdate));
271     iu->table = table;
272     iu->beforec = beforec;
273     iu->before = copy_argv(before, beforec);
274     iu->afterc = afterc;
275     iu->after = copy_argv(after, afterc);
276     sq_save_data(incremental_sq, iu);
277
278 #ifdef DEBUG
279     sprintf(buffer, "INCREMENTAL(%s, [", table);
280     for (i = 0; i < beforec; i++) {
281         if (i == 0)
282           strcat(buffer, strtrim(before[0]));
283         else {
284             strcat(buffer, ", ");
285             strcat(buffer, strtrim(before[i]));
286         }
287     }
288     strcat(buffer, "], [");
289     for (i = 0; i < afterc; i++) {
290         if (i == 0)
291           strcat(buffer, strtrim(after[0]));
292         else {
293             strcat(buffer, ", ");
294             strcat(buffer, strtrim(after[i]));
295         }
296     }
297     strcat(buffer, "])");
298     com_err(whoami, 0, buffer);
299 #endif DEBUG
300 ##}
301
302
303 /* Called when the current transaction is committed to start any queued
304  * incremental updates
305  */
306
307 incremental_update()
308 {
309     struct iupdate *iu;
310     char *argv[MAXARGC * 2 + 4], cafter[3], cbefore[3];
311     int i;
312
313     while (sq_get_data(incremental_sq, &iu)) {
314         argv[1] = iu->table;
315         sprintf(cbefore, "%d", iu->beforec);
316         argv[2] = cbefore;
317         sprintf(cafter, "%d", iu->afterc);
318         argv[3] = cafter;
319         for (i = 0; i < iu->beforec; i++)
320           argv[4 + i] = iu->before[i];
321         for (i = 0; i < iu->afterc; i++)
322           argv[4 + iu->beforec + i] = iu->after[i];
323         invoke_updates(argv, 4 + iu->beforec + iu->afterc);
324         free_argv(iu->before, iu->beforec);
325         free_argv(iu->after, iu->afterc);
326         free(iu);
327     }
328     sq_destroy(incremental_sq);
329     incremental_sq = sq_create();
330 }
331
332
333 /* Actually start incremental updates.  This caches the update table
334  * the first time it is called.
335  */
336
337 struct inc_cache {
338     struct inc_cache *next;
339     char *table;
340     char *service;
341 };
342
343
344 invoke_updates(argv, argc)
345 char **argv;
346 int argc;
347 ##{
348     static int inited = 0;
349     static struct inc_cache *cache;
350     struct inc_cache *c;
351 ##  char tab[17], serv[17];
352     int pid, i;
353     char prog[64];
354
355     if (!inited) {
356         inited++;
357
358 ##      retrieve (tab = incremental.table, serv = incremental.service) {
359             c = (struct inc_cache *)malloc(sizeof(struct inc_cache));
360             c->next = cache;
361             c->table = strsave(strtrim(tab));
362             c->service = strsave(strtrim(serv));
363             cache = c;
364 ##      }
365     }
366
367     for (c = cache; c; c = c->next) {
368         if (!strcmp(c->table, argv[1])) {
369             sprintf(prog, "/u1/sms/bin/%s.incr", c->service);
370 #ifdef DEBUG
371             com_err(whoami, 0, "forking %s", prog);
372 #endif
373             argv[0] = prog;
374             argv[argc] = 0;
375             pid = vfork();
376             switch (pid) {
377             case 0:
378                 for (i = getdtablesize() - 1; i > 2; i--)
379                   close(i);
380                 execv(prog, argv);
381                 exit(1);
382             case -1:
383                 com_err(whoami, 0, "Failed to start incremental update");
384                 return;
385             default:
386                 return;
387             }
388         }
389     }
390 ##}
391
392
393 /* Called when the current transaction is aborted to throw away any queued
394  * incremental updates
395  */
396
397 incremental_flush()
398 {
399     struct iupdate *iu;
400
401     while (sq_get_data(incremental_sq, &iu)) {
402         free_argv(iu->before, iu->beforec);
403         free_argv(iu->after, iu->afterc);
404         free(iu);
405     }
406     sq_destroy(incremental_sq);
407     incremental_sq = sq_create();
408 }
409
410
411 char **copy_argv(argv, argc)
412 char **argv;
413 int argc;
414 {
415     char **ret = (char **)malloc(sizeof(char *) * argc);
416     while (--argc >= 0)
417       ret[argc] = strsave(strtrim(argv[argc]));
418     return(ret);
419 }
420
421 free_argv(argv, argc)
422 char **argv;
423 int argc;
424 {
425     while (--argc >= 0)
426       free(argv[argc]);
427     free(argv);
428 }
This page took 0.072107 seconds and 5 git commands to generate.