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