rx: Remove RX_CALL_BUSY
[openafs.git] / src / WINNT / afssvrcfg / partitions_page.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 /*
11  * INCLUDES _________________________________________________________________
12  *
13  */
14 #include <winsock2.h>
15 #include <ws2tcpip.h>
16
17 extern "C" {
18 #include <afsconfig.h>
19 #include <afs/param.h>
20 #include <afs/stds.h>
21 #include <roken.h>
22 }
23
24 #include "afscfg.h"
25 #include "resource.h"
26 #include "create_partition_dlg.h"
27 #include "partition_utils.h"
28 #include "salvage_results_dlg.h"
29 extern "C" {
30 #include <afs\afs_vosAdmin.h>
31 #include <afs\afs_clientAdmin.h>
32 }
33
34
35 // TODO:  Add context menu to fastlist
36
37
38 /*
39  * DEFINITIONS _________________________________________________________________
40  *
41  */
42 #define MAX_PARTITIONS  26
43
44 static HWND hDlg = 0;
45 static HWND hPartitionList = 0;
46 static HLISTITEM hSelectedItem;
47
48 static TCHAR szYes[cchRESOURCE];
49 static TCHAR szNo[cchRESOURCE];
50
51 static const UINT DISK_DRIVE_IMAGE = 0;
52 //static const UINT DISABLED_DISK_DRIVE_IMAGE = 1;
53 //static const UINT DISK_DRIVE_WITH_WARNING_IMAGE = 2;
54
55 // Remember the config state of the FS so we can detect when it changes.
56 // When it changes we must redisplay the partition info.
57 static CONFIG_STATE configFS;
58
59
60
61 /*
62  * PROTOTYPES _________________________________________________________________
63  *
64  */
65 BOOL ShowSalvageDlg(HWND hParent, LPCTSTR pszPartitionName);
66
67 static void OnCreatePartitions();
68 static void OnInitDialog(HWND hwndDlg);
69 static void SetupListCols();
70 static void AddColumn(int nWidth, LPCTSTR pszTitle, DWORD dwFlags = FLCF_JUSTIFY_LEFT);
71 static void ShowPartitions();
72 cfg_partitionEntry_t *GetPartitionTableFromRegistry(int& cEntries);
73 static vos_partitionEntry_t *GetPartitionTableFromVos(int &nNumPartitions);
74 static void OnListSelection(LPFLN_ITEMSELECT_PARAMS pItemParms);
75 static void SetupImageLists();
76 static void OnRemove();
77 static BOOL CheckShowPartitions();
78 static void OnSalvage();
79 static void CheckEnableSalvage();
80
81
82 /*
83  * EXPORTED FUNCTIONS _________________________________________________________________
84  *
85  */
86 /*
87  * Dialog Proc _________________________________________________________________
88  *
89  */
90 BOOL CALLBACK PartitionsPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
91 {
92     if (AfsAppLib_HandleHelp(IDD_PARTITIONS_PAGE, hwndDlg, uMsg, wParam, lParam))
93         return TRUE;
94
95     switch (uMsg) {
96     case WM_INITDIALOG:
97         OnInitDialog(hwndDlg);
98         break;
99
100     case WM_COMMAND:
101         switch (LOWORD(wParam)) {
102         case IDINIT:
103             CheckShowPartitions();
104             break;
105
106         case IDC_CREATE_PARTITIONS:
107             OnCreatePartitions();
108             break;
109
110         case IDC_REMOVE:
111             OnRemove();
112             break;
113
114         case IDC_SALVAGE:
115             OnSalvage();
116             break;
117         }
118         break;
119
120     case WM_NOTIFY:
121         if ((((LPNMHDR)lParam)->code) == FLN_ITEMSELECT)
122             OnListSelection((LPFLN_ITEMSELECT_PARAMS)lParam);
123         break;
124     }
125
126     return FALSE;
127 }
128
129 void UpdatePartitionList()
130 {
131     ShowPartitions();
132     CheckEnableSalvage();
133 }
134
135
136 /*
137  * STATIC FUNCTIONS _________________________________________________________________
138  *
139  */
140
141 /*
142  * Event Handler Functions _________________________________________________________________
143  *
144  */
145 static void OnInitDialog(HWND hwndDlg)
146 {
147     hDlg = hwndDlg;
148
149 //  PropSheet_CancelToClose(GetParent(hDlg));
150
151     hSelectedItem = 0;
152
153     hPartitionList = GetDlgItem(hDlg, IDC_PARTITION_LIST);
154     _ASSERTE(hPartitionList);
155
156     SetupImageLists();
157
158     GetString(szYes, IDS_YES);
159     GetString(szNo, IDS_NO);
160
161     SetupListCols();
162
163     configFS = g_CfgData.configFS;
164
165     ShowPartitions();
166
167     CheckEnableSalvage();
168 }
169
170 static void OnCreatePartitions()
171 {
172     if (CreatePartition(hDlg))
173         ShowPartitions();
174 }
175
176 static void OnListSelection(LPFLN_ITEMSELECT_PARAMS pItemParms)
177 {
178     ASSERT(pItemParms);
179
180     hSelectedItem = pItemParms->hItem;
181
182     ENABLE_STATE es = pItemParms->hItem ? ES_ENABLE : ES_DISABLE;
183
184     SetEnable(hDlg, IDC_REMOVE, es);
185     SetEnable(hDlg, IDC_REMOVE_MSG, es);
186 }
187
188 static void OnRemove()
189 {
190     ASSERT(hSelectedItem);
191     ASSERT(g_hServer);
192
193     afs_status_t nStatus;
194
195     BOOL bExported = (BOOL)FastList_GetItemParam(hPartitionList, hSelectedItem);
196     if (bExported) {
197         MsgBox(hDlg, IDS_CANT_DELETE_EXPORTED_PARTITION, GetAppTitleID(), MB_OK | MB_ICONSTOP);
198         return;
199     }
200
201     LPCTSTR pszPartitionName = FastList_GetItemText(hPartitionList, hSelectedItem, 0);
202     ASSERT(pszPartitionName);
203
204     int nResult = Message(MB_ICONQUESTION | MB_YESNO, GetAppTitleID(), IDS_DELETE_PARTITION_PROMPT, TEXT("%s"), pszPartitionName);
205     if (nResult == IDNO)
206         return;
207
208     g_LogFile.Write("Removing partition '%s'.\r\n", (char *)S2A(pszPartitionName));
209     nResult = cfg_HostPartitionTableRemoveEntry(g_hServer, S2A(pszPartitionName), &nStatus);
210     if (!nResult) {
211         ShowError(hDlg, nStatus, IDS_REMOVE_PARTITION_ERROR);
212         return;
213     }
214
215     FastList_RemoveItem(hPartitionList, hSelectedItem);
216
217     CheckEnableSalvage();
218 }
219
220 static void OnSalvage()
221 {
222     // Can't salvage if the file server is not configured
223     if (!Configured(g_CfgData.configFS)) {
224         ShowError(hDlg, 0, IDS_CANT_SALVAGE_WHEN_FS_NOT_CONFIGURED);
225         return;
226     }
227
228     LPCTSTR pszPartitionName = TEXT("");
229
230     if (hSelectedItem) {
231         pszPartitionName = FastList_GetItemText(hPartitionList, hSelectedItem, 0);
232         ASSERT(pszPartitionName);
233     }
234
235     if (!ShowSalvageDlg(hDlg, pszPartitionName))
236         return;
237
238     ShowSalvageResults(hDlg);
239
240     // Since a salvage was performed, there may be partitions exported that were
241     // not exported before the salvage.  Salvage may stop and restart the file
242     // server, which will pick up the previously unexported partitions.  We will
243     // update our partition list in case this has happened.
244     UpdatePartitionList();
245 }
246
247
248 /*
249  * Utility Functions _________________________________________________________________
250  *
251  */
252 static BOOL CheckShowPartitions()
253 {
254     if (configFS != g_CfgData.configFS) {
255         configFS = g_CfgData.configFS;
256         UpdatePartitionList();
257         return TRUE;
258     }
259
260     return FALSE;
261 }
262
263 static void SetupImageLists()
264 {
265     HIMAGELIST hiList = ImageList_Create(16, 16, TRUE, 1, 1);
266
267     AfsAppLib_AddToImageList(hiList, IDI_AGGREGATE, FALSE);
268     AfsAppLib_AddToImageList(hiList, IDI_DISABLED_DISK_DRIVE, FALSE);
269
270     FastList_SetImageLists(hPartitionList, hiList, 0);
271 }
272
273 static void AddColumn(int nWidth, LPCTSTR pszTitle, DWORD dwFlags)
274 {
275     static int nCol = 1;
276     FASTLISTCOLUMN col;
277
278     col.dwFlags = dwFlags;
279     col.cxWidth = nWidth;
280     lstrcpy(col.szText, pszTitle);
281
282     FastList_SetColumn(hPartitionList, nCol++, &col);
283 }
284
285 static void SetupListCols()
286 {
287     TCHAR szMsg[cchRESOURCE];
288
289     AddColumn(75, GetResString(IDS_NAME, szMsg));
290     AddColumn(55, GetResString(IDS_DRIVE, szMsg));
291     AddColumn(60, GetResString(IDS_EXPORTED, szMsg));
292     AddColumn(75, GetResString(IDS_TOTAL, szMsg), FLCF_JUSTIFY_RIGHT);
293     AddColumn(75, GetResString(IDS_FREE, szMsg), FLCF_JUSTIFY_RIGHT);
294 }
295
296 cfg_partitionEntry_t *GetPartitionTableFromRegistry(int& cEntries)
297 {
298     afs_status_t nStatus;
299
300     // Read the parition table out of the registry
301     int nResult = ReadPartitionTable(&nStatus);
302     if (!nResult) {
303         ShowError(hDlg, nStatus, IDS_READ_PARTITIONS_ERROR);
304         return 0;
305     }
306
307     return GetPartitionTable(cEntries);
308 }
309
310 static vos_partitionEntry_t *GetPartitionTableFromVos(int &nNumPartitions)
311 {
312     ASSERT(g_hCell);
313     ASSERT(g_CfgData.szHostname[0]);
314
315     nNumPartitions = 0;
316
317     if (g_CfgData.configFS != CS_ALREADY_CONFIGURED)
318         return 0;
319
320     static vos_partitionEntry_t aPartitions[MAX_PARTITIONS];
321     afs_status_t nStatus, nIgnore;
322     void *hServer = 0;
323     int nNumParts = 0;
324
325     // Open this server
326     g_LogFile.Write("Opening server %s.\r\n", GetHostnameA());
327     int nResult = vos_ServerOpen(g_hCell, GetHostnameA(), &hServer, &nStatus);
328     if (nResult) {
329
330         // Read the partition info
331         g_LogFile.Write("Reading paritition information for this server.\r\n");
332         void *iterID;
333
334         nResult = vos_PartitionGetBegin(g_hCell, hServer, 0, &iterID, &nStatus);
335         if (nResult) {
336             while (nNumParts < MAX_PARTITIONS) {
337                 nResult = vos_PartitionGetNext(iterID, &aPartitions[nNumParts], &nStatus);
338                 if (!nResult) {
339                     if (nStatus == ADMITERATORDONE) {
340                         nResult = 1;
341                         nStatus = 0;
342                     }
343                     break;
344                 }
345
346                 nNumParts++;
347             }
348             vos_PartitionGetDone(iterID, &nIgnore);
349         }
350         vos_ServerClose(hServer, &nIgnore);
351     }
352
353     if (!nResult) {
354         ShowError(hDlg, nStatus, IDS_GET_PARTITION_LIST_ERROR);
355         return 0;
356     }
357
358     nNumPartitions = nNumParts;
359
360     return aPartitions;
361 }
362
363 // Convert a disk space value in Kbytes into a string
364 static LPTSTR DiskSpaceToString(int nSpace)
365 {
366     const float oneMB = 1024;   // in K bytes
367     const double oneGB = oneMB * 1024;
368     const double oneTB = oneGB * 1024;
369
370     static TCHAR szSpace[64];
371     double space;
372     LPTSTR pszUnits;
373
374     space = nSpace;
375
376     if (space >= oneTB) {
377         space /= oneTB;
378         pszUnits = TEXT(" TB");
379     } else if (space >= oneGB) {
380         space /= oneGB;
381         pszUnits = TEXT(" GB");
382     } else if (space >= oneMB) {
383         space /= oneMB;
384         pszUnits = TEXT(" MB");
385     } else
386         pszUnits = TEXT(" KB");
387
388     int nNumDecimals = 0;
389     if (space - double(int(space)) > 0)
390         nNumDecimals = 2;
391
392     _stprintf(szSpace, TEXT("%3.*f%s"), nNumDecimals, space, pszUnits);
393
394     return szSpace;
395 }
396
397 static void ShowPartitions()
398 {
399     FastList_RemoveAll(hPartitionList);
400
401     int cRegParts = 0, cVosParts = 0;
402
403     // If we got nothing from the registry, then leave the list empty
404     cfg_partitionEntry_t *pRegParts = GetPartitionTableFromRegistry(cRegParts);
405     if (!pRegParts)
406         return;
407
408     // If we failed to get vos info, then only show the registry info
409     vos_partitionEntry_t *pVosParts = GetPartitionTableFromVos(cVosParts);
410     if (!pVosParts)
411         cVosParts = 0;
412
413     // We have two partition tables, one from the registry and one from the vos
414     // library.  The one from the vos library tells us the partitions that are
415     // currently exported.  The one from the registry tells us the partitions
416     // that will be exported after the file server restarts.  The registry list
417     // should always be at least as big as the vos list.  The vos list can be
418     // smaller if one of the disks could not be exported.  To add a new partition,
419     // an entry must be added to the registry table and then the file server must
420     // be restarted.  To remove an entry, the partition must not be exported (due
421     // to an error) or the file server must not be running, in which case nothing
422     // will be exported.
423
424     // To display the partitions to the user, we use the list from the registry,
425     // looking up each of its entries in the vos list to see if it is exported,
426     // and if it is, to get its size info.
427
428
429     for (int nCurRegPart = 0; nCurRegPart < cRegParts; nCurRegPart++) {
430         LPTSTR pPartNameAsString = AnsiToString(pRegParts[nCurRegPart].partitionName);
431
432         // Show the partition in the list
433         FASTLISTADDITEM ai = { 0, DISK_DRIVE_IMAGE, IMAGE_NOIMAGE, pPartNameAsString, 0, 0 };
434         HLISTITEM hItem = FastList_AddItem(hPartitionList, &ai);
435
436         FreeString(pPartNameAsString);
437
438         FastList_SetItemText(hPartitionList, hItem, 1, pRegParts[nCurRegPart].deviceName);
439
440         // For the rest of the info we need to know if this guy is exported.
441         // Look him up in the vos table.
442         BOOL bExported = FALSE;
443         int nTotalSpace = 0;
444         int nFreeSpace = 0;
445
446         for (int nCurVosPart = 0; nCurVosPart < cVosParts; nCurVosPart++) {
447             if (stricmp(pVosParts[nCurVosPart].name, pRegParts[nCurRegPart].partitionName) == 0) {
448                 bExported = TRUE;
449                 nTotalSpace = pVosParts[nCurVosPart].totalSpace;
450                 nFreeSpace = pVosParts[nCurVosPart].totalFreeSpace;
451                 break;
452             }
453         }
454
455         FastList_SetItemText(hPartitionList, hItem, 2, bExported ? szYes : szNo);
456         FastList_SetItemText(hPartitionList, hItem, 3, bExported ? DiskSpaceToString(nTotalSpace) : TEXT(""));
457         FastList_SetItemText(hPartitionList, hItem, 4, bExported ? DiskSpaceToString(nFreeSpace) : TEXT(""));
458
459         // Set the item param to indicate that this partition is exported or not
460         FastList_SetItemParam(hPartitionList, hItem, bExported);
461     }
462 }
463
464 static void CheckEnableSalvage()
465 {
466     ENABLE_STATE es = (FastList_GetItemCount(hPartitionList) > 0) ? ES_ENABLE : ES_DISABLE;
467
468     SetEnable(hDlg, IDC_SALVAGE, es);
469     SetEnable(hDlg, IDC_SALVAGE_MSG, es);
470 }
471