windows-vs2005b2-20050706
[openafs.git] / src / WINNT / afsadmsvr / TaAfsAdmSvrCallback.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 #include <afs/param.h>
11 #include <afs/stds.h>
12
13 #include "TaAfsAdmSvrInternal.h"
14
15 /*
16  * VARIABLES __________________________________________________________________
17  *
18  */
19
20 typedef struct
21    {
22    CALLBACKTYPE Type;
23    BOOL fFinished;
24    LPASACTION pAction;
25    } CALLBACKDATA, *LPCALLBACKDATA;
26
27 static struct
28    {
29    HANDLE heCallback;
30    LPHASHLIST pListCallbacks;
31    BOOL fStopManagers;
32    size_t cManagers;
33    } l;
34
35
36 /*
37  * CALLBACKS __________________________________________________________________
38  *
39  */
40
41 void AfsAdmSvr_FreeCallbackData (LPCALLBACKDATA pData)
42 {
43    if (pData)
44       {
45       if (pData->pAction)
46          Delete (pData->pAction);
47       Delete (pData);
48       }
49 }
50
51
52 void AfsAdmSvr_CallbackManager (void)
53 {
54    AfsAdmSvr_Enter();
55    if ((++l.cManagers) == 1)
56       {
57       l.heCallback = CreateEvent (NULL, TRUE, FALSE, TEXT("AfsAdmSvr_CallbackManager Event"));
58       l.pListCallbacks = New (HASHLIST);
59       }
60    AfsAdmSvr_Leave();
61
62    for (;;)
63       {
64       WaitForSingleObjectEx (l.heCallback, INFINITE, FALSE);
65
66       if (l.fStopManagers)
67          break;
68
69       // We must ensure that we don't block the server's operations because
70       // a callback doesn't go through; since other operations may need
71       // access to the l.pListCallbacks structure in order to queue new
72       // callbacks, we can't leave it locked by issuing callbacks while
73       // enumerating it. Instead we'll copy the list into a local copy,
74       // clear it, and enumerate that local copy--other threads can then
75       // continue to add new requests to l.pListCallbacks.
76       //
77       AfsAdmSvr_Enter();
78
79       LPHASHLIST pList = New (HASHLIST);
80       LPENUM pEnum;
81       for (pEnum = l.pListCallbacks->FindFirst(); pEnum; pEnum = pEnum->FindNext())
82          {
83          LPCALLBACKDATA pData = (LPCALLBACKDATA)( pEnum->GetObject() );
84          pList->Add (pData);
85          l.pListCallbacks->Remove (pData);
86          }
87
88       ResetEvent (l.heCallback);
89       AfsAdmSvr_Leave();
90
91       // Now enumerate that copied list, and issue callbacks for each item.
92       //
93       for (pEnum = pList->FindFirst(); pEnum; pEnum = pEnum->FindNext())
94          {
95          LPCALLBACKDATA pData = (LPCALLBACKDATA)( pEnum->GetObject() );
96
97          try {
98             switch (pData->Type)
99                {
100                case cbtACTION:
101                   AfsAdmSvrCallback_Action (pData->pAction, pData->fFinished);
102                   break;
103                }
104          } catch(...) {
105             ;
106          }
107
108          pList->Remove (pData);
109          AfsAdmSvr_FreeCallbackData (pData);
110          }
111
112       Delete (pList);
113       }
114
115    AfsAdmSvr_Enter();
116    if ((--l.cManagers) == 0)
117       {
118       Delete (l.pListCallbacks);
119       l.pListCallbacks = NULL;
120       CloseHandle (l.heCallback);
121       l.heCallback = NULL;
122       }
123    AfsAdmSvr_Leave();
124 }
125
126
127 void AfsAdmSvr_PostCallback (CALLBACKTYPE Type, BOOL fFinished, LPASACTION pAction, DWORD dwRemoveMe)
128 {
129    AfsAdmSvr_Enter();
130    if (l.pListCallbacks)
131       {
132       LPCALLBACKDATA pData = New (CALLBACKDATA);
133       memset (pData, 0x00, sizeof(CALLBACKDATA));
134       pData->Type = Type;
135       pData->fFinished = fFinished;
136       if (pAction)
137          {
138          pData->pAction = New (ASACTION);
139          memcpy (pData->pAction, pAction, sizeof(ASACTION));
140          }
141
142       l.pListCallbacks->Add (pData);
143       SetEvent (l.heCallback);
144       }
145    AfsAdmSvr_Leave();
146 }
147
148
149 void AfsAdmSvr_PostCallback (CALLBACKTYPE Type, BOOL fFinished, LPASACTION pAction)
150 {
151    AfsAdmSvr_PostCallback (Type, fFinished, pAction, 0);
152 }
153
154
155 void AfsAdmSvr_StopCallbackManagers (void)
156 {
157    AfsAdmSvr_Enter();
158    if (l.cManagers)
159       {
160       l.fStopManagers = TRUE;
161       SetEvent (l.heCallback);
162       }
163    AfsAdmSvr_Leave();
164 }
165