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
11 #include <afs/param.h>
15 #include <WINNT/afsclass.h>
20 * DEFINITIONS ________________________________________________________________
24 // Each SERVER object maintains a list of aggregates and a list
25 // of services; those lists have hashtables placed across their
26 // names (and, for aggregates, their IDs) for faster lookup.
27 // The default table size in a HASHLIST is 1000 elements--that's
28 // too large for a list of aggregates or services on a server,
29 // as it's enough to handle up to 30,000 objects before the table
30 // would need to resize iteself (see the documentation in
31 // hashlist.cpp for info). Instead, we choose a more reasonable
32 // default table size.
34 #define cKEYAGGREGATENAME_TABLESIZE 100
35 #define cKEYAGGREGATEID_TABLESIZE 100
37 #define cKEYSERVICENAME_TABLESIZE 50
41 * VARIABLES __________________________________________________________________
47 * PROTOTYPES _________________________________________________________________
53 * ROUTINES ___________________________________________________________________
58 SERVER::SERVER (LPCELL lpCellParent, LPTSTR pszName)
60 m_lpiCell = lpCellParent->GetIdentifier();
62 lstrcpy (m_szName, pszName);
73 m_fCanGetAggregates = TRUE;
74 m_fAggregatesOutOfDate = TRUE;
75 m_lAggregates = New (HASHLIST);
76 m_lAggregates->SetCriticalSection (AfsClass_GetCriticalSection());
77 m_lkAggregateName = m_lAggregates->CreateKey ("Aggregate Name", SERVER::KeyAggregateName_Compare, SERVER::KeyAggregateName_HashObject, SERVER::KeyAggregateName_HashData, cKEYAGGREGATENAME_TABLESIZE);
78 m_lkAggregateID = m_lAggregates->CreateKey ("Aggregate ID", SERVER::KeyAggregateID_Compare, SERVER::KeyAggregateID_HashObject, SERVER::KeyAggregateID_HashData, cKEYAGGREGATEID_TABLESIZE);
80 m_fCanGetServices = TRUE;
81 m_fServicesOutOfDate = TRUE;
82 m_lServices = New (HASHLIST);
83 m_lServices->SetCriticalSection (AfsClass_GetCriticalSection());
84 m_lkServiceName = m_lServices->CreateKey ("Service Name", SERVER::KeyServiceName_Compare, SERVER::KeyServiceName_HashObject, SERVER::KeyServiceName_HashData, cKEYSERVICENAME_TABLESIZE);
92 m_fVLDBOutOfDate = FALSE; /* FIXME: added because it was missing */
93 m_fStatusOutOfDate = TRUE;
94 memset (&m_ss, 0x00, sizeof(SERVERSTATUS));
98 SERVER::~SERVER (void)
103 if ((lpCell = m_lpiCell->OpenCell()) != NULL)
105 (lpCell->m_nServersUnmonitored)--;
111 m_lpiThis->m_cRef --;
114 Delete (m_lAggregates);
115 Delete (m_lServices);
119 void SERVER::FreeAll (void)
137 void SERVER::FreeAggregates (void)
139 for (LPENUM pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
141 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
142 m_lAggregates->Remove (lpAggregate);
143 Delete (lpAggregate);
148 void SERVER::FreeServices (void)
150 for (LPENUM pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
152 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
153 m_lServices->Remove (lpService);
159 void SERVER::SendDeleteNotifications (void)
161 for (LPENUM pEnum = m_lAggregates->FindFirst(); pEnum; pEnum = pEnum->FindNext())
163 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
164 lpAggregate->SendDeleteNotifications ();
167 for (pEnum = m_lServices->FindFirst(); pEnum; pEnum = pEnum->FindNext())
169 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
170 lpService->SendDeleteNotifications();
173 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
177 void SERVER::Close (void)
183 LPIDENT SERVER::GetIdentifier (void)
185 if (m_lpiThis == NULL)
187 if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
188 m_lpiThis = New2 (IDENT,(this));
189 m_lpiThis->m_cRef ++;
196 PVOID SERVER::OpenBosObject (PVOID *phCell, ULONG *pStatus)
200 if ((m_lpCellBOS = m_lpiCell->OpenCell (pStatus)) != NULL)
202 if ((m_hCellBOS = m_lpCellBOS->GetCellObject (pStatus)) != NULL)
204 TCHAR szCell[ cchNAME ];
205 m_lpiCell->GetCellName (szCell);
208 wp.wpBosServerOpen.hCell = m_hCellBOS;
209 wp.wpBosServerOpen.pszServer = m_szName;
210 if (Worker_DoTask (wtaskBosServerOpen, &wp, pStatus))
211 m_hBOS = wp.wpBosServerOpen.hServer;
216 m_lpCellBOS->Close();
226 *phCell = m_hCellBOS;
233 BOOL SERVER::CloseBosObject (ULONG *pStatus)
237 if ((m_cReqBOS > 0) && ((--m_cReqBOS) == 0))
242 wp.wpBosServerClose.hServer = m_hBOS;
243 if (!Worker_DoTask (wtaskBosServerClose, &wp, pStatus))
247 if (m_lpCellBOS != NULL)
249 m_lpCellBOS->Close();
258 PVOID SERVER::OpenVosObject (PVOID *phCell, ULONG *pStatus)
263 if ((lpCell = m_lpiCell->OpenCell (pStatus)) != NULL)
265 m_hCellVOS = lpCell->GetCellObject (pStatus);
270 if (m_hCellVOS && !m_hVOS)
272 TCHAR szCell[ cchNAME ];
273 m_lpiCell->GetCellName (szCell);
276 wp.wpVosServerOpen.hCell = m_hCellVOS;
277 wp.wpVosServerOpen.pszServer = m_szName;
278 if (Worker_DoTask (wtaskVosServerOpen, &wp, pStatus))
279 m_hVOS = wp.wpVosServerOpen.hServer;
285 *phCell = m_hCellVOS;
292 BOOL SERVER::CloseVosObject (ULONG *pStatus)
296 if ((m_cReqVOS > 0) && ((--m_cReqVOS) == 0))
301 wp.wpVosServerClose.hServer = m_hVOS;
302 if (!Worker_DoTask (wtaskVosServerClose, &wp, pStatus))
314 void SERVER::Invalidate (void)
316 if (!m_fAggregatesOutOfDate || !m_fServicesOutOfDate || !m_fStatusOutOfDate)
318 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
320 m_fAggregatesOutOfDate = TRUE;
321 m_fServicesOutOfDate = TRUE;
322 m_fStatusOutOfDate = TRUE;
325 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
330 void SERVER::InvalidateStatus (void)
332 if (!m_fStatusOutOfDate)
334 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
336 m_fStatusOutOfDate = TRUE;
339 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
344 void SERVER::InvalidateServices (void)
346 if (!m_fServicesOutOfDate)
348 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
350 m_fServicesOutOfDate = TRUE;
353 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
358 BOOL SERVER::RefreshAggregates (BOOL fNotify, ULONG *pStatus)
363 if (m_fAggregatesOutOfDate)
365 m_fAggregatesOutOfDate = FALSE;
370 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin, GetIdentifier());
372 // First thing is to forget about what aggregates we think we have
375 for (LPENUM pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
377 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
378 lpAggregate->SendDeleteNotifications();
379 m_lAggregates->Remove (lpAggregate);
380 Delete (lpAggregate);
383 // Next, the harder part: look through the server to find a list
388 if ((hVOS = OpenVosObject (&hCell, &status)) == NULL)
392 WORKERPACKET wpBegin;
393 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
394 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
396 if (!Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status))
403 wpNext.wpVosPartitionGetNext.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
404 if (!Worker_DoTask (wtaskVosPartitionGetNext, &wpNext, &status))
406 if (status == ADMITERATORDONE)
413 vos_partitionEntry_p pData = &wpNext.wpVosPartitionGetNext.Data;
415 LPTSTR pszName = AnsiToString (pData->name);
416 LPTSTR pszDevice = AnsiToString (pData->deviceName);
418 LPAGGREGATE lpAggregate = New2 (AGGREGATE,(this, pszName, pszDevice));
420 lpAggregate->m_as.dwID = lpAggregate->GetID();
422 FreeString (pszDevice, pData->deviceName);
423 FreeString (pszName, pData->name);
425 lpAggregate->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
426 lpAggregate->m_as.ckStorageTotal = pData->totalSpace;
427 lpAggregate->m_as.ckStorageFree = pData->totalFreeSpace;
428 m_lAggregates->Add (lpAggregate);
430 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpAggregate->GetIdentifier());
434 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
435 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
442 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd, GetIdentifier(), ((rc) ? 0 : status));
452 BOOL SERVER::RefreshServices (BOOL fNotify, ULONG *pStatus)
457 if (m_fServicesOutOfDate)
459 m_fServicesOutOfDate = FALSE;
464 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesBegin, GetIdentifier());
466 // First thing is to forget about what services we think we have now.
468 for (LPENUM pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
470 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
471 lpService->SendDeleteNotifications();
472 m_lServices->Remove (lpService);
476 // Next, the harder part: look through the server to find a list
481 if ((hBOS = OpenBosObject (&hCell, &status)) == NULL)
485 WORKERPACKET wpBegin;
486 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
487 if (!Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status))
491 LPSERVICE lpService = New2 (SERVICE,(this, TEXT("BOS")));
492 m_lServices->Add (lpService);
493 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
497 TCHAR szServiceName[ cchNAME ];
500 wpNext.wpBosProcessNameGetNext.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
501 wpNext.wpBosProcessNameGetNext.pszService = szServiceName;
503 if (!Worker_DoTask (wtaskBosProcessNameGetNext, &wpNext, &status))
505 if (status == ADMITERATORDONE)
512 lpService = New2 (SERVICE,(this, wpNext.wpBosProcessNameGetNext.pszService));
513 m_lServices->Add (lpService);
514 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
518 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
519 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
526 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesEnd, GetIdentifier(), ((rc) ? 0 : status));
536 BOOL SERVER::RefreshStatus (BOOL fNotify, ULONG *pStatus)
541 if (m_fStatusOutOfDate)
543 m_fStatusOutOfDate = FALSE;
546 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
549 if ((lpCell = OpenCell (&status)) == NULL)
554 if ((hCell = lpCell->GetCellObject (&status)) == NULL)
559 wp.wpClientAFSServerGet.hCell = hCell;
560 wp.wpClientAFSServerGet.pszServer = m_szName;
562 if (!Worker_DoTask (wtaskClientAFSServerGet, &wp, &status))
568 for (size_t iAddr = 0; iAddr < AFS_MAX_SERVER_ADDRESS; ++iAddr)
570 if (wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ] == 0)
572 AfsClass_IntToAddress (&m_ss.aAddresses[ m_ss.nAddresses++ ], wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ]);
575 lpCell->m_lServers->Update (this); // That update affected a hashlistkey
582 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
591 void SERVER::GetName (LPTSTR pszName)
593 SERVER::ShortenName (pszName, m_szName);
597 void SERVER::GetLongName (LPTSTR pszName)
599 lstrcpy (pszName, m_szName);
603 LPCELL SERVER::OpenCell (ULONG *pStatus)
605 return m_lpiCell->OpenCell (pStatus);
608 BOOL SERVER::GetStatus (LPSERVERSTATUS lpss, BOOL fNotify, ULONG *pStatus)
613 rc = RefreshStatus (fNotify, pStatus);
615 memcpy (lpss, &m_ss, sizeof(SERVERSTATUS));
620 short SERVER::GetGhostStatus (void)
626 PVOID SERVER::GetUserParam (void)
628 return GetIdentifier()->GetUserParam();
632 void SERVER::SetUserParam (PVOID pUserNew)
634 GetIdentifier()->SetUserParam (pUserNew);
638 void SERVER::ShortenName (LPTSTR pszTarget, LPTSTR pszSource, BOOL fForce)
640 lstrcpy (pszTarget, pszSource);
642 if (fForce || !fLongServerNames)
644 // If the name is really an IP address, don't shorten it.
646 BOOL fIsIPAddress = TRUE;
647 for (LPTSTR pch = pszTarget; *pch && fIsIPAddress; ++pch)
649 if (!isdigit(*pch) && !(*pch == TEXT('.')))
650 fIsIPAddress = FALSE;
655 if ((pszTarget = (LPTSTR)lstrchr (pszTarget, TEXT('.'))) != NULL)
656 *pszTarget = TEXT('\0');
662 BOOL SERVER::fIsMonitored (void)
668 BOOL SERVER::SetMonitor (BOOL fShouldMonitor, ULONG *pStatus)
673 if (m_fMonitor != fShouldMonitor)
676 if ((lpCell = m_lpiCell->OpenCell (&status)) == NULL)
680 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
682 if ((m_fMonitor = fShouldMonitor) == FALSE)
685 (lpCell->m_nServersUnmonitored)++;
687 else // (fMonitor == TRUE)
689 (lpCell->m_nServersUnmonitored)--;
691 rc = RefreshAll (&status);
694 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
706 * REFRESHALL __________________________________________________________________
708 * If a server is down, or doesn't have an VOS process running, it could
709 * take some time before we time out trying to talk to the server. During
710 * the course of a refresh, the first timeout-and-fail that we will hit is
711 * our call to wtaskVosPartitionGetBegin; since this call is very quick if
712 * it's going to be successful, we can safely perform this call once up-front
713 * to test to see if the server is listening at all. That test is performed
714 * on a separate thread, so that in the event the request times out, we can
715 * simply discard the thread and let it terminate on its own.
725 } REFRESHSECTION, *LPREFRESHSECTION;
727 static REFRESHSECTION *aRefSec = NULL;
728 static size_t cRefSec = 0;
729 static LPCRITICAL_SECTION pcsRefSec = NULL;
731 void AfsClass_InitRefreshSections (void)
733 if (pcsRefSec == NULL)
735 pcsRefSec = New (CRITICAL_SECTION);
736 InitializeCriticalSection (pcsRefSec);
741 void AfsClass_SkipRefresh (int idSection)
743 AfsClass_InitRefreshSections();
744 EnterCriticalSection (pcsRefSec);
746 if (aRefSec && (idSection < (int)cRefSec))
748 if (aRefSec[ idSection ].fInUse)
750 aRefSec[ idSection ].fCanceled = TRUE;
754 LeaveCriticalSection (pcsRefSec);
758 DWORD WINAPI SERVER::CanTalkToServer_ThreadProc (PVOID lp)
760 int idSection = (int)lp;
762 // Until we post a notification saying that we've entered
763 // a section, we don't need to worry about the aRefSec[] entry
764 // being invalid. Once that post is made, the user can skip
765 // the section at any time--so we'll have to check frequently,
766 // always under the pcsRefSec critical section.
768 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionStart, NULL, NULL, NULL, NULL, idSection, 0);
770 BOOL fAggregatesOK = FALSE;
771 BOOL fServicesOK = FALSE;
772 BOOL fContinue = TRUE;
774 // Try to get the BOS object for this server. Remember, there's
775 // a catch here: we can only assume that the aRefSec[idSection].lpServer
776 // pointer is valid so long as we're within the pcsRefSec critical
777 // section! (if we're in that critsec, we can verify that no one
778 // has canceled the operation--and if no one has, there is a thread
779 // hanging around which holds the library's critsec, which ensures
780 // the lpServer pointer won't have been freed.)
786 TCHAR szServer[ cchNAME ];
788 EnterCriticalSection (pcsRefSec);
789 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
793 hCell = aRefSec[ idSection ].hCell;
794 aRefSec[ idSection ].lpServer->GetLongName (szServer);
796 LeaveCriticalSection (pcsRefSec);
801 wp.wpBosServerOpen.hCell = hCell;
802 wp.wpBosServerOpen.pszServer = szServer;
805 fContinue = Worker_DoTask (wtaskBosServerOpen, &wp, &status);
807 EnterCriticalSection (pcsRefSec);
808 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
811 aRefSec[ idSection ].lpServer->m_lastStatus = status;
813 hBOS = wp.wpBosServerOpen.hServer;
814 LeaveCriticalSection (pcsRefSec);
819 WORKERPACKET wpBegin;
820 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
823 fContinue = Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status);
825 EnterCriticalSection (pcsRefSec);
826 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
829 aRefSec[ idSection ].lpServer->m_lastStatus = status;
830 LeaveCriticalSection (pcsRefSec);
835 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
836 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
838 // We can talk to BOS!
843 // If we couldn't talk to BOS, it's a sure bet the server is down--
844 // and regardless, if BOS isn't around, VOS isn't either. So
845 // we may not even have to test that.
850 wp.wpVosServerOpen.hCell = hCell;
851 wp.wpVosServerOpen.pszServer = szServer;
854 fContinue = Worker_DoTask (wtaskVosServerOpen, &wp, &status);
856 EnterCriticalSection (pcsRefSec);
857 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
860 aRefSec[ idSection ].lpServer->m_lastStatus = status;
862 hVOS = wp.wpVosServerOpen.hServer;
863 LeaveCriticalSection (pcsRefSec);
868 WORKERPACKET wpBegin;
869 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
870 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
873 fContinue = Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status);
875 EnterCriticalSection (pcsRefSec);
876 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
879 aRefSec[ idSection ].lpServer->m_lastStatus = status;
880 LeaveCriticalSection (pcsRefSec);
885 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
886 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
888 // We can talk to VOS!
889 fAggregatesOK = TRUE;
893 // Close the VOS and BOS objects we obtained.
898 wp.wpBosServerClose.hServer = hBOS;
899 Worker_DoTask (wtaskBosServerClose, &wp);
904 wp.wpVosServerClose.hServer = hVOS;
905 Worker_DoTask (wtaskVosServerClose, &wp);
908 // Return our entry in the RefSec array back to the pool.
909 // If the request was never canceled, there is another
910 // thread waiting to hear our results--update the server
911 // entry specified by RefSec before leaving.
913 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionEnd, NULL, NULL, NULL, NULL, idSection, 0);
915 EnterCriticalSection (pcsRefSec);
916 if ( (aRefSec[ idSection ].fInUse) && (!aRefSec[ idSection ].fCanceled) )
918 aRefSec[ idSection ].lpServer->m_fCanGetAggregates = fAggregatesOK;
919 aRefSec[ idSection ].lpServer->m_fCanGetServices = fServicesOK;
921 aRefSec[ idSection ].fInUse = FALSE;
922 LeaveCriticalSection (pcsRefSec);
927 BOOL SERVER::CanTalkToServer (ULONG *pStatus)
929 // Ensure the server exists in the cell at all--
930 // this call just updates the server's IP addresses
931 // etc (information it gets from the database servers)
932 // and doesn't require talking to the server itself.
934 if (!RefreshStatus (FALSE, pStatus))
937 // Find a new refsec array element to use...
939 AfsClass_InitRefreshSections();
940 EnterCriticalSection (pcsRefSec);
942 for (int idSection = 0; idSection < (int)cRefSec; ++idSection)
944 if (!aRefSec[ idSection ].fInUse)
947 if (idSection == (int)cRefSec)
949 if (!REALLOC (aRefSec, cRefSec, 1+idSection, 4))
952 *pStatus = GetLastError();
953 LeaveCriticalSection (pcsRefSec);
957 aRefSec[ idSection ].fInUse = TRUE;
958 aRefSec[ idSection ].fCanceled = FALSE;
959 aRefSec[ idSection ].lpServer = this;
960 aRefSec[ idSection ].hCell = NULL;
963 if ((lpCell = OpenCell()) != NULL)
965 aRefSec[ idSection ].hCell = lpCell->GetCellObject();
969 LeaveCriticalSection (pcsRefSec);
971 // Until we find out differently, assume that we won't be
972 // able to query VOS or BOS on this server.
974 m_fCanGetAggregates = FALSE;
975 m_fCanGetServices = FALSE;
978 // Fork a separate thread, on which to quickly try to talk
983 if ((hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)CanTalkToServer_ThreadProc, (PVOID)idSection, 0, &dwThreadID)) == NULL)
985 EnterCriticalSection (pcsRefSec);
986 aRefSec[ idSection ].fInUse = FALSE;
987 LeaveCriticalSection (pcsRefSec);
989 *pStatus = GetLastError();
992 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
994 // Wait for that thread to terminate, or for our
995 // newly-allocated RefSec entry to be marked Canceled.
997 for (DWORD dw = STILL_ACTIVE; dw == STILL_ACTIVE; )
999 EnterCriticalSection (pcsRefSec);
1001 GetExitCodeThread (hThread, &dw);
1002 if (dw == STILL_ACTIVE)
1004 if ( (aRefSec[ idSection ].fInUse) &&
1005 (aRefSec[ idSection ].lpServer == this) &&
1006 (aRefSec[ idSection ].fCanceled) )
1008 if (m_lastStatus == 0)
1009 m_lastStatus = ERROR_CANCELLED;
1014 LeaveCriticalSection (pcsRefSec);
1016 if (dw == STILL_ACTIVE)
1017 Sleep(100); // wait another brief instant
1020 // dw == 0 : user canceled operation (thread is still running!)
1021 // dw == 1 : thread completed successfully, and set fCanTalkTo* flags.
1023 // Note that the thread will clear aRefSec[idSection].fInUse when it
1024 // terminates (so, if dw!=-1, it has already done so).
1027 *pStatus = m_lastStatus;
1028 return (dw == 0) ? FALSE : TRUE;
1032 BOOL SERVER::RefreshAll (ULONG *pStatus, double dInit, double dFactor)
1037 if (m_fAggregatesOutOfDate || m_fServicesOutOfDate)
1039 if ((++cRefreshAllReq) == 1)
1041 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier(), 0);
1044 double perAGGREGATES = 65.0; // % of time spent finding aggs & sets
1045 double perSERVICES = 25.0; // % of time spent finding services
1046 double perVLDB = 10.0; // % of time spent finding VLDB info
1048 if (cRefreshAllReq >= 2) // being called as part of a cell-wide op?
1050 perAGGREGATES = 80.0; // % of time spent finding aggs & sets
1051 perSERVICES = 20.0; // % of time spent finding services
1052 perVLDB = 0.0; // we won't query VLDB stuff ourself.
1055 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
1057 if (!CanTalkToServer (&status)) // Determines fCanGetAggregates, fCanGetServices
1065 if (!m_fCanGetAggregates)
1068 m_fAggregatesOutOfDate = FALSE;
1072 size_t nAggregates = 0;
1073 size_t iAggregate = 0;
1075 for (LPAGGREGATE lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1078 lpAggregate->Close();
1083 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1085 ULONG perComplete = (ULONG)( ((double)perAGGREGATES / 100.0) * ((double)iAggregate * 100.0 / nAggregates) );
1086 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpAggregate->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1088 lpAggregate->RefreshFilesets (TRUE);
1089 lpAggregate->Close();
1096 if (!m_fCanGetServices)
1099 m_fServicesOutOfDate = FALSE;
1103 size_t nServices = 0;
1104 size_t iService = 0;
1106 for (LPSERVICE lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1114 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1116 ULONG perComplete = (ULONG)( (double)perAGGREGATES + ((double)perSERVICES / 100.0) * ((double)iService * 100.0 / nServices) );
1117 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpService->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1119 lpService->RefreshStatus (TRUE);
1127 if (cRefreshAllReq == 1) // not being called as part of a cell-wide op?
1130 if ((lpCell = OpenCell()) != NULL)
1132 lpCell->RefreshVLDB (GetIdentifier(), TRUE, NULL);
1138 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
1140 if ((--cRefreshAllReq) == 0)
1142 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd, GetIdentifier(), NULL, NULL, NULL, 100, m_lastStatus);
1146 if (rc && m_lastStatus)
1155 * AGGREGATES _________________________________________________________________
1159 LPAGGREGATE SERVER::OpenAggregate (LPTSTR pszName, ULONG *pStatus)
1161 if (!RefreshAggregates (TRUE, pStatus))
1164 LPAGGREGATE lpAggregate;
1165 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateName->GetFirstObject (pszName))) != NULL)
1172 LPAGGREGATE SERVER::OpenAggregate (ULONG dwID, ULONG *pStatus)
1174 if (!RefreshAggregates (TRUE, pStatus))
1177 LPAGGREGATE lpAggregate;
1178 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateID->GetFirstObject (&dwID))) != NULL)
1185 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1187 return AggregateFindFirst (phEnum, NULL, fNotify, pStatus);
1191 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1193 LPAGGREGATE lpAggregate = NULL;
1195 if (!RefreshAggregates (fNotify, pStatus))
1198 if (lpiFind != NULL)
1200 lpAggregate = lpiFind->OpenAggregate();
1203 else if ((*phEnum = m_lAggregates->FindFirst()) != NULL)
1205 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1209 if (!lpAggregate && pStatus)
1210 *pStatus = ERROR_FILE_NOT_FOUND;
1215 LPAGGREGATE SERVER::AggregateFindNext (HENUM *phEnum)
1217 LPAGGREGATE lpAggregate = NULL;
1221 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1223 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1232 void SERVER::AggregateFindClose (HENUM *phEnum)
1243 * SERVICES ___________________________________________________________________
1247 LPSERVICE SERVER::OpenService (LPTSTR pszName, ULONG *pStatus)
1249 if (!RefreshServices (TRUE, pStatus))
1252 LPSERVICE lpService;
1253 if ((lpService = (LPSERVICE)(m_lkServiceName->GetFirstObject (pszName))) != NULL)
1260 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1262 return ServiceFindFirst (phEnum, NULL, fNotify, pStatus);
1266 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1268 LPSERVICE lpService = NULL;
1270 if (!RefreshServices (fNotify, pStatus))
1273 if (lpiFind != NULL)
1275 lpService = lpiFind->OpenService();
1278 else if ((*phEnum = m_lServices->FindFirst()) != NULL)
1280 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1284 if (!lpService && pStatus)
1285 *pStatus = ERROR_FILE_NOT_FOUND;
1290 LPSERVICE SERVER::ServiceFindNext (HENUM *phEnum)
1292 LPSERVICE lpService = NULL;
1296 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1298 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1307 void SERVER::ServiceFindClose (HENUM *phEnum)
1318 * HASH KEYS __________________________________________________________________
1322 BOOL CALLBACK SERVER::KeyAggregateName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1324 return !lstrcmp (((LPAGGREGATE)pObject)->m_szName, (LPTSTR)pData);
1327 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1329 return SERVER::KeyAggregateName_HashData (pKey, ((LPAGGREGATE)pObject)->m_szName);
1332 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1334 return HashString ((LPTSTR)pData);
1338 BOOL CALLBACK SERVER::KeyAggregateID_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1340 return (((LPAGGREGATE)pObject)->m_as.dwID == *(ULONG*)pData);
1343 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1345 return SERVER::KeyAggregateID_HashData (pKey, &((LPAGGREGATE)pObject)->m_as.dwID);
1348 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashData (LPHASHLISTKEY pKey, PVOID pData)
1350 return (HASHVALUE)*(ULONG*)pData;
1354 BOOL CALLBACK SERVER::KeyServiceName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1356 return !lstrcmp (((LPSERVICE)pObject)->m_szName, (LPTSTR)pData);
1359 HASHVALUE CALLBACK SERVER::KeyServiceName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1361 return SERVER::KeyServiceName_HashData (pKey, ((LPSERVICE)pObject)->m_szName);
1364 HASHVALUE CALLBACK SERVER::KeyServiceName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1366 return HashString ((LPTSTR)pData);