ticket-2618-patches-20031207
[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 void
93 dlqMoveb(fromptr, toptr)
94      dlqlinkP fromptr;
95      dlqlinkP toptr;
96 {
97     dlqlinkP tailptr;
98
99     DLQ_ASSERT_HEAD(fromptr);
100     DLQ_ASSERT_HEAD(toptr);
101
102     if (dlqEmpty(fromptr))
103         return (0);
104
105     tailptr = toptr->dlq_prev;
106
107     tailptr->dlq_next = fromptr->dlq_next;
108     tailptr->dlq_next->dlq_prev = tailptr;
109
110     /* now fix up the last item in the new chain */
111     tailptr = fromptr->dlq_prev;
112
113     tailptr->dlq_next = toptr;
114     toptr->dlq_prev = tailptr;
115
116     fromptr->dlq_next = fromptr;
117     fromptr->dlq_prev = fromptr;
118     return (0);
119 }
120
121 /* dlqUnlinkb
122  *      unlink the last item on the queue
123  */
124
125 dlqlinkP
126 dlqUnlinkb(headptr)
127      dlqlinkP headptr;
128 {
129     dlqlinkP ptr;
130     DLQ_ASSERT_HEAD(headptr);
131
132     if (dlqEmpty(headptr))
133         return (0);
134
135     ptr = headptr->dlq_prev;
136     ptr->dlq_prev->dlq_next = headptr;
137     headptr->dlq_prev = ptr->dlq_prev;
138
139     ptr->dlq_next = ptr;
140     ptr->dlq_prev = ptr;
141     return (ptr);
142 }
143
144 /* dlqUnlinkf
145  *      unlink the item on the front of the queue
146  */
147
148 dlqlinkP
149 dlqUnlinkf(headptr)
150      dlqlinkP headptr;
151 {
152     dlqlinkP ptr;
153     DLQ_ASSERT_HEAD(headptr);
154
155     if (dlqEmpty(headptr))
156         return (0);
157
158     ptr = headptr->dlq_next;
159
160     headptr->dlq_next = ptr->dlq_next;
161     ptr->dlq_next->dlq_prev = headptr;
162
163     ptr->dlq_next = ptr;
164     ptr->dlq_prev = ptr;
165     return (ptr);
166 }
167
168 /* dlqUnlink
169  *      unlink the specified item from the queue.
170  */
171
172 dlqUnlink(ptr)
173      dlqlinkP ptr;
174 {
175     /* must not be the queue head */
176     if (ptr->dlq_type == DLQ_HEAD) {
177         printf("dlqUnlink: invalid unlink\n");
178         exit(1);
179     }
180
181     ptr->dlq_prev->dlq_next = ptr->dlq_next;
182     ptr->dlq_next->dlq_prev = ptr->dlq_prev;
183
184     ptr->dlq_next = 0;
185     ptr->dlq_prev = 0;
186 }
187
188 /* dlqFront
189  *      return point to item at front of queuen
190  */
191
192 dlqlinkP
193 dlqFront(headptr)
194      dlqlinkP headptr;
195 {
196     DLQ_ASSERT_HEAD(headptr);
197
198     if (dlqEmpty(headptr))
199         return (0);
200
201     return (headptr->dlq_next);
202 }
203
204 int
205 dlqCount(headptr)
206      dlqlinkP headptr;
207 {
208     dlqlinkP ptr;
209     int count = 0;
210
211     DLQ_ASSERT_HEAD(headptr);
212
213     ptr = headptr->dlq_next;
214     while (ptr != headptr) {
215         ptr = ptr->dlq_next;
216         count++;
217     }
218     return (count);
219 }
220
221 dlqTraverseQueue(headptr, fn1, fn2)
222      dlqlinkP headptr;
223      int (*fn1) ();
224      int (*fn2) ();
225 {
226     dlqlinkP ptr, oldPtr;
227
228     DLQ_ASSERT_HEAD(headptr);
229
230     ptr = headptr->dlq_next;
231     while (ptr != headptr) {
232         if (fn2 && ptr->dlq_structPtr)
233             (*fn2) (ptr->dlq_structPtr);
234         oldPtr = ptr;
235         ptr = ptr->dlq_next;
236         if (fn1)
237             (*fn1) (oldPtr);
238     }
239     return (0);
240 }