joe-beuhler-patches-20031122
[openafs.git] / src / bucoord / dlq.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 #ifdef HAVE_STDLIB_H
13 #include <stdlib.h>
14 #endif
15
16 RCSID
17     ("$Header$");
18
19 #include <afs/bubasics.h>
20
21 #define DLQ_ASSERT_HEAD(headptr)                                \
22         if ( (headptr)->dlq_type != DLQ_HEAD )                  \
23         {                                                       \
24             printf("file %s line %d, invalid queue head\n",     \
25                    __FILE__, __LINE__);                         \
26             exit(1);                                            \
27         }
28
29
30 /* dlqEmpty
31  * exit:
32  *      1 - queue is empty
33  *      0 - items on queue
34  */
35
36 dlqEmpty(headptr)
37      dlqlinkP headptr;
38 {
39     DLQ_ASSERT_HEAD(headptr);
40     if (headptr->dlq_next == headptr)
41         return (1);
42     return (0);
43 }
44
45 dlqInit(headptr)
46      dlqlinkP headptr;
47 {
48     headptr->dlq_next = headptr;
49     headptr->dlq_prev = headptr;
50     headptr->dlq_type = DLQ_HEAD;
51     headptr->dlq_structPtr = NULL;
52     return (0);
53 }
54
55 /* dlqLinkf
56  *      link item to front of chain
57  */
58 dlqLinkf(headptr, entryptr)
59      dlqlinkP headptr;
60      dlqlinkP entryptr;
61 {
62     DLQ_ASSERT_HEAD(headptr);
63     /* link in as first item in chain */
64     entryptr->dlq_next = headptr->dlq_next;
65     headptr->dlq_next->dlq_prev = entryptr;
66     entryptr->dlq_prev = headptr;
67     headptr->dlq_next = entryptr;
68     return (0);
69 }
70
71 /* dlqLinkb
72  *      link item to end of chain
73  */
74
75 dlqLinkb(headptr, entryptr)
76      dlqlinkP headptr;
77      dlqlinkP entryptr;
78 {
79     DLQ_ASSERT_HEAD(headptr);
80     entryptr->dlq_next = headptr;
81     entryptr->dlq_prev = headptr->dlq_prev;
82
83     headptr->dlq_prev = entryptr;
84     entryptr->dlq_prev->dlq_next = entryptr;
85     return (0);
86 }
87
88 /* dlqMoveb
89  *      move all the items on the fromptr and append to the toptr's list
90  */
91
92 dlqMoveb(fromptr, toptr)
93      dlqlinkP fromptr;
94      dlqlinkP toptr;
95 {
96     dlqlinkP tailptr;
97
98     DLQ_ASSERT_HEAD(fromptr);
99     DLQ_ASSERT_HEAD(toptr);
100
101     if (dlqEmpty(fromptr))
102         return (0);
103
104     tailptr = toptr->dlq_prev;
105
106     tailptr->dlq_next = fromptr->dlq_next;
107     tailptr->dlq_next->dlq_prev = tailptr;
108
109     /* now fix up the last item in the new chain */
110     tailptr = fromptr->dlq_prev;
111
112     tailptr->dlq_next = toptr;
113     toptr->dlq_prev = tailptr;
114
115     fromptr->dlq_next = fromptr;
116     fromptr->dlq_prev = fromptr;
117     return (0);
118 }
119
120 /* dlqUnlinkb
121  *      unlink the last item on the queue
122  */
123
124 dlqlinkP
125 dlqUnlinkb(headptr)
126      dlqlinkP headptr;
127 {
128     dlqlinkP ptr;
129     DLQ_ASSERT_HEAD(headptr);
130
131     if (dlqEmpty(headptr))
132         return (0);
133
134     ptr = headptr->dlq_prev;
135     ptr->dlq_prev->dlq_next = headptr;
136     headptr->dlq_prev = ptr->dlq_prev;
137
138     ptr->dlq_next = ptr;
139     ptr->dlq_prev = ptr;
140     return (ptr);
141 }
142
143 /* dlqUnlinkf
144  *      unlink the item on the front of the queue
145  */
146
147 dlqlinkP
148 dlqUnlinkf(headptr)
149      dlqlinkP headptr;
150 {
151     dlqlinkP ptr;
152     DLQ_ASSERT_HEAD(headptr);
153
154     if (dlqEmpty(headptr))
155         return (0);
156
157     ptr = headptr->dlq_next;
158
159     headptr->dlq_next = ptr->dlq_next;
160     ptr->dlq_next->dlq_prev = headptr;
161
162     ptr->dlq_next = ptr;
163     ptr->dlq_prev = ptr;
164     return (ptr);
165 }
166
167 /* dlqUnlink
168  *      unlink the specified item from the queue.
169  */
170
171 dlqUnlink(ptr)
172      dlqlinkP ptr;
173 {
174     /* must not be the queue head */
175     if (ptr->dlq_type == DLQ_HEAD) {
176         printf("dlqUnlink: invalid unlink\n");
177         exit(1);
178     }
179
180     ptr->dlq_prev->dlq_next = ptr->dlq_next;
181     ptr->dlq_next->dlq_prev = ptr->dlq_prev;
182
183     ptr->dlq_next = 0;
184     ptr->dlq_prev = 0;
185 }
186
187 /* dlqFront
188  *      return point to item at front of queuen
189  */
190
191 dlqlinkP
192 dlqFront(headptr)
193      dlqlinkP headptr;
194 {
195     DLQ_ASSERT_HEAD(headptr);
196
197     if (dlqEmpty(headptr))
198         return (0);
199
200     return (headptr->dlq_next);
201 }
202
203 int
204 dlqCount(headptr)
205      dlqlinkP headptr;
206 {
207     dlqlinkP ptr;
208     int count = 0;
209
210     DLQ_ASSERT_HEAD(headptr);
211
212     ptr = headptr->dlq_next;
213     while (ptr != headptr) {
214         ptr = ptr->dlq_next;
215         count++;
216     }
217     return (count);
218 }
219
220 dlqTraverseQueue(headptr, fn1, fn2)
221      dlqlinkP headptr;
222      int (*fn1) ();
223      int (*fn2) ();
224 {
225     dlqlinkP ptr, oldPtr;
226
227     DLQ_ASSERT_HEAD(headptr);
228
229     ptr = headptr->dlq_next;
230     while (ptr != headptr) {
231         if (fn2 && ptr->dlq_structPtr)
232             (*fn2) (ptr->dlq_structPtr);
233         oldPtr = ptr;
234         ptr = ptr->dlq_next;
235         if (fn1)
236             (*fn1) (oldPtr);
237     }
238     return (0);
239 }