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
14 #include <afs/param.h>
18 #include <WINNT/afsclass.h>
23 * DEFINITIONS ________________________________________________________________
27 // Each SERVER object maintains a list of aggregates and a list
28 // of services; those lists have hashtables placed across their
29 // names (and, for aggregates, their IDs) for faster lookup.
30 // The default table size in a HASHLIST is 1000 elements--that's
31 // too large for a list of aggregates or services on a server,
32 // as it's enough to handle up to 30,000 objects before the table
33 // would need to resize iteself (see the documentation in
34 // hashlist.cpp for info). Instead, we choose a more reasonable
35 // default table size.
37 #define cKEYAGGREGATENAME_TABLESIZE 100
38 #define cKEYAGGREGATEID_TABLESIZE 100
40 #define cKEYSERVICENAME_TABLESIZE 50
44 * VARIABLES __________________________________________________________________
50 * PROTOTYPES _________________________________________________________________
56 * ROUTINES ___________________________________________________________________
61 SERVER::SERVER (LPCELL lpCellParent, LPTSTR pszName)
63 m_lpiCell = lpCellParent->GetIdentifier();
65 lstrcpy (m_szName, pszName);
76 m_fCanGetAggregates = TRUE;
77 m_fAggregatesOutOfDate = TRUE;
78 m_lAggregates = New (HASHLIST);
79 m_lAggregates->SetCriticalSection (AfsClass_GetCriticalSection());
80 m_lkAggregateName = m_lAggregates->CreateKey ("Aggregate Name", SERVER::KeyAggregateName_Compare, SERVER::KeyAggregateName_HashObject, SERVER::KeyAggregateName_HashData, cKEYAGGREGATENAME_TABLESIZE);
81 m_lkAggregateID = m_lAggregates->CreateKey ("Aggregate ID", SERVER::KeyAggregateID_Compare, SERVER::KeyAggregateID_HashObject, SERVER::KeyAggregateID_HashData, cKEYAGGREGATEID_TABLESIZE);
83 m_fCanGetServices = TRUE;
84 m_fServicesOutOfDate = TRUE;
85 m_lServices = New (HASHLIST);
86 m_lServices->SetCriticalSection (AfsClass_GetCriticalSection());
87 m_lkServiceName = m_lServices->CreateKey ("Service Name", SERVER::KeyServiceName_Compare, SERVER::KeyServiceName_HashObject, SERVER::KeyServiceName_HashData, cKEYSERVICENAME_TABLESIZE);
95 m_fVLDBOutOfDate = FALSE; /* FIXME: added because it was missing */
96 m_fStatusOutOfDate = TRUE;
97 memset (&m_ss, 0x00, sizeof(SERVERSTATUS));
101 SERVER::~SERVER (void)
106 if ((lpCell = m_lpiCell->OpenCell()) != NULL)
108 (lpCell->m_nServersUnmonitored)--;
114 m_lpiThis->m_cRef --;
117 Delete (m_lAggregates);
118 Delete (m_lServices);
122 void SERVER::FreeAll (void)
140 void SERVER::FreeAggregates (void)
142 for (LPENUM pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
144 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
145 m_lAggregates->Remove (lpAggregate);
146 Delete (lpAggregate);
151 void SERVER::FreeServices (void)
153 for (LPENUM pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
155 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
156 m_lServices->Remove (lpService);
162 void SERVER::SendDeleteNotifications (void)
165 for (pEnum = m_lAggregates->FindFirst(); pEnum; pEnum = pEnum->FindNext())
167 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
168 lpAggregate->SendDeleteNotifications ();
171 for (pEnum = m_lServices->FindFirst(); pEnum; pEnum = pEnum->FindNext())
173 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
174 lpService->SendDeleteNotifications();
177 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
181 void SERVER::Close (void)
187 LPIDENT SERVER::GetIdentifier (void)
189 if (m_lpiThis == NULL)
191 if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
192 m_lpiThis = New2 (IDENT,(this));
193 m_lpiThis->m_cRef ++;
200 PVOID SERVER::OpenBosObject (PVOID *phCell, ULONG *pStatus)
204 if ((m_lpCellBOS = m_lpiCell->OpenCell (pStatus)) != NULL)
206 if ((m_hCellBOS = m_lpCellBOS->GetCellObject (pStatus)) != NULL)
208 TCHAR szCell[ cchNAME ];
209 m_lpiCell->GetCellName (szCell);
212 wp.wpBosServerOpen.hCell = m_hCellBOS;
213 wp.wpBosServerOpen.pszServer = m_szName;
214 if (Worker_DoTask (wtaskBosServerOpen, &wp, pStatus))
215 m_hBOS = wp.wpBosServerOpen.hServer;
220 m_lpCellBOS->Close();
230 *phCell = m_hCellBOS;
237 BOOL SERVER::CloseBosObject (ULONG *pStatus)
241 if ((m_cReqBOS > 0) && ((--m_cReqBOS) == 0))
246 wp.wpBosServerClose.hServer = m_hBOS;
247 if (!Worker_DoTask (wtaskBosServerClose, &wp, pStatus))
251 if (m_lpCellBOS != NULL)
253 m_lpCellBOS->Close();
262 PVOID SERVER::OpenVosObject (PVOID *phCell, ULONG *pStatus)
267 if ((lpCell = m_lpiCell->OpenCell (pStatus)) != NULL)
269 m_hCellVOS = lpCell->GetCellObject (pStatus);
274 if (m_hCellVOS && !m_hVOS)
276 TCHAR szCell[ cchNAME ];
277 m_lpiCell->GetCellName (szCell);
280 wp.wpVosServerOpen.hCell = m_hCellVOS;
281 wp.wpVosServerOpen.pszServer = m_szName;
282 if (Worker_DoTask (wtaskVosServerOpen, &wp, pStatus))
283 m_hVOS = wp.wpVosServerOpen.hServer;
289 *phCell = m_hCellVOS;
296 BOOL SERVER::CloseVosObject (ULONG *pStatus)
300 if ((m_cReqVOS > 0) && ((--m_cReqVOS) == 0))
305 wp.wpVosServerClose.hServer = m_hVOS;
306 if (!Worker_DoTask (wtaskVosServerClose, &wp, pStatus))
318 void SERVER::Invalidate (void)
320 if (!m_fAggregatesOutOfDate || !m_fServicesOutOfDate || !m_fStatusOutOfDate)
322 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
324 m_fAggregatesOutOfDate = TRUE;
325 m_fServicesOutOfDate = TRUE;
326 m_fStatusOutOfDate = TRUE;
329 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
334 void SERVER::InvalidateStatus (void)
336 if (!m_fStatusOutOfDate)
338 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
340 m_fStatusOutOfDate = TRUE;
343 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
348 void SERVER::InvalidateServices (void)
350 if (!m_fServicesOutOfDate)
352 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
354 m_fServicesOutOfDate = TRUE;
357 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
362 BOOL SERVER::RefreshAggregates (BOOL fNotify, ULONG *pStatus)
367 if (m_fAggregatesOutOfDate)
369 m_fAggregatesOutOfDate = FALSE;
374 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin, GetIdentifier());
376 // First thing is to forget about what aggregates we think we have
380 for (pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
382 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
383 lpAggregate->SendDeleteNotifications();
384 m_lAggregates->Remove (lpAggregate);
385 Delete (lpAggregate);
388 // Next, the harder part: look through the server to find a list
393 if ((hVOS = OpenVosObject (&hCell, &status)) == NULL)
397 WORKERPACKET wpBegin;
398 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
399 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
401 if (!Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status))
408 wpNext.wpVosPartitionGetNext.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
409 if (!Worker_DoTask (wtaskVosPartitionGetNext, &wpNext, &status))
411 if (status == ADMITERATORDONE)
418 vos_partitionEntry_p pData = &wpNext.wpVosPartitionGetNext.Data;
420 LPTSTR pszName = AnsiToString (pData->name);
421 LPTSTR pszDevice = AnsiToString (pData->deviceName);
423 LPAGGREGATE lpAggregate = New2 (AGGREGATE,(this, pszName, pszDevice));
425 lpAggregate->m_as.dwID = lpAggregate->GetID();
427 FreeString (pszDevice, pData->deviceName);
428 FreeString (pszName, pData->name);
430 lpAggregate->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
431 lpAggregate->m_as.ckStorageTotal = pData->totalSpace;
432 lpAggregate->m_as.ckStorageFree = pData->totalFreeSpace;
433 m_lAggregates->Add (lpAggregate);
435 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpAggregate->GetIdentifier());
439 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
440 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
447 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd, GetIdentifier(), ((rc) ? 0 : status));
457 BOOL SERVER::RefreshServices (BOOL fNotify, ULONG *pStatus)
462 if (m_fServicesOutOfDate)
464 m_fServicesOutOfDate = FALSE;
469 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesBegin, GetIdentifier());
471 // First thing is to forget about what services we think we have now.
474 for (pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
476 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
477 lpService->SendDeleteNotifications();
478 m_lServices->Remove (lpService);
482 // Next, the harder part: look through the server to find a list
487 if ((hBOS = OpenBosObject (&hCell, &status)) == NULL)
491 WORKERPACKET wpBegin;
492 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
493 if (!Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status))
497 LPSERVICE lpService = New2 (SERVICE,(this, TEXT("BOS")));
498 m_lServices->Add (lpService);
499 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
503 TCHAR szServiceName[ cchNAME ];
506 wpNext.wpBosProcessNameGetNext.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
507 wpNext.wpBosProcessNameGetNext.pszService = szServiceName;
509 if (!Worker_DoTask (wtaskBosProcessNameGetNext, &wpNext, &status))
511 if (status == ADMITERATORDONE)
518 lpService = New2 (SERVICE,(this, wpNext.wpBosProcessNameGetNext.pszService));
519 m_lServices->Add (lpService);
520 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
524 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
525 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
532 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesEnd, GetIdentifier(), ((rc) ? 0 : status));
542 BOOL SERVER::RefreshStatus (BOOL fNotify, ULONG *pStatus)
547 if (m_fStatusOutOfDate)
549 m_fStatusOutOfDate = FALSE;
552 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
555 if ((lpCell = OpenCell (&status)) == NULL)
560 if ((hCell = lpCell->GetCellObject (&status)) == NULL)
565 wp.wpClientAFSServerGet.hCell = hCell;
566 wp.wpClientAFSServerGet.pszServer = m_szName;
568 if (!Worker_DoTask (wtaskClientAFSServerGet, &wp, &status))
574 for (size_t iAddr = 0; iAddr < AFS_MAX_SERVER_ADDRESS; ++iAddr)
576 if (wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ] == 0)
578 AfsClass_IntToAddress (&m_ss.aAddresses[ m_ss.nAddresses++ ], wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ]);
581 lpCell->m_lServers->Update (this); // That update affected a hashlistkey
588 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
597 void SERVER::GetName (LPTSTR pszName)
599 SERVER::ShortenName (pszName, m_szName);
603 void SERVER::GetLongName (LPTSTR pszName)
605 lstrcpy (pszName, m_szName);
609 LPCELL SERVER::OpenCell (ULONG *pStatus)
611 return m_lpiCell->OpenCell (pStatus);
614 BOOL SERVER::GetStatus (LPSERVERSTATUS lpss, BOOL fNotify, ULONG *pStatus)
619 rc = RefreshStatus (fNotify, pStatus);
621 memcpy (lpss, &m_ss, sizeof(SERVERSTATUS));
626 short SERVER::GetGhostStatus (void)
632 PVOID SERVER::GetUserParam (void)
634 return GetIdentifier()->GetUserParam();
638 void SERVER::SetUserParam (PVOID pUserNew)
640 GetIdentifier()->SetUserParam (pUserNew);
644 void SERVER::ShortenName (LPTSTR pszTarget, LPTSTR pszSource, BOOL fForce)
646 lstrcpy (pszTarget, pszSource);
648 if (fForce || !fLongServerNames)
650 // If the name is really an IP address, don't shorten it.
652 BOOL fIsIPAddress = TRUE;
653 for (LPTSTR pch = pszTarget; *pch && fIsIPAddress; ++pch)
655 if (!isdigit(*pch) && !(*pch == TEXT('.')))
656 fIsIPAddress = FALSE;
661 if ((pszTarget = (LPTSTR)lstrchr (pszTarget, TEXT('.'))) != NULL)
662 *pszTarget = TEXT('\0');
668 BOOL SERVER::fIsMonitored (void)
674 BOOL SERVER::SetMonitor (BOOL fShouldMonitor, ULONG *pStatus)
679 if (m_fMonitor != fShouldMonitor)
682 if ((lpCell = m_lpiCell->OpenCell (&status)) == NULL)
686 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
688 if ((m_fMonitor = fShouldMonitor) == FALSE)
691 (lpCell->m_nServersUnmonitored)++;
693 else // (fMonitor == TRUE)
695 (lpCell->m_nServersUnmonitored)--;
697 rc = RefreshAll (&status);
700 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
712 * REFRESHALL __________________________________________________________________
714 * If a server is down, or doesn't have an VOS process running, it could
715 * take some time before we time out trying to talk to the server. During
716 * the course of a refresh, the first timeout-and-fail that we will hit is
717 * our call to wtaskVosPartitionGetBegin; since this call is very quick if
718 * it's going to be successful, we can safely perform this call once up-front
719 * to test to see if the server is listening at all. That test is performed
720 * on a separate thread, so that in the event the request times out, we can
721 * simply discard the thread and let it terminate on its own.
731 } REFRESHSECTION, *LPREFRESHSECTION;
733 static REFRESHSECTION *aRefSec = NULL;
734 static size_t cRefSec = 0;
735 static LPCRITICAL_SECTION pcsRefSec = NULL;
737 void AfsClass_InitRefreshSections (void)
739 if (pcsRefSec == NULL)
741 pcsRefSec = New (CRITICAL_SECTION);
742 InitializeCriticalSection (pcsRefSec);
747 void AfsClass_SkipRefresh (int idSection)
749 AfsClass_InitRefreshSections();
750 EnterCriticalSection (pcsRefSec);
752 if (aRefSec && (idSection < (int)cRefSec))
754 if (aRefSec[ idSection ].fInUse)
756 aRefSec[ idSection ].fCanceled = TRUE;
760 LeaveCriticalSection (pcsRefSec);
764 DWORD WINAPI SERVER::CanTalkToServer_ThreadProc (PVOID lp)
766 int idSection = PtrToInt(lp);
768 // Until we post a notification saying that we've entered
769 // a section, we don't need to worry about the aRefSec[] entry
770 // being invalid. Once that post is made, the user can skip
771 // the section at any time--so we'll have to check frequently,
772 // always under the pcsRefSec critical section.
774 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionStart, NULL, NULL, NULL, NULL, idSection, 0);
776 BOOL fAggregatesOK = FALSE;
777 BOOL fServicesOK = FALSE;
778 BOOL fContinue = TRUE;
780 // Try to get the BOS object for this server. Remember, there's
781 // a catch here: we can only assume that the aRefSec[idSection].lpServer
782 // pointer is valid so long as we're within the pcsRefSec critical
783 // section! (if we're in that critsec, we can verify that no one
784 // has canceled the operation--and if no one has, there is a thread
785 // hanging around which holds the library's critsec, which ensures
786 // the lpServer pointer won't have been freed.)
792 TCHAR szServer[ cchNAME ];
794 EnterCriticalSection (pcsRefSec);
795 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
799 hCell = aRefSec[ idSection ].hCell;
800 aRefSec[ idSection ].lpServer->GetLongName (szServer);
802 LeaveCriticalSection (pcsRefSec);
807 wp.wpBosServerOpen.hCell = hCell;
808 wp.wpBosServerOpen.pszServer = szServer;
811 fContinue = Worker_DoTask (wtaskBosServerOpen, &wp, &status);
813 EnterCriticalSection (pcsRefSec);
814 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
817 aRefSec[ idSection ].lpServer->m_lastStatus = status;
819 hBOS = wp.wpBosServerOpen.hServer;
820 LeaveCriticalSection (pcsRefSec);
825 WORKERPACKET wpBegin;
826 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
829 fContinue = Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status);
831 EnterCriticalSection (pcsRefSec);
832 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
835 aRefSec[ idSection ].lpServer->m_lastStatus = status;
836 LeaveCriticalSection (pcsRefSec);
841 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
842 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
844 // We can talk to BOS!
849 // If we couldn't talk to BOS, it's a sure bet the server is down--
850 // and regardless, if BOS isn't around, VOS isn't either. So
851 // we may not even have to test that.
856 wp.wpVosServerOpen.hCell = hCell;
857 wp.wpVosServerOpen.pszServer = szServer;
860 fContinue = Worker_DoTask (wtaskVosServerOpen, &wp, &status);
862 EnterCriticalSection (pcsRefSec);
863 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
866 aRefSec[ idSection ].lpServer->m_lastStatus = status;
868 hVOS = wp.wpVosServerOpen.hServer;
869 LeaveCriticalSection (pcsRefSec);
874 WORKERPACKET wpBegin;
875 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
876 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
879 fContinue = Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status);
881 EnterCriticalSection (pcsRefSec);
882 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
885 aRefSec[ idSection ].lpServer->m_lastStatus = status;
886 LeaveCriticalSection (pcsRefSec);
891 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
892 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
894 // We can talk to VOS!
895 fAggregatesOK = TRUE;
899 // Close the VOS and BOS objects we obtained.
904 wp.wpBosServerClose.hServer = hBOS;
905 Worker_DoTask (wtaskBosServerClose, &wp);
910 wp.wpVosServerClose.hServer = hVOS;
911 Worker_DoTask (wtaskVosServerClose, &wp);
914 // Return our entry in the RefSec array back to the pool.
915 // If the request was never canceled, there is another
916 // thread waiting to hear our results--update the server
917 // entry specified by RefSec before leaving.
919 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionEnd, NULL, NULL, NULL, NULL, idSection, 0);
921 EnterCriticalSection (pcsRefSec);
922 if ( (aRefSec[ idSection ].fInUse) && (!aRefSec[ idSection ].fCanceled) )
924 aRefSec[ idSection ].lpServer->m_fCanGetAggregates = fAggregatesOK;
925 aRefSec[ idSection ].lpServer->m_fCanGetServices = fServicesOK;
927 aRefSec[ idSection ].fInUse = FALSE;
928 LeaveCriticalSection (pcsRefSec);
933 BOOL SERVER::CanTalkToServer (ULONG *pStatus)
935 // Ensure the server exists in the cell at all--
936 // this call just updates the server's IP addresses
937 // etc (information it gets from the database servers)
938 // and doesn't require talking to the server itself.
940 if (!RefreshStatus (FALSE, pStatus))
943 // Find a new refsec array element to use...
945 AfsClass_InitRefreshSections();
946 EnterCriticalSection (pcsRefSec);
949 for (idSection = 0; idSection < (int)cRefSec; ++idSection)
951 if (!aRefSec[ idSection ].fInUse)
954 if (idSection == (int)cRefSec)
956 if (!REALLOC (aRefSec, cRefSec, 1+idSection, 4))
959 *pStatus = GetLastError();
960 LeaveCriticalSection (pcsRefSec);
964 aRefSec[ idSection ].fInUse = TRUE;
965 aRefSec[ idSection ].fCanceled = FALSE;
966 aRefSec[ idSection ].lpServer = this;
967 aRefSec[ idSection ].hCell = NULL;
970 if ((lpCell = OpenCell()) != NULL)
972 aRefSec[ idSection ].hCell = lpCell->GetCellObject();
976 LeaveCriticalSection (pcsRefSec);
978 // Until we find out differently, assume that we won't be
979 // able to query VOS or BOS on this server.
981 m_fCanGetAggregates = FALSE;
982 m_fCanGetServices = FALSE;
985 // Fork a separate thread, on which to quickly try to talk
990 if ((hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)CanTalkToServer_ThreadProc, IntToPtr(idSection), 0, &dwThreadID)) == NULL)
992 EnterCriticalSection (pcsRefSec);
993 aRefSec[ idSection ].fInUse = FALSE;
994 LeaveCriticalSection (pcsRefSec);
996 *pStatus = GetLastError();
999 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
1001 // Wait for that thread to terminate, or for our
1002 // newly-allocated RefSec entry to be marked Canceled.
1005 for (dw = STILL_ACTIVE; dw == STILL_ACTIVE; )
1007 EnterCriticalSection (pcsRefSec);
1009 GetExitCodeThread (hThread, &dw);
1010 if (dw == STILL_ACTIVE)
1012 if ( (aRefSec[ idSection ].fInUse) &&
1013 (aRefSec[ idSection ].lpServer == this) &&
1014 (aRefSec[ idSection ].fCanceled) )
1016 if (m_lastStatus == 0)
1017 m_lastStatus = ERROR_CANCELLED;
1022 LeaveCriticalSection (pcsRefSec);
1024 if (dw == STILL_ACTIVE)
1025 Sleep(100); // wait another brief instant
1028 // dw == 0 : user canceled operation (thread is still running!)
1029 // dw == 1 : thread completed successfully, and set fCanTalkTo* flags.
1031 // Note that the thread will clear aRefSec[idSection].fInUse when it
1032 // terminates (so, if dw!=-1, it has already done so).
1035 *pStatus = m_lastStatus;
1036 return (dw == 0) ? FALSE : TRUE;
1040 BOOL SERVER::RefreshAll (ULONG *pStatus, double dInit, double dFactor)
1045 if (m_fAggregatesOutOfDate || m_fServicesOutOfDate)
1047 if ((++cRefreshAllReq) == 1)
1049 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier(), 0);
1052 double perAGGREGATES = 65.0; // % of time spent finding aggs & sets
1053 double perSERVICES = 25.0; // % of time spent finding services
1054 double perVLDB = 10.0; // % of time spent finding VLDB info
1056 if (cRefreshAllReq >= 2) // being called as part of a cell-wide op?
1058 perAGGREGATES = 80.0; // % of time spent finding aggs & sets
1059 perSERVICES = 20.0; // % of time spent finding services
1060 perVLDB = 0.0; // we won't query VLDB stuff ourself.
1063 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
1065 if (!CanTalkToServer (&status)) // Determines fCanGetAggregates, fCanGetServices
1073 if (!m_fCanGetAggregates)
1076 m_fAggregatesOutOfDate = FALSE;
1080 size_t nAggregates = 0;
1081 size_t iAggregate = 0;
1083 LPAGGREGATE lpAggregate;
1084 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1087 lpAggregate->Close();
1092 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1094 ULONG perComplete = (ULONG)( ((double)perAGGREGATES / 100.0) * ((double)iAggregate * 100.0 / nAggregates) );
1095 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpAggregate->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1097 lpAggregate->RefreshFilesets (TRUE);
1098 lpAggregate->Close();
1105 if (!m_fCanGetServices)
1108 m_fServicesOutOfDate = FALSE;
1112 size_t nServices = 0;
1113 size_t iService = 0;
1115 LPSERVICE lpService;
1116 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1124 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1126 ULONG perComplete = (ULONG)( (double)perAGGREGATES + ((double)perSERVICES / 100.0) * ((double)iService * 100.0 / nServices) );
1127 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpService->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1129 lpService->RefreshStatus (TRUE);
1137 if (cRefreshAllReq == 1) // not being called as part of a cell-wide op?
1140 if ((lpCell = OpenCell()) != NULL)
1142 lpCell->RefreshVLDB (GetIdentifier(), TRUE, NULL);
1148 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
1150 if ((--cRefreshAllReq) == 0)
1152 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd, GetIdentifier(), NULL, NULL, NULL, 100, m_lastStatus);
1156 if (rc && m_lastStatus)
1165 * AGGREGATES _________________________________________________________________
1169 LPAGGREGATE SERVER::OpenAggregate (LPTSTR pszName, ULONG *pStatus)
1171 if (!RefreshAggregates (TRUE, pStatus))
1174 LPAGGREGATE lpAggregate;
1175 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateName->GetFirstObject (pszName))) != NULL)
1182 LPAGGREGATE SERVER::OpenAggregate (ULONG dwID, ULONG *pStatus)
1184 if (!RefreshAggregates (TRUE, pStatus))
1187 LPAGGREGATE lpAggregate;
1188 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateID->GetFirstObject (&dwID))) != NULL)
1195 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1197 return AggregateFindFirst (phEnum, NULL, fNotify, pStatus);
1201 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1203 LPAGGREGATE lpAggregate = NULL;
1205 if (!RefreshAggregates (fNotify, pStatus))
1208 if (lpiFind != NULL)
1210 lpAggregate = lpiFind->OpenAggregate();
1213 else if ((*phEnum = m_lAggregates->FindFirst()) != NULL)
1215 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1219 if (!lpAggregate && pStatus)
1220 *pStatus = ERROR_FILE_NOT_FOUND;
1225 LPAGGREGATE SERVER::AggregateFindNext (HENUM *phEnum)
1227 LPAGGREGATE lpAggregate = NULL;
1231 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1233 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1242 void SERVER::AggregateFindClose (HENUM *phEnum)
1253 * SERVICES ___________________________________________________________________
1257 LPSERVICE SERVER::OpenService (LPTSTR pszName, ULONG *pStatus)
1259 if (!RefreshServices (TRUE, pStatus))
1262 LPSERVICE lpService;
1263 if ((lpService = (LPSERVICE)(m_lkServiceName->GetFirstObject (pszName))) != NULL)
1270 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1272 return ServiceFindFirst (phEnum, NULL, fNotify, pStatus);
1276 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1278 LPSERVICE lpService = NULL;
1280 if (!RefreshServices (fNotify, pStatus))
1283 if (lpiFind != NULL)
1285 lpService = lpiFind->OpenService();
1288 else if ((*phEnum = m_lServices->FindFirst()) != NULL)
1290 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1294 if (!lpService && pStatus)
1295 *pStatus = ERROR_FILE_NOT_FOUND;
1300 LPSERVICE SERVER::ServiceFindNext (HENUM *phEnum)
1302 LPSERVICE lpService = NULL;
1306 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1308 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1317 void SERVER::ServiceFindClose (HENUM *phEnum)
1328 * HASH KEYS __________________________________________________________________
1332 BOOL CALLBACK SERVER::KeyAggregateName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1334 return !lstrcmp (((LPAGGREGATE)pObject)->m_szName, (LPTSTR)pData);
1337 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1339 return SERVER::KeyAggregateName_HashData (pKey, ((LPAGGREGATE)pObject)->m_szName);
1342 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1344 return HashString ((LPTSTR)pData);
1348 BOOL CALLBACK SERVER::KeyAggregateID_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1350 return (((LPAGGREGATE)pObject)->m_as.dwID == *(ULONG*)pData);
1353 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1355 return SERVER::KeyAggregateID_HashData (pKey, &((LPAGGREGATE)pObject)->m_as.dwID);
1358 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashData (LPHASHLISTKEY pKey, PVOID pData)
1360 return (HASHVALUE)*(ULONG*)pData;
1364 BOOL CALLBACK SERVER::KeyServiceName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1366 return !lstrcmp (((LPSERVICE)pObject)->m_szName, (LPTSTR)pData);
1369 HASHVALUE CALLBACK SERVER::KeyServiceName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1371 return SERVER::KeyServiceName_HashData (pKey, ((LPSERVICE)pObject)->m_szName);
1374 HASHVALUE CALLBACK SERVER::KeyServiceName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1376 return HashString ((LPTSTR)pData);