c4cb5d7e1ecf6b929cd1b1a24acf4bfd401f99d8
[openafs.git] / src / WINNT / afsclass / c_set.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 FILESET::FILESET (LPAGGREGATE lpAggregateParent, LPVOLUMEID pvid, LPTSTR pszName)
44 {
45    m_lpiAggregate = lpAggregateParent->GetIdentifier();
46    m_lpiServer = lpAggregateParent->m_lpiServer;
47    m_lpiCell = lpAggregateParent->m_lpiCell;
48    m_lpiThis = NULL;
49    m_lpiThisRW = NULL;
50    m_lpiThisBK = NULL;
51    m_idVolume = *pvid;
52
53    lstrcpy (m_szName, pszName);
54    m_wGhost = 0;
55
56    m_fStatusOutOfDate = TRUE;
57    memset (&m_fs, 0x00, sizeof(FILESETSTATUS));
58    m_fs.id = *pvid;
59
60    lpAggregateParent->InvalidateAllocation();
61 }
62
63
64 FILESET::~FILESET (void)
65 {
66    if (m_lpiThis)
67       m_lpiThis->m_cRef --;
68 }
69
70
71 void FILESET::SendDeleteNotifications (void)
72 {
73    NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
74 }
75
76
77 void FILESET::Close (void)
78 {
79    AfsClass_Leave();
80 }
81
82
83 LPIDENT FILESET::GetIdentifier (void)
84 {
85    if (m_lpiThis == NULL)
86       {
87       TCHAR szCell[ cchNAME ];
88       TCHAR szServer[ cchNAME ];
89       TCHAR szAggregate[ cchNAME ];
90       m_lpiAggregate->GetCellName (szCell);
91       m_lpiAggregate->GetLongServerName (szServer);
92       m_lpiAggregate->GetAggregateName (szAggregate);
93
94       // Finding the identifier for a fileset is a little tricky, because
95       // (a) a fileset identifier's unique "key" includes the fileset's
96       // aggregate, and (b) filesets can move around in the cell.
97       //
98       // We'll search through our list of IDENTs and see if we can find
99       // an old IDENT object that refers to this fileset; if we can't find
100       // one, we'll create a new one. To make sure we have an accurate match,
101       // we'll require that the IDENT we find match all of the following
102       // criteria:
103       //    1- The identifier must point to a fileset
104       //    2- The identifier must have the same fileset ID as this FILESET
105       //    3- The identifier's cRef must be zero (i.e., there should
106       //       not be another FILESET object out there which thinks *it*
107       //       uses that IDENT)
108       //    4- The identifier must (obviously) point to the cell in which
109       //       this FILESET object resides
110       //    5- If this is a fileset replica, the IDENT must be on the same
111       //       aggregate as this fileset
112       //
113       // Note that the IDENT class maintains its list of IDENTs in a
114       // HASHLIST that a key placed on volume IDs. We'll use that key
115       // to speed up our search enormously.
116       //
117       BOOL fRequireSameAggregate = ProbablyReplica();
118
119       for (LPENUM pEnum = IDENT::x_lkFilesetID->FindFirst (&m_idVolume); pEnum; pEnum = pEnum->FindNext())
120          {
121
122          // Only volumes which match this fileset ID will get here.
123          //
124          LPIDENT lpiFind = (LPIDENT)( pEnum->GetObject() );
125
126          if (lpiFind->m_iType != itFILESET)
127             continue;
128          if (lpiFind->m_cRef != 0)
129             continue;
130          if (lstrcmpi (szCell, lpiFind->m_szCell))
131             continue;
132          if (fRequireSameAggregate)
133             {
134             if (lstrcmpi (szServer, lpiFind->m_szServer))
135                continue;
136             if (lstrcmpi (szAggregate, lpiFind->m_szAggregate))
137                continue;
138             }
139
140          // Found a match! Update the IDENT's name and location,
141          // to ensure it jives with reality... for instance, if
142          // a fileset has been moved, we'll need to fix the
143          // server and aggregate names. Since this affects one
144          // of the keys in the IDENT class's hashlist, update that list.
145          //
146          Delete (pEnum);
147          m_lpiThis = lpiFind;
148          lstrcpy (m_lpiThis->m_szServer, szServer);
149          lstrcpy (m_lpiThis->m_szAggregate, szAggregate);
150          lstrcpy (m_lpiThis->m_szFileset, m_szName);
151          m_lpiThis->Update();
152          break;
153          }
154
155       if (m_lpiThis == NULL)
156          m_lpiThis = New2 (IDENT,(this));  // Create a new IDENT if necessary.
157
158       m_lpiThis->m_cRef ++;
159       }
160
161    return m_lpiThis;
162 }
163
164
165 LPIDENT FILESET::GetReadWriteIdentifier (ULONG *pStatus)
166 {
167    if (m_lpiThisRW == NULL)
168       {
169       if (RefreshStatus (TRUE, pStatus))
170          {
171          if ((m_lpiThisRW = IDENT::FindIdent (this, &m_fs.idReadWrite)) == NULL)
172             {
173             if (pStatus)
174                *pStatus = ERROR_FILE_NOT_FOUND;
175             }
176          }
177       }
178
179    return m_lpiThisRW;
180 }
181
182
183 LPIDENT FILESET::GetReadOnlyIdentifier (LPIDENT lpiParent, ULONG *pStatus)
184 {
185    LPIDENT lpiRO = NULL;
186
187    if (RefreshStatus (TRUE, pStatus))
188       {
189       if (lpiParent == NULL)
190          lpiParent = m_lpiCell;
191
192       if (m_fs.idReplica)
193          {
194          lpiRO = IDENT::FindFileset (lpiParent, &m_fs.idReplica);
195          }
196       else
197          {
198          TCHAR szNameRO[ cchNAME ];
199          lstrcpy (szNameRO, m_szName);
200
201          LPCTSTR pszExtension;
202          if ((pszExtension = lstrrchr (szNameRO, TEXT('.'))) == NULL)
203             lstrcat (szNameRO, TEXT(".readonly"));
204          else if (lstrcmpi (pszExtension, TEXT(".readonly")) && lstrcmpi (pszExtension, TEXT(".backup")))
205             lstrcat (szNameRO, TEXT(".readonly"));
206
207          lpiRO = IDENT::FindFileset (lpiParent, szNameRO);
208          }
209
210       if (lpiRO == NULL)
211          {
212          if (pStatus)
213             *pStatus = ERROR_FILE_NOT_FOUND;
214          }
215       }
216
217    return lpiRO;
218 }
219
220
221 LPIDENT FILESET::GetCloneIdentifier (ULONG *pStatus)
222 {
223    if (m_lpiThisBK == NULL)
224       {
225       if (RefreshStatus (TRUE, pStatus))
226          {
227          if ((m_lpiThisBK = IDENT::FindIdent (this, &m_fs.idClone)) == NULL)
228             {
229             if (pStatus)
230                *pStatus = ERROR_FILE_NOT_FOUND;
231             }
232          }
233       }
234
235    return m_lpiThisBK;
236 }
237
238
239 void FILESET::Invalidate (void)
240 {
241    if (!m_fStatusOutOfDate)
242       {
243       if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
244          m_fStatusOutOfDate = TRUE;
245
246       LPAGGREGATE lpAggregate;
247       if ((lpAggregate = m_lpiAggregate->OpenAggregate()) != NULL)
248          {
249          lpAggregate->InvalidateAllocation();
250          lpAggregate->Close();
251          }
252
253       NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
254       }
255 }
256
257
258 BOOL FILESET::RefreshStatus (BOOL fNotify, ULONG *pStatus)
259 {
260    BOOL rc = TRUE;
261    DWORD status = 0;
262
263    if (m_fStatusOutOfDate && (m_wGhost & GHOST_HAS_SERVER_ENTRY))
264       {
265       m_fStatusOutOfDate = FALSE;
266
267       if (fNotify)
268          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
269
270       LPSERVER lpServer;
271       if ((lpServer = OpenServer (&status)) == NULL)
272          rc = FALSE;
273       else
274          {
275          PVOID hCell;
276          PVOID hVOS;
277          if ((hVOS = lpServer->OpenVosObject (&hCell, &status)) == NULL)
278             rc = FALSE;
279          else
280             {
281             WORKERPACKET wp;
282             wp.wpVosVolumeGet.hCell = hCell;
283             wp.wpVosVolumeGet.hServer = hVOS;
284             wp.wpVosVolumeGet.idPartition = NO_PARTITION;
285             wp.wpVosVolumeGet.idVolume = m_idVolume;
286
287             LPAGGREGATE lpAggregate;
288             if ((lpAggregate = m_lpiAggregate->OpenAggregate()) != NULL)
289                {
290                wp.wpVosVolumeGet.idPartition = lpAggregate->GetID();
291                lpAggregate->Close();
292                }
293
294             if (!Worker_DoTask (wtaskVosVolumeGet, &wp, &status))
295                rc = FALSE;
296             else
297                {
298                SetStatusFromVOS (&wp.wpVosVolumeGet.Data);
299
300                if ((lpAggregate = m_lpiAggregate->OpenAggregate()) != NULL)
301                   {
302                   lpAggregate->InvalidateAllocation();
303                   lpAggregate->Close();
304                   }
305                }
306
307             lpServer->CloseVosObject();
308             }
309
310          lpServer->Close();
311          }
312
313       if (fNotify)
314          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
315       }
316
317    if (pStatus && !rc)
318       *pStatus = status;
319    return TRUE;
320 }
321
322
323 void FILESET::GetName (LPTSTR pszName)
324 {
325    lstrcpy (pszName, m_szName);
326 }
327
328
329 void FILESET::GetID (LPVOLUMEID pvid)
330 {
331    *pvid = m_idVolume;
332 }
333
334
335 LPCELL FILESET::OpenCell (ULONG *pStatus)
336 {
337    return m_lpiCell->OpenCell (pStatus);
338 }
339
340
341 LPSERVER FILESET::OpenServer (ULONG *pStatus)
342 {
343    return m_lpiServer->OpenServer (pStatus);
344 }
345
346
347 LPAGGREGATE FILESET::OpenAggregate (ULONG *pStatus)
348 {
349    return m_lpiAggregate->OpenAggregate (pStatus);
350 }
351
352
353 BOOL FILESET::GetStatus (LPFILESETSTATUS lpfs, BOOL fNotify, ULONG *pStatus)
354 {
355    if (!RefreshStatus (fNotify, pStatus))
356       return FALSE;
357
358    memcpy (lpfs, &m_fs, sizeof(FILESETSTATUS));
359    return TRUE;
360 }
361
362
363 short FILESET::GetGhostStatus (void)
364 {
365    return m_wGhost;
366 }
367
368
369 PVOID FILESET::GetUserParam (void)
370 {
371    return GetIdentifier()->GetUserParam();
372 }
373
374
375 void FILESET::SetUserParam (PVOID pUserNew)
376 {
377    GetIdentifier()->SetUserParam (pUserNew);
378 }
379
380
381 BOOL FILESET::ProbablyReplica (void)
382 {
383    LPCTSTR pszExtension;
384
385    if ((pszExtension = lstrrchr (m_szName, TEXT('.'))) == NULL)
386       return FALSE;
387
388    if (lstrcmpi (pszExtension, TEXT(".readonly")))
389       return FALSE;
390
391    return TRUE;
392 }
393
394
395 void FILESET::SetStatusFromVOS (PVOID lp)
396 {
397    vos_volumeEntry_p pEntry = (vos_volumeEntry_p)lp;
398
399    m_fs.id = m_idVolume;
400    m_fs.idReadWrite = pEntry->readWriteId;
401    m_fs.idReplica = pEntry->readOnlyId;
402    m_fs.idClone = pEntry->backupId;
403    AfsClass_UnixTimeToSystemTime (&m_fs.timeCreation,   pEntry->creationDate);
404    AfsClass_UnixTimeToSystemTime (&m_fs.timeLastUpdate, pEntry->lastUpdateDate);
405    AfsClass_UnixTimeToSystemTime (&m_fs.timeLastAccess, pEntry->lastAccessDate);
406    AfsClass_UnixTimeToSystemTime (&m_fs.timeLastBackup, pEntry->lastBackupDate);
407    AfsClass_UnixTimeToSystemTime (&m_fs.timeCopyCreation, pEntry->copyCreationDate);
408    m_fs.nFiles = pEntry->fileCount;
409    m_fs.ckQuota = pEntry->maxQuota;
410    m_fs.ckUsed = pEntry->currentSize;
411 \r
412    switch (pEntry->type)\r
413       {\r
414       case VOS_BACKUP_VOLUME:\r
415          m_fs.Type = ftCLONE;\r
416          m_fs.idClone = pEntry->id;\r
417          break;\r
418       case VOS_READ_ONLY_VOLUME:\r
419          m_fs.Type = ftREPLICA;\r
420          m_fs.idReplica = pEntry->id;\r
421          break;\r
422       case VOS_READ_WRITE_VOLUME:\r
423          m_fs.Type = ftREADWRITE;\r
424          m_fs.idReadWrite = pEntry->id;\r
425          break;\r
426       }
427
428    m_fs.State &= fsMASK_VLDB;
429
430    switch (pEntry->status)
431       {
432       case VOS_SALVAGE:
433          m_fs.State |= fsSALVAGE;
434          break;
435       case VOS_NO_VNODE:
436          m_fs.State |= fsNO_VNODE;
437          break;
438       case VOS_NO_VOL:
439          m_fs.State |= fsNO_VOL;
440          break;
441       case VOS_NO_SERVICE:
442          m_fs.State |= fsNO_SERVICE;
443          break;
444       case VOS_OFFLINE:
445          m_fs.State |= fsOFFLINE;
446          break;
447       case VOS_DISK_FULL:
448          m_fs.State |= fsDISK_FULL;
449          break;
450       case VOS_OVER_QUOTA:
451          m_fs.State |= fsOVER_QUOTA;
452          break;
453       case VOS_BUSY:
454          m_fs.State |= fsBUSY;
455          break;
456       case VOS_MOVED:
457          m_fs.State |= fsMOVED;
458          break;
459       }
460 }
461