windows-hookdll-20050419
[openafs.git] / src / WINNT / afsd / cm_daemon.c
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 #ifndef DJGPP
14 #include <windows.h>
15 #include <winsock2.h>
16 #else
17 #include <netdb.h>
18 #endif /* !DJGPP */
19 #include <stdlib.h>
20 #include <malloc.h>
21 #include <string.h>
22
23 #include <rx/rx.h>
24 #include <rx/rx_prototypes.h>
25
26 #include "afsd.h"
27
28 long cm_daemonCheckInterval = 30;
29 long cm_daemonTokenCheckInterval = 180;
30
31 osi_rwlock_t cm_daemonLock;
32
33 long cm_bkgQueueCount;          /* # of queued requests */
34
35 int cm_bkgWaitingForCount;      /* true if someone's waiting for cm_bkgQueueCount to drop */
36
37 cm_bkgRequest_t *cm_bkgListp;           /* first elt in the list of requests */
38 cm_bkgRequest_t *cm_bkgListEndp;        /* last elt in the list of requests */
39
40 static int daemon_ShutdownFlag = 0;
41
42 void cm_BkgDaemon(long parm)
43 {
44     cm_bkgRequest_t *rp;
45
46     rx_StartClientThread();
47
48     lock_ObtainWrite(&cm_daemonLock);
49     while (daemon_ShutdownFlag == 0) {
50         if (!cm_bkgListEndp) {
51             osi_SleepW((long) &cm_bkgListp, &cm_daemonLock);
52             lock_ObtainWrite(&cm_daemonLock);
53             continue;
54         }
55                 
56         /* we found a request */
57         rp = cm_bkgListEndp;
58         cm_bkgListEndp = (cm_bkgRequest_t *) osi_QPrev(&rp->q);
59         osi_QRemove((osi_queue_t **) &cm_bkgListp, &rp->q);
60         osi_assert(cm_bkgQueueCount-- > 0);
61         lock_ReleaseWrite(&cm_daemonLock);
62
63         (*rp->procp)(rp->scp, rp->p1, rp->p2, rp->p3, rp->p4, rp->userp);
64                 
65         cm_ReleaseUser(rp->userp);
66         cm_ReleaseSCache(rp->scp);
67         free(rp);
68
69         lock_ObtainWrite(&cm_daemonLock);
70     }
71     lock_ReleaseWrite(&cm_daemonLock);
72 }
73
74 void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, long p1, long p2, long p3, long p4,
75         cm_user_t *userp)
76 {
77     cm_bkgRequest_t *rp;
78         
79     rp = malloc(sizeof(*rp));
80     memset(rp, 0, sizeof(*rp));
81         
82     cm_HoldSCache(scp);
83     rp->scp = scp;
84     cm_HoldUser(userp);
85     rp->userp = userp;
86     rp->procp = procp;
87     rp->p1 = p1;
88     rp->p2 = p2;
89     rp->p3 = p3;
90     rp->p4 = p4;
91
92     lock_ObtainWrite(&cm_daemonLock);
93     cm_bkgQueueCount++;
94     osi_QAdd((osi_queue_t **) &cm_bkgListp, &rp->q);
95     if (!cm_bkgListEndp) 
96         cm_bkgListEndp = rp;
97     lock_ReleaseWrite(&cm_daemonLock);
98
99     osi_Wakeup((long) &cm_bkgListp);
100 }
101
102 /* periodic check daemon */
103 void cm_Daemon(long parm)
104 {
105     unsigned long now;
106     unsigned long lastLockCheck;
107     unsigned long lastVolCheck;
108     unsigned long lastCBExpirationCheck;
109     unsigned long lastDownServerCheck;
110     unsigned long lastUpServerCheck;
111     unsigned long lastTokenCacheCheck;
112     char thostName[200];
113     unsigned long code;
114     struct hostent *thp;
115     HMODULE hHookDll;
116
117     /* ping all file servers, up or down, with unauthenticated connection,
118      * to find out whether we have all our callbacks from the server still.
119      * Also, ping down VLDBs.
120      */
121     /*
122      * Seed the random number generator with our own address, so that
123      * clients starting at the same time don't all do vol checks at the
124      * same time.
125      */
126     gethostname(thostName, sizeof(thostName));
127     thp = gethostbyname(thostName);
128     if (thp == NULL)    /* In djgpp, gethostname returns the netbios
129                            name of the machine.  gethostbyname will fail
130                            looking this up if it differs from DNS name. */
131         code = 0;
132     else
133         memcpy(&code, thp->h_addr_list[0], 4);
134     srand(ntohl(code));
135
136     now = osi_Time();
137     lastVolCheck = now - 1800 + (rand() % 3600);
138     lastCBExpirationCheck = now - 60 + (rand() % 60);
139     lastLockCheck = now - 60 + (rand() % 60);
140     lastDownServerCheck = now - cm_daemonCheckInterval/2 + (rand() % cm_daemonCheckInterval);
141     lastUpServerCheck = now - 1800 + (rand() % 3600);
142     lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
143
144     while (daemon_ShutdownFlag == 0) {
145         thrd_Sleep(30 * 1000);          /* sleep 30 seconds */
146         if (daemon_ShutdownFlag == 1)
147             return;
148
149         /* find out what time it is */
150         now = osi_Time();
151
152         /* check down servers */
153         if (now > lastDownServerCheck + cm_daemonCheckInterval) {
154             lastDownServerCheck = now;
155             cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
156         }
157
158         /* check up servers */
159         if (now > lastUpServerCheck + 3600) {
160             lastUpServerCheck = now;
161             cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL);
162         }
163
164         if (now > lastVolCheck + 3600) {
165             lastVolCheck = now;
166             cm_CheckVolumes();
167         }
168
169         if (now > lastCBExpirationCheck + 60) {
170             lastCBExpirationCheck = now;
171             cm_CheckCBExpiration();
172         }
173
174         if (now > lastLockCheck + 60) {
175             lastLockCheck = now;
176             cm_CheckLocks();
177         }
178
179         if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval) {
180             lastTokenCacheCheck = now;
181             cm_CheckTokenCache(now);
182         }
183
184         /* allow an exit to be called prior to stopping the service */
185         hHookDll = LoadLibrary(AFSD_HOOK_DLL);
186         if (hHookDll)
187         {
188             BOOL hookRc = TRUE;
189             AfsdDaemonHook daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
190             if (daemonHook)
191             {
192                 hookRc = daemonHook();
193             }
194             FreeLibrary(hHookDll);
195             hHookDll = NULL;
196
197             if (hookRc == FALSE)
198             {
199                 SetEvent(WaitToTerminate);
200             }
201         }
202     }
203 }       
204
205 void cm_DaemonShutdown(void)
206 {
207     daemon_ShutdownFlag = 1;
208 }
209
210 void cm_InitDaemon(int nDaemons)
211 {
212     static osi_once_t once;
213     long pid;
214     thread_t phandle;
215     int i;
216         
217     if (osi_Once(&once)) {
218         lock_InitializeRWLock(&cm_daemonLock, "cm_daemonLock");
219         osi_EndOnce(&once);
220                 
221         /* creating pinging daemon */
222         phandle = thrd_Create((SecurityAttrib) 0, 0,
223                                (ThreadFunc) cm_Daemon, 0, 0, &pid, "cm_Daemon");
224         osi_assert(phandle != NULL);
225
226         thrd_CloseHandle(phandle);
227         for(i=0; i < nDaemons; i++) {
228             phandle = thrd_Create((SecurityAttrib) 0, 0,
229                                    (ThreadFunc) cm_BkgDaemon, 0, 0, &pid,
230                                    "cm_BkgDaemon");
231             osi_assert(phandle != NULL);
232             thrd_CloseHandle(phandle);
233         }
234     }
235 }