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