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