afscp: enable debugging support in the volume portion
[openafs.git] / src / libafscp / afscp_volume.c
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <afsconfig.h>
28 #include <afs/param.h>
29
30 #include <roken.h>
31
32 #include <search.h>
33
34 #include <afs/vlserver.h>
35 #include <afs/vldbint.h>
36 #include <afs/volint.h>
37 #include "afscp.h"
38 #include "afscp_internal.h"
39
40 static int
41 icompare(const void *pa, const void *pb)
42 {
43     const struct afscp_volume *va = pa, *vb = pb;
44
45     if (va->id > vb->id)
46         return 1;
47     if (va->id < vb->id)
48         return -1;
49     return 0;
50 }
51
52 static int
53 ncompare(const void *pa, const void *pb)
54 {
55     const struct afscp_volume *va = pa, *vb = pb;
56
57     if (va->voltype > vb->voltype)
58         return 1;
59     if (vb->voltype < va->voltype)
60         return -1;
61     return strcmp(va->name, vb->name);
62 }
63
64 union allvldbentry {
65     struct uvldbentry u;
66     struct nvldbentry n;
67     struct vldbentry o;
68 };
69
70 struct afscp_volume *
71 afscp_VolumeByName(struct afscp_cell *cell, const char *vname,
72                    afs_int32 intype)
73 {
74     union allvldbentry u;
75     struct afscp_volume *ret, key;
76     struct afscp_server *server;
77     afs_int32 code, vtype, type, srv;
78     void *s;
79 #ifdef AFSCP_DEBUG
80     struct in_addr i;
81 #endif
82     if (intype == RWVOL)
83         vtype = VLSF_RWVOL;
84     else if (intype == ROVOL)
85         vtype = VLSF_ROVOL;
86     else if (intype == BACKVOL)
87         vtype = VLSF_BACKVOL;
88     else {
89         afscp_errno = EINVAL;
90         return NULL;
91     }
92
93     memset(&key, 0, sizeof(key));
94     strlcpy(key.name, vname, sizeof(key.name));
95     key.voltype = vtype;
96     s = tfind(&key, &cell->volsbyname, ncompare);
97     if (s) {
98         ret = *(struct afscp_volume **)s;
99         return ret;
100     }
101
102     type = 0;
103     code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, (char *)vname, &u.u);
104     if (code == RXGEN_OPCODE) {
105         type = 1;
106         code =
107             ubik_VL_GetEntryByNameN(cell->vlservers, 0, (char *)vname, &u.n);
108         if (code == RXGEN_OPCODE) {
109             type = 2;
110             code = ubik_VL_GetEntryByNameO(cell->vlservers, 0, (char *)vname,
111                                            &u.o);
112         }
113     }
114     if (code != 0) {
115         afscp_errno = code;
116         return NULL;
117     }
118     ret = malloc(sizeof(struct afscp_volume));
119     if (ret == NULL) {
120         afscp_errno = ENOMEM;
121         return NULL;
122     }
123     memset(ret, 0, sizeof(struct afscp_volume));
124     strlcpy(ret->name, u.u.name, sizeof(ret->name));
125     ret->nservers = 0;
126     ret->cell = cell;
127     switch (type) {
128     case 0:
129         ret->id = u.u.volumeId[intype];
130         for (srv = 0; srv < u.u.nServers; srv++) {
131             if ((u.u.serverFlags[srv] & vtype) == 0)
132                 continue;
133             afs_dprintf(("uvldbentry server %d flags: %x\n", srv,
134                          u.u.serverFlags[srv]));
135
136             if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0)
137                 server =
138                     afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low);
139             else
140                 server = afscp_ServerById(cell, &u.u.serverNumber[srv]);
141             if (!server)
142                 continue;
143             ret->servers[ret->nservers++] = server->index;
144         }
145         break;
146     case 1:
147         ret->id = u.n.volumeId[intype];
148         for (srv = 0; srv < u.n.nServers; srv++) {
149             if ((u.n.serverFlags[srv] & vtype) == 0)
150                 continue;
151             server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]);
152             if (!server)
153                 continue;
154             ret->servers[ret->nservers++] = server->index;
155         }
156         break;
157     case 2:
158         ret->id = u.o.volumeId[intype];
159         for (srv = 0; srv < u.o.nServers; srv++) {
160             if ((u.o.serverFlags[srv] & vtype) == 0)
161                 continue;
162             server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]);
163             if (!server)
164                 continue;
165             ret->servers[ret->nservers++] = server->index;
166         }
167         break;
168     }
169     if (!ret->nservers || !ret->id) {
170         free(ret);
171         return NULL;
172     }
173
174     ret->voltype = intype;
175     server = afscp_ServerByIndex(ret->servers[0]);
176 #ifdef AFSCP_DEBUG
177     if (server != NULL)
178         i.s_addr = server->addrs[0];
179     else
180         i.s_addr = 0;
181 #endif
182     afs_dprintf(("New volume BYNAME %s (%lu) on %s (%d)\n", ret->name,
183                  afs_printable_uint32_lu(ret->id),
184                  inet_ntoa(i), ret->servers[0]));
185     s = tsearch(&key, &cell->volsbyname, ncompare);
186     if (s)
187         *(struct afscp_volume **)s = ret;
188     key.id = ret->id;
189     s = tsearch(&key, &cell->volsbyid, icompare);
190     if (s)
191         *(struct afscp_volume **)s = ret;
192     return ret;
193 }
194
195 struct afscp_volume *
196 afscp_VolumeById(struct afscp_cell *cell, afs_uint32 id)
197 {
198     union allvldbentry u;
199     struct afscp_volume *ret, key;
200     struct afscp_server *server;
201     afs_int32 code, vtype, type, srv;
202     int voltype = -1;
203     char idbuffer[16];
204     void *s;
205 #ifdef AFSCP_DEBUG
206     struct in_addr i;
207 #endif
208
209     memset(&key, 0, sizeof(key));
210     key.id = id;
211     s = tfind(&key, &cell->volsbyid, icompare);
212     if (s) {
213         ret = *(struct afscp_volume **)s;
214         return ret;
215     }
216
217     snprintf(idbuffer, sizeof(idbuffer), "%lu", afs_printable_uint32_lu(id));
218     type = 0;
219     code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, idbuffer, &u.u);
220     if (code == RXGEN_OPCODE) {
221         type = 1;
222         code = ubik_VL_GetEntryByIDN(cell->vlservers, 0, id, -1, &u.n);
223         if (code == RXGEN_OPCODE) {
224             type = 2;
225             code = ubik_VL_GetEntryByID(cell->vlservers, 0, id, -1, &u.o);
226         }
227     }
228     if (code != 0) {
229         afscp_errno = code;
230         return NULL;
231     }
232     ret = malloc(sizeof(struct afscp_volume));
233     if (ret == NULL) {
234         afscp_errno = ENOMEM;
235         return NULL;
236     }
237     memset(ret, 0, sizeof(struct afscp_volume));
238     strlcpy(ret->name, u.u.name, sizeof(ret->name));
239     ret->nservers = 0;
240     ret->cell = cell;
241
242     switch (type) {
243     case 0:
244         if (id == u.u.volumeId[RWVOL]) {
245             vtype = VLSF_RWVOL;
246             voltype = RWVOL;
247         } else if (id == u.u.volumeId[ROVOL]) {
248             vtype = VLSF_ROVOL;
249             voltype = ROVOL;
250         } else if (id == u.u.volumeId[BACKVOL]) {
251             vtype = VLSF_BACKVOL;
252             voltype = BACKVOL;
253         } else {
254             vtype = 0;
255             voltype = -1;
256         }
257         for (srv = 0; srv < u.u.nServers; srv++) {
258             if ((u.u.serverFlags[srv] & vtype) == 0)
259                 continue;
260             if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0)
261                 server =
262                     afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low);
263             else
264                 server = afscp_ServerById(cell, &u.u.serverNumber[srv]);
265             if (!server)
266                 continue;
267             ret->servers[ret->nservers++] = server->index;
268         }
269         break;
270     case 1:
271         if (id == u.n.volumeId[RWVOL]) {
272             vtype = VLSF_RWVOL;
273             voltype = RWVOL;
274         } else if (id == u.n.volumeId[ROVOL]) {
275             vtype = VLSF_ROVOL;
276             voltype = ROVOL;
277         } else if (id == u.n.volumeId[BACKVOL]) {
278             vtype = VLSF_BACKVOL;
279             voltype = BACKVOL;
280         } else {
281             vtype = 0;
282             voltype = -1;
283         }
284         for (srv = 0; srv < u.n.nServers; srv++) {
285             if ((u.n.serverFlags[srv] & vtype) == 0)
286                 continue;
287             server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]);
288             if (server == NULL)
289                 continue;
290             ret->servers[ret->nservers++] = server->index;
291         }
292         break;
293     case 2:
294         if (id == u.o.volumeId[RWVOL]) {
295             vtype = VLSF_RWVOL;
296             voltype = RWVOL;
297         } else if (id == u.o.volumeId[ROVOL]) {
298             vtype = VLSF_ROVOL;
299             voltype = ROVOL;
300         } else if (id == u.o.volumeId[BACKVOL]) {
301             vtype = VLSF_BACKVOL;
302             voltype = BACKVOL;
303         } else {
304             vtype = 0;
305             voltype = -1;
306         }
307         for (srv = 0; srv < u.o.nServers; srv++) {
308             if ((u.o.serverFlags[srv] & vtype) == 0)
309                 continue;
310             server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]);
311             if (server == NULL)
312                 continue;
313             ret->servers[ret->nservers++] = server->index;
314         }
315         break;
316     }
317     ret->voltype = voltype;
318     server = afscp_ServerByIndex(ret->servers[0]);
319 #ifdef AFSCP_DEBUG
320     if (server)
321         i.s_addr = server->addrs[0];
322     else
323         i.s_addr = 0;
324 #endif
325     afs_dprintf(("New volume BYID %s (%lu) on %s (%d)\n", ret->name,
326                  afs_printable_uint32_lu(ret->id), inet_ntoa(i),
327                  ret->servers[0]));
328     s = tsearch(&key, &cell->volsbyid, icompare);
329     if (s)
330         *(struct afscp_volume **)s = ret;
331     strlcpy(key.name, ret->name, sizeof(key.name));
332     s = tsearch(&key, &cell->volsbyname, ncompare);
333     if (s)
334         *(struct afscp_volume **)s = ret;
335     return ret;
336 }