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