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