]> andersk Git - moira.git/blame - dbck/members.pc
Command line printer manipulation client, and build goo.
[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
462ff705 48char *db = "moira/moira";
68bbc9c3 49
50main(argc, argv)
51int argc;
52char **argv;
ab4c45a4 53{
68bbc9c3 54 char buf[256];
55
56#ifdef DEBUG
57 if (argc > 1)
58 debug = atoi(argv[1]);
33c9f867 59#endif /* DEBUG */
68bbc9c3 60
ab4c45a4 61/* ingres sms */
462ff705 62 EXEC SQL CONNECT :db;
ab4c45a4 63/* begin transaction */
64/* range of m is imembers */
65 /* No equivalent */
68bbc9c3 66
ab05f33a 67 lists = create_hash(50000);
68 members = create_hash(300000);
68bbc9c3 69 records = 0;
70
71 load_members();
72#ifdef DEBUG
73 if (debug > 3)
74 hash_step(lists, display_member, NULL);
33c9f867 75#endif /* DEBUG */
68bbc9c3 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");
ab4c45a4 85/* end transaction */
86 EXEC SQL COMMIT WORK;
68bbc9c3 87 } else {
33c9f867 88#endif /* FIXERRORS */
68bbc9c3 89 printf("Aborting transaction\n");
ab4c45a4 90/* abort */
91 EXEC SQL ROLLBACK WORK;
68bbc9c3 92#ifdef FIXERRORS
93 }
33c9f867 94#endif /* FIXERRORS */
68bbc9c3 95
ab4c45a4 96/* exit */
97 /* No equivalent (?) */
68bbc9c3 98 printf("Done.\n");
99
100 exit(0);
ab4c45a4 101}
68bbc9c3 102
103
68bbc9c3 104load_members()
ab4c45a4 105{
68bbc9c3 106 struct member *m, *m1, *md, *ma;
107 struct member_list *descendants, *ancestors, *desc, *ance, la, ld;
ab4c45a4 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;
68bbc9c3 112 struct save_queue *sq;
113
114 printf("Loading members\n");
115 sq = sq_create();
116
ab4c45a4 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
68bbc9c3 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);
33c9f867 132#endif /* DEBUG */
68bbc9c3 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));
33c9f867 161#endif /* DEBUG */
68bbc9c3 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);
33c9f867 179#endif /* DEBUG */
68bbc9c3 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));
33c9f867 186#endif /* DEBUG */
68bbc9c3 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));
33c9f867 198#endif /* DEBUG */
68bbc9c3 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();
ab4c45a4 209 }
210 EXEC SQL CLOSE csrm1;
68bbc9c3 211 printf("created %d records\n", records);
ab4c45a4 212}
68bbc9c3 213
214verify_members()
ab4c45a4 215{
68bbc9c3 216 struct member *m;
217 struct save_queue *sq;
ab4c45a4 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;
68bbc9c3 222 int errxtra, errbref, errbdir;
223#ifdef DEBUG
224 int ref0, ref1, ref2, ref3, refg;
225 int db0, db1, db2, db3, dbg;
33c9f867 226#endif /* DEBUG */
68bbc9c3 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;
33c9f867 234#endif /* DEBUG */
68bbc9c3 235 sq = sq_create();
ab4c45a4 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
68bbc9c3 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 }
33c9f867 257#endif /* DEBUG */
68bbc9c3 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 }
33c9f867 278#endif /* DEBUG */
68bbc9c3 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 }
ab4c45a4 287 }
288 EXEC SQL CLOSE csrm2;
68bbc9c3 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 }
33c9f867 298#endif /* DEBUG */
ab4c45a4 299}
68bbc9c3 300
301
302fix_members()
ab4c45a4 303{
68bbc9c3 304 struct member *m;
305 struct save_queue *sq;
306 int errmis = 0;
ab4c45a4 307 EXEC SQL BEGIN DECLARE SECTION;
308 int list_id, member_id, rowcount;
309 char mtype[9];
310 EXEC SQL END DECLARE SECTION;
68bbc9c3 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
ab4c45a4 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;
462ff705 336 rowcount = sqlca.sqlerrd[2];
337 if (rowcount > 0)
338 printf("%d entr%s deleted\n", rowcount,
339 rowcount == 1 ? "y" : "ies");
33c9f867 340#endif /* FIXERRORS */
68bbc9c3 341 }
342 if (errmis > 0)
343 printf("Added %d missing records\n", errmis);
ab4c45a4 344}
68bbc9c3 345
346
347insert_list(m)
348struct member *m;
349{
44d12d58 350 struct member_list *l, *l1;
68bbc9c3 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;
ab05f33a 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 }
68bbc9c3 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
388insert_member(m)
389struct member *m;
390{
44d12d58 391 struct member_list *l, *l1;
68bbc9c3 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;
ab05f33a 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 }
68bbc9c3 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
430struct member *find_member(listid, memberid)
431int listid;
432int memberid;
433{
44d12d58 434 struct member_list *l;
68bbc9c3 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*/
444void fix_member(dummy, l, errmis)
445int dummy;
446struct member_list *l;
447int *errmis;
ab4c45a4 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;
68bbc9c3 453 char buf[2];
44d12d58 454 struct member *m;
68bbc9c3 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
ab4c45a4 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);
462ff705 490 rowcount = sqlca.sqlerrd[2];
491 if (rowcount > 0)
492 printf("%d entr%s added\n", rowcount,
493 rowcount == 1 ? "y" : "ies");
33c9f867 494#endif /* FIXERRORS */
68bbc9c3 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
ab4c45a4 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;
462ff705 522 rowcount = sqlca.sqlerrd[2];
523 if (rowcount > 0)
524 printf("%d entr%s updated\n", rowcount,
525 rowcount == 1 ? "y" : "ies");
33c9f867 526#endif /* FIXERRORS */
68bbc9c3 527 }
ab4c45a4 528}
68bbc9c3 529
530
531struct member *allocmember()
532{
44d12d58 533 struct member *m;
68bbc9c3 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
546int isinchain(m, l)
547struct member *m;
44d12d58 548struct member_list *l;
68bbc9c3 549{
550 for (; l; l = l->next)
551 if (l->member == m)
552 return(1);
553 return(0);
554}
555
556
557int chainlen(l)
44d12d58 558struct member_list *l;
68bbc9c3 559{
44d12d58 560 int i;
68bbc9c3 561 for (i = 0; l; l = l->next, i++);
562 return(i);
563}
564
565
566#ifdef DEBUG
567
568/*ARGSUSED*/
569void display_member(key, l, dummy1)
570int key, dummy1;
571struct 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
33c9f867 592#endif /* DEBUG */
This page took 0.389089 seconds and 5 git commands to generate.