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