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 <afsconfig.h>
15 #include <afs/param.h>
22 #include "svr_general.h"
23 #include "svc_general.h"
24 #include "agg_general.h"
25 #include "set_general.h"
31 * DEFINITIONS ________________________________________________________________
35 #define cREALLOC_DISPATCH 32
39 * VARIABLES __________________________________________________________________
43 static CRITICAL_SECTION csDispatch;
45 static LPNOTIFYCALLBACK Handler = NULL;
53 } *aDispatchList = NULL;
55 static size_t nDispatchList = 0;
58 typedef struct NOTIFYQUEUEITEM
60 struct NOTIFYQUEUEITEM *pNext;
63 } NOTIFYQUEUEITEM, *LPNOTIFYQUEUEITEM;
65 static LPNOTIFYQUEUEITEM pDispatchQueuePop = NULL;
66 static LPNOTIFYQUEUEITEM pDispatchQueuePushAfter = NULL;
70 * PROTOTYPES _________________________________________________________________
74 BOOL CALLBACK DispatchNotification (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
76 void DispatchNotification_AltThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
78 void DispatchNotification_MainThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
82 * ROUTINES ___________________________________________________________________
86 void CreateNotificationDispatch (void)
88 InitializeCriticalSection (&csDispatch);
90 Handler = New2 (NOTIFYCALLBACK,((NOTIFYCALLBACKPROC)DispatchNotification, 0L));
94 void PostNotification (NOTIFYEVENT evt, LPIDENT lpi)
96 NOTIFYCALLBACK::SendNotificationToAll (evt, lpi);
101 * DispatchNotification
103 * This routine is called by our NOTIFYCALLBACK object ("Handler") whenever
104 * anything interesting happens within the library. Note that it's called
105 * on whatever thread the library is using--for that reason, we only handle
106 * some of the requests right away. The rest get posted to our DispatchQueue,
107 * to be popped off by g.hMain's thread.
111 BOOL CALLBACK DispatchNotification (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
113 // Some things must be done right now--for instance, if we've just created
114 // or deleted a SERVER object, we'll load or free that server's preferences
115 // instantly. So, give our on-alternate-thread handler a chance to
116 // look over the notification.
118 DispatchNotification_AltThread (evt, pParams);
120 // Then push this notification onto our DispatchQueue, so that the main
121 // pump will pop off each request in turn and take a look at it.
123 EnterCriticalSection (&csDispatch);
125 LPNOTIFYQUEUEITEM lpnqi = New (NOTIFYQUEUEITEM);
128 memcpy (&lpnqi->Params, pParams, sizeof(NOTIFYPARAMS));
130 if (pDispatchQueuePushAfter != NULL)
131 pDispatchQueuePushAfter->pNext = lpnqi;
132 pDispatchQueuePushAfter = lpnqi;
134 if (pDispatchQueuePop == NULL)
135 pDispatchQueuePop = lpnqi;
137 LeaveCriticalSection (&csDispatch);
143 void DispatchNotification_OnPump (void)
150 EnterCriticalSection (&csDispatch);
152 if (!pDispatchQueuePop)
156 LPNOTIFYQUEUEITEM lpnqiNext = pDispatchQueuePop->pNext;
157 memcpy (&nqi, pDispatchQueuePop, sizeof(NOTIFYQUEUEITEM));
159 if (pDispatchQueuePushAfter == pDispatchQueuePop)
160 pDispatchQueuePushAfter = NULL;
161 Delete (pDispatchQueuePop);
162 pDispatchQueuePop = lpnqiNext;
165 LeaveCriticalSection (&csDispatch);
169 DispatchNotification_MainThread (nqi.evt, &nqi.Params);
175 void DispatchNotification_AltThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
177 LPIDENT lpiEvt = pParams->lpi1;
181 case evtRefreshStatusEnd:
182 if (lpiEvt && (lpiEvt->fIsService() || lpiEvt->fIsAggregate() || lpiEvt->fIsFileset()))
184 Alert_RemoveSecondary (lpiEvt);
185 Alert_Scout_QueueCheckServer (lpiEvt);
187 if (lpiEvt && lpiEvt->fIsServer())
190 if ((lpsp = (LPSERVER_PREF)lpiEvt->GetUserParam()) != NULL)
193 if ((lpServer = lpiEvt->OpenServer()) != NULL)
195 if (lpsp->fIsMonitored != lpServer->fIsMonitored())
197 g.sub = Subsets_SetMonitor (g.sub, lpiEvt, lpServer->fIsMonitored());
198 UpdateDisplay_ServerWindow (FALSE, lpiEvt);
200 lpsp->fIsMonitored = lpServer->fIsMonitored();
205 Alert_Scout_ServerStatus (lpiEvt, pParams->status);
209 // When we get a create request, use the object's Get/SetUserParam()
210 // methods to attach an allocated structure to the thing--the structure
211 // contains the preferences for the server/fileset/etc (for instance,
212 // its warning threshholds, any current scout problems, etc).
213 // On delete requests, free that structure.
216 if (lpiEvt->fIsServer())
218 PVOID pPref = Server_LoadPreferences (lpiEvt);
219 lpiEvt->SetUserParam (pPref);
221 // Should this server be monitored?
223 if (!Subsets_fMonitorServer (g.sub, lpiEvt))
226 if ((lpServer = lpiEvt->OpenServer()) != NULL)
228 lpServer->SetMonitor (FALSE);
233 Alert_Scout_SetOutOfDate (lpiEvt);
235 else if (lpiEvt->fIsService())
237 PVOID pPref = Services_LoadPreferences (lpiEvt);
238 lpiEvt->SetUserParam (pPref);
240 else if (lpiEvt->fIsAggregate())
242 PVOID pPref = Aggregates_LoadPreferences (lpiEvt);
243 lpiEvt->SetUserParam (pPref);
245 else if (lpiEvt->fIsFileset())
247 PVOID pPref = Filesets_LoadPreferences (lpiEvt);
248 lpiEvt->SetUserParam (pPref);
250 if (!lpiEvt->fIsCell())
252 Alert_Scout_QueueCheckServer (lpiEvt);
256 // When we get a create request, use the object's Get/SetUserParam()
257 // methods to attach an allocated structure to the thing--the structure
258 // contains the preferences for the server/fileset/etc (for instance,
259 // its warning threshholds, any current scout problems, etc).
260 // On delete requests, free that structure.
263 if (lpiEvt->fIsServer())
265 PVOID pPref = lpiEvt->GetUserParam();
266 lpiEvt->SetUserParam (0);
267 if (pPref) Delete (pPref);
269 else if (lpiEvt->fIsService() || lpiEvt->fIsAggregate() || lpiEvt->fIsFileset())
271 Alert_RemoveSecondary (lpiEvt);
272 PVOID pPref = lpiEvt->GetUserParam();
273 lpiEvt->SetUserParam (0);
274 if (pPref) Delete (pPref);
281 void DispatchNotification_MainThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
283 LPIDENT lpiEvt = pParams->lpi1;
285 // There are several notifications which are sent when beginning or ending
286 // lengthy operations. These "actions" each get a window indicating
287 // progress, and get added to our ongoing list of actions-in-progress.
289 ActionNotification_MainThread (evt, pParams);
291 // The real reason for this routine is as a dispatcher for the AFSClass's
292 // notifications: various windows throughout the app register themselves
293 // with this dispatcher, and thereby get a message whenever a particular
294 // event of interest to that window happens. Just what notifications
295 // are "of interest" is specified by the window when it registers with
298 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
300 if (!aDispatchList[ iDispatch ].hWnd)
303 BOOL fDispatch = FALSE;
305 // WHEN_CELL_OPENED + NULL -> notify if any new cell is opened
306 // WHEN_OBJECT_CHANGES + NULL -> notify if anything at all changes
307 // WHEN_OBJECT_CHANGES + lpi -> notify if this object changes
308 // WHEN_SVCS(etc)_CHANGE + NULL -> notify if any service at all changes
309 // WHEN_SVCS(etc)_CHANGE + lpi -> notify if any svc on this svr changes
311 switch (aDispatchList[ iDispatch ].when)
313 case WHEN_CELL_OPENED:
314 if (evt == evtCreate && lpiEvt->fIsCell())
318 case WHEN_OBJECT_CHANGES:
319 if ( (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
320 (aDispatchList[ iDispatch ].lpiObject == NULL) )
322 if (evt != evtCreate)
327 case WHEN_SVRS_CHANGE:
331 case evtRefreshServersBegin:
332 case evtRefreshServersEnd:
333 if ( (lpiEvt && lpiEvt->fIsCell()) ||
334 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
335 (aDispatchList[ iDispatch ].lpiObject == NULL) )
337 if (lpiEvt && lpiEvt->fIsCell())
344 case evtRefreshStatusBegin:
345 case evtRefreshStatusEnd:
346 case evtAlertsChanged:
347 if (lpiEvt && lpiEvt->fIsServer())
349 if (aDispatchList[ iDispatch ].lpiObject == NULL)
353 LPIDENT lpiEvtCell = lpiEvt->GetCell();
355 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtCell)
363 case WHEN_SETS_CHANGE:
367 case evtRefreshFilesetsBegin:
368 case evtRefreshFilesetsEnd:
370 LPIDENT lpiEvtSvr = NULL;
371 if (lpiEvt && !lpiEvt->fIsCell())
372 lpiEvtSvr = lpiEvt->GetServer();
374 if ( (lpiEvt && lpiEvt->fIsCell()) ||
375 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
376 (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr) ||
377 (aDispatchList[ iDispatch ].lpiObject == NULL) )
379 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer() || lpiEvt->fIsAggregate()))
387 case evtRefreshStatusBegin:
388 case evtRefreshStatusEnd:
389 case evtAlertsChanged:
390 if (lpiEvt && lpiEvt->fIsFileset())
392 if (aDispatchList[ iDispatch ].lpiObject == NULL)
396 LPIDENT lpiEvtAgg = lpiEvt->GetAggregate();
397 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
399 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtAgg)
401 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
409 case WHEN_AGGS_CHANGE:
412 case evtRefreshAggregatesBegin:
413 case evtRefreshAggregatesEnd:
414 if ( (lpiEvt && lpiEvt->fIsCell()) ||
415 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
416 (aDispatchList[ iDispatch ].lpiObject == NULL) )
418 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer()))
425 case evtRefreshStatusBegin:
426 case evtRefreshStatusEnd:
427 case evtAlertsChanged:
428 if (lpiEvt && lpiEvt->fIsAggregate())
430 if (aDispatchList[ iDispatch ].lpiObject == NULL)
434 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
436 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
444 case WHEN_SVCS_CHANGE:
447 case evtRefreshServicesBegin:
448 case evtRefreshServicesEnd:
449 if ( (lpiEvt && lpiEvt->fIsCell()) ||
450 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
451 (aDispatchList[ iDispatch ].lpiObject == NULL) )
453 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer()))
460 case evtRefreshStatusBegin:
461 case evtRefreshStatusEnd:
462 case evtAlertsChanged:
463 if (lpiEvt && lpiEvt->fIsService())
465 if (aDispatchList[ iDispatch ].lpiObject == NULL)
469 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
471 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
482 LPNOTIFYSTRUCT lpns = New (NOTIFYSTRUCT);
483 lpns->hwndTarget = aDispatchList[ iDispatch ].hWnd;
485 memcpy (&lpns->Params, pParams, sizeof(NOTIFYPARAMS));
486 lpns->Params.lpUser = aDispatchList[ iDispatch ].lpUser;
488 PostMessage (aDispatchList[ iDispatch ].hWnd,
489 WM_NOTIFY_FROM_DISPATCH,
497 void NotifyMe (NOTIFYWHEN when, LPIDENT lpiObject, HWND hWnd, LPARAM lpUser)
499 EnterCriticalSection (&csDispatch);
502 for (iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
504 if ( (aDispatchList[ iDispatch ].hWnd == hWnd) &&
505 (aDispatchList[ iDispatch ].when == when) &&
506 (aDispatchList[ iDispatch ].lpiObject == lpiObject) )
508 LeaveCriticalSection (&csDispatch);
513 for (iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
515 if (!aDispatchList[ iDispatch ].hWnd)
519 if (iDispatch >= nDispatchList)
521 if (!REALLOC (aDispatchList, nDispatchList, 1+iDispatch, cREALLOC_DISPATCH))
523 LeaveCriticalSection (&csDispatch);
528 aDispatchList[ iDispatch ].hWnd = hWnd;
529 aDispatchList[ iDispatch ].when = when;
530 aDispatchList[ iDispatch ].lpiObject = lpiObject;
531 aDispatchList[ iDispatch ].lpUser = lpUser;
533 LeaveCriticalSection (&csDispatch);
537 void DontNotifyMe (NOTIFYWHEN when, LPIDENT lpiObject, HWND hWnd)
539 EnterCriticalSection (&csDispatch);
541 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
543 if ( (aDispatchList[ iDispatch ].hWnd == hWnd) &&
544 (aDispatchList[ iDispatch ].when == when) &&
545 (aDispatchList[ iDispatch ].lpiObject == lpiObject) )
547 aDispatchList[ iDispatch ].hWnd = NULL;
551 LeaveCriticalSection (&csDispatch);
555 void DontNotifyMeEver (HWND hWnd)
557 EnterCriticalSection (&csDispatch);
559 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
561 if (aDispatchList[ iDispatch ].hWnd == hWnd)
563 aDispatchList[ iDispatch ].hWnd = NULL;
567 LeaveCriticalSection (&csDispatch);