10 #define max(x, y) ((x) > (y) ? (x) : (y))
19 unsigned short u_direct:1;
20 unsigned short u_baddirect:1;
21 unsigned short u_found:1;
22 unsigned short u_scanned:1;
25 } *find_member(), *allocmember();
26 #define frefc flags.u_flags.u_ref_count
27 #define fdirect flags.u_flags.u_direct
28 #define fbaddirect flags.u_flags.u_baddirect
29 #define ffound flags.u_flags.u_found
30 #define fscanned flags.u_flags.u_scanned
31 #define fall flags.all
33 #define member2id(c, id) (((c & 0xff) << 24) | (id & 0xffffff))
34 #define id2type(id) ((id >> 24) & 0xff)
35 #define id2id(id) (id & 0xffffff)
38 struct member_list *next;
39 struct member *member;
42 struct hash *lists, *members;
43 void fix_member(), display_member();
44 int debug = 0, records = 0;
55 debug = atoi(argv[1]);
60 ## range of m is imembers
62 lists = create_hash(10000);
63 members = create_hash(10000);
69 hash_step(lists, display_member, NULL);
75 printf("Commit changes (Y/N)?");
77 fgets(buf, sizeof(buf), stdin);
78 if (buf[0] == 'Y' || buf[0] == 'y') {
79 printf("Ending transaction\n");
83 printf("Aborting transaction\n");
99 struct member *m, *m1, *md, *ma;
100 struct member_list *descendants, *ancestors, *desc, *ance, la, ld;
101 ## int list_id, member_id, ref_count, ref;
103 struct save_queue *sq;
105 printf("Loading members\n");
108 ## retrieve (list_id = m.#list_id, member_id = m.#member_id,
109 ## mtype = m.#member_type, ref_count = m.#ref_count)
110 ## where m.direct = 1 {
113 printf("Working on list %d member %s %d refc %d\n",
114 list_id, mtype, member_id, ref_count);
116 if ((m = find_member(list_id, member2id(mtype[0], member_id))) == NULL) {
118 m->list_id = list_id;
119 m->member_id = member2id(mtype[0], member_id);
124 la.next = (struct member_list *) hash_lookup(members,
125 member2id('L', list_id));
127 if (isinchain(m, la.next))
132 ld.next = (struct member_list *) hash_lookup(lists, member_id);
136 if (isinchain(m, ld.next))
142 printf("%d ancestors, %d descendants\n",
143 chainlen(ance), chainlen(desc));
145 for (ancestors = ance; ancestors; ancestors = ancestors->next) {
146 ma = ancestors->member;
147 for (descendants = desc; descendants; descendants=descendants->next) {
148 md = descendants->member;
149 if (member2id('L', ma->list_id) == md->member_id)
150 fprintf(stderr, "Loop detected! list %d member %d\n",
151 md->list_id, ma->member_id);
152 ref = md->frefc * ma->frefc;
154 ref = max(md->frefc, ma->frefc);
160 printf("Checking list %d member %d, ref = %d\n",
161 ma->list_id, id2id(md->member_id), ref);
163 if (m1 = find_member(ma->list_id, md->member_id)) {
167 printf("set refc to %d (%d) on list %d, member %d\n",
168 m1->frefc, ref, m1->list_id, id2id(m1->member_id));
170 if (ma == m && md == m)
174 m1->list_id = ma->list_id;
175 m1->member_id = md->member_id;
179 printf("set new refc to %d (%d) on list %d, member %d\n",
180 m1->frefc, ref, m1->list_id, id2id(m1->member_id));
182 sq_save_data(sq, m1);
186 while (sq_get_data(sq, &m)) {
193 printf("created %d records\n", records);
199 struct save_queue *sq;
200 ## int list_id, member_id, ref_count, dflag;
202 int errxtra, errbref, errbdir;
204 int ref0, ref1, ref2, ref3, refg;
205 int db0, db1, db2, db3, dbg;
208 /* verify members from database */
209 printf("Verifying members\n");
210 errxtra = errbref = errbdir = 0;
212 ref0 = ref1 = ref2 = ref3 = refg = 0;
213 db0 = db1 = db2 = db3 = dbg = 0;
216 ## retrieve (list_id = m.#list_id, member_id = m.#member_id,
217 ## mtype = m.member_type, ref_count = m.#ref_count,
218 ## dflag = m.#direct) {
222 case 0: db0++; break;
223 case 1: db1++; break;
224 case 2: db2++; break;
225 case 3: db3++; break;
229 m = find_member(list_id, member2id(mtype[0], member_id));
232 m->list_id = list_id;
233 m->member_id = member2id(mtype[0], member_id);
235 m->frefc = ref_count;
243 case 0: ref0++; break;
244 case 1: ref1++; break;
245 case 2: ref2++; break;
246 case 3: ref3++; break;
250 m->frefc -= ref_count;
253 if (m->fdirect != dflag) {
259 printf("Found %d extra records, %d bad ref counts, %d bad direct flags\n",
260 errxtra, errbref, errbdir);
263 printf("Found in db: %d 0; %d 1; %d 2; %d 3; %d > 3\n",
264 db0, db1, db2, db3, dbg);
265 printf("Found refs: %d 0; %d 1; %d 2; %d 3; %d > 3\n",
266 ref0, ref1, ref2, ref3, refg);
275 struct save_queue *sq;
277 ## int list_id, member_id, rowcount;
282 printf("Fixing errors\n");
283 hash_step(lists, fix_member, &errmis);
284 while (sq_get_data(sq, &m)) {
285 printf("Extraneous member record, deleting:\n");
286 list_id = m->list_id;
287 member_id = id2id(m->member_id);
288 switch (id2type(m->member_id)) {
289 case 'U': strcpy(mtype, "USER"); break;
290 case 'L': strcpy(mtype, "LIST"); break;
291 case 'S': strcpy(mtype, "STRING"); break;
292 case 'K': strcpy(mtype, "KERBEROS"); break;
294 mtype[0] = id2type(m->member_id);
297 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
298 list_id, mtype, member_id, m->frefc, m->fdirect);
300 ## delete m where m.#list_id = list_id and m.#member_id = member_id
301 ## and m.member_type = mtype
302 ## inquire_equel(rowcount = "rowcount")
303 printf(" %d rows deleted\n", rowcount);
307 printf("Added %d missing records\n", errmis);
314 register struct member_list *l, *l1;
316 l = (struct member_list *) hash_lookup(lists, m->list_id);
318 l = (struct member_list *)malloc(sizeof(struct member_list));
320 fprintf(stderr, "No memory for insert_list\n");
325 hash_store(lists, m->list_id, l);
328 for (l1 = l; l1; l1 = l1->next)
329 if (l1->member->member_id == m->member_id) {
330 fprintf(stderr, "Found 2nd copy of list record for\n");
331 fprintf(stderr, "List: %d, Member: %c %d, Refc: %d, Direct %d\n",
332 m->list_id, id2type(m->member_id), id2id(m->member_id),
333 m->frefc, m->fdirect);
334 kill(getpid(), SIGQUIT);
338 l1 = (struct member_list *)malloc(sizeof(struct member_list));
340 fprintf(stderr, "No memory for insert_list\n");
352 register struct member_list *l, *l1;
354 l = (struct member_list *) hash_lookup(members, m->member_id);
356 l = (struct member_list *)malloc(sizeof(struct member_list));
358 fprintf(stderr, "No memory for insert_member\n");
363 hash_store(members, m->member_id, l);
367 for (l1 = l; l1; l1 = l1->next)
368 if (l1->member->list_id == m->list_id) {
369 fprintf(stderr, "Found 2nd copy of member 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);
377 l1 = (struct member_list *)malloc(sizeof(struct member_list));
379 fprintf(stderr, "No memory for insert_member\n");
388 struct member *find_member(listid, memberid)
392 register struct member_list *l;
394 for (l = (struct member_list *) hash_lookup(lists, listid); l; l = l->next)
395 if (l->member->member_id == memberid)
402 void fix_member(dummy, l, errmis)
404 struct member_list *l;
407 ## int list_id, member_id, ref_count, dflag, rowcount;
410 register struct member *m;
412 for (; l; l = l->next) {
418 if (m->fbaddirect == 0 && m->frefc == 0 && m->ffound == 1)
420 if (m->ffound == 0) {
421 printf("Missing member record, adding:\n");
422 list_id = m->list_id;
423 member_id = id2id(m->member_id);
424 ref_count = m->frefc;
426 switch (id2type(m->member_id)) {
427 case 'U': mtype = "USER"; break;
428 case 'L': mtype = "LIST"; break;
429 case 'S': mtype = "STRING"; break;
430 case 'K': mtype = "KERBEROS"; break;
433 buf[0] = id2type(m->member_id);
436 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
437 list_id, mtype, member_id, ref_count, dflag);
440 ## append imembers (#list_id = list_id, #member_id = member_id,
441 ## member_type = mtype, #ref_count = ref_count,
443 ## inquire_equel(rowcount = "rowcount")
444 printf(" %d rows added\n", rowcount);
448 printf("Member record has bad ref_count and/or direct flag, fixing\n");
449 list_id = m->list_id;
450 member_id = id2id(m->member_id);
451 ref_count = m->frefc;
453 switch (id2type(m->member_id)) {
454 case 'U': mtype = "USER"; break;
455 case 'L': mtype = "LIST"; break;
456 case 'S': mtype = "STRING"; break;
457 case 'K': mtype = "KERBEROS"; break;
460 buf[0] = id2type(m->member_id);
463 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
464 list_id, mtype, member_id, ref_count, dflag);
466 ## replace m (#ref_count = m.#ref_count + ref_count, direct = dflag)
467 ## where m.#list_id = list_id and m.#member_id = member_id and
468 ## m.member_type = mtype
469 ## inquire_equel(rowcount = "rowcount");
470 printf(" %d rows fixed\n", rowcount);
476 struct member *allocmember()
478 register struct member *m;
480 m = (struct member *) malloc(sizeof(struct member));
482 fprintf(stderr, "No memory for new member\n");
493 register struct member_list *l;
495 for (; l; l = l->next)
503 register struct member_list *l;
506 for (i = 0; l; l = l->next, i++);
514 void display_member(key, l, dummy1)
516 struct member_list *l;
522 for(; l; l = l->next) {
524 switch (id2type(m->member_id)) {
525 case 'U': mtype = "USER"; break;
526 case 'L': mtype = "LIST"; break;
527 case 'S': mtype = "STRING"; break;
528 case 'K': mtype = "KERBEROS"; break;
529 default: mtype = "???"; break;
531 printf("List: %d, Member: %s %d, Refc: %d, Direct %d\n",
532 m->list_id, mtype, id2id(m->member_id), m->frefc,