2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
27 #include <rx/rx_prototypes.h>
28 #include <WINNT/afsreg.h>
33 long cm_daemonCheckDownInterval = 180;
34 long cm_daemonCheckUpInterval = 240;
35 long cm_daemonCheckVolInterval = 3600;
36 long cm_daemonCheckCBInterval = 60;
37 long cm_daemonCheckVolCBInterval = 0;
38 long cm_daemonCheckLockInterval = 60;
39 long cm_daemonTokenCheckInterval = 180;
40 long cm_daemonCheckOfflineVolInterval = 600;
41 long cm_daemonPerformanceTuningInterval = 0;
42 long cm_daemonRankServerInterval = 600;
43 long cm_daemonRDRShakeExtentsInterval = 0;
45 osi_rwlock_t cm_daemonLock;
47 long cm_bkgQueueCount; /* # of queued requests */
49 int cm_bkgWaitingForCount; /* true if someone's waiting for cm_bkgQueueCount to drop */
51 cm_bkgRequest_t *cm_bkgListp; /* first elt in the list of requests */
52 cm_bkgRequest_t *cm_bkgListEndp; /* last elt in the list of requests */
54 extern int powerStateSuspended;
55 int daemon_ShutdownFlag = 0;
56 static int cm_nDaemons = 0;
57 static time_t lastIPAddrChange = 0;
59 static EVENT_HANDLE cm_Daemon_ShutdownEvent = NULL;
60 static EVENT_HANDLE cm_LockDaemon_ShutdownEvent = NULL;
61 static EVENT_HANDLE cm_IPAddrDaemon_ShutdownEvent = NULL;
62 static EVENT_HANDLE cm_BkgDaemon_ShutdownEvent[CM_MAX_DAEMONS] =
63 {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
65 void * cm_IpAddrDaemon(void * vparm)
67 extern void smb_CheckVCs(void);
68 char * name = "cm_IPAddrDaemon_ShutdownEvent";
70 cm_IPAddrDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
71 if ( GetLastError() == ERROR_ALREADY_EXISTS )
72 afsi_log("Event Object Already Exists: %s", name);
74 rx_StartClientThread();
76 while (daemon_ShutdownFlag == 0) {
79 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
80 Result = NotifyAddrChange(NULL,NULL);
81 if (Result == NO_ERROR && daemon_ShutdownFlag == 0) {
82 lastIPAddrChange = osi_Time();
84 smb_SetLanAdapterChangeDetected();
85 cm_SetLanAdapterChangeDetected();
86 thrd_ResetEvent(cm_IPAddrDaemon_ShutdownEvent);
90 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
95 afs_int32 cm_RequestWillBlock(cm_bkgRequest_t *rp)
97 afs_int32 willBlock = 0;
99 if (rp->procp == cm_BkgStore) {
101 * If the datastoring flag is set, it means that another
102 * thread is already performing an exclusive store operation
103 * on this file. The exclusive state will be cleared once
104 * the file server locks the vnode. Therefore, at most two
105 * threads can be actively involved in storing data at a time
108 lock_ObtainRead(&rp->scp->rw);
109 willBlock = (rp->scp->flags & CM_SCACHEFLAG_DATASTORING);
110 lock_ReleaseRead(&rp->scp->rw);
112 else if (rp->procp == RDR_BkgFetch || rp->procp == cm_BkgPrefetch) {
114 * Attempt to determine if there is a conflict on the requested
115 * range of the file. If the first in the range does not exist
116 * in the cache assume there is no conflict. If the buffer does
117 * exist, check to see if an I/O operation is in progress
118 * by using the writing and reading flags as an indicator.
121 cm_buf_t *bufp = NULL;
123 base.LowPart = rp->p1;
124 base.HighPart = rp->p2;
126 bufp = buf_Find(&rp->scp->fid, &base);
128 willBlock = (bufp->flags & (CM_BUF_WRITING|CM_BUF_READING));
136 void * cm_BkgDaemon(void * vparm)
141 long daemonID = (long)(LONG_PTR)vparm;
143 snprintf(name, sizeof(name), "cm_BkgDaemon_ShutdownEvent%u", daemonID);
145 cm_BkgDaemon_ShutdownEvent[daemonID] = thrd_CreateEvent(NULL, FALSE, FALSE, name);
146 if ( GetLastError() == ERROR_ALREADY_EXISTS )
147 afsi_log("Event Object Already Exists: %s", name);
149 rx_StartClientThread();
151 lock_ObtainWrite(&cm_daemonLock);
152 while (daemon_ShutdownFlag == 0) {
155 if (powerStateSuspended) {
159 if (!cm_bkgListEndp) {
160 osi_SleepW((LONG_PTR)&cm_bkgListp, &cm_daemonLock);
161 lock_ObtainWrite(&cm_daemonLock);
165 /* we found a request */
166 for (rp = cm_bkgListEndp; rp; rp = (cm_bkgRequest_t *) osi_QPrev(&rp->q))
168 if (rp->scp->flags & CM_SCACHEFLAG_DELETED)
172 * If the request has active I/O such that this worker would
173 * be forced to block, leave the request in the queue and move
174 * on to one that might be available for servicing.
176 if (cm_RequestWillBlock(rp)) {
181 if (cm_ServerAvailable(&rp->scp->fid, rp->userp))
187 * Couldn't find a request that we could process at the
188 * current time. If there were requests that would cause
189 * the worker to block, sleep for 25ms so it can promptly
190 * respond when it is available. Otherwise, sleep for 1s.
192 * This polling cycle needs to be replaced with a proper
193 * producer/consumer dynamic worker pool.
195 lock_ReleaseWrite(&cm_daemonLock);
196 Sleep(willBlock ? 25 : 1000);
197 lock_ObtainWrite(&cm_daemonLock);
201 osi_QRemoveHT((osi_queue_t **) &cm_bkgListp, (osi_queue_t **) &cm_bkgListEndp, &rp->q);
202 osi_assertx(cm_bkgQueueCount-- > 0, "cm_bkgQueueCount 0");
203 lock_ReleaseWrite(&cm_daemonLock);
205 osi_Log1(afsd_logp,"cm_BkgDaemon processing request 0x%p", rp);
207 if (rp->scp->flags & CM_SCACHEFLAG_DELETED) {
208 osi_Log1(afsd_logp,"cm_BkgDaemon DELETED scp 0x%x",rp->scp);
209 code = CM_ERROR_BADFD;
211 #ifdef DEBUG_REFCOUNT
212 osi_Log2(afsd_logp,"cm_BkgDaemon (before) scp 0x%x ref %d",rp->scp, rp->scp->refCount);
214 code = (*rp->procp)(rp->scp, rp->p1, rp->p2, rp->p3, rp->p4, rp->userp, &rp->req);
215 #ifdef DEBUG_REFCOUNT
216 osi_Log2(afsd_logp,"cm_BkgDaemon (after) scp 0x%x ref %d",rp->scp, rp->scp->refCount);
221 * Keep the following list synchronized with the
222 * error code list in cm_BkgStore.
223 * cm_SyncOpDone(CM_SCACHESYNC_ASYNCSTORE) will be called there unless
224 * one of these errors has occurred.
227 case CM_ERROR_TIMEDOUT: /* or server restarting */
229 case CM_ERROR_WOULDBLOCK:
230 case CM_ERROR_ALLBUSY:
231 case CM_ERROR_ALLDOWN:
232 case CM_ERROR_ALLOFFLINE:
233 case CM_ERROR_PARTIALWRITE:
234 if (rp->procp == cm_BkgStore ||
235 rp->procp == RDR_BkgFetch) {
237 "cm_BkgDaemon re-queueing failed request 0x%p code 0x%x",
239 lock_ObtainWrite(&cm_daemonLock);
241 osi_QAddT((osi_queue_t **) &cm_bkgListp, (osi_queue_t **)&cm_bkgListEndp, &rp->q);
243 } /* otherwise fall through */
244 case 0: /* success */
245 default: /* other error */
247 osi_Log1(afsd_logp,"cm_BkgDaemon SUCCESS: request 0x%p", rp);
249 osi_Log2(afsd_logp,"cm_BkgDaemon FAILED: request dropped 0x%p code 0x%x",
252 cm_ReleaseUser(rp->userp);
253 cm_ReleaseSCache(rp->scp);
255 lock_ObtainWrite(&cm_daemonLock);
258 lock_ReleaseWrite(&cm_daemonLock);
259 thrd_SetEvent(cm_BkgDaemon_ShutdownEvent[daemonID]);
264 void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
265 cm_user_t *userp, cm_req_t *reqp)
269 rp = malloc(sizeof(*rp));
270 memset(rp, 0, sizeof(*rp));
283 lock_ObtainWrite(&cm_daemonLock);
285 osi_QAdd((osi_queue_t **) &cm_bkgListp, &rp->q);
288 lock_ReleaseWrite(&cm_daemonLock);
290 osi_Wakeup((LONG_PTR) &cm_bkgListp);
294 IsWindowsFirewallPresent(void)
299 BOOLEAN result = FALSE;
300 LPQUERY_SERVICE_CONFIG pConfig = NULL;
304 /* Open services manager */
305 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
306 if (!scm) return FALSE;
308 /* Open Windows Firewall service */
309 svc = OpenService(scm, "MpsSvc", SERVICE_QUERY_CONFIG);
311 afsi_log("MpsSvc Service could not be opened for query: 0x%x", GetLastError());
312 svc = OpenService(scm, "SharedAccess", SERVICE_QUERY_CONFIG);
314 afsi_log("SharedAccess Service could not be opened for query: 0x%x", GetLastError());
319 /* Query Windows Firewall service config, first just to get buffer size */
320 /* Expected to fail, so don't test return value */
321 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
322 status = GetLastError();
323 if (status != ERROR_INSUFFICIENT_BUFFER)
326 /* Allocate buffer */
327 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
331 /* Query Windows Firewall service config, this time for real */
332 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
334 afsi_log("QueryServiceConfig failed: 0x%x", GetLastError());
338 /* Is it autostart? */
339 afsi_log("AutoStart 0x%x", pConfig->dwStartType);
340 if (pConfig->dwStartType < SERVICE_DEMAND_START)
346 CloseServiceHandle(svc);
348 CloseServiceHandle(scm);
354 cm_DaemonCheckInit(void)
361 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
362 0, KEY_QUERY_VALUE, &parmKey);
366 dummyLen = sizeof(DWORD);
367 code = RegQueryValueEx(parmKey, "daemonCheckDownInterval", NULL, NULL,
368 (BYTE *) &dummy, &dummyLen);
369 if (code == ERROR_SUCCESS && dummy)
370 cm_daemonCheckDownInterval = dummy;
371 afsi_log("daemonCheckDownInterval is %d", cm_daemonCheckDownInterval);
373 dummyLen = sizeof(DWORD);
374 code = RegQueryValueEx(parmKey, "daemonCheckUpInterval", NULL, NULL,
375 (BYTE *) &dummy, &dummyLen);
376 if (code == ERROR_SUCCESS && dummy)
377 cm_daemonCheckUpInterval = dummy;
378 afsi_log("daemonCheckUpInterval is %d", cm_daemonCheckUpInterval);
380 dummyLen = sizeof(DWORD);
381 code = RegQueryValueEx(parmKey, "daemonCheckVolInterval", NULL, NULL,
382 (BYTE *) &dummy, &dummyLen);
383 if (code == ERROR_SUCCESS && dummy)
384 cm_daemonCheckVolInterval = dummy;
385 afsi_log("daemonCheckVolInterval is %d", cm_daemonCheckVolInterval);
387 dummyLen = sizeof(DWORD);
388 code = RegQueryValueEx(parmKey, "daemonCheckCBInterval", NULL, NULL,
389 (BYTE *) &dummy, &dummyLen);
390 if (code == ERROR_SUCCESS && dummy)
391 cm_daemonCheckCBInterval = dummy;
392 afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval);
394 dummyLen = sizeof(DWORD);
395 code = RegQueryValueEx(parmKey, "daemonCheckVolCBInterval", NULL, NULL,
396 (BYTE *) &dummy, &dummyLen);
397 if (code == ERROR_SUCCESS && dummy)
398 cm_daemonCheckVolCBInterval = dummy;
399 afsi_log("daemonCheckVolCBInterval is %d", cm_daemonCheckVolCBInterval);
401 dummyLen = sizeof(DWORD);
402 code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL,
403 (BYTE *) &dummy, &dummyLen);
404 if (code == ERROR_SUCCESS && dummy)
405 cm_daemonCheckLockInterval = dummy;
406 afsi_log("daemonCheckLockInterval is %d", cm_daemonCheckLockInterval);
408 dummyLen = sizeof(DWORD);
409 code = RegQueryValueEx(parmKey, "daemonCheckTokenInterval", NULL, NULL,
410 (BYTE *) &dummy, &dummyLen);
411 if (code == ERROR_SUCCESS && dummy)
412 cm_daemonTokenCheckInterval = dummy;
413 afsi_log("daemonCheckTokenInterval is %d", cm_daemonTokenCheckInterval);
415 dummyLen = sizeof(DWORD);
416 code = RegQueryValueEx(parmKey, "daemonCheckOfflineVolInterval", NULL, NULL,
417 (BYTE *) &dummy, &dummyLen);
418 if (code == ERROR_SUCCESS && dummy)
419 cm_daemonCheckOfflineVolInterval = dummy;
420 afsi_log("daemonCheckOfflineVolInterval is %d", cm_daemonCheckOfflineVolInterval);
422 dummyLen = sizeof(DWORD);
423 code = RegQueryValueEx(parmKey, "daemonRDRShakeExtentsInterval", NULL, NULL,
424 (BYTE *) &dummy, &dummyLen);
425 if (code == ERROR_SUCCESS && dummy)
426 cm_daemonRDRShakeExtentsInterval = dummy;
427 afsi_log("daemonRDRShakeExtentsInterval is %d", cm_daemonRDRShakeExtentsInterval);
429 dummyLen = sizeof(DWORD);
430 code = RegQueryValueEx(parmKey, "daemonPerformanceTuningInterval", NULL, NULL,
431 (BYTE *) &dummy, &dummyLen);
432 if (code == ERROR_SUCCESS)
433 cm_daemonPerformanceTuningInterval = dummy;
434 afsi_log("daemonPerformanceTuningInterval is %d", cm_daemonPerformanceTuningInterval);
436 dummyLen = sizeof(DWORD);
437 code = RegQueryValueEx(parmKey, "daemonRankServerInterval", NULL, NULL,
438 (BYTE *) &dummy, &dummyLen);
439 if (code == ERROR_SUCCESS && dummy)
440 cm_daemonRankServerInterval = dummy;
441 afsi_log("daemonRankServerInterval is %d", cm_daemonRankServerInterval);
443 RegCloseKey(parmKey);
445 if (cm_daemonPerformanceTuningInterval)
446 cm_PerformanceTuningInit();
449 /* periodic lock check daemon */
450 void * cm_LockDaemon(void * vparm)
453 time_t lastLockCheck;
454 char * name = "cm_LockDaemon_ShutdownEvent";
456 cm_LockDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
457 if ( GetLastError() == ERROR_ALREADY_EXISTS )
458 afsi_log("Event Object Already Exists: %s", name);
461 lastLockCheck = now - cm_daemonCheckLockInterval/2 + (rand() % cm_daemonCheckLockInterval);
463 while (daemon_ShutdownFlag == 0) {
464 if (powerStateSuspended) {
471 if (now > lastLockCheck + cm_daemonCheckLockInterval &&
472 daemon_ShutdownFlag == 0 &&
473 powerStateSuspended == 0) {
476 if (daemon_ShutdownFlag == 1)
480 thrd_Sleep(1000); /* sleep 1 second */
482 thrd_SetEvent(cm_LockDaemon_ShutdownEvent);
487 /* periodic check daemon */
488 void * cm_Daemon(void *vparm)
492 time_t lastCBExpirationCheck;
493 time_t lastVolCBRenewalCheck;
494 time_t lastDownServerCheck;
495 time_t lastUpServerCheck;
496 time_t lastTokenCacheCheck;
497 time_t lastBusyVolCheck;
498 time_t lastPerformanceCheck;
499 time_t lastServerRankCheck;
500 time_t lastRDRShakeExtents;
505 char * name = "cm_Daemon_ShutdownEvent";
506 int configureFirewall = IsWindowsFirewallPresent();
507 int bAddrChangeCheck = 0;
509 cm_Daemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
510 if ( GetLastError() == ERROR_ALREADY_EXISTS )
511 afsi_log("Event Object Already Exists: %s", name);
513 if (!configureFirewall) {
514 afsi_log("No Windows Firewall detected");
517 if (cm_freelanceEnabled && cm_freelanceImportCellServDB)
518 cm_FreelanceImportCellServDB();
520 /* ping all file servers, up or down, with unauthenticated connection,
521 * to find out whether we have all our callbacks from the server still.
522 * Also, ping down VLDBs.
525 * Seed the random number generator with our own address, so that
526 * clients starting at the same time don't all do vol checks at the
529 gethostname(thostName, sizeof(thostName));
530 thp = gethostbyname(thostName);
531 if (thp == NULL) /* In djgpp, gethostname returns the netbios
532 name of the machine. gethostbyname will fail
533 looking this up if it differs from DNS name. */
536 memcpy(&code, thp->h_addr_list[0], 4);
540 cm_DaemonCheckInit();
543 lastVolCheck = now - cm_daemonCheckVolInterval/2 + (rand() % cm_daemonCheckVolInterval);
544 lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval);
545 if (cm_daemonCheckVolCBInterval)
546 lastVolCBRenewalCheck = now - cm_daemonCheckVolCBInterval/2 + (rand() % cm_daemonCheckVolCBInterval);
547 lastDownServerCheck = now - cm_daemonCheckDownInterval/2 + (rand() % cm_daemonCheckDownInterval);
548 lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval);
549 lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
550 if (cm_daemonCheckOfflineVolInterval)
551 lastBusyVolCheck = now - cm_daemonCheckOfflineVolInterval/2 * (rand() % cm_daemonCheckOfflineVolInterval);
552 if (cm_daemonPerformanceTuningInterval)
553 lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval);
554 lastServerRankCheck = now - cm_daemonRankServerInterval/2 * (rand() % cm_daemonRankServerInterval);
555 if (cm_daemonRDRShakeExtentsInterval)
556 lastRDRShakeExtents = now - cm_daemonRDRShakeExtentsInterval/2 * (rand() % cm_daemonRDRShakeExtentsInterval);
558 while (daemon_ShutdownFlag == 0) {
559 if (powerStateSuspended) {
563 /* check to see if the listener threads halted due to network
564 * disconnect or other issues. If so, attempt to restart them.
566 smb_RestartListeners(0);
568 if (daemon_ShutdownFlag == 1)
571 if (configureFirewall) {
572 /* Open Microsoft Firewall to allow in port 7001 */
573 switch (icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT)) {
575 afsi_log("Windows Firewall Configuration succeeded");
576 configureFirewall = 0;
579 afsi_log("Invalid Windows Firewall Port Set");
582 afsi_log("Unable to open Windows Firewall Profile");
585 afsi_log("Unable to create/modify Windows Firewall Port entries");
588 afsi_log("Unknown Windows Firewall Configuration error");
592 /* find out what time it is */
595 /* Determine whether an address change took place that we need to respond to */
596 if (bAddrChangeCheck)
597 bAddrChangeCheck = 0;
599 if (lastIPAddrChange != 0 && lastIPAddrChange + 2500 < now) {
600 bAddrChangeCheck = 1;
601 lastIPAddrChange = 0;
604 /* check down servers */
605 if ((bAddrChangeCheck || now > lastDownServerCheck + cm_daemonCheckDownInterval) &&
606 daemon_ShutdownFlag == 0 &&
607 powerStateSuspended == 0) {
608 lastDownServerCheck = now;
609 osi_Log0(afsd_logp, "cm_Daemon CheckDownServers");
610 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
611 if (daemon_ShutdownFlag == 1)
616 if (bAddrChangeCheck &&
617 daemon_ShutdownFlag == 0 &&
618 powerStateSuspended == 0) {
619 cm_ForceNewConnectionsAllServers();
622 /* check up servers */
623 if ((bAddrChangeCheck || now > lastUpServerCheck + cm_daemonCheckUpInterval) &&
624 daemon_ShutdownFlag == 0 &&
625 powerStateSuspended == 0) {
626 lastUpServerCheck = now;
627 osi_Log0(afsd_logp, "cm_Daemon CheckUpServers");
628 cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL);
629 if (daemon_ShutdownFlag == 1)
634 if (bAddrChangeCheck &&
635 daemon_ShutdownFlag == 0 &&
636 powerStateSuspended == 0) {
638 cm_VolStatus_Network_Addr_Change();
642 * Once every five minutes inspect the volume list and enforce
643 * the volume location expiration time.
645 if (now > lastVolCheck + 300 &&
646 daemon_ShutdownFlag == 0 &&
647 powerStateSuspended == 0) {
649 cm_RefreshVolumes(cm_daemonCheckVolInterval);
650 if (daemon_ShutdownFlag == 1)
655 /* Rank all up servers */
656 if ((now > lastServerRankCheck + cm_daemonRankServerInterval) &&
657 daemon_ShutdownFlag == 0 &&
658 powerStateSuspended == 0) {
659 lastServerRankCheck = now;
660 osi_Log0(afsd_logp, "cm_Daemon RankServer");
662 if(daemon_ShutdownFlag == 1)
667 if (cm_daemonCheckVolCBInterval &&
668 now > lastVolCBRenewalCheck + cm_daemonCheckVolCBInterval &&
669 daemon_ShutdownFlag == 0 &&
670 powerStateSuspended == 0) {
671 lastVolCBRenewalCheck = now;
672 cm_VolumeRenewROCallbacks();
673 if (daemon_ShutdownFlag == 1)
678 if ((bAddrChangeCheck || (cm_daemonCheckOfflineVolInterval &&
679 now > lastBusyVolCheck + cm_daemonCheckOfflineVolInterval)) &&
680 daemon_ShutdownFlag == 0 &&
681 powerStateSuspended == 0) {
682 lastBusyVolCheck = now;
683 cm_CheckOfflineVolumes();
684 if (daemon_ShutdownFlag == 1)
689 if (now > lastCBExpirationCheck + cm_daemonCheckCBInterval &&
690 daemon_ShutdownFlag == 0 &&
691 powerStateSuspended == 0) {
692 lastCBExpirationCheck = now;
693 cm_CheckCBExpiration();
694 if (daemon_ShutdownFlag == 1)
699 if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval &&
700 daemon_ShutdownFlag == 0 &&
701 powerStateSuspended == 0) {
702 lastTokenCacheCheck = now;
703 cm_CheckTokenCache(now);
704 if (daemon_ShutdownFlag == 1)
709 if (cm_daemonRDRShakeExtentsInterval &&
710 now > lastRDRShakeExtents + cm_daemonRDRShakeExtentsInterval &&
711 daemon_ShutdownFlag == 0 &&
712 powerStateSuspended == 0) {
715 lastRDRShakeExtents = now;
716 if (cm_data.buf_redirCount > cm_data.buf_freeCount)
717 buf_RDRShakeSomeExtentsFree(&req, FALSE, 10 /* seconds */);
718 if (daemon_ShutdownFlag == 1)
723 /* allow an exit to be called prior to stopping the service */
724 hHookDll = cm_LoadAfsdHookLib();
728 AfsdDaemonHook daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
731 hookRc = daemonHook();
733 FreeLibrary(hHookDll);
738 SetEvent(WaitToTerminate);
741 if (daemon_ShutdownFlag == 1) {
747 if (cm_daemonPerformanceTuningInterval &&
748 now > lastPerformanceCheck + cm_daemonPerformanceTuningInterval &&
749 daemon_ShutdownFlag == 0 &&
750 powerStateSuspended == 0) {
751 lastPerformanceCheck = now;
752 cm_PerformanceTuningCheck();
753 if (daemon_ShutdownFlag == 1)
759 * sleep .5 seconds. if the thread blocks for a long time
760 * we risk not being able to close the cache before Windows
761 * kills our process during system shutdown.
766 thrd_SetEvent(cm_Daemon_ShutdownEvent);
771 void cm_DaemonShutdown(void)
776 daemon_ShutdownFlag = 1;
777 osi_Wakeup((LONG_PTR) &cm_bkgListp);
779 /* wait for shutdown */
780 for ( i=0; i<cm_nDaemons; i++) {
781 if (cm_BkgDaemon_ShutdownEvent[i])
782 code = thrd_WaitForSingleObject_Event(cm_BkgDaemon_ShutdownEvent[i], INFINITE);
785 if (cm_Daemon_ShutdownEvent)
786 code = thrd_WaitForSingleObject_Event(cm_Daemon_ShutdownEvent, INFINITE);
788 if (cm_LockDaemon_ShutdownEvent)
789 code = thrd_WaitForSingleObject_Event(cm_LockDaemon_ShutdownEvent, INFINITE);
793 * Do not waste precious time waiting for the ipaddr daemon to shutdown.
794 * When it does it means we have lost our network connection and we need
795 * it during cache shutdown in order to notify the file servers that this
796 * client is giving up all callbacks.
798 if (cm_IPAddrDaemon_ShutdownEvent)
799 code = thrd_WaitForSingleObject_Event(cm_IPAddrDaemon_ShutdownEvent, INFINITE);
803 void cm_InitDaemon(int nDaemons)
805 static osi_once_t once;
807 pthread_attr_t tattr;
811 pthread_attr_init(&tattr);
812 pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
814 cm_nDaemons = (nDaemons > CM_MAX_DAEMONS) ? CM_MAX_DAEMONS : nDaemons;
816 if (osi_Once(&once)) {
817 lock_InitializeRWLock(&cm_daemonLock, "cm_daemonLock",
818 LOCK_HIERARCHY_DAEMON_GLOBAL);
821 /* creating IP Address Change monitor daemon */
822 pstatus = pthread_create(&phandle, &tattr, cm_IpAddrDaemon, 0);
823 osi_assertx(pstatus == 0, "cm_IpAddrDaemon thread creation failure");
825 /* creating pinging daemon */
826 pstatus = pthread_create(&phandle, &tattr, cm_Daemon, 0);
827 osi_assertx(pstatus == 0, "cm_Daemon thread creation failure");
829 pstatus = pthread_create(&phandle, &tattr, cm_LockDaemon, 0);
830 osi_assertx(pstatus == 0, "cm_LockDaemon thread creation failure");
832 for(i=0; i < cm_nDaemons; i++) {
833 pstatus = pthread_create(&phandle, &tattr, cm_BkgDaemon, (LPVOID)(LONG_PTR)i);
834 osi_assertx(pstatus == 0, "cm_BkgDaemon thread creation failure");
838 pthread_attr_destroy(&tattr);