]> andersk Git - moira.git/blame - dbck/members.pc
check indirect entries in imembers as well as direct ones.
[moira.git] / dbck / members.pc
CommitLineData
68bbc9c3 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
ab4c45a4 12EXEC SQL INCLUDE sqlca;
13
68bbc9c3 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
48
49main(argc, argv)
50int argc;
51char **argv;
ab4c45a4 52{
68bbc9c3 53 char buf[256];
54
55#ifdef DEBUG
56 if (argc > 1)
57 debug = atoi(argv[1]);
58#endif DEBUG
59
ab4c45a4 60/* ingres sms */
61 EXEC SQL CONNECT moira;
62/* begin transaction */
63/* range of m is imembers */
64 /* No equivalent */
68bbc9c3 65
ab05f33a 66 lists = create_hash(50000);
67 members = create_hash(300000);
68bbc9c3 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");
ab4c45a4 84/* end transaction */
85 EXEC SQL COMMIT WORK;
68bbc9c3 86 } else {
87#endif FIXERRORS
88 printf("Aborting transaction\n");
ab4c45a4 89/* abort */
90 EXEC SQL ROLLBACK WORK;
68bbc9c3 91#ifdef FIXERRORS
92 }
93#endif FIXERRORS
94
ab4c45a4 95/* exit */
96 /* No equivalent (?) */
68bbc9c3 97 printf("Done.\n");
98
99 exit(0);
ab4c45a4 100}
68bbc9c3 101
102
68bbc9c3 103load_members()
ab4c45a4 104{
68bbc9c3 105 struct member *m, *m1, *md, *ma;
106 struct member_list *descendants, *ancestors, *desc, *ance, la, ld;
ab4c45a4 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;
68bbc9c3 111 struct save_queue *sq;
112
113 printf("Loading members\n");
114 sq = sq_create();
115
ab4c45a4 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
68bbc9c3 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();
ab4c45a4 208 }
209 EXEC SQL CLOSE csrm1;
68bbc9c3 210 printf("created %d records\n", records);
ab4c45a4 211}
68bbc9c3 212
213verify_members()
ab4c45a4 214{
68bbc9c3 215 struct member *m;
216 struct save_queue *sq;
ab4c45a4 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;
68bbc9c3 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();
ab4c45a4 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
68bbc9c3 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 }
ab4c45a4 286 }
287 EXEC SQL CLOSE csrm2;
68bbc9c3 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
ab4c45a4 298}
68bbc9c3 299
300
301fix_members()
ab4c45a4 302{
68bbc9c3 303 struct member *m;
304 struct save_queue *sq;
305 int errmis = 0;
ab4c45a4 306 EXEC SQL BEGIN DECLARE SECTION;
307 int list_id, member_id, rowcount;
308 char mtype[9];
309 EXEC SQL END DECLARE SECTION;
68bbc9c3 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
ab4c45a4 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);
68bbc9c3 336 printf(" %d rows deleted\n", rowcount);
337#endif FIXERRORS
338 }
339 if (errmis > 0)
340 printf("Added %d missing records\n", errmis);
ab4c45a4 341}
68bbc9c3 342
343
344insert_list(m)
345struct member *m;
346{
44d12d58 347 struct member_list *l, *l1;
68bbc9c3 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;
ab05f33a 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 }
68bbc9c3 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
385insert_member(m)
386struct member *m;
387{
44d12d58 388 struct member_list *l, *l1;
68bbc9c3 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;
ab05f33a 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 }
68bbc9c3 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
427struct member *find_member(listid, memberid)
428int listid;
429int memberid;
430{
44d12d58 431 struct member_list *l;
68bbc9c3 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*/
441void fix_member(dummy, l, errmis)
442int dummy;
443struct member_list *l;
444int *errmis;
ab4c45a4 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;
68bbc9c3 450 char buf[2];
44d12d58 451 struct member *m;
68bbc9c3 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
ab4c45a4 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);
68bbc9c3 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
ab4c45a4 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);
68bbc9c3 518 printf(" %d rows fixed\n", rowcount);
519#endif FIXERRORS
520 }
ab4c45a4 521}
68bbc9c3 522
523
524struct member *allocmember()
525{
44d12d58 526 struct member *m;
68bbc9c3 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
539int isinchain(m, l)
540struct member *m;
44d12d58 541struct member_list *l;
68bbc9c3 542{
543 for (; l; l = l->next)
544 if (l->member == m)
545 return(1);
546 return(0);
547}
548
549
550int chainlen(l)
44d12d58 551struct member_list *l;
68bbc9c3 552{
44d12d58 553 int i;
68bbc9c3 554 for (i = 0; l; l = l->next, i++);
555 return(i);
556}
557
558
559#ifdef DEBUG
560
561/*ARGSUSED*/
562void display_member(key, l, dummy1)
563int key, dummy1;
564struct 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.196682 seconds and 5 git commands to generate.