Windows: AFSTearDownExtents may experience active extents
[openafs.git] / src / WINNT / afsadmsvr / TaAfsAdmSvrClientCache.cpp
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 <winsock2.h>
11 #include <ws2tcpip.h>
12
13 extern "C" {
14 #include <afs/param.h>
15 #include <afs/stds.h>
16 }
17
18 #include "TaAfsAdmSvrClientInternal.h"
19 #include <WINNT/AfsAppLib.h>
20
21
22 /*
23  * VARIABLES __________________________________________________________________
24  *
25  */
26
27 typedef struct
28    {
29    ASID idCell;
30    LPHASHLIST pCache;
31    LPHASHLISTKEY pCacheKeyAsid;
32    DWORD cReqCache;
33    } CELLCACHE, *LPCELLCACHE;
34
35 static struct
36    {
37    LPHASHLIST pCells;
38    LPHASHLISTKEY pCellsKeyAsid;
39    } l;
40
41
42 /*
43  * PROTOTYPES _________________________________________________________________
44  *
45  */
46
47 BOOL CALLBACK CacheKeyAsid_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData);
48 HASHVALUE CALLBACK CacheKeyAsid_HashObject (LPHASHLISTKEY pKey, PVOID pObject);
49 HASHVALUE CALLBACK CacheKeyAsid_HashData (LPHASHLISTKEY pKey, PVOID pData);
50
51 BOOL CALLBACK CellsKeyAsid_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData);
52 HASHVALUE CALLBACK CellsKeyAsid_HashObject (LPHASHLISTKEY pKey, PVOID pObject);
53 HASHVALUE CALLBACK CellsKeyAsid_HashData (LPHASHLISTKEY pKey, PVOID pData);
54
55
56 /*
57  * ROUTINES ___________________________________________________________________
58  *
59  */
60
61 LPCELLCACHE GetCellCache (ASID idCell)
62 {
63    if (!l.pCells)
64       return NULL;
65
66    return (LPCELLCACHE)(l.pCellsKeyAsid->GetFirstObject (&idCell));
67 }
68
69
70 BOOL CreateCellCache (ASID idCell)
71 {
72    asc_Enter();
73
74    if (!l.pCells)
75       {
76       l.pCells = New (HASHLIST);
77       l.pCells->SetCriticalSection (asc_GetCriticalSection());
78       l.pCellsKeyAsid = l.pCells->CreateKey (TEXT("ASID"), CellsKeyAsid_Compare, CellsKeyAsid_HashObject, CellsKeyAsid_HashData);
79       }
80
81    LPCELLCACHE pcc;
82    if ((pcc = GetCellCache (idCell)) == NULL)
83       {
84       pcc = New (CELLCACHE);
85       memset (pcc, 0x00, sizeof(CELLCACHE));
86       pcc->idCell = idCell;
87       pcc->pCache = New (HASHLIST);
88       pcc->pCache->SetCriticalSection (asc_GetCriticalSection());
89       pcc->pCacheKeyAsid = pcc->pCache->CreateKey (TEXT("ASID"), CacheKeyAsid_Compare, CacheKeyAsid_HashObject, CacheKeyAsid_HashData);
90       l.pCells->Add (pcc);
91       }
92    pcc->cReqCache ++;
93
94    asc_Leave();
95    return TRUE;
96 }
97
98
99 BOOL DestroyCellCache (ASID idCell)
100 {
101    asc_Enter();
102
103    LPCELLCACHE pcc;
104    if ((pcc = GetCellCache (idCell)) == NULL)
105       {
106       asc_Leave();
107       return FALSE;
108       }
109
110    if (!pcc->cReqCache || !(--(pcc->cReqCache)))
111       {
112       if (pcc->pCache)
113          {
114          for (LPENUM pEnum = pcc->pCache->FindFirst(); pEnum; pEnum = pEnum->FindNext())
115             {
116             LPASOBJPROP pProp = (LPASOBJPROP)( pEnum->GetObject() );
117             pcc->pCache->Remove (pProp);
118             Delete (pProp);
119             }
120
121          Delete (pcc->pCache);
122          }
123
124       l.pCells->Remove (pcc);
125       Delete (pcc);
126       }
127
128    asc_Leave();
129    return TRUE;
130 }
131
132
133 LPASOBJPROP GetCachedProperties (ASID idCell, ASID idObject)
134 {
135    LPASOBJPROP pCachedProperties = NULL;
136    asc_Enter();
137
138    LPCELLCACHE pcc;
139    if ((pcc = GetCellCache (idCell)) != NULL)
140       {
141       pCachedProperties = (LPASOBJPROP)(pcc->pCacheKeyAsid->GetFirstObject (&idObject));
142       }
143
144    asc_Leave();
145    return pCachedProperties;
146 }
147
148
149 void UpdateCachedProperties (ASID idCell, ASID idObject, LPASOBJPROP pProperties)
150 {
151    if (pProperties)
152       {
153       asc_Enter();
154
155       LPCELLCACHE pcc;
156       if ((pcc = GetCellCache (idCell)) != NULL)
157          {
158          LPASOBJPROP pCachedProperties;
159          if ((pCachedProperties = (LPASOBJPROP)(pcc->pCacheKeyAsid->GetFirstObject (&idObject))) == NULL)
160             {
161             pCachedProperties = New (ASOBJPROP);
162             memcpy (pCachedProperties, pProperties, sizeof(ASOBJPROP));
163             pcc->pCache->Add (pCachedProperties);
164             }
165          else // Just update?
166             {
167             memcpy (pCachedProperties, pProperties, sizeof(ASOBJPROP));
168             // Note: don't need to call pcc->pCache->Update(), because
169             // we haven't affected any indices (the old and new ASOBJPROP
170             // structures should have the same ASID)
171             }
172          }
173
174       NotifyObjectListeners (idCell, idObject);
175       asc_Leave();
176       }
177 }
178
179
180 BOOL RefreshCachedProperties (UINT_PTR idClient, ASID idCell, ASID idObject, AFSADMSVR_GET_LEVEL GetLevel, ULONG *pStatus)
181 {
182    BOOL rc = TRUE;
183    ULONG status = 0;
184
185    RpcTryExcept
186       {
187       LPASOBJPROP pProperties = GetCachedProperties (idCell, idObject);
188       DWORD verProperties = (pProperties) ? (pProperties->verProperties) : verPROP_NO_OBJECT;
189
190       ASOBJPROP NewProperties;
191       if ((rc = AfsAdmSvr_GetObject (idClient, RETURN_IF_OUT_OF_DATE, GetLevel, idObject, verProperties, &NewProperties, &status)) != FALSE)
192          {
193          if (NewProperties.idObject == idObject)
194             {
195             UpdateCachedProperties (idCell, idObject, &NewProperties);
196             }
197          }
198       }
199    RpcExcept(1)
200       {
201       rc = FALSE;
202       status = RPC_S_CALL_FAILED_DNE;
203       }
204    RpcEndExcept
205
206    if (!rc && pStatus)
207       *pStatus = status;
208    return rc;
209 }
210
211
212 BOOL RefreshCachedProperties (UINT_PTR idClient, ASID idCell, LPASIDLIST pAsidList, AFSADMSVR_GET_LEVEL GetLevel, ULONG *pStatus)
213 {
214    BOOL rc = TRUE;
215    ULONG status = 0;
216
217    if (pAsidList->cEntries)
218       {
219       RpcTryExcept
220          {
221          for (size_t iObject = 0; iObject < pAsidList->cEntries; ++iObject)
222             {
223             LPASOBJPROP pProperties = GetCachedProperties (idCell, pAsidList->aEntries[ iObject ].idObject);
224             pAsidList->aEntries[ iObject ].lParam = (pProperties) ? (pProperties->verProperties) : verPROP_NO_OBJECT;
225             }
226
227          LPASOBJPROPLIST pNewProperties = NULL;
228          if ((rc = AfsAdmSvr_GetObjects (idClient, RETURN_IF_OUT_OF_DATE, GetLevel, pAsidList, &pNewProperties, &status)) != FALSE)
229             {
230             if (pNewProperties)
231                {
232                for (size_t iObject = 0; iObject < pNewProperties->cEntries; ++iObject)
233                   {
234                   UpdateCachedProperties (idCell, pNewProperties->aEntries[ iObject ].ObjectProperties.idObject, &pNewProperties->aEntries[ iObject ].ObjectProperties);
235                   }
236                AfsAdmSvr_FreeObjPropList (&pNewProperties);
237                }
238             }
239          }
240       RpcExcept(1)
241          {
242          rc = FALSE;
243          status = RPC_S_CALL_FAILED_DNE;
244          }
245       RpcEndExcept
246       }
247
248    if (!rc && pStatus)
249       *pStatus = status;
250    return rc;
251 }
252
253
254 /*
255  * HASHLIST KEYS ______________________________________________________________
256  *
257  */
258
259 BOOL CALLBACK CacheKeyAsid_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
260 {
261    return (((LPASOBJPROP)pObject)->idObject == *(ASID*)pData);
262 }
263
264 HASHVALUE CALLBACK CacheKeyAsid_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
265 {
266    return CacheKeyAsid_HashData (pKey, &((LPASOBJPROP)pObject)->idObject);
267 }
268
269 HASHVALUE CALLBACK CacheKeyAsid_HashData (LPHASHLISTKEY pKey, PVOID pData)
270 {
271    return (HASHVALUE)*(ASID*)pData;
272 }
273
274
275 BOOL CALLBACK CellsKeyAsid_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
276 {
277    return (((LPCELLCACHE)pObject)->idCell == *(ASID*)pData);
278 }
279
280 HASHVALUE CALLBACK CellsKeyAsid_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
281 {
282    return CellsKeyAsid_HashData (pKey, &((LPCELLCACHE)pObject)->idCell);
283 }
284
285 HASHVALUE CALLBACK CellsKeyAsid_HashData (LPHASHLISTKEY pKey, PVOID pData)
286 {
287    return (HASHVALUE)*(ASID*)pData;
288 }
289