]> andersk Git - moira.git/blob - dbck/members.qc
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / dbck / members.qc
1 /* $Header$
2  */
3
4 #include <stdio.h>
5 #include <signal.h>
6 #include <moira.h>
7
8 #define FIXERRORS
9
10 #define max(x, y)       ((x) > (y) ? (x) : (y))
11
12 struct member {
13     int list_id;
14     int member_id;
15     union {
16         short all;
17         struct {
18             short u_ref_count:12;
19             unsigned short u_direct:1;
20             unsigned short u_baddirect:1;
21             unsigned short u_found:1;
22             unsigned short u_scanned:1;
23         } u_flags;
24     } flags;
25 } *find_member(), *allocmember();
26 #define frefc           flags.u_flags.u_ref_count
27 #define fdirect         flags.u_flags.u_direct
28 #define fbaddirect      flags.u_flags.u_baddirect
29 #define ffound          flags.u_flags.u_found
30 #define fscanned        flags.u_flags.u_scanned
31 #define fall            flags.all
32
33 #define member2id(c, id)        (((c & 0xff) << 24) | (id & 0xffffff))
34 #define id2type(id)             ((id >> 24) & 0xff)
35 #define id2id(id)               (id & 0xffffff)
36
37 struct member_list {
38     struct member_list *next;
39     struct member *member;
40 };
41
42 struct hash *lists, *members;
43 void fix_member(), display_member();
44 int debug = 0, records = 0;
45
46
47 main(argc, argv)
48 int argc;
49 char **argv;
50 ##{
51     char buf[256];
52
53 #ifdef DEBUG
54     if (argc > 1)
55       debug = atoi(argv[1]);
56 #endif DEBUG
57
58 ##  ingres sms
59 ##  begin transaction
60 ##  range of m is imembers
61
62     lists = create_hash(10000);
63     members = create_hash(10000);
64     records = 0;
65
66     load_members();
67 #ifdef DEBUG
68     if (debug > 3)
69       hash_step(lists, display_member, NULL);
70 #endif DEBUG
71     verify_members();
72     fix_members();
73
74 #ifdef FIXERRORS
75     printf("Commit changes (Y/N)?");
76     fflush(stdout);
77     fgets(buf, sizeof(buf), stdin);
78     if (buf[0] == 'Y' || buf[0] == 'y') {
79         printf("Ending transaction\n");
80 ##      end transaction
81     } else {
82 #endif FIXERRORS
83         printf("Aborting transaction\n");
84 ##      abort
85 #ifdef FIXERRORS
86     }
87 #endif FIXERRORS
88
89 ##  exit
90     printf("Done.\n");
91
92     exit(0);
93 ##}
94
95
96
97 load_members()
98 ##{
99     struct member *m, *m1, *md, *ma;
100     struct member_list *descendants, *ancestors, *desc, *ance, la, ld;
101 ##  int list_id, member_id, ref_count, ref;
102 ##  char mtype[9];
103     struct save_queue *sq;
104
105     printf("Loading members\n");
106     sq = sq_create();
107
108 ##  retrieve (list_id = m.#list_id, member_id = m.#member_id,
109 ##            mtype = m.#member_type, ref_count = m.#ref_count)
110 ##      where m.direct = 1 {
111 #ifdef DEBUG
112       if (debug > 5)
113         printf("Working on list %d member %s %d refc %d\n",
114                list_id, mtype, member_id, ref_count);
115 #endif DEBUG
116       if ((m = find_member(list_id, member2id(mtype[0], member_id))) == NULL) {
117           m = allocmember();
118           m->list_id = list_id;
119           m->member_id = member2id(mtype[0], member_id);
120           insert_list(m);
121           insert_member(m);
122       }
123       m->fdirect = 1;
124       la.next = (struct member_list *) hash_lookup(members,
125                                                    member2id('L', list_id));
126       la.member = m;
127       if (isinchain(m, la.next))
128         ance = la.next;
129       else
130         ance = &la;
131       if (mtype[0] == 'L')
132         ld.next = (struct member_list *) hash_lookup(lists, member_id);
133       else
134         ld.next = NULL;
135       ld.member = m;
136       if (isinchain(m, ld.next))
137         desc = ld.next;
138       else
139         desc = &ld;
140 #ifdef DEBUG
141       if (debug > 5)
142         printf("%d ancestors, %d descendants\n",
143                chainlen(ance), chainlen(desc));
144 #endif DEBUG
145       for (ancestors = ance; ancestors; ancestors = ancestors->next) {
146           ma = ancestors->member;
147           for (descendants = desc; descendants; descendants=descendants->next) {
148               md = descendants->member;
149               if (member2id('L', ma->list_id) == md->member_id)
150                 fprintf(stderr, "Loop detected! list %d member %d\n",
151                         md->list_id, ma->member_id);
152               ref = md->frefc * ma->frefc;
153               if (ref == 0) {
154                   ref = max(md->frefc, ma->frefc);
155                   if (ref == 0)
156                     ref = 1;
157               }
158 #ifdef DEBUG
159               if (debug > 5)
160                 printf("Checking list %d member %d, ref = %d\n",
161                        ma->list_id, id2id(md->member_id), ref);
162 #endif DEBUG
163               if (m1 = find_member(ma->list_id, md->member_id)) {
164                   m1->frefc += ref;
165 #ifdef DEBUG
166                   if (debug > 5)
167                     printf("set refc to %d (%d) on list %d, member %d\n",
168                            m1->frefc, ref, m1->list_id, id2id(m1->member_id));
169 #endif DEBUG
170                   if (ma == m && md == m)
171                     m1->fdirect = 1;
172               } else {
173                   m1 = allocmember();
174                   m1->list_id = ma->list_id;
175                   m1->member_id = md->member_id;
176                   m1->frefc = ref;
177 #ifdef DEBUG
178                   if (debug > 5)
179                     printf("set new refc to %d (%d) on list %d, member %d\n",
180                            m1->frefc, ref, m1->list_id, id2id(m1->member_id));
181 #endif DEBUG
182                   sq_save_data(sq, m1);
183               }
184           }
185       }
186       while (sq_get_data(sq, &m)) {
187           insert_list(m);
188           insert_member(m);
189       }
190       sq_destroy(sq);
191       sq = sq_create();
192 ##  }
193     printf("created %d records\n", records);
194 ##}
195
196 verify_members()
197 ##{
198     struct member *m;
199     struct save_queue *sq;
200 ##  int list_id, member_id, ref_count, dflag;
201 ##  char mtype[9];
202     int errxtra, errbref, errbdir;
203 #ifdef DEBUG
204     int ref0, ref1, ref2, ref3, refg;
205     int db0, db1, db2, db3, dbg;
206 #endif DEBUG
207
208     /* verify members from database */
209     printf("Verifying members\n");
210     errxtra = errbref = errbdir = 0;
211 #ifdef DEBUG
212     ref0 = ref1 = ref2 = ref3 = refg = 0;
213     db0 = db1 = db2 = db3 = dbg = 0;
214 #endif DEBUG
215     sq = sq_create();
216 ##  retrieve (list_id = m.#list_id, member_id = m.#member_id,
217 ##            mtype = m.member_type, ref_count = m.#ref_count,
218 ##            dflag = m.#direct) {
219 #ifdef DEBUG
220       if (debug > 1)
221         switch (ref_count) {
222         case 0: db0++; break;
223         case 1: db1++; break;
224         case 2: db2++; break;
225         case 3: db3++; break;
226         default: dbg++;
227         }
228 #endif DEBUG
229       m = find_member(list_id, member2id(mtype[0], member_id));
230       if (m == NULL) {
231           m = allocmember();
232           m->list_id = list_id;
233           m->member_id = member2id(mtype[0], member_id);
234           m->fdirect = dflag;
235           m->frefc = ref_count;
236           sq_save_data(sq, m);
237           errxtra++;
238       } else {
239           m->ffound = 1;
240 #ifdef DEBUG    
241           if (debug > 1)
242             switch (m->frefc) {
243             case 0: ref0++; break;
244             case 1: ref1++; break;
245             case 2: ref2++; break;
246             case 3: ref3++; break;
247             default: refg++;
248             }
249 #endif DEBUG
250           m->frefc -= ref_count;
251           if (m->frefc != 0)
252             errbref++;
253           if (m->fdirect != dflag) {
254               m->fbaddirect = 1;
255               errbdir++;
256           }
257       }
258 ##  }
259     printf("Found %d extra records, %d bad ref counts, %d bad direct flags\n",
260            errxtra, errbref, errbdir);
261 #ifdef DEBUG
262     if (debug > 1) {
263         printf("Found in db: %d 0; %d 1; %d 2; %d 3; %d > 3\n",
264                db0, db1, db2, db3, dbg);
265         printf("Found  refs: %d 0; %d 1; %d 2; %d 3; %d > 3\n",
266                ref0, ref1, ref2, ref3, refg);
267     }
268 #endif DEBUG
269 ##}
270
271
272 fix_members()
273 ##{
274     struct member *m;
275     struct save_queue *sq;
276     int errmis = 0;
277 ##  int list_id, member_id, rowcount;
278 ##  char mtype[9];
279     char buf[512];
280
281     /* fix any errors */
282     printf("Fixing errors\n");
283     hash_step(lists, fix_member, &errmis);
284     while (sq_get_data(sq, &m)) {
285         printf("Extraneous member record, deleting:\n");
286         list_id = m->list_id;
287         member_id = id2id(m->member_id);
288         switch (id2type(m->member_id)) {
289         case 'U': strcpy(mtype, "USER"); break;
290         case 'L': strcpy(mtype, "LIST"); break;
291         case 'S': strcpy(mtype, "STRING"); break;
292         case 'K': strcpy(mtype, "KERBEROS"); break;
293         default:
294             mtype[0] = id2type(m->member_id);
295             mtype[1] = 0;
296         }
297         printf("  List: %d, Member: %s %d, Refc: %d, Direct %d\n",
298                list_id, mtype, member_id, m->frefc, m->fdirect);
299 #ifdef FIXERRORS
300 ##      delete m where m.#list_id = list_id and m.#member_id = member_id
301 ##              and m.member_type = mtype
302 ##      inquire_equel(rowcount = "rowcount")
303         printf("  %d rows deleted\n", rowcount);
304 #endif FIXERRORS
305     }
306     if (errmis > 0)
307       printf("Added %d missing records\n", errmis);
308 ##}
309
310
311 insert_list(m)
312 struct member *m;
313 {
314     register struct member_list *l, *l1;
315
316     l = (struct member_list *) hash_lookup(lists, m->list_id);
317     if (l == NULL) {
318         l = (struct member_list *)malloc(sizeof(struct member_list));
319         if (l == NULL) {
320             fprintf(stderr, "No memory for insert_list\n");
321             exit(1);
322         }
323         l->next = NULL;
324         l->member = m;
325         hash_store(lists, m->list_id, l);
326         return;
327     }
328     for (l1 = l; l1; l1 = l1->next)
329       if (l1->member->member_id == m->member_id) {
330           fprintf(stderr, "Found 2nd copy of list record for\n");
331           fprintf(stderr, "List: %d, Member: %c %d, Refc: %d, Direct %d\n",
332                   m->list_id, id2type(m->member_id), id2id(m->member_id),
333                   m->frefc, m->fdirect);
334           kill(getpid(), SIGQUIT);
335           exit(2);
336       }
337
338     l1 = (struct member_list *)malloc(sizeof(struct member_list));
339     if (l1 == NULL) {
340         fprintf(stderr, "No memory for insert_list\n");
341         exit(1);
342     }
343     l1->next = l->next;
344     l->next = l1;
345     l1->member = m;
346 }
347
348
349 insert_member(m)
350 struct member *m;
351 {
352     register struct member_list *l, *l1;
353
354     l = (struct member_list *) hash_lookup(members, m->member_id);
355     if (l == NULL) {
356         l = (struct member_list *)malloc(sizeof(struct member_list));
357         if (l == NULL) {
358             fprintf(stderr, "No memory for insert_member\n");
359             exit(1);
360         }
361         l->next = NULL;
362         l->member = m;
363         hash_store(members, m->member_id, l);
364         return;
365     }
366
367     for (l1 = l; l1; l1 = l1->next)
368       if (l1->member->list_id == m->list_id) {
369           fprintf(stderr, "Found 2nd copy of member record for\n");
370           fprintf(stderr, "List: %d, Member: %c %d, Refc: %d, Direct %d\n",
371                   m->list_id, id2type(m->member_id), id2id(m->member_id),
372                   m->frefc, m->fdirect);
373           kill(getpid(), SIGQUIT);
374           exit(2);
375       }
376
377     l1 = (struct member_list *)malloc(sizeof(struct member_list));
378     if (l1 == NULL) {
379         fprintf(stderr, "No memory for insert_member\n");
380         exit(1);
381     }
382     l1->next = l->next;
383     l->next = l1;
384     l1->member = m;
385 }
386
387
388 struct member *find_member(listid, memberid)
389 int listid;
390 int memberid;
391 {
392     register struct member_list *l;
393
394     for (l = (struct member_list *) hash_lookup(lists, listid); l; l = l->next)
395       if (l->member->member_id == memberid)
396         return(l->member);
397     return(NULL);
398 }
399
400
401 /*ARGSUSED*/
402 void fix_member(dummy, l, errmis)
403 int dummy;
404 struct member_list *l;
405 int *errmis;
406 ##{
407 ##  int list_id, member_id, ref_count, dflag, rowcount;
408 ##  char *mtype;
409     char buf[2];
410     register struct member *m;
411
412     for (; l; l = l->next) {
413         m = l->member;
414
415         if (m->fscanned)
416           continue;
417         m->fscanned = 1;
418         if (m->fbaddirect == 0 && m->frefc == 0 && m->ffound == 1)
419           continue;
420         if (m->ffound == 0) {
421             printf("Missing member record, adding:\n");
422             list_id = m->list_id;
423             member_id = id2id(m->member_id);
424             ref_count = m->frefc;
425             dflag = m->fdirect;
426             switch (id2type(m->member_id)) {
427             case 'U': mtype = "USER"; break;
428             case 'L': mtype = "LIST"; break;
429             case 'S': mtype = "STRING"; break;
430             case 'K': mtype = "KERBEROS"; break;
431             default:
432                 mtype = buf;
433                 buf[0] = id2type(m->member_id);
434                 buf[1] = 0;
435             }
436             printf("  List: %d, Member: %s %d, Refc: %d, Direct %d\n",
437                    list_id, mtype, member_id, ref_count, dflag);
438             (*errmis)++;
439 #ifdef FIXERRORS
440 ##          append imembers (#list_id = list_id, #member_id = member_id,
441 ##                           member_type = mtype, #ref_count = ref_count,
442 ##                           direct = dflag);
443 ##          inquire_equel(rowcount = "rowcount")
444             printf("  %d rows added\n", rowcount);
445 #endif FIXERRORS
446             continue;
447         }
448         printf("Member record has bad ref_count and/or direct flag, fixing\n");
449         list_id = m->list_id;
450         member_id = id2id(m->member_id);
451         ref_count = m->frefc;
452         dflag = m->fdirect;
453         switch (id2type(m->member_id)) {
454         case 'U': mtype = "USER"; break;
455         case 'L': mtype = "LIST"; break;
456         case 'S': mtype = "STRING"; break;
457         case 'K': mtype = "KERBEROS"; break;
458         default:
459             mtype = buf;
460             buf[0] = id2type(m->member_id);
461             buf[1] = 0;
462         }
463         printf("  List: %d, Member: %s %d, Refc: %d, Direct %d\n",
464                list_id, mtype, member_id, ref_count, dflag);
465 #ifdef FIXERRORS
466 ##      replace m (#ref_count = m.#ref_count + ref_count, direct = dflag)
467 ##        where m.#list_id = list_id and m.#member_id = member_id and
468 ##          m.member_type = mtype
469 ##      inquire_equel(rowcount = "rowcount");
470         printf("  %d rows fixed\n", rowcount);
471 #endif FIXERRORS
472     }
473 ##}
474
475
476 struct member *allocmember()
477 {
478     register struct member *m;
479
480     m = (struct member *) malloc(sizeof(struct member));
481     if (m == NULL) {
482         fprintf(stderr, "No memory for new member\n");
483         exit(1);
484     }
485     m->fall = 0;
486     records++;
487     return(m);
488 }
489
490
491 int isinchain(m, l)
492 struct member *m;
493 register struct member_list *l;
494 {
495     for (; l; l = l->next)
496       if (l->member == m)
497         return(1);
498     return(0);
499 }
500
501
502 int chainlen(l)
503 register struct member_list *l;
504 {
505     register int i;
506     for (i = 0; l; l = l->next, i++);
507     return(i);
508 }
509
510
511 #ifdef DEBUG
512
513 /*ARGSUSED*/
514 void display_member(key, l, dummy1)
515 int key, dummy1;
516 struct member_list *l;
517 {
518     struct member *m;
519     char *mtype;
520
521     printf("%d*", key);
522     for(; l; l = l->next) {
523         m = l->member;
524         switch (id2type(m->member_id)) {
525         case 'U': mtype = "USER"; break;
526         case 'L': mtype = "LIST"; break;
527         case 'S': mtype = "STRING"; break;
528         case 'K': mtype = "KERBEROS"; break;
529         default: mtype = "???"; break;
530         }
531         printf("List: %d, Member: %s %d, Refc: %d, Direct %d\n",
532                m->list_id, mtype, id2id(m->member_id), m->frefc,
533                m->fdirect);
534     }
535 }
536
537 #endif DEBUG
This page took 0.081124 seconds and 5 git commands to generate.