ubik-call-sucks-20060704
[openafs.git] / src / libadmin / vos / 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 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID
14     ("$Header$");
15
16 #include "lockprocs.h"
17 #ifdef HAVE_STRING_H
18 #include <string.h>
19 #else
20 #ifdef HAVE_STRINGS_H
21 #include <strings.h>
22 #endif
23 #endif
24
25 /* Finds an index in VLDB entry that matches the volume type, server, and partition.
26  * If type is zero, will match first index of ANY type (RW, BK, or RO).
27  * If server is zero, will match first index of ANY server and partition 
28  * Zero is a valid partition field.
29  */
30 static int
31 FindIndex(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
32           afs_int32 server, afs_int32 part, afs_int32 type)
33 {
34     afs_status_t tst = 0;
35     int e;
36     int equal = 0;
37
38     for (e = 0; (e < entry->nServers) && !tst; e++) {
39         if (!type || (entry->serverFlags[e] & type)) {
40             VLDB_IsSameAddrs(cellHandle, entry->serverNumber[e], server,
41                              &equal, &tst);
42             if ((!server || (entry->serverPartition[e] == part))
43                 && (!server || equal)) {
44                 break;
45             }
46             if (type == ITSRWVOL) {
47                 /* quit when we are looking for RW entry (there's only 1) */
48                 return -1;
49             }
50         }
51     }
52
53     if (e >= entry->nServers) {
54         return -1;              /* Didn't find it */
55     }
56
57     return e;                   /* return the index */
58 }
59
60 /* Changes the rw site only */
61 static void
62 SetAValue(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
63           afs_int32 oserver, afs_int32 opart, afs_int32 nserver,
64           afs_int32 npart, afs_int32 type)
65 {
66     int e;
67
68     e = FindIndex(cellHandle, entry, oserver, opart, type);
69     if (e == -1)
70         return;                 /* If didn't find it, just return */
71
72     entry->serverNumber[e] = nserver;
73     entry->serverPartition[e] = npart;
74
75     /* Now move rest of entries up */
76     if ((nserver == 0L) && (npart == 0L)) {
77         for (e++; e < entry->nServers; e++) {
78             entry->serverNumber[e - 1] = entry->serverNumber[e];
79             entry->serverPartition[e - 1] = entry->serverPartition[e];
80             entry->serverFlags[e - 1] = entry->serverFlags[e];
81         }
82     }
83 }
84
85 /* Changes the RW site only */
86 void
87 Lp_SetRWValue(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
88               afs_int32 oserver, afs_int32 opart, afs_int32 nserver,
89               afs_int32 npart)
90 {
91     SetAValue(cellHandle, entry, oserver, opart, nserver, npart, ITSRWVOL);
92 }
93
94 /* Changes the RO site only */
95 void
96 Lp_SetROValue(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
97               afs_int32 oserver, afs_int32 opart, afs_int32 nserver,
98               afs_int32 npart)
99 {
100     SetAValue(cellHandle, entry, oserver, opart, nserver, npart, ITSROVOL);
101 }
102
103 /* Returns success if this server and partition matches the RW entry */
104 int
105 Lp_Match(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
106          afs_int32 server, afs_int32 part, afs_status_p st)
107 {
108     if (FindIndex(cellHandle, entry, server, part, ITSRWVOL) == -1)
109         return 0;
110     return 1;
111 }
112
113 /* Return the index of the RO entry (plus 1) if it exists, else return 0 */
114 int
115 Lp_ROMatch(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
116            afs_int32 server, afs_int32 part, afs_status_p st)
117 {
118     return (FindIndex(cellHandle, entry, server, part, ITSROVOL) + 1);
119 }
120
121 /* Return the index of the RW entry if it exists, else return -1 */
122 int
123 Lp_GetRwIndex(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
124               afs_status_p st)
125 {
126     return (FindIndex(cellHandle, entry, 0, 0, ITSRWVOL));
127 }
128
129 /*initialize queue pointed by <ahead>*/
130 void
131 Lp_QInit(struct qHead *ahead)
132 {
133     ahead->count = 0;
134     ahead->next = NULL;
135 }
136
137 /*add <elem> in front of queue <ahead> */
138 void
139 Lp_QAdd(struct qHead *ahead, struct aqueue *elem)
140 {
141     struct aqueue *temp;
142
143     if (ahead->count == 0) {
144         ahead->count += 1;
145         ahead->next = elem;
146         elem->next = NULL;
147     } else {
148         temp = ahead->next;
149         ahead->count += 1;
150         ahead->next = elem;
151         elem->next = temp;
152     }
153 }
154
155 int
156 Lp_QScan(struct qHead *ahead, afs_int32 id, int *success,
157          struct aqueue **elem, afs_status_p st)
158 {
159     struct aqueue *cptr;
160
161     cptr = ahead->next;
162     while (cptr != NULL) {
163         if (cptr->ids[RWVOL] == id) {
164             *success = 1;
165             *elem = cptr;
166             return 0;
167         }
168         cptr = cptr->next;
169     }
170     *success = 0;
171     return 0;
172 }
173
174 /*return the element in the beginning of the queue <ahead>, free
175 *the space used by that element . <success> indicates if enumeration was ok*/
176 void
177 Lp_QEnumerate(struct qHead *ahead, int *success, struct aqueue *elem,
178               afs_status_p st)
179 {
180     int i;
181     struct aqueue *temp;
182
183     if (ahead->count > 0) {     /*more elements left */
184         ahead->count -= 1;
185         temp = ahead->next;
186         ahead->next = ahead->next->next;
187         strncpy(elem->name, temp->name, VOLSER_OLDMAXVOLNAME);
188         for (i = 0; i < 3; i++) {
189             elem->ids[i] = temp->ids[i];
190             elem->copyDate[i] = temp->copyDate[i];
191             elem->isValid[i] = temp->isValid[i];
192         }
193         elem->next = NULL;
194         *success = 1;
195         free(temp);
196     } else                      /*queue is empty */
197         *success = 0;
198 }