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_general.h"
22 #include "svc_general.h"
23 #include "agg_general.h"
24 #include "set_general.h"
30 * DEFINITIONS ________________________________________________________________
34 #define cREALLOC_DISPATCH 32
38 * VARIABLES __________________________________________________________________
42 static CRITICAL_SECTION csDispatch;
44 static LPNOTIFYCALLBACK Handler = NULL;
52 } *aDispatchList = NULL;
54 static size_t nDispatchList = 0;
57 typedef struct NOTIFYQUEUEITEM
59 struct NOTIFYQUEUEITEM *pNext;
62 } NOTIFYQUEUEITEM, *LPNOTIFYQUEUEITEM;
64 static LPNOTIFYQUEUEITEM pDispatchQueuePop = NULL;
65 static LPNOTIFYQUEUEITEM pDispatchQueuePushAfter = NULL;
69 * PROTOTYPES _________________________________________________________________
73 BOOL CALLBACK DispatchNotification (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
75 void DispatchNotification_AltThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
77 void DispatchNotification_MainThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
81 * ROUTINES ___________________________________________________________________
85 void CreateNotificationDispatch (void)
87 InitializeCriticalSection (&csDispatch);
89 Handler = New2 (NOTIFYCALLBACK,((NOTIFYCALLBACKPROC)DispatchNotification, 0L));
93 void PostNotification (NOTIFYEVENT evt, LPIDENT lpi)
95 NOTIFYCALLBACK::SendNotificationToAll (evt, lpi);
100 * DispatchNotification
102 * This routine is called by our NOTIFYCALLBACK object ("Handler") whenever
103 * anything interesting happens within the library. Note that it's called
104 * on whatever thread the library is using--for that reason, we only handle
105 * some of the requests right away. The rest get posted to our DispatchQueue,
106 * to be popped off by g.hMain's thread.
110 BOOL CALLBACK DispatchNotification (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
112 // Some things must be done right now--for instance, if we've just created
113 // or deleted a SERVER object, we'll load or free that server's preferences
114 // instantly. So, give our on-alternate-thread handler a chance to
115 // look over the notification.
117 DispatchNotification_AltThread (evt, pParams);
119 // Then push this notification onto our DispatchQueue, so that the main
120 // pump will pop off each request in turn and take a look at it.
122 EnterCriticalSection (&csDispatch);
124 LPNOTIFYQUEUEITEM lpnqi = New (NOTIFYQUEUEITEM);
127 memcpy (&lpnqi->Params, pParams, sizeof(NOTIFYPARAMS));
129 if (pDispatchQueuePushAfter != NULL)
130 pDispatchQueuePushAfter->pNext = lpnqi;
131 pDispatchQueuePushAfter = lpnqi;
133 if (pDispatchQueuePop == NULL)
134 pDispatchQueuePop = lpnqi;
136 LeaveCriticalSection (&csDispatch);
142 void DispatchNotification_OnPump (void)
149 EnterCriticalSection (&csDispatch);
151 if (!pDispatchQueuePop)
155 LPNOTIFYQUEUEITEM lpnqiNext = pDispatchQueuePop->pNext;
156 memcpy (&nqi, pDispatchQueuePop, sizeof(NOTIFYQUEUEITEM));
158 if (pDispatchQueuePushAfter == pDispatchQueuePop)
159 pDispatchQueuePushAfter = NULL;
160 Delete (pDispatchQueuePop);
161 pDispatchQueuePop = lpnqiNext;
164 LeaveCriticalSection (&csDispatch);
168 DispatchNotification_MainThread (nqi.evt, &nqi.Params);
174 void DispatchNotification_AltThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
176 LPIDENT lpiEvt = pParams->lpi1;
180 case evtRefreshStatusEnd:
181 if (lpiEvt && (lpiEvt->fIsService() || lpiEvt->fIsAggregate() || lpiEvt->fIsFileset()))
183 Alert_RemoveSecondary (lpiEvt);
184 Alert_Scout_QueueCheckServer (lpiEvt);
186 if (lpiEvt && lpiEvt->fIsServer())
189 if ((lpsp = (LPSERVER_PREF)lpiEvt->GetUserParam()) != NULL)
192 if ((lpServer = lpiEvt->OpenServer()) != NULL)
194 if (lpsp->fIsMonitored != lpServer->fIsMonitored())
196 g.sub = Subsets_SetMonitor (g.sub, lpiEvt, lpServer->fIsMonitored());
197 UpdateDisplay_ServerWindow (FALSE, lpiEvt);
199 lpsp->fIsMonitored = lpServer->fIsMonitored();
204 Alert_Scout_ServerStatus (lpiEvt, pParams->status);
208 // When we get a create request, use the object's Get/SetUserParam()
209 // methods to attach an allocated structure to the thing--the structure
210 // contains the preferences for the server/fileset/etc (for instance,
211 // its warning threshholds, any current scout problems, etc).
212 // On delete requests, free that structure.
215 if (lpiEvt->fIsServer())
217 PVOID pPref = Server_LoadPreferences (lpiEvt);
218 lpiEvt->SetUserParam (pPref);
220 // Should this server be monitored?
222 if (!Subsets_fMonitorServer (g.sub, lpiEvt))
225 if ((lpServer = lpiEvt->OpenServer()) != NULL)
227 lpServer->SetMonitor (FALSE);
232 Alert_Scout_SetOutOfDate (lpiEvt);
234 else if (lpiEvt->fIsService())
236 PVOID pPref = Services_LoadPreferences (lpiEvt);
237 lpiEvt->SetUserParam (pPref);
239 else if (lpiEvt->fIsAggregate())
241 PVOID pPref = Aggregates_LoadPreferences (lpiEvt);
242 lpiEvt->SetUserParam (pPref);
244 else if (lpiEvt->fIsFileset())
246 PVOID pPref = Filesets_LoadPreferences (lpiEvt);
247 lpiEvt->SetUserParam (pPref);
249 if (!lpiEvt->fIsCell())
251 Alert_Scout_QueueCheckServer (lpiEvt);
255 // When we get a create request, use the object's Get/SetUserParam()
256 // methods to attach an allocated structure to the thing--the structure
257 // contains the preferences for the server/fileset/etc (for instance,
258 // its warning threshholds, any current scout problems, etc).
259 // On delete requests, free that structure.
262 if (lpiEvt->fIsServer())
264 PVOID pPref = lpiEvt->GetUserParam();
265 lpiEvt->SetUserParam (0);
266 if (pPref) Delete (pPref);
268 else if (lpiEvt->fIsService() || lpiEvt->fIsAggregate() || lpiEvt->fIsFileset())
270 Alert_RemoveSecondary (lpiEvt);
271 PVOID pPref = lpiEvt->GetUserParam();
272 lpiEvt->SetUserParam (0);
273 if (pPref) Delete (pPref);
280 void DispatchNotification_MainThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
282 LPIDENT lpiEvt = pParams->lpi1;
284 // There are several notifications which are sent when beginning or ending
285 // lengthy operations. These "actions" each get a window indicating
286 // progress, and get added to our ongoing list of actions-in-progress.
288 ActionNotification_MainThread (evt, pParams);
290 // The real reason for this routine is as a dispatcher for the AFSClass's
291 // notifications: various windows throughout the app register themselves
292 // with this dispatcher, and thereby get a message whenever a particular
293 // event of interest to that window happens. Just what notifications
294 // are "of interest" is specified by the window when it registers with
297 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
299 if (!aDispatchList[ iDispatch ].hWnd)
302 BOOL fDispatch = FALSE;
304 // WHEN_CELL_OPENED + NULL -> notify if any new cell is opened
305 // WHEN_OBJECT_CHANGES + NULL -> notify if anything at all changes
306 // WHEN_OBJECT_CHANGES + lpi -> notify if this object changes
307 // WHEN_SVCS(etc)_CHANGE + NULL -> notify if any service at all changes
308 // WHEN_SVCS(etc)_CHANGE + lpi -> notify if any svc on this svr changes
310 switch (aDispatchList[ iDispatch ].when)
312 case WHEN_CELL_OPENED:
313 if (evt == evtCreate && lpiEvt->fIsCell())
317 case WHEN_OBJECT_CHANGES:
318 if ( (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
319 (aDispatchList[ iDispatch ].lpiObject == NULL) )
321 if (evt != evtCreate)
326 case WHEN_SVRS_CHANGE:
330 case evtRefreshServersBegin:
331 case evtRefreshServersEnd:
332 if ( (lpiEvt && lpiEvt->fIsCell()) ||
333 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
334 (aDispatchList[ iDispatch ].lpiObject == NULL) )
336 if (lpiEvt && lpiEvt->fIsCell())
343 case evtRefreshStatusBegin:
344 case evtRefreshStatusEnd:
345 case evtAlertsChanged:
346 if (lpiEvt && lpiEvt->fIsServer())
348 if (aDispatchList[ iDispatch ].lpiObject == NULL)
352 LPIDENT lpiEvtCell = lpiEvt->GetCell();
354 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtCell)
362 case WHEN_SETS_CHANGE:
366 case evtRefreshFilesetsBegin:
367 case evtRefreshFilesetsEnd:
369 LPIDENT lpiEvtSvr = NULL;
370 if (lpiEvt && !lpiEvt->fIsCell())
371 lpiEvtSvr = lpiEvt->GetServer();
373 if ( (lpiEvt && lpiEvt->fIsCell()) ||
374 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
375 (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr) ||
376 (aDispatchList[ iDispatch ].lpiObject == NULL) )
378 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer() || lpiEvt->fIsAggregate()))
386 case evtRefreshStatusBegin:
387 case evtRefreshStatusEnd:
388 case evtAlertsChanged:
389 if (lpiEvt && lpiEvt->fIsFileset())
391 if (aDispatchList[ iDispatch ].lpiObject == NULL)
395 LPIDENT lpiEvtAgg = lpiEvt->GetAggregate();
396 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
398 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtAgg)
400 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
408 case WHEN_AGGS_CHANGE:
411 case evtRefreshAggregatesBegin:
412 case evtRefreshAggregatesEnd:
413 if ( (lpiEvt && lpiEvt->fIsCell()) ||
414 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
415 (aDispatchList[ iDispatch ].lpiObject == NULL) )
417 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer()))
424 case evtRefreshStatusBegin:
425 case evtRefreshStatusEnd:
426 case evtAlertsChanged:
427 if (lpiEvt && lpiEvt->fIsAggregate())
429 if (aDispatchList[ iDispatch ].lpiObject == NULL)
433 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
435 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
443 case WHEN_SVCS_CHANGE:
446 case evtRefreshServicesBegin:
447 case evtRefreshServicesEnd:
448 if ( (lpiEvt && lpiEvt->fIsCell()) ||
449 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
450 (aDispatchList[ iDispatch ].lpiObject == NULL) )
452 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer()))
459 case evtRefreshStatusBegin:
460 case evtRefreshStatusEnd:
461 case evtAlertsChanged:
462 if (lpiEvt && lpiEvt->fIsService())
464 if (aDispatchList[ iDispatch ].lpiObject == NULL)
468 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
470 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
481 LPNOTIFYSTRUCT lpns = New (NOTIFYSTRUCT);
482 lpns->hwndTarget = aDispatchList[ iDispatch ].hWnd;
484 memcpy (&lpns->Params, pParams, sizeof(NOTIFYPARAMS));
485 lpns->Params.lpUser = aDispatchList[ iDispatch ].lpUser;
487 PostMessage (aDispatchList[ iDispatch ].hWnd,
488 WM_NOTIFY_FROM_DISPATCH,
496 void NotifyMe (NOTIFYWHEN when, LPIDENT lpiObject, HWND hWnd, LPARAM lpUser)
498 EnterCriticalSection (&csDispatch);
501 for (iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
503 if ( (aDispatchList[ iDispatch ].hWnd == hWnd) &&
504 (aDispatchList[ iDispatch ].when == when) &&
505 (aDispatchList[ iDispatch ].lpiObject == lpiObject) )
507 LeaveCriticalSection (&csDispatch);
512 for (iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
514 if (!aDispatchList[ iDispatch ].hWnd)
518 if (iDispatch >= nDispatchList)
520 if (!REALLOC (aDispatchList, nDispatchList, 1+iDispatch, cREALLOC_DISPATCH))
522 LeaveCriticalSection (&csDispatch);
527 aDispatchList[ iDispatch ].hWnd = hWnd;
528 aDispatchList[ iDispatch ].when = when;
529 aDispatchList[ iDispatch ].lpiObject = lpiObject;
530 aDispatchList[ iDispatch ].lpUser = lpUser;
532 LeaveCriticalSection (&csDispatch);
536 void DontNotifyMe (NOTIFYWHEN when, LPIDENT lpiObject, HWND hWnd)
538 EnterCriticalSection (&csDispatch);
540 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
542 if ( (aDispatchList[ iDispatch ].hWnd == hWnd) &&
543 (aDispatchList[ iDispatch ].when == when) &&
544 (aDispatchList[ iDispatch ].lpiObject == lpiObject) )
546 aDispatchList[ iDispatch ].hWnd = NULL;
550 LeaveCriticalSection (&csDispatch);
554 void DontNotifyMeEver (HWND hWnd)
556 EnterCriticalSection (&csDispatch);
558 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
560 if (aDispatchList[ iDispatch ].hWnd == hWnd)
562 aDispatchList[ iDispatch ].hWnd = NULL;
566 LeaveCriticalSection (&csDispatch);