source: trunk/third/moira/dbck/members.pc @ 24250

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