ab585f0b5eb3fcfc1f833c0eae8433a16cc35af6
[openafs.git] / src / afs / afs_axscache.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 "afs/sysincludes.h"    /* Standard vendor system headers */
17 #include "afsincludes.h"        /* Afs-based standard headers */
18 #include "afs/afs_stats.h"      /* statistics */
19 #include "afs/stds.h"
20 static struct axscache *afs_axsfreelist = NULL;
21 static struct xfreelist {
22     struct xfreelist *next;
23 } *xfreemallocs = 0;
24 static int afs_xaxscnt = 0;
25 afs_rwlock_t afs_xaxs;
26
27 /* takes an address of an access cache & uid, returns ptr */
28 /* PRECONDITION: first field has been checked and doesn't match! 
29  * INVARIANT:  isparent(i,j) ^ isparent(j,i)  (ie, they switch around)
30  */
31 struct axscache *
32 afs_SlowFindAxs(struct axscache **cachep, afs_int32 id)
33 {
34     register struct axscache *i, *j;
35
36     j = (*cachep);
37     i = j->next;
38     while (i) {
39         if (i->uid == id) {
40             axs_Front(cachep, j, i);    /* maintain LRU queue */
41             return (i);
42         }
43
44         if ((j = i->next)) {    /* ASSIGNMENT HERE! */
45             if (j->uid == id) {
46                 axs_Front(cachep, i, j);
47                 return (j);
48             }
49         } else
50             return ((struct axscache *)NULL);
51         i = j->next;
52     }
53     return ((struct axscache *)NULL);
54 }
55
56
57 #define NAXSs (1000 / sizeof(struct axscache))
58 struct axscache *
59 axs_Alloc(void)
60 {
61     register struct axscache *i, *j, *xsp;
62     struct axscache *h;
63     int k;
64
65     ObtainWriteLock(&afs_xaxs, 174);
66     if ((h = afs_axsfreelist)) {
67         afs_axsfreelist = h->next;
68     } else {
69         h = i = j =
70             (struct axscache *)afs_osi_Alloc(NAXSs * sizeof(struct axscache));
71         afs_xaxscnt++;
72         xsp = (struct axscache *)xfreemallocs;
73         xfreemallocs = (struct xfreelist *)h;
74         xfreemallocs->next = (struct xfreelist *)xsp;
75         for (k = 0; k < NAXSs - 1; k++, i++) {
76             i->uid = -2;
77             i->axess = 0;
78             i->next = ++j;      /* need j because order of evaluation not defined */
79         }
80         i->uid = -2;
81         i->axess = 0;
82         i->next = NULL;
83         afs_axsfreelist = h->next;
84     }
85     ReleaseWriteLock(&afs_xaxs);
86     return (h);
87 }
88
89
90 #define axs_Free(axsp) { \
91  ObtainWriteLock(&afs_xaxs,175);             \
92  axsp->next = afs_axsfreelist;           \
93  afs_axsfreelist = axsp;                 \
94  ReleaseWriteLock(&afs_xaxs);            \
95 }
96
97
98 /* I optimize for speed on lookup, and don't give a RIP about delete.
99  */
100 void
101 afs_RemoveAxs(struct axscache **headp, struct axscache *axsp)
102 {
103     struct axscache *i, *j;
104
105     if (*headp && axsp) {       /* is bullet-proofing really neccessary? */
106         if (*headp == axsp) {   /* most common case, I think */
107             *headp = axsp->next;
108             axs_Free(axsp);
109             return;
110         }
111
112         i = *headp;
113         j = i->next;
114
115         while (j) {
116             if (j == axsp) {
117                 i->next = j->next;
118                 axs_Free(axsp);
119                 return;
120             }
121             if ((i = j->next)) {        /* ASSIGNMENT HERE! */
122                 j->next = i->next;
123                 axs_Free(axsp);
124                 return;
125             }
126         }
127     }
128     /* end of "if neither pointer is NULL" */
129     return;                     /* !#@  FAILED to find it! */
130 }
131
132
133 /* 
134  * Takes an entire list of access cache structs and prepends them, lock, stock,
135  * and barrel, to the front of the freelist.
136  */
137 void
138 afs_FreeAllAxs(struct axscache **headp)
139 {
140     struct axscache *i, *j;
141
142     i = *headp;
143     j = NULL;
144
145     while (i) {                 /* chase down the list 'til we reach the end */
146         j = i->next;
147         if (!j) {
148             ObtainWriteLock(&afs_xaxs, 176);
149             i->next = afs_axsfreelist;  /* tack on the freelist to the end */
150             afs_axsfreelist = *headp;
151             ReleaseWriteLock(&afs_xaxs);
152             *headp = NULL;
153             return;
154         }
155         i = j->next;
156     }
157
158     if (j) {                    /* we ran off the end of the list... */
159         ObtainWriteLock(&afs_xaxs, 177);
160         j->next = afs_axsfreelist;      /* tack on the freelist to the end */
161         afs_axsfreelist = *headp;
162         ReleaseWriteLock(&afs_xaxs);
163     }
164     *headp = NULL;
165     return;
166 }
167
168
169 /* doesn't appear to be used at all */
170 #if 0
171 static void
172 shutdown_xscache(void)
173 {
174     struct xfreelist *xp, *nxp;
175
176     RWLOCK_INIT(&afs_xaxs, "afs_xaxs");
177     xp = xfreemallocs;
178     while (xp) {
179         nxp = xp->next;
180         afs_osi_Free((char *)xp, NAXSs * sizeof(struct axscache));
181         xp = nxp;
182     }
183     afs_axsfreelist = NULL;
184     xfreemallocs = NULL;
185 }
186 #endif