10 #define max(x, y) ((x) > (y) ? (x) : (y))
12 EXEC SQL INCLUDE sqlca;
21 unsigned short u_direct:1;
22 unsigned short u_baddirect:1;
23 unsigned short u_found:1;
24 unsigned short u_scanned:1;
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
35 #define member2id(c, id) (((c & 0xff) << 24) | (id & 0xffffff))
36 #define id2type(id) ((id >> 24) & 0xff)
37 #define id2id(id) (id & 0xffffff)
40 struct member_list *next;
41 struct member *member;
44 struct hash *lists, *members;
45 void fix_member(), display_member();
46 int debug = 0, records = 0;
57 debug = atoi(argv[1]);
61 EXEC SQL CONNECT moira;
62 /* begin transaction */
63 /* range of m is imembers */
66 lists = create_hash(10000);
67 members = create_hash(10000);
73 hash_step(lists, display_member, NULL);
79 printf("Commit changes (Y/N)?");
81 fgets(buf, sizeof(buf), stdin);
82 if (buf[0] == 'Y' || buf[0] == 'y') {
83 printf("Ending transaction\n");
88 printf("Aborting transaction\n");
90 EXEC SQL ROLLBACK WORK;
96 /* No equivalent (?) */
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;
111 EXEC SQL END DECLARE SECTION;
112 struct save_queue *sq;
114 printf("Loading members\n");
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
125 EXEC SQL FETCH csrm1 INTO :list_id, :member_id, :mtype, :ref_count;
126 if(sqlca.sqlcode != 0) break;
130 printf("Working on list %d member %s %d refc %d\n",
131 list_id, mtype, member_id, ref_count);
133 if ((m = find_member(list_id, member2id(mtype[0], member_id))) == NULL) {
135 m->list_id = list_id;
136 m->member_id = member2id(mtype[0], member_id);
141 la.next = (struct member_list *) hash_lookup(members,
142 member2id('L', list_id));
144 if (isinchain(m, la.next))
149 ld.next = (struct member_list *) hash_lookup(lists, member_id);
153 if (isinchain(m, ld.next))
159 printf("%d ancestors, %d descendants\n",
160 chainlen(ance), chainlen(desc));
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;
171 ref = max(md->frefc, ma->frefc);
177 printf("Checking list %d member %d, ref = %d\n",
178 ma->list_id, id2id(md->member_id), ref);
180 if (m1 = find_member(ma->list_id, md->member_id)) {
184 printf("set refc to %d (%d) on list %d, member %d\n",
185 m1->frefc, ref, m1->list_id, id2id(m1->member_id));
187 if (ma == m && md == m)
191 m1->list_id = ma->list_id;
192 m1->member_id = md->member_id;
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));
199 sq_save_data(sq, m1);
203 while (sq_get_data(sq, &m)) {
210 EXEC SQL CLOSE csrm1;
211 printf("created %d records\n", records);
217 struct save_queue *sq;
218 EXEC SQL BEGIN DECLARE SECTION;
219 int list_id, member_id, ref_count, dflag;
221 EXEC SQL END DECLARE SECTION;
222 int errxtra, errbref, errbdir;
224 int ref0, ref1, ref2, ref3, refg;
225 int db0, db1, db2, db3, dbg;
228 /* verify members from database */
229 printf("Verifying members\n");
230 errxtra = errbref = errbdir = 0;
232 ref0 = ref1 = ref2 = ref3 = refg = 0;
233 db0 = db1 = db2 = db3 = dbg = 0;
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
245 INTO :list_id, :member_id, :mtype, :ref_count, :dflag;
246 if(sqlca.sqlcode != 0) break;
251 case 0: db0++; break;
252 case 1: db1++; break;
253 case 2: db2++; break;
254 case 3: db3++; break;
258 m = find_member(list_id, member2id(mtype[0], member_id));
261 m->list_id = list_id;
262 m->member_id = member2id(mtype[0], member_id);
264 m->frefc = ref_count;
272 case 0: ref0++; break;
273 case 1: ref1++; break;
274 case 2: ref2++; break;
275 case 3: ref3++; break;
279 m->frefc -= ref_count;
282 if (m->fdirect != dflag) {
288 EXEC SQL CLOSE csrm2;
289 printf("Found %d extra records, %d bad ref counts, %d bad direct flags\n",
290 errxtra, errbref, errbdir);
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);
305 struct save_queue *sq;
307 EXEC SQL BEGIN DECLARE SECTION;
308 int list_id, member_id, rowcount;
310 EXEC SQL END DECLARE SECTION;
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;
326 mtype[0] = id2type(m->member_id);
329 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
330 list_id, mtype, member_id, m->frefc, m->fdirect);
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 EXEC SQL INQUIRE_SQL(:rowcount = rowcount);
337 printf(" %d rows deleted\n", rowcount);
341 printf("Added %d missing records\n", errmis);
348 register struct member_list *l, *l1;
350 l = (struct member_list *) hash_lookup(lists, m->list_id);
352 l = (struct member_list *)malloc(sizeof(struct member_list));
354 fprintf(stderr, "No memory for insert_list\n");
359 hash_store(lists, m->list_id, l);
362 for (l1 = l; l1; l1 = l1->next)
363 if (l1->member->member_id == m->member_id) {
364 fprintf(stderr, "Found 2nd copy of list record for\n");
365 fprintf(stderr, "List: %d, Member: %c %d, Refc: %d, Direct %d\n",
366 m->list_id, id2type(m->member_id), id2id(m->member_id),
367 m->frefc, m->fdirect);
368 kill(getpid(), SIGQUIT);
372 l1 = (struct member_list *)malloc(sizeof(struct member_list));
374 fprintf(stderr, "No memory for insert_list\n");
386 register struct member_list *l, *l1;
388 l = (struct member_list *) hash_lookup(members, m->member_id);
390 l = (struct member_list *)malloc(sizeof(struct member_list));
392 fprintf(stderr, "No memory for insert_member\n");
397 hash_store(members, m->member_id, l);
401 for (l1 = l; l1; l1 = l1->next)
402 if (l1->member->list_id == m->list_id) {
403 fprintf(stderr, "Found 2nd copy of member record for\n");
404 fprintf(stderr, "List: %d, Member: %c %d, Refc: %d, Direct %d\n",
405 m->list_id, id2type(m->member_id), id2id(m->member_id),
406 m->frefc, m->fdirect);
407 kill(getpid(), SIGQUIT);
411 l1 = (struct member_list *)malloc(sizeof(struct member_list));
413 fprintf(stderr, "No memory for insert_member\n");
422 struct member *find_member(listid, memberid)
426 register struct member_list *l;
428 for (l = (struct member_list *) hash_lookup(lists, listid); l; l = l->next)
429 if (l->member->member_id == memberid)
436 void fix_member(dummy, l, errmis)
438 struct member_list *l;
441 EXEC SQL BEGIN DECLARE SECTION;
442 int list_id, member_id, ref_count, dflag, rowcount;
444 EXEC SQL END DECLARE SECTION;
446 register struct member *m;
448 for (; l; l = l->next) {
454 if (m->fbaddirect == 0 && m->frefc == 0 && m->ffound == 1)
456 if (m->ffound == 0) {
457 printf("Missing member record, adding:\n");
458 list_id = m->list_id;
459 member_id = id2id(m->member_id);
460 ref_count = m->frefc;
462 switch (id2type(m->member_id)) {
463 case 'U': mtype = "USER"; break;
464 case 'L': mtype = "LIST"; break;
465 case 'S': mtype = "STRING"; break;
466 case 'K': mtype = "KERBEROS"; break;
469 buf[0] = id2type(m->member_id);
472 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
473 list_id, mtype, member_id, ref_count, dflag);
476 /* append imembers (#list_id = list_id, #member_id = member_id,
477 * member_type = mtype, #ref_count = ref_count,
478 * direct = dflag); */
479 EXEC SQL INSERT INTO imembers (list_id, member_id,
480 member_type, ref_count, direct)
481 VALUES (:list_id, :member_id, :mtype, :ref_count, :dflag);
482 EXEC SQL INQUIRE_SQL(:rowcount = rowcount);
483 printf(" %d rows added\n", rowcount);
487 printf("Member record has bad ref_count and/or direct flag, fixing\n");
488 list_id = m->list_id;
489 member_id = id2id(m->member_id);
490 ref_count = m->frefc;
492 switch (id2type(m->member_id)) {
493 case 'U': mtype = "USER"; break;
494 case 'L': mtype = "LIST"; break;
495 case 'S': mtype = "STRING"; break;
496 case 'K': mtype = "KERBEROS"; break;
499 buf[0] = id2type(m->member_id);
502 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
503 list_id, mtype, member_id, ref_count, dflag);
505 /* replace m (#ref_count = m.#ref_count + ref_count, direct = dflag)
506 * where m.#list_id = list_id and m.#member_id = member_id and
507 * m.member_type = mtype */
508 EXEC SQL UPDATE imembers
509 SET ref_count=ref_count+:ref_count, direct = :dflag
510 WHERE list_id = :list_id AND member_id = :member_id AND
512 EXEC SQL INQUIRE_SQL(:rowcount = rowcount);
513 printf(" %d rows fixed\n", rowcount);
519 struct member *allocmember()
521 register struct member *m;
523 m = (struct member *) malloc(sizeof(struct member));
525 fprintf(stderr, "No memory for new member\n");
536 register struct member_list *l;
538 for (; l; l = l->next)
546 register struct member_list *l;
549 for (i = 0; l; l = l->next, i++);
557 void display_member(key, l, dummy1)
559 struct member_list *l;
565 for(; l; l = l->next) {
567 switch (id2type(m->member_id)) {
568 case 'U': mtype = "USER"; break;
569 case 'L': mtype = "LIST"; break;
570 case 'S': mtype = "STRING"; break;
571 case 'K': mtype = "KERBEROS"; break;
572 default: mtype = "???"; break;
574 printf("List: %d, Member: %s %d, Refc: %d, Direct %d\n",
575 m->list_id, mtype, id2id(m->member_id), m->frefc,