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