d18bbda47356f99d04b3260c9a82e2787d9862f4
[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
21 #include <sys/types.h>
22 #ifdef AFS_NT40_ENV
23 #include <winsock2.h>
24 #else
25 #include <netinet/in.h>
26 #endif
27 #include <string.h>
28 #include <afs/voldefs.h>
29 #include <rx/xdr.h>
30 #include <rx/rx.h>
31 #include <afs/vlserver.h>
32 #include <afs/nfs.h>
33 #include <afs/afsint.h>
34 #include "volint.h"
35 #include "volser.h"
36 #include "lockdata.h"
37
38 #include "vsutils_prototypes.h"
39 #include "lockprocs_prototypes.h"
40
41 /* Finds an index in VLDB entry that matches the volume type, server, and partition.
42  * If type is zero, will match first index of ANY type (RW, BK, or RO).
43  * If server is zero, will match first index of ANY server and partition 
44  * Zero is a valid partition field.
45  */
46 int
47 FindIndex(struct nvldbentry *entry, afs_int32 server, afs_int32 part, afs_int32 type)
48 {
49     int e;
50     afs_int32 error = 0;
51
52     for (e = 0; (e < entry->nServers) && !error; e++) {
53         if (!type || (entry->serverFlags[e] & type)) {
54             if ((!server || (entry->serverPartition[e] == part))
55                 && (!server
56                     || VLDB_IsSameAddrs(entry->serverNumber[e], server,
57                                         &error)))
58                 break;
59             if (type == ITSRWVOL)
60                 return -1;      /* quit when we are looking for RW entry (there's only 1) */
61         }
62     }
63
64     if (error) {
65         fprintf(STDERR,
66                 "Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
67                 entry->serverNumber[e], error);
68         return -1;
69     }
70
71     if (e >= entry->nServers)
72         return -1;              /* Didn't find it */
73
74     return e;                   /* return the index */
75 }
76
77 /* Changes the rw site only */
78 void
79 SetAValue(struct nvldbentry *entry, afs_int32 oserver, afs_int32 opart,
80           afs_int32 nserver, afs_int32 npart, afs_int32 type)
81 {
82     int e;
83     afs_int32 error = 0;
84
85     e = FindIndex(entry, oserver, opart, type);
86     if (e == -1)
87         return;                 /* If didn't find it, just return */
88
89     entry->serverNumber[e] = nserver;
90     entry->serverPartition[e] = npart;
91
92     /* Now move rest of entries up */
93     if ((nserver == 0L) && (npart == 0L)) {
94         for (e++; e < entry->nServers; e++) {
95             entry->serverNumber[e - 1] = entry->serverNumber[e];
96             entry->serverPartition[e - 1] = entry->serverPartition[e];
97             entry->serverFlags[e - 1] = entry->serverFlags[e];
98         }
99     }
100 }
101
102 /* Changes the RW site only */
103 void
104 Lp_SetRWValue(struct nvldbentry *entry, afs_int32 oserver, afs_int32 opart, 
105               afs_int32 nserver, afs_int32 npart)
106 {
107     SetAValue(entry, oserver, opart, nserver, npart, ITSRWVOL);
108 }
109
110 /* Changes the RO site only */
111 void
112 Lp_SetROValue(struct nvldbentry *entry, afs_int32 oserver, 
113               afs_int32 opart, afs_int32 nserver, afs_int32 npart)
114 {
115     SetAValue(entry, oserver, opart, nserver, npart, ITSROVOL);
116 }
117
118 /* Returns success if this server and partition matches the RW entry */
119 int 
120 Lp_Match(afs_int32 server, afs_int32 part,
121          struct nvldbentry *entry)
122 {
123     if (FindIndex(entry, server, part, ITSRWVOL) == -1)
124         return 0;
125     return 1;
126 }
127
128 /* Return the index of the RO entry (plus 1) if it exists, else return 0 */
129 int 
130 Lp_ROMatch(afs_int32 server, afs_int32 part, struct nvldbentry *entry)
131 {
132     return (FindIndex(entry, server, part, ITSROVOL) + 1);
133 }
134
135 /* Return the index of the RW entry if it exists, else return -1 */
136 int 
137 Lp_GetRwIndex(struct nvldbentry *entry)
138 {
139     return (FindIndex(entry, 0, 0, ITSRWVOL));
140 }
141
142 /*initialize queue pointed by <ahead>*/
143 void
144 Lp_QInit(struct qHead *ahead)
145 {
146     ahead->count = 0;
147     ahead->next = NULL;
148 }
149
150 /*add <elem> in front of queue <ahead> */
151 void
152 Lp_QAdd(struct qHead *ahead, struct aqueue *elem)
153 {
154     struct aqueue *temp;
155
156     if (ahead->count == 0) {
157         ahead->count += 1;
158         ahead->next = elem;
159         elem->next = NULL;
160     } else {
161         temp = ahead->next;
162         ahead->count += 1;
163         ahead->next = elem;
164         elem->next = temp;
165     }
166 }
167
168 int 
169 Lp_QScan(struct qHead *ahead, afs_int32 id, int *success, struct aqueue **elem)
170 {
171     struct aqueue *cptr;
172
173     cptr = ahead->next;
174     while (cptr != NULL) {
175         if (cptr->ids[RWVOL] == id) {
176             *success = 1;
177             *elem = cptr;
178             return 0;
179         }
180         cptr = cptr->next;
181     }
182     *success = 0;
183     return 0;
184 }
185
186 /*return the element in the beginning of the queue <ahead>, free
187 *the space used by that element . <success> indicates if enumeration was ok*/
188 void
189 Lp_QEnumerate(struct qHead *ahead, int *success, struct aqueue *elem)
190 {
191     int i;
192     struct aqueue *temp;
193
194     if (ahead->count > 0) {     /*more elements left */
195         ahead->count -= 1;
196         temp = ahead->next;
197         ahead->next = ahead->next->next;
198         strncpy(elem->name, temp->name, VOLSER_OLDMAXVOLNAME);
199         for (i = 0; i < 3; i++) {
200             elem->ids[i] = temp->ids[i];
201             elem->copyDate[i] = temp->copyDate[i];
202             elem->isValid[i] = temp->isValid[i];
203         }
204         elem->next = NULL;
205         *success = 1;
206         free(temp);
207     } else                      /*queue is empty */
208         *success = 0;
209 }
210
211 void
212 Lp_QTraverse(struct qHead *ahead)
213 {
214     int count;
215     struct aqueue *old, *new;
216
217     old = ahead->next;
218     new = old->next;
219     count = ahead->count;
220     printf
221         ("traversing the internal queue, which groups all the related volumes on a per partition basis\n");
222     while (count > 0) {
223         printf("---------------------------\n");
224         printf("%s RW-Id %lu", old->name, (unsigned long)old->ids[RWVOL]);
225         if (old->isValid[RWVOL])
226             printf(" valid ");
227         else
228             printf(" invalid ");
229         printf("RO-Id %lu", (unsigned long)old->ids[ROVOL]);
230         if (old->isValid[ROVOL])
231             printf(" valid ");
232         else
233             printf(" invalid ");
234         printf("BACKUP-Id %lu", (unsigned long)old->ids[BACKVOL]);
235         if (old->isValid[BACKVOL])
236             printf(" valid ");
237         else
238             printf(" invalid ");
239         printf("\n");
240         printf("---------------------------\n");
241         old = new;
242         if (count != 1)
243             new = new->next;
244         count--;
245     }
246 }