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