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