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
11 #include <afs/param.h>
18 #include "svr_general.h"
19 #include "svc_general.h"
20 #include "agg_general.h"
21 #include "set_general.h"
27 * DEFINITIONS ________________________________________________________________
31 #define cREALLOC_DISPATCH 32
35 * VARIABLES __________________________________________________________________
39 static CRITICAL_SECTION csDispatch;
41 static LPNOTIFYCALLBACK Handler = NULL;
49 } *aDispatchList = NULL;
51 static size_t nDispatchList = 0;
54 typedef struct NOTIFYQUEUEITEM
56 struct NOTIFYQUEUEITEM *pNext;
59 } NOTIFYQUEUEITEM, *LPNOTIFYQUEUEITEM;
61 static LPNOTIFYQUEUEITEM pDispatchQueuePop = NULL;
62 static LPNOTIFYQUEUEITEM pDispatchQueuePushAfter = NULL;
66 * PROTOTYPES _________________________________________________________________
70 BOOL CALLBACK DispatchNotification (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
72 void DispatchNotification_AltThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
74 void DispatchNotification_MainThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams);
78 * ROUTINES ___________________________________________________________________
82 void CreateNotificationDispatch (void)
84 InitializeCriticalSection (&csDispatch);
86 Handler = New2 (NOTIFYCALLBACK,((NOTIFYCALLBACKPROC)DispatchNotification, 0L));
90 void PostNotification (NOTIFYEVENT evt, LPIDENT lpi)
92 NOTIFYCALLBACK::SendNotificationToAll (evt, lpi);
97 * DispatchNotification
99 * This routine is called by our NOTIFYCALLBACK object ("Handler") whenever
100 * anything interesting happens within the library. Note that it's called
101 * on whatever thread the library is using--for that reason, we only handle
102 * some of the requests right away. The rest get posted to our DispatchQueue,
103 * to be popped off by g.hMain's thread.
107 BOOL CALLBACK DispatchNotification (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
109 // Some things must be done right now--for instance, if we've just created
110 // or deleted a SERVER object, we'll load or free that server's preferences
111 // instantly. So, give our on-alternate-thread handler a chance to
112 // look over the notification.
114 DispatchNotification_AltThread (evt, pParams);
116 // Then push this notification onto our DispatchQueue, so that the main
117 // pump will pop off each request in turn and take a look at it.
119 EnterCriticalSection (&csDispatch);
121 LPNOTIFYQUEUEITEM lpnqi = New (NOTIFYQUEUEITEM);
124 memcpy (&lpnqi->Params, pParams, sizeof(NOTIFYPARAMS));
126 if (pDispatchQueuePushAfter != NULL)
127 pDispatchQueuePushAfter->pNext = lpnqi;
128 pDispatchQueuePushAfter = lpnqi;
130 if (pDispatchQueuePop == NULL)
131 pDispatchQueuePop = lpnqi;
133 LeaveCriticalSection (&csDispatch);
139 void DispatchNotification_OnPump (void)
146 EnterCriticalSection (&csDispatch);
148 if (!pDispatchQueuePop)
152 LPNOTIFYQUEUEITEM lpnqiNext = pDispatchQueuePop->pNext;
153 memcpy (&nqi, pDispatchQueuePop, sizeof(NOTIFYQUEUEITEM));
155 if (pDispatchQueuePushAfter == pDispatchQueuePop)
156 pDispatchQueuePushAfter = NULL;
157 Delete (pDispatchQueuePop);
158 pDispatchQueuePop = lpnqiNext;
161 LeaveCriticalSection (&csDispatch);
165 DispatchNotification_MainThread (nqi.evt, &nqi.Params);
171 void DispatchNotification_AltThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
173 LPIDENT lpiEvt = pParams->lpi1;
177 case evtRefreshStatusEnd:
178 if (lpiEvt && (lpiEvt->fIsService() || lpiEvt->fIsAggregate() || lpiEvt->fIsFileset()))
180 Alert_RemoveSecondary (lpiEvt);
181 Alert_Scout_QueueCheckServer (lpiEvt);
183 if (lpiEvt && lpiEvt->fIsServer())
186 if ((lpsp = (LPSERVER_PREF)lpiEvt->GetUserParam()) != NULL)
189 if ((lpServer = lpiEvt->OpenServer()) != NULL)
191 if (lpsp->fIsMonitored != lpServer->fIsMonitored())
193 g.sub = Subsets_SetMonitor (g.sub, lpiEvt, lpServer->fIsMonitored());
194 UpdateDisplay_ServerWindow (FALSE, lpiEvt);
196 lpsp->fIsMonitored = lpServer->fIsMonitored();
201 Alert_Scout_ServerStatus (lpiEvt, pParams->status);
205 // When we get a create request, use the object's Get/SetUserParam()
206 // methods to attach an allocated structure to the thing--the structure
207 // contains the preferences for the server/fileset/etc (for instance,
208 // its warning threshholds, any current scout problems, etc).
209 // On delete requests, free that structure.
212 if (lpiEvt->fIsServer())
214 PVOID pPref = Server_LoadPreferences (lpiEvt);
215 lpiEvt->SetUserParam (pPref);
217 // Should this server be monitored?
219 if (!Subsets_fMonitorServer (g.sub, lpiEvt))
222 if ((lpServer = lpiEvt->OpenServer()) != NULL)
224 lpServer->SetMonitor (FALSE);
229 Alert_Scout_SetOutOfDate (lpiEvt);
231 else if (lpiEvt->fIsService())
233 PVOID pPref = Services_LoadPreferences (lpiEvt);
234 lpiEvt->SetUserParam (pPref);
236 else if (lpiEvt->fIsAggregate())
238 PVOID pPref = Aggregates_LoadPreferences (lpiEvt);
239 lpiEvt->SetUserParam (pPref);
241 else if (lpiEvt->fIsFileset())
243 PVOID pPref = Filesets_LoadPreferences (lpiEvt);
244 lpiEvt->SetUserParam (pPref);
246 if (!lpiEvt->fIsCell())
248 Alert_Scout_QueueCheckServer (lpiEvt);
252 // When we get a create request, use the object's Get/SetUserParam()
253 // methods to attach an allocated structure to the thing--the structure
254 // contains the preferences for the server/fileset/etc (for instance,
255 // its warning threshholds, any current scout problems, etc).
256 // On delete requests, free that structure.
259 if (lpiEvt->fIsServer())
261 PVOID pPref = lpiEvt->GetUserParam();
262 lpiEvt->SetUserParam (0);
263 if (pPref) Delete (pPref);
265 else if (lpiEvt->fIsService() || lpiEvt->fIsAggregate() || lpiEvt->fIsFileset())
267 Alert_RemoveSecondary (lpiEvt);
268 PVOID pPref = lpiEvt->GetUserParam();
269 lpiEvt->SetUserParam (0);
270 if (pPref) Delete (pPref);
277 void DispatchNotification_MainThread (NOTIFYEVENT evt, PNOTIFYPARAMS pParams)
279 LPIDENT lpiEvt = pParams->lpi1;
281 // There are several notifications which are sent when beginning or ending
282 // lengthy operations. These "actions" each get a window indicating
283 // progress, and get added to our ongoing list of actions-in-progress.
285 ActionNotification_MainThread (evt, pParams);
287 // The real reason for this routine is as a dispatcher for the AFSClass's
288 // notifications: various windows throughout the app register themselves
289 // with this dispatcher, and thereby get a message whenever a particular
290 // event of interest to that window happens. Just what notifications
291 // are "of interest" is specified by the window when it registers with
294 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
296 if (!aDispatchList[ iDispatch ].hWnd)
299 BOOL fDispatch = FALSE;
301 // WHEN_CELL_OPENED + NULL -> notify if any new cell is opened
302 // WHEN_OBJECT_CHANGES + NULL -> notify if anything at all changes
303 // WHEN_OBJECT_CHANGES + lpi -> notify if this object changes
304 // WHEN_SVCS(etc)_CHANGE + NULL -> notify if any service at all changes
305 // WHEN_SVCS(etc)_CHANGE + lpi -> notify if any svc on this svr changes
307 switch (aDispatchList[ iDispatch ].when)
309 case WHEN_CELL_OPENED:
310 if (evt == evtCreate && lpiEvt->fIsCell())
314 case WHEN_OBJECT_CHANGES:
315 if ( (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
316 (aDispatchList[ iDispatch ].lpiObject == NULL) )
318 if (evt != evtCreate)
323 case WHEN_SVRS_CHANGE:
327 case evtRefreshServersBegin:
328 case evtRefreshServersEnd:
329 if ( (lpiEvt && lpiEvt->fIsCell()) ||
330 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
331 (aDispatchList[ iDispatch ].lpiObject == NULL) )
333 if (lpiEvt && lpiEvt->fIsCell())
340 case evtRefreshStatusBegin:
341 case evtRefreshStatusEnd:
342 case evtAlertsChanged:
343 if (lpiEvt && lpiEvt->fIsServer())
345 if (aDispatchList[ iDispatch ].lpiObject == NULL)
349 LPIDENT lpiEvtCell = lpiEvt->GetCell();
351 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtCell)
359 case WHEN_SETS_CHANGE:
363 case evtRefreshFilesetsBegin:
364 case evtRefreshFilesetsEnd:
366 LPIDENT lpiEvtSvr = NULL;
367 if (lpiEvt && !lpiEvt->fIsCell())
368 lpiEvtSvr = lpiEvt->GetServer();
370 if ( (lpiEvt && lpiEvt->fIsCell()) ||
371 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
372 (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr) ||
373 (aDispatchList[ iDispatch ].lpiObject == NULL) )
375 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer() || lpiEvt->fIsAggregate()))
383 case evtRefreshStatusBegin:
384 case evtRefreshStatusEnd:
385 case evtAlertsChanged:
386 if (lpiEvt && lpiEvt->fIsFileset())
388 if (aDispatchList[ iDispatch ].lpiObject == NULL)
392 LPIDENT lpiEvtAgg = lpiEvt->GetAggregate();
393 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
395 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtAgg)
397 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
405 case WHEN_AGGS_CHANGE:
408 case evtRefreshAggregatesBegin:
409 case evtRefreshAggregatesEnd:
410 if ( (lpiEvt && lpiEvt->fIsCell()) ||
411 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
412 (aDispatchList[ iDispatch ].lpiObject == NULL) )
414 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer()))
421 case evtRefreshStatusBegin:
422 case evtRefreshStatusEnd:
423 case evtAlertsChanged:
424 if (lpiEvt && lpiEvt->fIsAggregate())
426 if (aDispatchList[ iDispatch ].lpiObject == NULL)
430 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
432 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
440 case WHEN_SVCS_CHANGE:
443 case evtRefreshServicesBegin:
444 case evtRefreshServicesEnd:
445 if ( (lpiEvt && lpiEvt->fIsCell()) ||
446 (aDispatchList[ iDispatch ].lpiObject == lpiEvt) ||
447 (aDispatchList[ iDispatch ].lpiObject == NULL) )
449 if (lpiEvt && (lpiEvt->fIsCell() || lpiEvt->fIsServer()))
456 case evtRefreshStatusBegin:
457 case evtRefreshStatusEnd:
458 case evtAlertsChanged:
459 if (lpiEvt && lpiEvt->fIsService())
461 if (aDispatchList[ iDispatch ].lpiObject == NULL)
465 LPIDENT lpiEvtSvr = lpiEvt->GetServer();
467 if (aDispatchList[ iDispatch ].lpiObject == lpiEvtSvr)
478 LPNOTIFYSTRUCT lpns = New (NOTIFYSTRUCT);
479 lpns->hwndTarget = aDispatchList[ iDispatch ].hWnd;
481 memcpy (&lpns->Params, pParams, sizeof(NOTIFYPARAMS));
482 lpns->Params.lpUser = aDispatchList[ iDispatch ].lpUser;
484 PostMessage (aDispatchList[ iDispatch ].hWnd,
485 WM_NOTIFY_FROM_DISPATCH,
493 void NotifyMe (NOTIFYWHEN when, LPIDENT lpiObject, HWND hWnd, LPARAM lpUser)
495 EnterCriticalSection (&csDispatch);
497 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
499 if ( (aDispatchList[ iDispatch ].hWnd == hWnd) &&
500 (aDispatchList[ iDispatch ].when == when) &&
501 (aDispatchList[ iDispatch ].lpiObject == lpiObject) )
503 LeaveCriticalSection (&csDispatch);
508 for (iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
510 if (!aDispatchList[ iDispatch ].hWnd)
514 if (iDispatch >= nDispatchList)
516 if (!REALLOC (aDispatchList, nDispatchList, 1+iDispatch, cREALLOC_DISPATCH))
518 LeaveCriticalSection (&csDispatch);
523 aDispatchList[ iDispatch ].hWnd = hWnd;
524 aDispatchList[ iDispatch ].when = when;
525 aDispatchList[ iDispatch ].lpiObject = lpiObject;
526 aDispatchList[ iDispatch ].lpUser = lpUser;
528 LeaveCriticalSection (&csDispatch);
532 void DontNotifyMe (NOTIFYWHEN when, LPIDENT lpiObject, HWND hWnd)
534 EnterCriticalSection (&csDispatch);
536 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
538 if ( (aDispatchList[ iDispatch ].hWnd == hWnd) &&
539 (aDispatchList[ iDispatch ].when == when) &&
540 (aDispatchList[ iDispatch ].lpiObject == lpiObject) )
542 aDispatchList[ iDispatch ].hWnd = NULL;
546 LeaveCriticalSection (&csDispatch);
550 void DontNotifyMeEver (HWND hWnd)
552 EnterCriticalSection (&csDispatch);
554 for (size_t iDispatch = 0; iDispatch < nDispatchList; ++iDispatch)
556 if (aDispatchList[ iDispatch ].hWnd == hWnd)
558 aDispatchList[ iDispatch ].hWnd = NULL;
562 LeaveCriticalSection (&csDispatch);