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