]> andersk Git - moira.git/blob - dbck/members.pc
use abstraction barriers (init script) for restarting named
[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 char *db = "moira/moira";
49
50 main(argc, argv)
51 int argc;
52 char **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
104 load_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
214 verify_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
302 fix_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
347 insert_list(m)
348 struct 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
388 insert_member(m)
389 struct 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
430 struct member *find_member(listid, memberid)
431 int listid;
432 int 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*/
444 void fix_member(dummy, l, errmis)
445 int dummy;
446 struct member_list *l;
447 int *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
531 struct 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
546 int isinchain(m, l)
547 struct member *m;
548 struct member_list *l;
549 {
550     for (; l; l = l->next)
551       if (l->member == m)
552         return(1);
553     return(0);
554 }
555
556
557 int chainlen(l)
558 struct 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*/
569 void display_member(key, l, dummy1)
570 int key, dummy1;
571 struct 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 */
This page took 0.451994 seconds and 5 git commands to generate.