windows-64-bit-type-safety-20051105
[openafs.git] / src / WINNT / afsclass / c_agg.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 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include <WINNT/afsclass.h>
16 #include "internal.h"
17
18
19 /*
20  * DEFINITIONS ________________________________________________________________
21  *
22  */
23
24
25 /*
26  * VARIABLES __________________________________________________________________
27  *
28  */
29
30
31 /*
32  * PROTOTYPES _________________________________________________________________
33  *
34  */
35
36
37 /*
38  * ROUTINES ___________________________________________________________________
39  *
40  */
41
42
43 AGGREGATE::AGGREGATE (LPSERVER lpServerParent, LPTSTR pszName, LPTSTR pszDevice)
44 {
45    m_lpiServer = lpServerParent->GetIdentifier();
46    m_lpiCell = lpServerParent->m_lpiCell;
47    m_lpiThis = NULL;
48
49    lstrcpy (m_szName, pszName);
50    lstrcpy (m_szDevice, pszDevice);
51    m_wGhost = 0;
52    m_idPartition = NO_PARTITION;
53
54    m_fFilesetsOutOfDate = TRUE;
55    m_lFilesets = New (HASHLIST);
56    m_lFilesets->SetCriticalSection (AfsClass_GetCriticalSection());
57    m_lkFilesetName = m_lFilesets->CreateKey ("Fileset Name", AGGREGATE::KeyFilesetName_Compare, AGGREGATE::KeyFilesetName_HashObject, AGGREGATE::KeyFilesetName_HashData);
58    m_lkFilesetID = m_lFilesets->CreateKey ("Fileset ID", AGGREGATE::KeyFilesetID_Compare, AGGREGATE::KeyFilesetID_HashObject, AGGREGATE::KeyFilesetID_HashData);
59
60    m_fStatusOutOfDate = TRUE;
61    m_fAllocationOutOfDate = TRUE;
62    memset (&m_as, 0x00, sizeof(AGGREGATESTATUS));
63 }
64
65
66 AGGREGATE::~AGGREGATE (void)
67 {
68    for (LPENUM pEnum = m_lFilesets->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
69       {
70       LPFILESET lpFileset = (LPFILESET)(pEnum->GetObject());
71       m_lFilesets->Remove (lpFileset);
72       Delete (lpFileset);
73       }
74    Delete (m_lFilesets);
75
76    if (m_lpiThis)
77       m_lpiThis->m_cRef --;
78 }
79
80
81 void AGGREGATE::SendDeleteNotifications (void)
82 {
83    for (LPENUM pEnum = m_lFilesets->FindFirst(); pEnum; pEnum = pEnum->FindNext())
84       {
85       LPFILESET lpFileset = (LPFILESET)(pEnum->GetObject());
86       lpFileset->SendDeleteNotifications();
87       }
88
89    NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
90 }
91
92
93 void AGGREGATE::Close (void)
94 {
95    AfsClass_Leave();
96 }
97
98
99 LPIDENT AGGREGATE::GetIdentifier (void)
100 {
101    if (m_lpiThis == NULL)
102       {
103       if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
104          m_lpiThis = New2 (IDENT,(this));
105       m_lpiThis->m_cRef ++;
106       }
107
108    return m_lpiThis;
109 }
110
111
112 void AGGREGATE::Invalidate (void)
113 {
114    if (!m_fStatusOutOfDate || !m_fFilesetsOutOfDate)
115       {
116       if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
117          {
118          m_fStatusOutOfDate = TRUE;
119          m_fFilesetsOutOfDate = TRUE;
120          }
121
122       NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
123       }
124 }
125
126
127 void AGGREGATE::InvalidateAllocation (void)
128 {
129    m_fAllocationOutOfDate = TRUE;
130 }
131
132
133 BOOL AGGREGATE::RefreshFilesets (BOOL fNotify, ULONG *pStatus)
134 {
135    BOOL rc = TRUE;
136    DWORD status = 0;
137
138    if (m_fFilesetsOutOfDate)
139       {
140       m_fFilesetsOutOfDate = FALSE;
141
142       // We'll need m_as.dwID to do this.
143       //
144       if (!RefreshStatus (fNotify, pStatus))
145          return FALSE;
146
147       if (fNotify)
148          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshFilesetsBegin, GetIdentifier());
149
150       // First thing is to forget about what filesets we think we have now.
151       //
152       for (LPENUM pEnum = m_lFilesets->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
153          {
154          LPFILESET lpFileset = (LPFILESET)(pEnum->GetObject());
155          lpFileset->SendDeleteNotifications();
156          m_lFilesets->Remove (lpFileset);
157          Delete (lpFileset);
158          }
159
160       // Next, the harder part: look through the server to find a list
161       // of filesets.
162       //
163       LPSERVER lpServer;
164       if ((lpServer = OpenServer (&status)) == NULL)
165          rc = FALSE;
166       else
167          {
168          PVOID hCell;
169          PVOID hVOS;
170          if ((hVOS = lpServer->OpenVosObject (&hCell, &status)) == NULL)
171             rc = FALSE;
172          else
173             {
174             WORKERPACKET wpBegin;
175             wpBegin.wpVosVolumeGetBegin.hCell = hCell;
176             wpBegin.wpVosVolumeGetBegin.hServer = hVOS;
177             wpBegin.wpVosVolumeGetBegin.idPartition = m_idPartition;
178
179             if (!Worker_DoTask (wtaskVosVolumeGetBegin, &wpBegin, &status))
180                rc = FALSE;
181             else
182                {
183                for (;;)
184                   {
185                   WORKERPACKET wpNext;
186                   wpNext.wpVosVolumeGetNext.hEnum = wpBegin.wpVosVolumeGetBegin.hEnum;
187                   if (!Worker_DoTask (wtaskVosVolumeGetNext, &wpNext, &status))
188                      {
189                      if (status == ADMITERATORDONE)
190                         status = 0;
191                      else
192                         rc = FALSE;
193                      break;
194                      }
195
196                   LPTSTR pszName = AnsiToString (wpNext.wpVosVolumeGetNext.Data.name);
197                   LPFILESET lpFileset = New2 (FILESET,(this, &wpNext.wpVosVolumeGetNext.Data.id, pszName));
198                   FreeString (pszName, wpNext.wpVosVolumeGetNext.Data.name);
199
200                   lpFileset->SetStatusFromVOS (&wpNext.wpVosVolumeGetNext.Data);
201                   lpFileset->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
202                   m_lFilesets->Add (lpFileset);
203                   NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpFileset->GetIdentifier());
204                   }
205
206                WORKERPACKET wpDone;
207                wpDone.wpVosVolumeGetDone.hEnum = wpBegin.wpVosVolumeGetBegin.hEnum;
208                Worker_DoTask (wtaskVosVolumeGetDone, &wpDone);
209                }
210
211             lpServer->CloseVosObject();
212             }
213
214          lpServer->Close();
215          }
216
217       InvalidateAllocation();
218
219       if (fNotify)
220          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshFilesetsEnd, GetIdentifier(), ((rc) ? 0 : status));
221       }
222
223    if (pStatus && !rc)
224       *pStatus = status;
225    return TRUE;
226 }
227
228
229 BOOL AGGREGATE::RefreshStatus (BOOL fNotify, ULONG *pStatus)
230 {
231    BOOL rc = TRUE;
232    DWORD status = 0;
233
234    if (m_fStatusOutOfDate)
235       {
236       m_fStatusOutOfDate = FALSE;
237
238       if (fNotify)
239          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
240
241       LPSERVER lpServer;
242       if ((lpServer = OpenServer (&status)) == NULL)
243          rc = FALSE;
244       else
245          {
246          PVOID hCell;
247          PVOID hVOS;
248          if ((hVOS = lpServer->OpenVosObject (&hCell, &status)) == NULL)
249             rc = FALSE;
250          else
251             {
252             WORKERPACKET wp;
253             wp.wpVosPartitionGet.hCell = hCell;
254             wp.wpVosPartitionGet.hServer = hVOS;
255             wp.wpVosPartitionGet.idPartition = m_idPartition;
256
257             if (!Worker_DoTask (wtaskVosPartitionGet, &wp, &status))
258                rc = FALSE;
259             else
260                {
261                m_as.ckStorageTotal = wp.wpVosPartitionGet.Data.totalSpace;
262                m_as.ckStorageFree = wp.wpVosPartitionGet.Data.totalFreeSpace;
263                }
264
265             m_as.dwID = GetID();
266             lpServer->CloseVosObject();
267             }
268
269          lpServer->Close();
270          }
271
272       if (fNotify)
273          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
274       }
275
276    if (rc && m_fAllocationOutOfDate)
277       {
278       if (fNotify)
279          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
280
281       m_as.ckStorageAllocated = CalculateAllocation (fNotify);
282       m_fAllocationOutOfDate = FALSE;
283
284       if (fNotify)
285          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier());
286       }
287
288    if (pStatus && !rc)
289       *pStatus = status;
290    return TRUE;
291 }
292
293
294 size_t AGGREGATE::CalculateAllocation (BOOL fNotify)
295 {
296    size_t ckAllocated = 0;
297
298    for (LPENUM pEnum = m_lFilesets->FindFirst(); pEnum; pEnum = pEnum->FindNext())
299       {
300       LPFILESET lpFileset = (LPFILESET)(pEnum->GetObject());
301
302       FILESETSTATUS fs;
303       if (lpFileset->GetStatus (&fs))
304          {
305          if (fs.Type == ftREADWRITE)
306             ckAllocated += fs.ckQuota;
307          }
308       }
309
310    return ckAllocated;
311 }
312
313
314 void AGGREGATE::GetName (LPTSTR pszName)
315 {
316    lstrcpy (pszName, m_szName);
317 }
318
319
320 void AGGREGATE::GetDevice (LPTSTR pszDevice)
321 {
322    lstrcpy (pszDevice, m_szDevice);
323 }
324
325
326 LPCELL AGGREGATE::OpenCell (ULONG *pStatus)
327 {
328    return m_lpiCell->OpenCell (pStatus);
329 }
330
331
332 LPSERVER AGGREGATE::OpenServer (ULONG *pStatus)
333 {
334    return m_lpiServer->OpenServer (pStatus);
335 }
336
337
338 /*
339  * FILESETS ___________________________________________________________________
340  *
341  */
342
343 LPFILESET AGGREGATE::OpenFileset (LPTSTR pszName, ULONG *pStatus)
344 {
345    if (!RefreshFilesets (TRUE, pStatus))
346       return NULL;
347
348    LPFILESET lpFileset;
349    if ((lpFileset = (LPFILESET)(m_lkFilesetName->GetFirstObject (pszName))) != NULL)
350       AfsClass_Enter();
351
352    return lpFileset;
353 }
354
355
356 LPFILESET AGGREGATE::OpenFileset (VOLUMEID *pvidFileset, ULONG *pStatus)
357 {
358    if (!RefreshFilesets (TRUE, pStatus))
359       return NULL;
360
361    LPFILESET lpFileset;
362    if ((lpFileset = (LPFILESET)(m_lkFilesetID->GetFirstObject (pvidFileset))) != NULL)
363       AfsClass_Enter();
364
365    return lpFileset;
366 }
367
368
369 LPFILESET AGGREGATE::FilesetFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
370 {
371    return FilesetFindFirst (phEnum, NULL, fNotify, pStatus);
372 }
373
374
375 LPFILESET AGGREGATE::FilesetFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
376 {
377    LPFILESET lpFileset = NULL;
378
379    if (!RefreshFilesets (fNotify, pStatus))
380       return NULL;
381
382    if (lpiFind != NULL)
383       {
384       lpFileset = lpiFind->OpenFileset();
385       *phEnum = NULL;
386       }
387    else if ((*phEnum = m_lFilesets->FindFirst()) != NULL)
388       {
389       lpFileset = (LPFILESET)( (*phEnum)->GetObject() );
390       AfsClass_Enter();
391       }
392
393    if (!lpFileset && pStatus)
394       *pStatus = ERROR_FILE_NOT_FOUND;
395    return lpFileset;
396 }
397
398
399 LPFILESET AGGREGATE::FilesetFindNext (HENUM *phEnum)
400 {
401    LPFILESET lpFileset = NULL;
402
403    if (*phEnum)
404       {
405       if ((*phEnum = (*phEnum)->FindNext()) != NULL)
406          {
407          lpFileset = (LPFILESET)( (*phEnum)->GetObject() );
408          AfsClass_Enter();
409          }
410       }
411
412    return lpFileset;
413 }
414
415
416 void AGGREGATE::FilesetFindClose (HENUM *phEnum)
417 {
418    if (*phEnum)
419       {
420       Delete (*phEnum);
421       *phEnum = NULL;
422       }
423 }
424
425
426 BOOL AGGREGATE::GetStatus (LPAGGREGATESTATUS lpas, BOOL fNotify, ULONG *pStatus)
427 {
428    if (!RefreshStatus (fNotify, pStatus))
429       return FALSE;
430
431    memcpy (lpas, &m_as, sizeof(AGGREGATESTATUS));
432    return TRUE;
433 }
434
435
436 short AGGREGATE::GetGhostStatus (void)
437 {
438    return m_wGhost;
439 }
440
441
442 PVOID AGGREGATE::GetUserParam (void)
443 {
444    return GetIdentifier()->GetUserParam();
445 }
446
447
448 void AGGREGATE::SetUserParam (PVOID pUserNew)
449 {
450    GetIdentifier()->SetUserParam (pUserNew);
451 }
452
453
454 int AGGREGATE::GetID (void)
455 {
456    if (m_idPartition == NO_PARTITION)
457       {
458       WORKERPACKET wp;
459       wp.wpVosPartitionNameToId.pszPartition = m_szName;
460
461       ULONG status;
462       if (Worker_DoTask (wtaskVosPartitionNameToId, &wp, &status))
463          m_idPartition = wp.wpVosPartitionNameToId.idPartition;
464       }
465
466    return m_idPartition;
467 }
468
469
470 /*
471  * HASH KEYS __________________________________________________________________
472  *
473  */
474
475 BOOL CALLBACK AGGREGATE::KeyFilesetName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
476 {
477    return !lstrcmp (((LPFILESET)pObject)->m_szName, (LPTSTR)pData);
478 }
479
480 HASHVALUE CALLBACK AGGREGATE::KeyFilesetName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
481 {
482    return AGGREGATE::KeyFilesetName_HashData (pKey, ((LPFILESET)pObject)->m_szName);
483 }
484
485 HASHVALUE CALLBACK AGGREGATE::KeyFilesetName_HashData (LPHASHLISTKEY pKey, PVOID pData)
486 {
487    return HashString ((LPTSTR)pData);
488 }
489
490
491 BOOL CALLBACK AGGREGATE::KeyFilesetID_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
492 {
493    return !memcmp (&((LPFILESET)pObject)->m_idVolume, (LPVOLUMEID)pData, sizeof(VOLUMEID));
494 }
495
496 HASHVALUE CALLBACK AGGREGATE::KeyFilesetID_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
497 {
498    return AGGREGATE::KeyFilesetID_HashData (pKey, &((LPFILESET)pObject)->m_idVolume);
499 }
500
501 HASHVALUE CALLBACK AGGREGATE::KeyFilesetID_HashData (LPHASHLISTKEY pKey, PVOID pData)
502 {
503    return (HASHVALUE)*((LPVOLUMEID)pData);
504 }
505