f4ad9aff2b6284da2a4fbc43e6f0c58075013954
[openafs.git] / src / volser / lockprocs.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  *  Module:         lockprocs.c
12  *  System:         Volser
13  *  Instituition:   ITC, CMU
14  *  Date:           December, 88
15  */
16
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20 #include <roken.h>
21
22 #include <sys/types.h>
23 #ifdef AFS_NT40_ENV
24 #include <winsock2.h>
25 #else
26 #include <netinet/in.h>
27 #endif
28 #include <string.h>
29 #include <afs/voldefs.h>
30 #include <rx/xdr.h>
31 #include <rx/rx.h>
32 #include <afs/vlserver.h>
33 #include <afs/nfs.h>
34 #include <afs/afsint.h>
35 #include <ubik.h>
36 #include "volint.h"
37 #include "volser.h"
38 #include "lockdata.h"
39
40 #include "vsutils_prototypes.h"
41 #include "lockprocs_prototypes.h"
42
43 struct ubik_client *cstruct;
44
45 /* Finds an index in VLDB entry that matches the volume type, server, and partition.
46  * If type is zero, will match first index of ANY type (RW, BK, or RO).
47  * If server is zero, will match first index of ANY server and partition
48  * Zero is a valid partition field.
49  */
50 static int
51 FindIndex(struct uvldbentry *entry, afs_uint32 server, afs_int32 part, afs_int32 type)
52 {
53     int e;
54     afs_int32 error = 0;
55     afsUUID m_uuid;
56     int uuid_valid = 0;
57
58     if (server && !afs_uuid_is_nil(&entry->serverNumber[0])) {
59         afs_int32 vcode, m_uniq=0;
60         bulkaddrs m_addrs;
61         ListAddrByAttributes m_attrs;
62         afs_int32 m_nentries;
63
64         m_attrs.Mask = VLADDR_IPADDR;
65         m_attrs.ipaddr = htonl(server);
66         m_nentries = 0;
67         m_addrs.bulkaddrs_val = 0;
68         m_addrs.bulkaddrs_len = 0;
69         vcode =
70             ubik_VL_GetAddrsU( cstruct, 0, &m_attrs,
71                                &m_uuid,
72                                &m_uniq, &m_nentries,
73                                &m_addrs);
74         uuid_valid = (vcode == 0);
75     }
76
77     for (e = 0; (e < entry->nServers) && !error; e++) {
78         if (!type || (entry->serverFlags[e] & type)) {
79             if ((!server || (entry->serverPartition[e] == part))
80                 && (!server
81                     || (uuid_valid && afs_uuid_equal(&m_uuid, &entry->serverNumber[e]))
82                     || VLDB_IsSameAddrs(entry->serverUnique[e], server, &error)))
83                 break;
84             if (type == ITSRWVOL)
85                 return -1;      /* quit when we are looking for RW entry (there's only 1) */
86         }
87     }
88
89     if (error) {
90         fprintf(STDERR,
91                 "Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
92                 entry->serverUnique[e], error);
93         return -1;
94     }
95
96     if (e >= entry->nServers)
97         return -1;              /* Didn't find it */
98
99     return e;                   /* return the index */
100 }
101
102 /* Changes the rw site only */
103 static void
104 SetAValue(struct uvldbentry *entry, afs_uint32 oserver, afs_int32 opart,
105           afs_uint32 nserver, afs_int32 npart, afs_int32 type)
106 {
107     int e;
108
109     e = FindIndex(entry, oserver, opart, type);
110     if (e == -1)
111         return;                 /* If didn't find it, just return */
112
113     entry->serverUnique[e] = nserver;
114     entry->serverPartition[e] = npart;
115
116     /* Now move rest of entries up */
117     if ((nserver == 0L) && (npart == 0L)) {
118         for (e++; e < entry->nServers; e++) {
119             entry->serverUnique[e - 1] = entry->serverUnique[e];
120             entry->serverPartition[e - 1] = entry->serverPartition[e];
121             entry->serverFlags[e - 1] = entry->serverFlags[e];
122         }
123     }
124 }
125
126 /* Changes the RW site only */
127 void
128 Lp_SetRWValue(struct nvldbentry *entryp, afs_uint32 oserver, afs_int32 opart,
129               afs_uint32 nserver, afs_int32 npart)
130 {
131     struct uvldbentry uentry;
132
133     nvlentry_to_uvlentry(entryp, &uentry);
134     SetAValue(&uentry, oserver, opart, nserver, npart, ITSRWVOL);
135     uvlentry_to_nvlentry(&uentry, entryp);
136 }
137
138 void
139 Lp_SetRWValueU(struct uvldbentry *entry, afs_uint32 oserver, afs_int32 opart,
140               afs_uint32 nserver, afs_int32 npart)
141 {
142     SetAValue(entry, oserver, opart, nserver, npart, ITSRWVOL);
143 }
144
145 /* Changes the RO site only */
146 void
147 Lp_SetROValue(struct nvldbentry *entryp, afs_uint32 oserver,
148               afs_int32 opart, afs_uint32 nserver, afs_int32 npart)
149 {
150     struct uvldbentry uentry;
151
152     nvlentry_to_uvlentry(entryp, &uentry);
153     SetAValue(&uentry, oserver, opart, nserver, npart, ITSROVOL);
154     uvlentry_to_nvlentry(&uentry, entryp);
155 }
156
157 void
158 Lp_SetROValueU(struct uvldbentry *entry, afs_uint32 oserver,
159               afs_int32 opart, afs_uint32 nserver, afs_int32 npart)
160 {
161     SetAValue(entry, oserver, opart, nserver, npart, ITSROVOL);
162 }
163
164 /* Returns success if this server and partition matches the RW entry */
165 int
166 Lp_Match(afs_uint32 server, afs_int32 part,
167          struct nvldbentry *entryp)
168 {
169     struct uvldbentry uentry;
170
171     nvlentry_to_uvlentry(entryp, &uentry);
172     if (FindIndex(&uentry, server, part, ITSRWVOL) == -1)
173         return 0;
174     uvlentry_to_nvlentry(&uentry, entryp);
175     return 1;
176 }
177
178 int
179 Lp_MatchU(afs_uint32 server, afs_int32 part,
180          struct uvldbentry *entry)
181 {
182     if (FindIndex(entry, server, part, ITSRWVOL) == -1)
183         return 0;
184     return 1;
185 }
186
187 /* Return the index of the RO entry (plus 1) if it exists, else return 0 */
188 int
189 Lp_ROMatch(afs_uint32 server, afs_int32 part, struct nvldbentry *entryp)
190 {
191     struct uvldbentry uentry;
192     int idx;
193
194     nvlentry_to_uvlentry(entryp, &uentry);
195     idx = (FindIndex(&uentry, server, part, ITSROVOL) + 1);
196     if (idx)
197         uvlentry_to_nvlentry(&uentry, entryp);
198     return idx;
199 }
200
201 int
202 Lp_ROMatchU(afs_uint32 server, afs_int32 part, struct uvldbentry *entry)
203 {
204     return (FindIndex(entry, server, part, ITSROVOL) + 1);
205 }
206
207 /* Return the index of the RW entry if it exists, else return -1 */
208 int
209 Lp_GetRwIndex(struct nvldbentry *entryp)
210 {
211     struct uvldbentry uentry;
212     int idx;
213
214     nvlentry_to_uvlentry(entryp, &uentry);
215     idx = (FindIndex(&uentry, 0, 0, ITSRWVOL));
216     if (idx > -1)
217         uvlentry_to_nvlentry(&uentry, entryp);
218     return idx;
219 }
220
221 int
222 Lp_GetRwIndexU(struct uvldbentry *entry)
223 {
224     return (FindIndex(entry, 0, 0, ITSRWVOL));
225 }
226
227 /*initialize queue pointed by <ahead>*/
228 void
229 Lp_QInit(struct qHead *ahead)
230 {
231     ahead->count = 0;
232     ahead->next = NULL;
233 }
234
235 /*add <elem> in front of queue <ahead> */
236 void
237 Lp_QAdd(struct qHead *ahead, struct aqueue *elem)
238 {
239     struct aqueue *temp;
240
241     if (ahead->count == 0) {
242         ahead->count += 1;
243         ahead->next = elem;
244         elem->next = NULL;
245     } else {
246         temp = ahead->next;
247         ahead->count += 1;
248         ahead->next = elem;
249         elem->next = temp;
250     }
251 }
252
253 int
254 Lp_QScan(struct qHead *ahead, afs_int32 id, int *success, struct aqueue **elem)
255 {
256     struct aqueue *cptr;
257
258     cptr = ahead->next;
259     while (cptr != NULL) {
260         if (cptr->ids[RWVOL] == id) {
261             *success = 1;
262             *elem = cptr;
263             return 0;
264         }
265         cptr = cptr->next;
266     }
267     *success = 0;
268     return 0;
269 }
270
271 /*return the element in the beginning of the queue <ahead>, free
272 *the space used by that element . <success> indicates if enumeration was ok*/
273 void
274 Lp_QEnumerate(struct qHead *ahead, int *success, struct aqueue *elem)
275 {
276     int i;
277     struct aqueue *temp;
278
279     if (ahead->count > 0) {     /*more elements left */
280         ahead->count -= 1;
281         temp = ahead->next;
282         ahead->next = ahead->next->next;
283         strncpy(elem->name, temp->name, VOLSER_OLDMAXVOLNAME);
284         for (i = 0; i < 3; i++) {
285             elem->ids[i] = temp->ids[i];
286             elem->copyDate[i] = temp->copyDate[i];
287             elem->isValid[i] = temp->isValid[i];
288         }
289         elem->next = NULL;
290         *success = 1;
291         free(temp);
292     } else                      /*queue is empty */
293         *success = 0;
294 }
295
296 void
297 Lp_QTraverse(struct qHead *ahead)
298 {
299     int count;
300     struct aqueue *old, *new;
301
302     old = ahead->next;
303     new = old->next;
304     count = ahead->count;
305     printf
306         ("traversing the internal queue, which groups all the related volumes on a per partition basis\n");
307     while (count > 0) {
308         printf("---------------------------\n");
309         printf("%s RW-Id %lu", old->name, (unsigned long)old->ids[RWVOL]);
310         if (old->isValid[RWVOL])
311             printf(" valid ");
312         else
313             printf(" invalid ");
314         printf("RO-Id %lu", (unsigned long)old->ids[ROVOL]);
315         if (old->isValid[ROVOL])
316             printf(" valid ");
317         else
318             printf(" invalid ");
319         printf("BACKUP-Id %lu", (unsigned long)old->ids[BACKVOL]);
320         if (old->isValid[BACKVOL])
321             printf(" valid ");
322         else
323             printf(" invalid ");
324         printf("\n");
325         printf("---------------------------\n");
326         old = new;
327         if (count != 1)
328             new = new->next;
329         count--;
330     }
331 }