]> andersk Git - moira.git/blob - afssync/sync.fast.qc
Faster membership editing
[moira.git] / afssync / sync.fast.qc
1 /* $Header$
2  *
3  *
4  *  (c) Copyright 1989 by the Massachusetts Institute of Technology.
5  *  For copying and distribution information, please see the file
6  *  <mit-copyright.h>.
7  */
8
9 #include <mit-copyright.h>
10 #include <stdio.h>
11 #include <sys/file.h>
12
13 #include <rx/xdr.h>
14 #include "ptint.h"
15 #include "ptserver.h"
16 #include "pterror.h"
17
18 #include <moira.h>
19 #include <moira_site.h>
20 #include <ctype.h>
21
22 #define min(x,y)        ((x) < (y) ? (x) : (y))
23 char *whoami = "sync";
24
25 char *malloc(), *strsave();
26 int dbase_fd;
27
28 long pos;               /* cheader.eofPtr */
29 long usercount;         /* cheader.usercount */
30 long groupcount;        /* cheader.groupcount */
31
32 struct hash *users;
33 struct hash *groups;
34
35 struct member {
36     struct entry *user;
37     struct entry *group;
38     struct member *unext;
39     struct member *gnext;
40 };
41
42 struct entry {
43     long id;
44     long pos;
45     struct member *members;
46 };
47
48 main(argc, argv)
49 int argc;
50 char **argv;
51 {
52 ##  char db[9];
53     
54     int status;
55     int ingerr();
56
57     if (!strcmp(argv[1], "-db")) {
58         strncpy(db, argv[2], sizeof(db)-1);
59         argc -= 2;
60         argv += 2;
61     }
62     if (argc != 2) {
63         fprintf(stderr, "usage: %s [-db sms] outfile\n", whoami);
64         exit(MR_ARGS);
65     }
66
67     dbase_fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0660);
68     if (dbase_fd < 0) {
69         perror("opening file %s", argv[1]);
70         exit(1);
71     }   
72     IIseterr(ingerr);
73
74     initialize_sms_error_table();
75     initialize_pt_error_table();
76     Initdb();                                   /* Initialize prdb */
77     
78     users = create_hash(10000);
79     groups = create_hash(15000);
80     
81     pos = ntohl(cheader.eofPtr);
82     usercount = ntohl(cheader.usercount);
83     groupcount = ntohl(cheader.groupcount);
84
85 ##  ingres db
86 ##  set lockmode session where level = table
87 ##  begin transaction
88
89     do_passwd();
90     do_groups();
91
92 ##  end transaction
93 ##  exit
94
95     exit(MR_SUCCESS);
96 }
97
98
99 do_passwd()
100 ##{
101 ##  char login[9];
102 ##  int uid, id;
103     int t, i, status;
104     struct prentry tentry;
105     struct entry *u;
106
107     t = time(0);
108     fprintf(stderr, "Doing users: %s", ctime(&t));
109     
110 ##  range of u is users
111 ##  retrieve (login = u.#login, uid = u.#uid, id = u.users_id)
112 ##      where u.#uid > 0 and (u.#status = 1 or u.#status = 2) {
113             lowercase(strtrim(login));
114
115             if (uid==ANONYMOUSID)
116                 status = PRIDEXIST;
117             else {
118                 bzero(&tentry, sizeof(tentry));
119                 strcpy(tentry.name, login);
120                 tentry.id = uid;
121                 tentry.owner = SYSADMINID;
122                 tentry.creator = SYSADMINID;
123                 tentry.flags = PRQUOTA;
124                 tentry.ngroups = tentry.nusers = 20;
125                 if (tentry.id > ntohl(cheader.maxID))
126                     cheader.maxID = htonl(tentry.id);
127                 usercount++;
128
129                 i = IDHash(tentry.id);
130                 tentry.nextID = ntohl(cheader.idHash[i]);
131                 cheader.idHash[i] = htonl(pos);
132
133                 i = NameHash(tentry.name);
134                 tentry.nextName = ntohl(cheader.nameHash[i]);
135                 cheader.nameHash[i] = htonl(pos);
136                 
137                 pr_WriteEntry(0, 0, pos, &tentry);
138
139                 u = (struct entry *)malloc(sizeof(struct entry));
140                 u->id = uid;
141                 u->pos = pos;
142                 u->members = 0;
143                 
144                 pos += ENTRYSIZE;
145                 status = 0;
146             }
147
148             if (status)
149                 fprintf(stderr, "Error adding user %s uid %d: %s\n",
150                         login, uid, error_message(status));
151             else
152                 hash_store(users, id, u);
153 ##  }
154 ##}
155
156
157
158 do_groups()
159 ##{
160     long status;
161     struct prentry gentry, uentry;
162     struct entry *u, *g;
163     struct bucket **p, *b;
164     struct member *m;
165     char namebuf[41];
166     int aid, t, i;
167 ##  char name[33];
168 ##  int gid, id, lid, hide;
169
170     t = time(0);
171     fprintf(stderr, "Doing groups: %s", ctime(&t));
172
173 ##  range of l is list
174 ##  range of m is imembers
175
176     /* get lock records */
177 ##  retrieve (name = l.modtime) where l.list_id = 0
178 ##  retrieve (name = users.modtime) where users.users_id = 0
179 ##  retrieve (name = l.#name, gid = l.#gid, lid = l.list_id, hide = l.hidden)
180 ##      where l.group != 0 and l.active != 0 and l.#gid > 0 {
181             lowercase(strtrim(name));
182             sprintf(namebuf, "system:%s", name);
183             aid = -gid;
184
185             if (aid==ANYUSERID || aid==AUTHUSERID)
186                 status = PRIDEXIST;
187             else {
188                 bzero(&gentry, sizeof(gentry));
189                 strcpy(gentry.name, namebuf);
190                 gentry.id = aid;
191                 gentry.owner = SYSADMINID;
192                 gentry.creator = SYSADMINID;
193                 if (hide)
194                     gentry.flags = PRGRP|PRACCESS|PRP_STATUS_ANY;
195                 else
196                     gentry.flags = PRGRP;
197                 if (gentry.id < ntohl(cheader.maxGroup))
198                     cheader.maxGroup = htonl(gentry.id);
199                 groupcount++;
200
201                 i = IDHash(gentry.id);
202                 gentry.nextID = ntohl(cheader.idHash[i]);
203                 cheader.idHash[i] = htonl(pos);
204
205                 i = NameHash(gentry.name);
206                 gentry.nextName = ntohl(cheader.nameHash[i]);
207                 cheader.nameHash[i] = htonl(pos);
208
209                 pr_WriteEntry(0, 0, pos, &gentry);
210                 AddToOwnerChain(0,gentry.id,gentry.owner);
211
212                 g = (struct entry *)malloc(sizeof(struct entry));
213                 g->id = aid;
214                 g->pos = pos;
215                 g->members = 0;
216                 
217                 pos += ENTRYSIZE;
218                 status = 0;
219             }
220             if (status)
221                 fprintf(stderr, "Error adding group %s id %d: %s\n",
222                         namebuf, aid, error_message(status));
223             else
224                 hash_store(groups, lid, g);
225
226 ##  }
227
228     cheader.groupcount = htonl(groupcount);
229     cheader.usercount = htonl(usercount);
230     cheader.eofPtr = htonl(pos);
231     pr_Write(0, 0, 0, &cheader, sizeof(cheader));
232     
233     t = time(0);
234     fprintf(stderr, "Doing members: %s", ctime(&t));
235
236 ##  retrieve (lid = m.list_id, id = m.member_id)
237 ##      where m.member_type = "USER" {
238       if ((u = (struct entry *)hash_lookup(users, id)) &&
239           (g = (struct entry *)hash_lookup(groups, lid))) {
240               m = (struct member *)malloc(sizeof(struct member));
241               m->user = u;
242               m->group = g;
243               m->unext = u->members;
244               m->gnext = g->members;
245               u->members = g->members = m;
246       }
247 ##  }
248
249     for (p = &(users->data[users->size - 1]); p >= users->data; p--) {
250         for (b = *p; b; b = b->next) {
251             if ((u = (struct entry *)b->data)->members == 0)
252                 continue;
253             pr_Read(0, 0, u->pos, &uentry, sizeof(uentry));
254             for (i=0, m=u->members; m && i<PRSIZE; m=m->unext, i++)
255                 uentry.entries[i] = htonl(m->group->id);
256             uentry.count = htonl(i);
257             pr_Write(0, 0, u->pos, &uentry, sizeof(uentry));
258             if (m) {
259                 pr_ReadEntry(0, 0, g->pos, &gentry);
260                 while (m) {
261                     AddToEntry(0, &uentry, u->pos, m->group->id);
262                     m = m->unext;
263                 }
264             }
265         }
266     }
267     for (p = &(groups->data[groups->size - 1]); p >= groups->data; p--) {
268         for (b = *p; b; b = b->next) {
269             if ((g = (struct entry *)b->data)->members == 0)
270                 continue;
271             pr_Read(0, 0, g->pos, &gentry, sizeof(gentry));
272             for (i=0, m=g->members; m && i<PRSIZE; m=m->gnext, i++)
273                 gentry.entries[i] = htonl(m->user->id);
274             gentry.count = htonl(i);
275             pr_Write(0, 0, g->pos, &gentry, sizeof(gentry));
276             if (m) {
277                 pr_ReadEntry(0, 0, g->pos, &gentry);
278                 while (m) {
279                     AddToEntry(0, &gentry, g->pos, m->user->id);
280                     m = m->gnext;
281                 }
282             }
283         }
284     }
285
286     t = time(0);
287     fprintf(stderr, "Done: %s", ctime(&t));
288
289 ##}
290
291
292 /*
293  * ingerr: (supposedly) called when Ingres indicates an error.
294  * I have not yet been able to get this to work to intercept a
295  * database open error.
296  */
297 #define INGRES_DEADLOCK 4700
298
299 static int ingerr(num)
300     int *num;
301 {
302     char buf[256];
303     int ingres_errno;
304
305     switch (*num) {
306     case INGRES_DEADLOCK:
307         ingres_errno = MR_DEADLOCK;
308         break;
309     default:
310         ingres_errno = MR_INGRES_ERR;
311     }
312     com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
313     exit(ingres_errno);
314 }
This page took 0.155601 seconds and 5 git commands to generate.