2 * Copyright 2000, International Business Machines Corporation and others.
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
14 #include <afs/param.h>
21 #include "svr_window.h"
26 #include "propcache.h"
30 * DEFINITIONS ________________________________________________________________
34 #define cREALLOC_DISPLAYQUEUE 128
36 #define cUPDATE_THREADS_MAX 4
40 * VARIABLES __________________________________________________________________
44 static size_t cDisplayQueueActive
= 0;
45 static size_t cDisplayQueue
= 0;
46 static size_t cUpdateThreadsActive
= 0;
47 static DISPLAYREQUEST
*aDisplayQueue
= NULL
;
48 static CRITICAL_SECTION
*pcsDisplayQueue
= NULL
;
50 static DISPLAYREQUEST drActiveSERVERS
;
51 static DISPLAYREQUEST drActiveSERVICES
;
52 static DISPLAYREQUEST drActiveAGGREGATES
;
53 static DISPLAYREQUEST drActiveFILESETS
;
54 static DISPLAYREQUEST drActiveSERVERWINDOW
;
59 LPIDENT lpiSelectOnDone
;
60 } *aWindowActOnDone
= NULL
;
61 static size_t cWindowActOnDone
= 0;
62 static CRITICAL_SECTION
*pcsWindowActOnDone
= NULL
;
66 * PROTOTYPES _________________________________________________________________
70 DWORD WINAPI
DisplayQueue_ThreadProc (PVOID lp
);
72 BOOL
DisplayQueueFilter (size_t idqVictim
, size_t idqKiller
);
76 * ROUTINES ___________________________________________________________________
80 BOOL CALLBACK
GetItemText (HWND hList
, LPFLN_GETITEMTEXT_PARAMS pfln
, UINT_PTR dwCookie
)
82 LPVIEWINFO lpvi
= (LPVIEWINFO
)dwCookie
;
83 LPIDENT lpi
= (LPIDENT
)(pfln
->item
.lParam
);
86 if (pfln
->item
.icol
< (int)lpvi
->nColsShown
)
88 size_t iCol
= lpvi
->aColumns
[ pfln
->item
.icol
];
90 BOOL fShowServerName
= !Server_GetServerForChild (GetParent(hList
));
94 DISPLAYTARGET dt
= dtSERVERS
;
95 if (lpvi
== &gr
.viewSet
)
97 else if (lpvi
== &gr
.viewSvc
)
99 else if ((lpvi
== &gr
.viewAgg
) || (lpvi
== &gr
.viewAggMove
) || (lpvi
== &gr
.viewAggCreate
) || (lpvi
== &gr
.viewAggRestore
))
101 else if (lpvi
== &gr
.viewRep
)
107 if (lpi
->fIsServer())
108 psz
= Server_GetColumnText (lpi
, (SERVERCOLUMN
)iCol
);
112 if (lpi
->fIsService())
113 psz
= Services_GetColumnText (lpi
, (SERVICECOLUMN
)iCol
, fShowServerName
);
117 if (lpi
->fIsAggregate())
118 psz
= Aggregates_GetColumnText (lpi
, (AGGREGATECOLUMN
)iCol
, fShowServerName
);
122 if (lpi
->fIsFileset())
123 psz
= Filesets_GetColumnText (lpi
, (FILESETCOLUMN
)iCol
, fShowServerName
);
124 else if (lpi
->fIsAggregate() && (pfln
->item
.icol
== setcolNAME
))
125 psz
= Aggregates_GetColumnText (lpi
, aggcolNAME
, FALSE
);
126 else if (lpi
->fIsServer() && (pfln
->item
.icol
== setcolNAME
))
127 psz
= Server_GetColumnText (lpi
, svrcolNAME
);
131 if (lpi
->fIsFileset())
132 psz
= Replicas_GetColumnText (lpi
, (REPLICACOLUMN
)iCol
);
138 lstrcpy (pfln
->item
.pszText
, (psz
) ? psz
: TEXT(""));
143 void Display_AddActOnDone (HWND hWnd
, WORD wAct
, LPIDENT lpiSelectOnDone
)
145 if (pcsWindowActOnDone
== NULL
)
147 pcsWindowActOnDone
= New (CRITICAL_SECTION
);
148 InitializeCriticalSection (pcsWindowActOnDone
);
150 EnterCriticalSection (pcsWindowActOnDone
);
153 for (ii
= 0; ii
< cWindowActOnDone
; ++ii
)
155 if (aWindowActOnDone
[ ii
].hWnd
== hWnd
)
158 if (ii
== cWindowActOnDone
)
160 for (ii
= 0; ii
< cWindowActOnDone
; ++ii
)
162 if (aWindowActOnDone
[ ii
].hWnd
== 0)
166 if (ii
== cWindowActOnDone
)
168 (void)REALLOC( aWindowActOnDone
, cWindowActOnDone
, 1+ii
, 1 );
170 if (ii
< cWindowActOnDone
)
172 aWindowActOnDone
[ ii
].hWnd
= hWnd
;
173 aWindowActOnDone
[ ii
].actOnDone
|= wAct
;
174 if (!aWindowActOnDone
[ ii
].lpiSelectOnDone
)
175 aWindowActOnDone
[ ii
].lpiSelectOnDone
= lpiSelectOnDone
;
178 LeaveCriticalSection (pcsWindowActOnDone
);
182 WORD
Display_FreeActOnDone (HWND hWnd
, LPIDENT
*plpiSelectOnDone
)
186 if (pcsWindowActOnDone
== NULL
)
188 pcsWindowActOnDone
= New (CRITICAL_SECTION
);
189 InitializeCriticalSection (pcsWindowActOnDone
);
191 EnterCriticalSection (pcsWindowActOnDone
);
193 for (size_t ii
= 0; ii
< cWindowActOnDone
; ++ii
)
195 if (aWindowActOnDone
[ ii
].hWnd
== hWnd
)
197 wAct
= aWindowActOnDone
[ ii
].actOnDone
;
198 if (!(*plpiSelectOnDone
))
199 *plpiSelectOnDone
= aWindowActOnDone
[ ii
].lpiSelectOnDone
;
201 aWindowActOnDone
[ ii
].actOnDone
= 0;
202 aWindowActOnDone
[ ii
].hWnd
= 0;
203 aWindowActOnDone
[ ii
].lpiSelectOnDone
= 0;
208 LeaveCriticalSection (pcsWindowActOnDone
);
213 void UpdateDisplay (LPDISPLAYREQUEST pdr
, BOOL fWait
)
215 BOOL fRunBeforeReturning
= FALSE
;
217 if (!ASSERT( pdr
&& pdr
->hChild
))
219 if (pdr
->lpiNotify
&& pdr
->lpiNotify
->fIsCell())
220 pdr
->lpiNotify
= NULL
;
222 if (pcsDisplayQueue
== NULL
)
224 pcsDisplayQueue
= New (CRITICAL_SECTION
);
225 InitializeCriticalSection (pcsDisplayQueue
);
226 memset (&drActiveSERVERS
, 0x00, sizeof(DISPLAYREQUEST
));
227 memset (&drActiveSERVICES
, 0x00, sizeof(DISPLAYREQUEST
));
228 memset (&drActiveAGGREGATES
, 0x00, sizeof(DISPLAYREQUEST
));
229 memset (&drActiveFILESETS
, 0x00, sizeof(DISPLAYREQUEST
));
230 memset (&drActiveSERVERWINDOW
, 0x00, sizeof(DISPLAYREQUEST
));
233 EnterCriticalSection (pcsDisplayQueue
);
236 for (idq
= 0; idq
< cDisplayQueue
; ++idq
)
238 if (!aDisplayQueue
[idq
].hChild
)
241 if (idq
== cDisplayQueue
)
243 (void)REALLOC (aDisplayQueue
, cDisplayQueue
, 1+idq
, cREALLOC_DISPLAYQUEUE
);
245 if (idq
< cDisplayQueue
)
247 memcpy (&aDisplayQueue
[idq
], pdr
, sizeof(DISPLAYREQUEST
));
249 // Filter the display queue--for instance, if there's a request
250 // to update all filesets, we don't need to file a request to
251 // update an individual fileset. Likewise, if we're about to
252 // file a request to update all filesets, nix all existing update-
253 // this-fileset and update-filesets-on-this-server requests.
255 for (size_t idqKiller
= 0; idqKiller
< cDisplayQueue
; ++idqKiller
)
257 if (DisplayQueueFilter (idq
, idqKiller
))
259 aDisplayQueue
[idq
].hChild
= 0;
264 // Hmmmm...even if there is no request in the queue which lets us
265 // kill this request, there may be a request actively being serviced
266 // *right now* which does so. Test for that case too.
268 if (aDisplayQueue
[idq
].hChild
)
270 if (DisplayQueueFilter (idq
, (size_t)-1))
271 aDisplayQueue
[idq
].hChild
= 0;
274 // Did the new request make it through all those tests? If so,
275 // see if we can remove any other entries because of this one.
276 // Then initiate a thread to actually do the work if there isn't one.
278 if (aDisplayQueue
[idq
].hChild
)
280 for (size_t idqVictim
= 0; idqVictim
< cDisplayQueue
; ++idqVictim
)
282 if (DisplayQueueFilter (idqVictim
, idq
))
284 InterlockedDecrementByWindow (aDisplayQueue
[idqVictim
].hChild
);
285 aDisplayQueue
[idqVictim
].hChild
= 0;
286 --cDisplayQueueActive
;
290 if (aDisplayQueue
[idq
].hChild
)
292 InterlockedIncrementByWindow (aDisplayQueue
[ idq
].hChild
);
296 aDisplayQueue
[idq
].hChild
= NULL
; // we'll handle this one.
297 fRunBeforeReturning
= TRUE
; // (remember to do so)
299 else if ((++cDisplayQueueActive
) >= 1)
301 if (cUpdateThreadsActive
< cUPDATE_THREADS_MAX
)
303 ++cUpdateThreadsActive
;
304 StartThread (DisplayQueue_ThreadProc
, 0);
311 LeaveCriticalSection (pcsDisplayQueue
);
313 if (fRunBeforeReturning
)
315 DisplayQueue_ThreadProc (pdr
);
320 DWORD WINAPI
DisplayQueue_ThreadProc (PVOID lp
)
322 LPDISPLAYREQUEST pdr
= (LPDISPLAYREQUEST
)lp
;
323 LPDISPLAYREQUEST pdrActive
= NULL
;
330 EnterCriticalSection (pcsDisplayQueue
);
333 memcpy (&dr
, pdr
, sizeof(DISPLAYREQUEST
));
338 for (idq
= 0; idq
< cDisplayQueue
; ++idq
)
340 if (aDisplayQueue
[idq
].hChild
)
342 memcpy (&dr
, &aDisplayQueue
[idq
], sizeof(DISPLAYREQUEST
));
343 memset (&aDisplayQueue
[idq
], 0x00, sizeof(DISPLAYREQUEST
));
344 --cDisplayQueueActive
;
348 if (idq
== cDisplayQueue
)
350 if (!pdr
) // Are we losing a background thread?
351 --cUpdateThreadsActive
;
352 LeaveCriticalSection (pcsDisplayQueue
);
359 case dtSERVERS
: pdrActive
= &drActiveSERVERS
; break;
360 case dtSERVICES
: pdrActive
= &drActiveSERVICES
; break;
361 case dtAGGREGATES
: pdrActive
= &drActiveAGGREGATES
; break;
362 case dtFILESETS
: pdrActive
= &drActiveFILESETS
; break;
363 case dtSERVERWINDOW
: pdrActive
= &drActiveSERVERWINDOW
; break;
366 memcpy (pdrActive
, &dr
, sizeof(DISPLAYREQUEST
));
368 LeaveCriticalSection (pcsDisplayQueue
);
375 Display_Cell_Internal (&dr
);
379 Display_Servers_Internal (&dr
);
383 Display_Services_Internal (&dr
);
387 Display_Aggregates_Internal (&dr
);
391 Display_Filesets_Internal (&dr
);
395 Display_Replicas_Internal (&dr
);
399 Display_ServerWindow_Internal (&dr
);
403 EnterCriticalSection (pcsDisplayQueue
);
404 LONG dw
= InterlockedDecrementByWindow (dr
.hChild
);
406 memset (pdrActive
, 0x00, sizeof(DISPLAYREQUEST
));
407 LeaveCriticalSection (pcsDisplayQueue
);
411 WORD actOnDone
= dr
.actOnDone
;
412 LPIDENT lpiSelectOnDone
= dr
.lpiToSelect
;
415 actOnDone
|= Display_FreeActOnDone (dr
.hList
, &lpiSelectOnDone
);
418 if ((actOnDone
& ACT_ENDCHANGE
) && dr
.hList
)
421 FL_EndChange (dr
.hList
, (LPARAM
)lpiSelectOnDone
);
422 else // must be a combobox
423 CB_EndChange (dr
.hList
, (LPARAM
)lpiSelectOnDone
);
426 if ((actOnDone
& ACT_UNCOVER
) && dr
.hList
)
427 AfsAppLib_Uncover (dr
.hList
);
429 if (actOnDone
& ACT_SELPREVIEW
)
431 LPIDENT lpiOld
= Server_GetServer (SERVERWINDOW_PREVIEWPANE
);
432 LPIDENT lpiNew
= (LPIDENT
)FL_GetSelectedData (GetDlgItem (g
.hMain
, IDC_SERVERS
));
433 if (lpiOld
!= lpiNew
)
434 Server_SelectServer (SERVERWINDOW_PREVIEWPANE
, lpiNew
, TRUE
);
439 Display_AddActOnDone (dr
.hList
, dr
.actOnDone
, dr
.lpiToSelect
);
444 } while (!lp
); // if given one task to do, stop; otherwise, loop forever
452 BOOL
DisplayQueueFilter (size_t idqVictim
, size_t idqKiller
)
454 if (idqVictim
== idqKiller
)
457 LPDISPLAYREQUEST pdrKiller
= (idqKiller
== (size_t)-1) ? NULL
: &aDisplayQueue
[ idqKiller
];
458 LPDISPLAYREQUEST pdrVictim
= &aDisplayQueue
[ idqVictim
];
460 // if there's currently an operation in progress for this window,
461 // we may have just been asked to filter out a new request based on
462 // what's being done now. {idqKiller==-1} signifies this case.
464 if (pdrKiller
== NULL
) // was idqKiller==-1 etc?
466 switch (pdrVictim
->dt
)
469 pdrKiller
= &drActiveSERVERS
;
473 pdrKiller
= &drActiveSERVICES
;
477 pdrKiller
= &drActiveAGGREGATES
;
481 pdrKiller
= &drActiveFILESETS
;
485 pdrKiller
= &drActiveSERVERWINDOW
;
493 if ( (pdrVictim
->dt
== pdrKiller
->dt
) &&
494 (pdrVictim
->hChild
== pdrKiller
->hChild
) )
496 // only some windows are subject to this filtering.
498 switch (pdrVictim
->dt
)
502 return FALSE
; // don't bother filtering these.
505 return TRUE
; // update svr window twice? why?
508 // if the new request talks about displaying information for a different
509 // server, the user must have selected or deselected a server in the
510 // list. we'll keep the new request.
512 if (pdrKiller
->lpiServer
!= pdrVictim
->lpiServer
)
515 // if pdrKiller is told to update everything, then all other requests
518 if (!pdrKiller
->lpiNotify
|| pdrKiller
->lpiNotify
->fIsCell())
521 // if pdrVictim is told to update everything, then we'll always bow to it.
523 if (!pdrVictim
->lpiNotify
|| pdrVictim
->lpiNotify
->fIsCell())
526 // kill any duplicate request to update a particular object.
528 if (pdrVictim
->lpiNotify
== pdrKiller
->lpiNotify
)
531 // kill any request to update a service or aggregate or fileset,
532 // if updating the entire associated server.
534 if ( (pdrKiller
->lpiNotify
->fIsServer()) &&
535 (pdrVictim
->lpiNotify
->GetServer() == pdrKiller
->lpiNotify
) )
538 // kill any request to update a fileset, if updating the entire
539 // associated aggregate.
541 if ( (pdrKiller
->lpiNotify
->fIsAggregate()) &&
542 (pdrVictim
->lpiNotify
->fIsFileset()) &&
543 (pdrVictim
->lpiNotify
->GetAggregate() == pdrKiller
->lpiNotify
) )
547 // hmmm...guess we need this request after all.
553 void UpdateDisplay_Cell (BOOL fWait
)
556 memset (&dr
, 0x00, sizeof(dr
));
558 dr
.hChild
= GetDlgItem (g
.hMain
, IDC_CELL
);
559 UpdateDisplay (&dr
, fWait
);
562 void UpdateDisplay_Servers (BOOL fWait
, LPIDENT lpiNotify
, ULONG status
)
565 memset (&dr
, 0x00, sizeof(dr
));
567 dr
.hChild
= GetDlgItem (g
.hMain
, IDC_SERVERS
);
568 dr
.lpiNotify
= lpiNotify
;
571 UpdateDisplay (&dr
, fWait
);
574 void UpdateDisplay_Services (BOOL fWait
, HWND hChild
, LPIDENT lpiNotify
, ULONG status
)
577 memset (&dr
, 0x00, sizeof(dr
));
580 dr
.lpiNotify
= lpiNotify
;
583 UpdateDisplay (&dr
, fWait
);
586 void UpdateDisplay_Aggregates (BOOL fWait
, HWND hListOrCombo
, LPIDENT lpiNotify
, ULONG status
, LPIDENT lpiServer
, LPIDENT lpiToSelect
, LPVIEWINFO lpvi
)
589 memset (&dr
, 0x00, sizeof(dr
));
590 dr
.dt
= dtAGGREGATES
;
591 dr
.hList
= hListOrCombo
;
592 dr
.hChild
= GetParent (hListOrCombo
);
593 dr
.lpiNotify
= lpiNotify
;
595 dr
.lpiServer
= (lpiServer
== NULL
) ? Server_GetServerForChild (dr
.hChild
) : lpiServer
;
596 dr
.lpiToSelect
= lpiToSelect
;
598 UpdateDisplay (&dr
, fWait
);
601 void UpdateDisplay_Filesets (BOOL fWait
, HWND hListOrCombo
, LPIDENT lpiNotify
, ULONG status
, LPIDENT lpiServer
, LPIDENT lpiAggregate
, LPIDENT lpiToSelect
)
604 memset (&dr
, 0x00, sizeof(dr
));
606 dr
.hList
= hListOrCombo
;
607 dr
.hChild
= GetParent (hListOrCombo
);
608 dr
.lpiNotify
= lpiNotify
;
610 dr
.lpiServer
= (lpiServer
== NULL
) ? Server_GetServerForChild (dr
.hChild
) : lpiServer
;
611 dr
.lpiAggregate
= lpiAggregate
;
612 dr
.lpiToSelect
= lpiToSelect
;
613 UpdateDisplay (&dr
, fWait
);
616 void UpdateDisplay_Replicas (BOOL fWait
, HWND hList
, LPIDENT lpiRW
, LPIDENT lpiRO
)
619 memset (&dr
, 0x00, sizeof(dr
));
621 dr
.hChild
= GetParent (hList
);
623 dr
.lpiNotify
= lpiRW
;
624 dr
.lpiToSelect
= lpiRO
;
626 UpdateDisplay (&dr
, fWait
);
630 void UpdateDisplay_ServerWindow (BOOL fWait
, LPIDENT lpiServer
)
632 // First, if there is a dedicated server window out there, update it.
635 if ((hServer
= PropCache_Search (pcSERVER
, lpiServer
)) != NULL
)
638 memset (&dr
, 0x00, sizeof(dr
));
639 dr
.dt
= dtSERVERWINDOW
;
641 dr
.lpiServer
= lpiServer
;
643 UpdateDisplay (&dr
, fWait
);
646 // Second, if the preview pane is visible and showing this server,
651 LPIDENT lpiPreview
= Server_GetServer (g
.hMain
);
652 if ((lpiPreview
== NULL
) || (lpiPreview
== lpiServer
))
655 memset (&dr
, 0x00, sizeof(dr
));
656 dr
.dt
= dtSERVERWINDOW
;
658 dr
.lpiServer
= lpiPreview
;
660 UpdateDisplay (&dr
, fWait
);
666 void UpdateDisplay_SetIconView (BOOL fWait
, HWND hDialog
, LPICONVIEW piv
, ICONVIEW ivNew
)
670 if (piv
== &gr
.ivSvr
)
672 UpdateDisplay_Servers (fWait
, NULL
, 0);
676 LPIDENT lpi
= Server_GetServer (hDialog
);
677 UpdateDisplay_ServerWindow (fWait
, lpi
);
682 ICONVIEW
Display_GetServerIconView (void)
686 if (gr
.fPreview
&& !gr
.fVert
)
687 lvs
= gr
.diHorz
.viewSvr
.lvsView
;
689 lvs
= gr
.diVert
.viewSvr
.lvsView
;
692 if (lvs
!= FLS_VIEW_LIST
)
699 BOOL
HandleColumnNotify (HWND hDlg
, UINT msg
, WPARAM wp
, LPARAM lp
, LPVIEWINFO pvi
)
701 if (msg
== WM_NOTIFY
)
703 HWND hList
= GetDlgItem (hDlg
, (int)((LPNMHDR
)lp
)->idFrom
);
704 if (fIsFastList (hList
))
706 switch (((LPNMHDR
)lp
)->code
)
708 case FLN_COLUMNRESIZE
:
709 FL_StoreView (hList
, pvi
);
712 case FLN_COLUMNCLICK
:
713 LPFLN_COLUMNCLICK_PARAMS pp
= (LPFLN_COLUMNCLICK_PARAMS
)lp
;
717 FastList_GetSortStyle (hList
, &iCol
, &fRev
);
719 if (iCol
== pp
->icol
)
720 FastList_SetSortStyle (hList
, iCol
, !fRev
);
722 FastList_SetSortStyle (hList
, pp
->icol
, FALSE
);
724 FL_StoreView (hList
, pvi
);