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

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