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