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