]> andersk Git - moira.git/blame - dbck/members.qc
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / dbck / members.qc
CommitLineData
af28107f 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
12struct member {
13 int list_id;
14 int member_id;
15 union {
16 short all;
17 struct {
18 short u_ref_count:12;
19 unsigned short u_direct:1;
20 unsigned short u_baddirect:1;
21 unsigned short u_found:1;
22 unsigned short u_scanned:1;
23 } u_flags;
24 } flags;
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
32
33#define member2id(c, id) (((c & 0xff) << 24) | (id & 0xffffff))
34#define id2type(id) ((id >> 24) & 0xff)
35#define id2id(id) (id & 0xffffff)
36
37struct member_list {
38 struct member_list *next;
39 struct member *member;
40};
41
42struct hash *lists, *members;
43void fix_member(), display_member();
44int debug = 0, records = 0;
45
46
47main(argc, argv)
48int argc;
49char **argv;
50##{
51 char buf[256];
52
53#ifdef DEBUG
54 if (argc > 1)
55 debug = atoi(argv[1]);
56#endif DEBUG
57
58## ingres sms
59## begin transaction
60## range of m is imembers
61
62 lists = create_hash(10000);
63 members = create_hash(10000);
64 records = 0;
65
66 load_members();
67#ifdef DEBUG
68 if (debug > 3)
69 hash_step(lists, display_member, NULL);
70#endif DEBUG
71 verify_members();
72 fix_members();
73
74#ifdef FIXERRORS
75 printf("Commit changes (Y/N)?");
76 fflush(stdout);
77 fgets(buf, sizeof(buf), stdin);
78 if (buf[0] == 'Y' || buf[0] == 'y') {
79 printf("Ending transaction\n");
80## end transaction
81 } else {
82#endif FIXERRORS
83 printf("Aborting transaction\n");
84## abort
85#ifdef FIXERRORS
86 }
87#endif FIXERRORS
88
89## exit
90 printf("Done.\n");
91
92 exit(0);
93##}
94
95
96
97load_members()
98##{
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;
102## char mtype[9];
103 struct save_queue *sq;
104
105 printf("Loading members\n");
106 sq = sq_create();
107
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 {
111#ifdef DEBUG
112 if (debug > 5)
113 printf("Working on list %d member %s %d refc %d\n",
114 list_id, mtype, member_id, ref_count);
115#endif DEBUG
116 if ((m = find_member(list_id, member2id(mtype[0], member_id))) == NULL) {
117 m = allocmember();
118 m->list_id = list_id;
119 m->member_id = member2id(mtype[0], member_id);
120 insert_list(m);
121 insert_member(m);
122 }
123 m->fdirect = 1;
124 la.next = (struct member_list *) hash_lookup(members,
125 member2id('L', list_id));
126 la.member = m;
127 if (isinchain(m, la.next))
128 ance = la.next;
129 else
130 ance = &la;
131 if (mtype[0] == 'L')
132 ld.next = (struct member_list *) hash_lookup(lists, member_id);
133 else
134 ld.next = NULL;
135 ld.member = m;
136 if (isinchain(m, ld.next))
137 desc = ld.next;
138 else
139 desc = &ld;
140#ifdef DEBUG
141 if (debug > 5)
142 printf("%d ancestors, %d descendants\n",
143 chainlen(ance), chainlen(desc));
144#endif DEBUG
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;
153 if (ref == 0) {
154 ref = max(md->frefc, ma->frefc);
155 if (ref == 0)
156 ref = 1;
157 }
158#ifdef DEBUG
159 if (debug > 5)
160 printf("Checking list %d member %d, ref = %d\n",
161 ma->list_id, id2id(md->member_id), ref);
162#endif DEBUG
163 if (m1 = find_member(ma->list_id, md->member_id)) {
164 m1->frefc += ref;
165#ifdef DEBUG
166 if (debug > 5)
167 printf("set refc to %d (%d) on list %d, member %d\n",
168 m1->frefc, ref, m1->list_id, id2id(m1->member_id));
169#endif DEBUG
170 if (ma == m && md == m)
171 m1->fdirect = 1;
172 } else {
173 m1 = allocmember();
174 m1->list_id = ma->list_id;
175 m1->member_id = md->member_id;
176 m1->frefc = ref;
177#ifdef DEBUG
178 if (debug > 5)
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));
181#endif DEBUG
182 sq_save_data(sq, m1);
183 }
184 }
185 }
186 while (sq_get_data(sq, &m)) {
187 insert_list(m);
188 insert_member(m);
189 }
190 sq_destroy(sq);
191 sq = sq_create();
192## }
193 printf("created %d records\n", records);
194##}
195
196verify_members()
197##{
198 struct member *m;
199 struct save_queue *sq;
200## int list_id, member_id, ref_count, dflag;
201## char mtype[9];
202 int errxtra, errbref, errbdir;
203#ifdef DEBUG
204 int ref0, ref1, ref2, ref3, refg;
205 int db0, db1, db2, db3, dbg;
206#endif DEBUG
207
208 /* verify members from database */
209 printf("Verifying members\n");
210 errxtra = errbref = errbdir = 0;
211#ifdef DEBUG
212 ref0 = ref1 = ref2 = ref3 = refg = 0;
213 db0 = db1 = db2 = db3 = dbg = 0;
214#endif DEBUG
215 sq = sq_create();
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) {
219#ifdef DEBUG
220 if (debug > 1)
221 switch (ref_count) {
222 case 0: db0++; break;
223 case 1: db1++; break;
224 case 2: db2++; break;
225 case 3: db3++; break;
226 default: dbg++;
227 }
228#endif DEBUG
229 m = find_member(list_id, member2id(mtype[0], member_id));
230 if (m == NULL) {
231 m = allocmember();
232 m->list_id = list_id;
233 m->member_id = member2id(mtype[0], member_id);
234 m->fdirect = dflag;
235 m->frefc = ref_count;
236 sq_save_data(sq, m);
237 errxtra++;
238 } else {
239 m->ffound = 1;
240#ifdef DEBUG
241 if (debug > 1)
242 switch (m->frefc) {
243 case 0: ref0++; break;
244 case 1: ref1++; break;
245 case 2: ref2++; break;
246 case 3: ref3++; break;
247 default: refg++;
248 }
249#endif DEBUG
250 m->frefc -= ref_count;
251 if (m->frefc != 0)
252 errbref++;
253 if (m->fdirect != dflag) {
254 m->fbaddirect = 1;
255 errbdir++;
256 }
257 }
258## }
259 printf("Found %d extra records, %d bad ref counts, %d bad direct flags\n",
260 errxtra, errbref, errbdir);
261#ifdef DEBUG
262 if (debug > 1) {
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);
267 }
268#endif DEBUG
269##}
270
271
272fix_members()
273##{
274 struct member *m;
275 struct save_queue *sq;
276 int errmis = 0;
277## int list_id, member_id, rowcount;
278## char mtype[9];
279 char buf[512];
280
281 /* fix any errors */
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;
293 default:
294 mtype[0] = id2type(m->member_id);
295 mtype[1] = 0;
296 }
297 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
298 list_id, mtype, member_id, m->frefc, m->fdirect);
299#ifdef FIXERRORS
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);
304#endif FIXERRORS
305 }
306 if (errmis > 0)
307 printf("Added %d missing records\n", errmis);
308##}
309
310
311insert_list(m)
312struct member *m;
313{
314 register struct member_list *l, *l1;
315
316 l = (struct member_list *) hash_lookup(lists, m->list_id);
317 if (l == NULL) {
318 l = (struct member_list *)malloc(sizeof(struct member_list));
319 if (l == NULL) {
320 fprintf(stderr, "No memory for insert_list\n");
321 exit(1);
322 }
323 l->next = NULL;
324 l->member = m;
325 hash_store(lists, m->list_id, l);
326 return;
327 }
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);
335 exit(2);
336 }
337
338 l1 = (struct member_list *)malloc(sizeof(struct member_list));
339 if (l1 == NULL) {
340 fprintf(stderr, "No memory for insert_list\n");
341 exit(1);
342 }
343 l1->next = l->next;
344 l->next = l1;
345 l1->member = m;
346}
347
348
349insert_member(m)
350struct member *m;
351{
352 register struct member_list *l, *l1;
353
354 l = (struct member_list *) hash_lookup(members, m->member_id);
355 if (l == NULL) {
356 l = (struct member_list *)malloc(sizeof(struct member_list));
357 if (l == NULL) {
358 fprintf(stderr, "No memory for insert_member\n");
359 exit(1);
360 }
361 l->next = NULL;
362 l->member = m;
363 hash_store(members, m->member_id, l);
364 return;
365 }
366
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);
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_member\n");
380 exit(1);
381 }
382 l1->next = l->next;
383 l->next = l1;
384 l1->member = m;
385}
386
387
388struct member *find_member(listid, memberid)
389int listid;
390int memberid;
391{
392 register struct member_list *l;
393
394 for (l = (struct member_list *) hash_lookup(lists, listid); l; l = l->next)
395 if (l->member->member_id == memberid)
396 return(l->member);
397 return(NULL);
398}
399
400
401/*ARGSUSED*/
402void fix_member(dummy, l, errmis)
403int dummy;
404struct member_list *l;
405int *errmis;
406##{
407## int list_id, member_id, ref_count, dflag, rowcount;
408## char *mtype;
409 char buf[2];
410 register struct member *m;
411
412 for (; l; l = l->next) {
413 m = l->member;
414
415 if (m->fscanned)
416 continue;
417 m->fscanned = 1;
418 if (m->fbaddirect == 0 && m->frefc == 0 && m->ffound == 1)
419 continue;
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;
425 dflag = m->fdirect;
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;
431 default:
432 mtype = buf;
433 buf[0] = id2type(m->member_id);
434 buf[1] = 0;
435 }
436 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
437 list_id, mtype, member_id, ref_count, dflag);
438 (*errmis)++;
439#ifdef FIXERRORS
440## append imembers (#list_id = list_id, #member_id = member_id,
441## member_type = mtype, #ref_count = ref_count,
442## direct = dflag);
443## inquire_equel(rowcount = "rowcount")
444 printf(" %d rows added\n", rowcount);
445#endif FIXERRORS
446 continue;
447 }
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;
452 dflag = m->fdirect;
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;
458 default:
459 mtype = buf;
460 buf[0] = id2type(m->member_id);
461 buf[1] = 0;
462 }
463 printf(" List: %d, Member: %s %d, Refc: %d, Direct %d\n",
464 list_id, mtype, member_id, ref_count, dflag);
465#ifdef FIXERRORS
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);
471#endif FIXERRORS
472 }
473##}
474
475
476struct member *allocmember()
477{
478 register struct member *m;
479
480 m = (struct member *) malloc(sizeof(struct member));
481 if (m == NULL) {
482 fprintf(stderr, "No memory for new member\n");
483 exit(1);
484 }
485 m->fall = 0;
486 records++;
487 return(m);
488}
489
490
491int isinchain(m, l)
492struct member *m;
493register struct member_list *l;
494{
495 for (; l; l = l->next)
496 if (l->member == m)
497 return(1);
498 return(0);
499}
500
501
502int chainlen(l)
503register struct member_list *l;
504{
505 register int i;
506 for (i = 0; l; l = l->next, i++);
507 return(i);
508}
509
510
511#ifdef DEBUG
512
513/*ARGSUSED*/
514void display_member(key, l, dummy1)
515int key, dummy1;
516struct member_list *l;
517{
518 struct member *m;
519 char *mtype;
520
521 printf("%d*", key);
522 for(; l; l = l->next) {
523 m = l->member;
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;
530 }
531 printf("List: %d, Member: %s %d, Refc: %d, Direct %d\n",
532 m->list_id, mtype, id2id(m->member_id), m->frefc,
533 m->fdirect);
534 }
535}
536
537#endif DEBUG
This page took 0.227043 seconds and 5 git commands to generate.