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