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)
162 for (pEnum = m_lAggregates->FindFirst(); pEnum; pEnum = pEnum->FindNext())
164 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
165 lpAggregate->SendDeleteNotifications ();
168 for (pEnum = m_lServices->FindFirst(); pEnum; pEnum = pEnum->FindNext())
170 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
171 lpService->SendDeleteNotifications();
174 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
178 void SERVER::Close (void)
184 LPIDENT SERVER::GetIdentifier (void)
186 if (m_lpiThis == NULL)
188 if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
189 m_lpiThis = New2 (IDENT,(this));
190 m_lpiThis->m_cRef ++;
197 PVOID SERVER::OpenBosObject (PVOID *phCell, ULONG *pStatus)
201 if ((m_lpCellBOS = m_lpiCell->OpenCell (pStatus)) != NULL)
203 if ((m_hCellBOS = m_lpCellBOS->GetCellObject (pStatus)) != NULL)
205 TCHAR szCell[ cchNAME ];
206 m_lpiCell->GetCellName (szCell);
209 wp.wpBosServerOpen.hCell = m_hCellBOS;
210 wp.wpBosServerOpen.pszServer = m_szName;
211 if (Worker_DoTask (wtaskBosServerOpen, &wp, pStatus))
212 m_hBOS = wp.wpBosServerOpen.hServer;
217 m_lpCellBOS->Close();
227 *phCell = m_hCellBOS;
234 BOOL SERVER::CloseBosObject (ULONG *pStatus)
238 if ((m_cReqBOS > 0) && ((--m_cReqBOS) == 0))
243 wp.wpBosServerClose.hServer = m_hBOS;
244 if (!Worker_DoTask (wtaskBosServerClose, &wp, pStatus))
248 if (m_lpCellBOS != NULL)
250 m_lpCellBOS->Close();
259 PVOID SERVER::OpenVosObject (PVOID *phCell, ULONG *pStatus)
264 if ((lpCell = m_lpiCell->OpenCell (pStatus)) != NULL)
266 m_hCellVOS = lpCell->GetCellObject (pStatus);
271 if (m_hCellVOS && !m_hVOS)
273 TCHAR szCell[ cchNAME ];
274 m_lpiCell->GetCellName (szCell);
277 wp.wpVosServerOpen.hCell = m_hCellVOS;
278 wp.wpVosServerOpen.pszServer = m_szName;
279 if (Worker_DoTask (wtaskVosServerOpen, &wp, pStatus))
280 m_hVOS = wp.wpVosServerOpen.hServer;
286 *phCell = m_hCellVOS;
293 BOOL SERVER::CloseVosObject (ULONG *pStatus)
297 if ((m_cReqVOS > 0) && ((--m_cReqVOS) == 0))
302 wp.wpVosServerClose.hServer = m_hVOS;
303 if (!Worker_DoTask (wtaskVosServerClose, &wp, pStatus))
315 void SERVER::Invalidate (void)
317 if (!m_fAggregatesOutOfDate || !m_fServicesOutOfDate || !m_fStatusOutOfDate)
319 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
321 m_fAggregatesOutOfDate = TRUE;
322 m_fServicesOutOfDate = TRUE;
323 m_fStatusOutOfDate = TRUE;
326 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
331 void SERVER::InvalidateStatus (void)
333 if (!m_fStatusOutOfDate)
335 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
337 m_fStatusOutOfDate = TRUE;
340 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
345 void SERVER::InvalidateServices (void)
347 if (!m_fServicesOutOfDate)
349 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
351 m_fServicesOutOfDate = TRUE;
354 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
359 BOOL SERVER::RefreshAggregates (BOOL fNotify, ULONG *pStatus)
364 if (m_fAggregatesOutOfDate)
366 m_fAggregatesOutOfDate = FALSE;
371 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin, GetIdentifier());
373 // First thing is to forget about what aggregates we think we have
377 for (pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
379 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
380 lpAggregate->SendDeleteNotifications();
381 m_lAggregates->Remove (lpAggregate);
382 Delete (lpAggregate);
385 // Next, the harder part: look through the server to find a list
390 if ((hVOS = OpenVosObject (&hCell, &status)) == NULL)
394 WORKERPACKET wpBegin;
395 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
396 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
398 if (!Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status))
405 wpNext.wpVosPartitionGetNext.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
406 if (!Worker_DoTask (wtaskVosPartitionGetNext, &wpNext, &status))
408 if (status == ADMITERATORDONE)
415 vos_partitionEntry_p pData = &wpNext.wpVosPartitionGetNext.Data;
417 LPTSTR pszName = AnsiToString (pData->name);
418 LPTSTR pszDevice = AnsiToString (pData->deviceName);
420 LPAGGREGATE lpAggregate = New2 (AGGREGATE,(this, pszName, pszDevice));
422 lpAggregate->m_as.dwID = lpAggregate->GetID();
424 FreeString (pszDevice, pData->deviceName);
425 FreeString (pszName, pData->name);
427 lpAggregate->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
428 lpAggregate->m_as.ckStorageTotal = pData->totalSpace;
429 lpAggregate->m_as.ckStorageFree = pData->totalFreeSpace;
430 m_lAggregates->Add (lpAggregate);
432 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpAggregate->GetIdentifier());
436 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
437 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
444 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd, GetIdentifier(), ((rc) ? 0 : status));
454 BOOL SERVER::RefreshServices (BOOL fNotify, ULONG *pStatus)
459 if (m_fServicesOutOfDate)
461 m_fServicesOutOfDate = FALSE;
466 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesBegin, GetIdentifier());
468 // First thing is to forget about what services we think we have now.
471 for (pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
473 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
474 lpService->SendDeleteNotifications();
475 m_lServices->Remove (lpService);
479 // Next, the harder part: look through the server to find a list
484 if ((hBOS = OpenBosObject (&hCell, &status)) == NULL)
488 WORKERPACKET wpBegin;
489 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
490 if (!Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status))
494 LPSERVICE lpService = New2 (SERVICE,(this, TEXT("BOS")));
495 m_lServices->Add (lpService);
496 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
500 TCHAR szServiceName[ cchNAME ];
503 wpNext.wpBosProcessNameGetNext.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
504 wpNext.wpBosProcessNameGetNext.pszService = szServiceName;
506 if (!Worker_DoTask (wtaskBosProcessNameGetNext, &wpNext, &status))
508 if (status == ADMITERATORDONE)
515 lpService = New2 (SERVICE,(this, wpNext.wpBosProcessNameGetNext.pszService));
516 m_lServices->Add (lpService);
517 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
521 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
522 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
529 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesEnd, GetIdentifier(), ((rc) ? 0 : status));
539 BOOL SERVER::RefreshStatus (BOOL fNotify, ULONG *pStatus)
544 if (m_fStatusOutOfDate)
546 m_fStatusOutOfDate = FALSE;
549 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
552 if ((lpCell = OpenCell (&status)) == NULL)
557 if ((hCell = lpCell->GetCellObject (&status)) == NULL)
562 wp.wpClientAFSServerGet.hCell = hCell;
563 wp.wpClientAFSServerGet.pszServer = m_szName;
565 if (!Worker_DoTask (wtaskClientAFSServerGet, &wp, &status))
571 for (size_t iAddr = 0; iAddr < AFS_MAX_SERVER_ADDRESS; ++iAddr)
573 if (wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ] == 0)
575 AfsClass_IntToAddress (&m_ss.aAddresses[ m_ss.nAddresses++ ], wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ]);
578 lpCell->m_lServers->Update (this); // That update affected a hashlistkey
585 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
594 void SERVER::GetName (LPTSTR pszName)
596 SERVER::ShortenName (pszName, m_szName);
600 void SERVER::GetLongName (LPTSTR pszName)
602 lstrcpy (pszName, m_szName);
606 LPCELL SERVER::OpenCell (ULONG *pStatus)
608 return m_lpiCell->OpenCell (pStatus);
611 BOOL SERVER::GetStatus (LPSERVERSTATUS lpss, BOOL fNotify, ULONG *pStatus)
616 rc = RefreshStatus (fNotify, pStatus);
618 memcpy (lpss, &m_ss, sizeof(SERVERSTATUS));
623 short SERVER::GetGhostStatus (void)
629 PVOID SERVER::GetUserParam (void)
631 return GetIdentifier()->GetUserParam();
635 void SERVER::SetUserParam (PVOID pUserNew)
637 GetIdentifier()->SetUserParam (pUserNew);
641 void SERVER::ShortenName (LPTSTR pszTarget, LPTSTR pszSource, BOOL fForce)
643 lstrcpy (pszTarget, pszSource);
645 if (fForce || !fLongServerNames)
647 // If the name is really an IP address, don't shorten it.
649 BOOL fIsIPAddress = TRUE;
650 for (LPTSTR pch = pszTarget; *pch && fIsIPAddress; ++pch)
652 if (!isdigit(*pch) && !(*pch == TEXT('.')))
653 fIsIPAddress = FALSE;
658 if ((pszTarget = (LPTSTR)lstrchr (pszTarget, TEXT('.'))) != NULL)
659 *pszTarget = TEXT('\0');
665 BOOL SERVER::fIsMonitored (void)
671 BOOL SERVER::SetMonitor (BOOL fShouldMonitor, ULONG *pStatus)
676 if (m_fMonitor != fShouldMonitor)
679 if ((lpCell = m_lpiCell->OpenCell (&status)) == NULL)
683 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
685 if ((m_fMonitor = fShouldMonitor) == FALSE)
688 (lpCell->m_nServersUnmonitored)++;
690 else // (fMonitor == TRUE)
692 (lpCell->m_nServersUnmonitored)--;
694 rc = RefreshAll (&status);
697 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
709 * REFRESHALL __________________________________________________________________
711 * If a server is down, or doesn't have an VOS process running, it could
712 * take some time before we time out trying to talk to the server. During
713 * the course of a refresh, the first timeout-and-fail that we will hit is
714 * our call to wtaskVosPartitionGetBegin; since this call is very quick if
715 * it's going to be successful, we can safely perform this call once up-front
716 * to test to see if the server is listening at all. That test is performed
717 * on a separate thread, so that in the event the request times out, we can
718 * simply discard the thread and let it terminate on its own.
728 } REFRESHSECTION, *LPREFRESHSECTION;
730 static REFRESHSECTION *aRefSec = NULL;
731 static size_t cRefSec = 0;
732 static LPCRITICAL_SECTION pcsRefSec = NULL;
734 void AfsClass_InitRefreshSections (void)
736 if (pcsRefSec == NULL)
738 pcsRefSec = New (CRITICAL_SECTION);
739 InitializeCriticalSection (pcsRefSec);
744 void AfsClass_SkipRefresh (int idSection)
746 AfsClass_InitRefreshSections();
747 EnterCriticalSection (pcsRefSec);
749 if (aRefSec && (idSection < (int)cRefSec))
751 if (aRefSec[ idSection ].fInUse)
753 aRefSec[ idSection ].fCanceled = TRUE;
757 LeaveCriticalSection (pcsRefSec);
761 DWORD WINAPI SERVER::CanTalkToServer_ThreadProc (PVOID lp)
763 int idSection = PtrToInt(lp);
765 // Until we post a notification saying that we've entered
766 // a section, we don't need to worry about the aRefSec[] entry
767 // being invalid. Once that post is made, the user can skip
768 // the section at any time--so we'll have to check frequently,
769 // always under the pcsRefSec critical section.
771 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionStart, NULL, NULL, NULL, NULL, idSection, 0);
773 BOOL fAggregatesOK = FALSE;
774 BOOL fServicesOK = FALSE;
775 BOOL fContinue = TRUE;
777 // Try to get the BOS object for this server. Remember, there's
778 // a catch here: we can only assume that the aRefSec[idSection].lpServer
779 // pointer is valid so long as we're within the pcsRefSec critical
780 // section! (if we're in that critsec, we can verify that no one
781 // has canceled the operation--and if no one has, there is a thread
782 // hanging around which holds the library's critsec, which ensures
783 // the lpServer pointer won't have been freed.)
789 TCHAR szServer[ cchNAME ];
791 EnterCriticalSection (pcsRefSec);
792 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
796 hCell = aRefSec[ idSection ].hCell;
797 aRefSec[ idSection ].lpServer->GetLongName (szServer);
799 LeaveCriticalSection (pcsRefSec);
804 wp.wpBosServerOpen.hCell = hCell;
805 wp.wpBosServerOpen.pszServer = szServer;
808 fContinue = Worker_DoTask (wtaskBosServerOpen, &wp, &status);
810 EnterCriticalSection (pcsRefSec);
811 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
814 aRefSec[ idSection ].lpServer->m_lastStatus = status;
816 hBOS = wp.wpBosServerOpen.hServer;
817 LeaveCriticalSection (pcsRefSec);
822 WORKERPACKET wpBegin;
823 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
826 fContinue = Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status);
828 EnterCriticalSection (pcsRefSec);
829 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
832 aRefSec[ idSection ].lpServer->m_lastStatus = status;
833 LeaveCriticalSection (pcsRefSec);
838 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
839 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
841 // We can talk to BOS!
846 // If we couldn't talk to BOS, it's a sure bet the server is down--
847 // and regardless, if BOS isn't around, VOS isn't either. So
848 // we may not even have to test that.
853 wp.wpVosServerOpen.hCell = hCell;
854 wp.wpVosServerOpen.pszServer = szServer;
857 fContinue = Worker_DoTask (wtaskVosServerOpen, &wp, &status);
859 EnterCriticalSection (pcsRefSec);
860 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
863 aRefSec[ idSection ].lpServer->m_lastStatus = status;
865 hVOS = wp.wpVosServerOpen.hServer;
866 LeaveCriticalSection (pcsRefSec);
871 WORKERPACKET wpBegin;
872 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
873 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
876 fContinue = Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status);
878 EnterCriticalSection (pcsRefSec);
879 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
882 aRefSec[ idSection ].lpServer->m_lastStatus = status;
883 LeaveCriticalSection (pcsRefSec);
888 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
889 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
891 // We can talk to VOS!
892 fAggregatesOK = TRUE;
896 // Close the VOS and BOS objects we obtained.
901 wp.wpBosServerClose.hServer = hBOS;
902 Worker_DoTask (wtaskBosServerClose, &wp);
907 wp.wpVosServerClose.hServer = hVOS;
908 Worker_DoTask (wtaskVosServerClose, &wp);
911 // Return our entry in the RefSec array back to the pool.
912 // If the request was never canceled, there is another
913 // thread waiting to hear our results--update the server
914 // entry specified by RefSec before leaving.
916 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionEnd, NULL, NULL, NULL, NULL, idSection, 0);
918 EnterCriticalSection (pcsRefSec);
919 if ( (aRefSec[ idSection ].fInUse) && (!aRefSec[ idSection ].fCanceled) )
921 aRefSec[ idSection ].lpServer->m_fCanGetAggregates = fAggregatesOK;
922 aRefSec[ idSection ].lpServer->m_fCanGetServices = fServicesOK;
924 aRefSec[ idSection ].fInUse = FALSE;
925 LeaveCriticalSection (pcsRefSec);
930 BOOL SERVER::CanTalkToServer (ULONG *pStatus)
932 // Ensure the server exists in the cell at all--
933 // this call just updates the server's IP addresses
934 // etc (information it gets from the database servers)
935 // and doesn't require talking to the server itself.
937 if (!RefreshStatus (FALSE, pStatus))
940 // Find a new refsec array element to use...
942 AfsClass_InitRefreshSections();
943 EnterCriticalSection (pcsRefSec);
946 for (idSection = 0; idSection < (int)cRefSec; ++idSection)
948 if (!aRefSec[ idSection ].fInUse)
951 if (idSection == (int)cRefSec)
953 if (!REALLOC (aRefSec, cRefSec, 1+idSection, 4))
956 *pStatus = GetLastError();
957 LeaveCriticalSection (pcsRefSec);
961 aRefSec[ idSection ].fInUse = TRUE;
962 aRefSec[ idSection ].fCanceled = FALSE;
963 aRefSec[ idSection ].lpServer = this;
964 aRefSec[ idSection ].hCell = NULL;
967 if ((lpCell = OpenCell()) != NULL)
969 aRefSec[ idSection ].hCell = lpCell->GetCellObject();
973 LeaveCriticalSection (pcsRefSec);
975 // Until we find out differently, assume that we won't be
976 // able to query VOS or BOS on this server.
978 m_fCanGetAggregates = FALSE;
979 m_fCanGetServices = FALSE;
982 // Fork a separate thread, on which to quickly try to talk
987 if ((hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)CanTalkToServer_ThreadProc, IntToPtr(idSection), 0, &dwThreadID)) == NULL)
989 EnterCriticalSection (pcsRefSec);
990 aRefSec[ idSection ].fInUse = FALSE;
991 LeaveCriticalSection (pcsRefSec);
993 *pStatus = GetLastError();
996 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
998 // Wait for that thread to terminate, or for our
999 // newly-allocated RefSec entry to be marked Canceled.
1002 for (dw = STILL_ACTIVE; dw == STILL_ACTIVE; )
1004 EnterCriticalSection (pcsRefSec);
1006 GetExitCodeThread (hThread, &dw);
1007 if (dw == STILL_ACTIVE)
1009 if ( (aRefSec[ idSection ].fInUse) &&
1010 (aRefSec[ idSection ].lpServer == this) &&
1011 (aRefSec[ idSection ].fCanceled) )
1013 if (m_lastStatus == 0)
1014 m_lastStatus = ERROR_CANCELLED;
1019 LeaveCriticalSection (pcsRefSec);
1021 if (dw == STILL_ACTIVE)
1022 Sleep(100); // wait another brief instant
1025 // dw == 0 : user canceled operation (thread is still running!)
1026 // dw == 1 : thread completed successfully, and set fCanTalkTo* flags.
1028 // Note that the thread will clear aRefSec[idSection].fInUse when it
1029 // terminates (so, if dw!=-1, it has already done so).
1032 *pStatus = m_lastStatus;
1033 return (dw == 0) ? FALSE : TRUE;
1037 BOOL SERVER::RefreshAll (ULONG *pStatus, double dInit, double dFactor)
1042 if (m_fAggregatesOutOfDate || m_fServicesOutOfDate)
1044 if ((++cRefreshAllReq) == 1)
1046 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier(), 0);
1049 double perAGGREGATES = 65.0; // % of time spent finding aggs & sets
1050 double perSERVICES = 25.0; // % of time spent finding services
1051 double perVLDB = 10.0; // % of time spent finding VLDB info
1053 if (cRefreshAllReq >= 2) // being called as part of a cell-wide op?
1055 perAGGREGATES = 80.0; // % of time spent finding aggs & sets
1056 perSERVICES = 20.0; // % of time spent finding services
1057 perVLDB = 0.0; // we won't query VLDB stuff ourself.
1060 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
1062 if (!CanTalkToServer (&status)) // Determines fCanGetAggregates, fCanGetServices
1070 if (!m_fCanGetAggregates)
1073 m_fAggregatesOutOfDate = FALSE;
1077 size_t nAggregates = 0;
1078 size_t iAggregate = 0;
1080 LPAGGREGATE lpAggregate;
1081 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1084 lpAggregate->Close();
1089 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1091 ULONG perComplete = (ULONG)( ((double)perAGGREGATES / 100.0) * ((double)iAggregate * 100.0 / nAggregates) );
1092 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpAggregate->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1094 lpAggregate->RefreshFilesets (TRUE);
1095 lpAggregate->Close();
1102 if (!m_fCanGetServices)
1105 m_fServicesOutOfDate = FALSE;
1109 size_t nServices = 0;
1110 size_t iService = 0;
1112 LPSERVICE lpService;
1113 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1121 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1123 ULONG perComplete = (ULONG)( (double)perAGGREGATES + ((double)perSERVICES / 100.0) * ((double)iService * 100.0 / nServices) );
1124 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpService->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1126 lpService->RefreshStatus (TRUE);
1134 if (cRefreshAllReq == 1) // not being called as part of a cell-wide op?
1137 if ((lpCell = OpenCell()) != NULL)
1139 lpCell->RefreshVLDB (GetIdentifier(), TRUE, NULL);
1145 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
1147 if ((--cRefreshAllReq) == 0)
1149 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd, GetIdentifier(), NULL, NULL, NULL, 100, m_lastStatus);
1153 if (rc && m_lastStatus)
1162 * AGGREGATES _________________________________________________________________
1166 LPAGGREGATE SERVER::OpenAggregate (LPTSTR pszName, ULONG *pStatus)
1168 if (!RefreshAggregates (TRUE, pStatus))
1171 LPAGGREGATE lpAggregate;
1172 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateName->GetFirstObject (pszName))) != NULL)
1179 LPAGGREGATE SERVER::OpenAggregate (ULONG dwID, ULONG *pStatus)
1181 if (!RefreshAggregates (TRUE, pStatus))
1184 LPAGGREGATE lpAggregate;
1185 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateID->GetFirstObject (&dwID))) != NULL)
1192 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1194 return AggregateFindFirst (phEnum, NULL, fNotify, pStatus);
1198 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1200 LPAGGREGATE lpAggregate = NULL;
1202 if (!RefreshAggregates (fNotify, pStatus))
1205 if (lpiFind != NULL)
1207 lpAggregate = lpiFind->OpenAggregate();
1210 else if ((*phEnum = m_lAggregates->FindFirst()) != NULL)
1212 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1216 if (!lpAggregate && pStatus)
1217 *pStatus = ERROR_FILE_NOT_FOUND;
1222 LPAGGREGATE SERVER::AggregateFindNext (HENUM *phEnum)
1224 LPAGGREGATE lpAggregate = NULL;
1228 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1230 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1239 void SERVER::AggregateFindClose (HENUM *phEnum)
1250 * SERVICES ___________________________________________________________________
1254 LPSERVICE SERVER::OpenService (LPTSTR pszName, ULONG *pStatus)
1256 if (!RefreshServices (TRUE, pStatus))
1259 LPSERVICE lpService;
1260 if ((lpService = (LPSERVICE)(m_lkServiceName->GetFirstObject (pszName))) != NULL)
1267 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1269 return ServiceFindFirst (phEnum, NULL, fNotify, pStatus);
1273 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1275 LPSERVICE lpService = NULL;
1277 if (!RefreshServices (fNotify, pStatus))
1280 if (lpiFind != NULL)
1282 lpService = lpiFind->OpenService();
1285 else if ((*phEnum = m_lServices->FindFirst()) != NULL)
1287 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1291 if (!lpService && pStatus)
1292 *pStatus = ERROR_FILE_NOT_FOUND;
1297 LPSERVICE SERVER::ServiceFindNext (HENUM *phEnum)
1299 LPSERVICE lpService = NULL;
1303 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1305 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1314 void SERVER::ServiceFindClose (HENUM *phEnum)
1325 * HASH KEYS __________________________________________________________________
1329 BOOL CALLBACK SERVER::KeyAggregateName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1331 return !lstrcmp (((LPAGGREGATE)pObject)->m_szName, (LPTSTR)pData);
1334 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1336 return SERVER::KeyAggregateName_HashData (pKey, ((LPAGGREGATE)pObject)->m_szName);
1339 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1341 return HashString ((LPTSTR)pData);
1345 BOOL CALLBACK SERVER::KeyAggregateID_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1347 return (((LPAGGREGATE)pObject)->m_as.dwID == *(ULONG*)pData);
1350 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1352 return SERVER::KeyAggregateID_HashData (pKey, &((LPAGGREGATE)pObject)->m_as.dwID);
1355 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashData (LPHASHLISTKEY pKey, PVOID pData)
1357 return (HASHVALUE)*(ULONG*)pData;
1361 BOOL CALLBACK SERVER::KeyServiceName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1363 return !lstrcmp (((LPSERVICE)pObject)->m_szName, (LPTSTR)pData);
1366 HASHVALUE CALLBACK SERVER::KeyServiceName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1368 return SERVER::KeyServiceName_HashData (pKey, ((LPSERVICE)pObject)->m_szName);
1371 HASHVALUE CALLBACK SERVER::KeyServiceName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1373 return HashString ((LPTSTR)pData);