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