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