Standardize License information
[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, NULL);
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       for (LPENUM pEnum = l.pListCallbacks->FindFirst(); pEnum; pEnum = pEnum->FindNext())
81          {
82          LPCALLBACKDATA pData = (LPCALLBACKDATA)( pEnum->GetObject() );
83          pList->Add (pData);
84          l.pListCallbacks->Remove (pData);
85          }
86
87       ResetEvent (l.heCallback);
88       AfsAdmSvr_Leave();
89
90       // Now enumerate that copied list, and issue callbacks for each item.
91       //
92       for (pEnum = pList->FindFirst(); pEnum; pEnum = pEnum->FindNext())
93          {
94          LPCALLBACKDATA pData = (LPCALLBACKDATA)( pEnum->GetObject() );
95
96          try {
97             switch (pData->Type)
98                {
99                case cbtACTION:
100                   AfsAdmSvrCallback_Action (pData->pAction, pData->fFinished);
101                   break;
102                }
103          } catch(...) {
104             ;
105          }
106
107          pList->Remove (pData);
108          AfsAdmSvr_FreeCallbackData (pData);
109          }
110
111       Delete (pList);
112       }
113
114    AfsAdmSvr_Enter();
115    if ((--l.cManagers) == 0)
116       {
117       Delete (l.pListCallbacks);
118       l.pListCallbacks = NULL;
119       CloseHandle (l.heCallback);
120       l.heCallback = NULL;
121       }
122    AfsAdmSvr_Leave();
123 }
124
125
126 void AfsAdmSvr_PostCallback (CALLBACKTYPE Type, BOOL fFinished, LPASACTION pAction, DWORD dwRemoveMe)
127 {
128    AfsAdmSvr_Enter();
129    if (l.pListCallbacks)
130       {
131       LPCALLBACKDATA pData = New (CALLBACKDATA);
132       memset (pData, 0x00, sizeof(CALLBACKDATA));
133       pData->Type = Type;
134       pData->fFinished = fFinished;
135       if (pAction)
136          {
137          pData->pAction = New (ASACTION);
138          memcpy (pData->pAction, pAction, sizeof(ASACTION));
139          }
140
141       l.pListCallbacks->Add (pData);
142       SetEvent (l.heCallback);
143       }
144    AfsAdmSvr_Leave();
145 }
146
147
148 void AfsAdmSvr_PostCallback (CALLBACKTYPE Type, BOOL fFinished, LPASACTION pAction)
149 {
150    AfsAdmSvr_PostCallback (Type, fFinished, pAction, 0);
151 }
152
153
154 void AfsAdmSvr_StopCallbackManagers (void)
155 {
156    AfsAdmSvr_Enter();
157    if (l.cManagers)
158       {
159       l.fStopManagers = TRUE;
160       SetEvent (l.heCallback);
161       }
162    AfsAdmSvr_Leave();
163 }
164