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