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_fStatusOutOfDate = TRUE;
93 memset (&m_ss, 0x00, sizeof(SERVERSTATUS));
97 SERVER::~SERVER (void)
102 if ((lpCell = m_lpiCell->OpenCell()) != NULL)
104 (lpCell->m_nServersUnmonitored)--;
110 m_lpiThis->m_cRef --;
113 Delete (m_lAggregates);
114 Delete (m_lServices);
118 void SERVER::FreeAll (void)
136 void SERVER::FreeAggregates (void)
138 for (LPENUM pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
140 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
141 m_lAggregates->Remove (lpAggregate);
142 Delete (lpAggregate);
147 void SERVER::FreeServices (void)
149 for (LPENUM pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
151 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
152 m_lServices->Remove (lpService);
158 void SERVER::SendDeleteNotifications (void)
160 for (LPENUM pEnum = m_lAggregates->FindFirst(); pEnum; pEnum = pEnum->FindNext())
162 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
163 lpAggregate->SendDeleteNotifications ();
166 for (pEnum = m_lServices->FindFirst(); pEnum; pEnum = pEnum->FindNext())
168 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
169 lpService->SendDeleteNotifications();
172 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
176 void SERVER::Close (void)
182 LPIDENT SERVER::GetIdentifier (void)
184 if (m_lpiThis == NULL)
186 if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
187 m_lpiThis = New2 (IDENT,(this));
188 m_lpiThis->m_cRef ++;
195 PVOID SERVER::OpenBosObject (PVOID *phCell, ULONG *pStatus)
199 if ((m_lpCellBOS = m_lpiCell->OpenCell (pStatus)) != NULL)
201 if ((m_hCellBOS = m_lpCellBOS->GetCellObject (pStatus)) != NULL)
203 TCHAR szCell[ cchNAME ];
204 m_lpiCell->GetCellName (szCell);
207 wp.wpBosServerOpen.hCell = m_hCellBOS;
208 wp.wpBosServerOpen.pszServer = m_szName;
209 if (Worker_DoTask (wtaskBosServerOpen, &wp, pStatus))
210 m_hBOS = wp.wpBosServerOpen.hServer;
215 m_lpCellBOS->Close();
225 *phCell = m_hCellBOS;
232 BOOL SERVER::CloseBosObject (ULONG *pStatus)
236 if ((m_cReqBOS > 0) && ((--m_cReqBOS) == 0))
241 wp.wpBosServerClose.hServer = m_hBOS;
242 if (!Worker_DoTask (wtaskBosServerClose, &wp, pStatus))
246 if (m_lpCellBOS != NULL)
248 m_lpCellBOS->Close();
257 PVOID SERVER::OpenVosObject (PVOID *phCell, ULONG *pStatus)
262 if ((lpCell = m_lpiCell->OpenCell (pStatus)) != NULL)
264 m_hCellVOS = lpCell->GetCellObject (pStatus);
269 if (m_hCellVOS && !m_hVOS)
271 TCHAR szCell[ cchNAME ];
272 m_lpiCell->GetCellName (szCell);
275 wp.wpVosServerOpen.hCell = m_hCellVOS;
276 wp.wpVosServerOpen.pszServer = m_szName;
277 if (Worker_DoTask (wtaskVosServerOpen, &wp, pStatus))
278 m_hVOS = wp.wpVosServerOpen.hServer;
284 *phCell = m_hCellVOS;
291 BOOL SERVER::CloseVosObject (ULONG *pStatus)
295 if ((m_cReqVOS > 0) && ((--m_cReqVOS) == 0))
300 wp.wpVosServerClose.hServer = m_hVOS;
301 if (!Worker_DoTask (wtaskVosServerClose, &wp, pStatus))
313 void SERVER::Invalidate (void)
315 if (!m_fAggregatesOutOfDate || !m_fServicesOutOfDate || !m_fStatusOutOfDate)
317 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
319 m_fAggregatesOutOfDate = TRUE;
320 m_fServicesOutOfDate = TRUE;
321 m_fStatusOutOfDate = TRUE;
324 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
329 void SERVER::InvalidateStatus (void)
331 if (!m_fStatusOutOfDate)
333 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
335 m_fStatusOutOfDate = TRUE;
338 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
343 void SERVER::InvalidateServices (void)
345 if (!m_fServicesOutOfDate)
347 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
349 m_fServicesOutOfDate = TRUE;
352 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
357 BOOL SERVER::RefreshAggregates (BOOL fNotify, ULONG *pStatus)
362 if (m_fAggregatesOutOfDate)
364 m_fAggregatesOutOfDate = FALSE;
369 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin, GetIdentifier());
371 // First thing is to forget about what aggregates we think we have
374 for (LPENUM pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
376 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
377 lpAggregate->SendDeleteNotifications();
378 m_lAggregates->Remove (lpAggregate);
379 Delete (lpAggregate);
382 // Next, the harder part: look through the server to find a list
387 if ((hVOS = OpenVosObject (&hCell, &status)) == NULL)
391 WORKERPACKET wpBegin;
392 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
393 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
395 if (!Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status))
402 wpNext.wpVosPartitionGetNext.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
403 if (!Worker_DoTask (wtaskVosPartitionGetNext, &wpNext, &status))
405 if (status == ADMITERATORDONE)
412 vos_partitionEntry_p pData = &wpNext.wpVosPartitionGetNext.Data;
414 LPTSTR pszName = AnsiToString (pData->name);
415 LPTSTR pszDevice = AnsiToString (pData->deviceName);
417 LPAGGREGATE lpAggregate = New2 (AGGREGATE,(this, pszName, pszDevice));
419 lpAggregate->m_as.dwID = lpAggregate->GetID();
421 FreeString (pszDevice, pData->deviceName);
422 FreeString (pszName, pData->name);
424 lpAggregate->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
425 lpAggregate->m_as.ckStorageTotal = pData->totalSpace;
426 lpAggregate->m_as.ckStorageFree = pData->totalFreeSpace;
427 m_lAggregates->Add (lpAggregate);
429 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpAggregate->GetIdentifier());
433 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
434 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
441 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd, GetIdentifier(), ((rc) ? 0 : status));
451 BOOL SERVER::RefreshServices (BOOL fNotify, ULONG *pStatus)
456 if (m_fServicesOutOfDate)
458 m_fServicesOutOfDate = FALSE;
463 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesBegin, GetIdentifier());
465 // First thing is to forget about what services we think we have now.
467 for (LPENUM pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
469 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
470 lpService->SendDeleteNotifications();
471 m_lServices->Remove (lpService);
475 // Next, the harder part: look through the server to find a list
480 if ((hBOS = OpenBosObject (&hCell, &status)) == NULL)
484 WORKERPACKET wpBegin;
485 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
486 if (!Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status))
490 LPSERVICE lpService = New2 (SERVICE,(this, TEXT("BOS")));
491 m_lServices->Add (lpService);
492 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
496 TCHAR szServiceName[ cchNAME ];
499 wpNext.wpBosProcessNameGetNext.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
500 wpNext.wpBosProcessNameGetNext.pszService = szServiceName;
502 if (!Worker_DoTask (wtaskBosProcessNameGetNext, &wpNext, &status))
504 if (status == ADMITERATORDONE)
511 lpService = New2 (SERVICE,(this, wpNext.wpBosProcessNameGetNext.pszService));
512 m_lServices->Add (lpService);
513 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
517 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
518 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
525 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesEnd, GetIdentifier(), ((rc) ? 0 : status));
535 BOOL SERVER::RefreshStatus (BOOL fNotify, ULONG *pStatus)
540 if (m_fStatusOutOfDate)
542 m_fStatusOutOfDate = FALSE;
545 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
548 if ((lpCell = OpenCell (&status)) == NULL)
553 if ((hCell = lpCell->GetCellObject (&status)) == NULL)
558 wp.wpClientAFSServerGet.hCell = hCell;
559 wp.wpClientAFSServerGet.pszServer = m_szName;
561 if (!Worker_DoTask (wtaskClientAFSServerGet, &wp, &status))
567 for (size_t iAddr = 0; iAddr < AFS_MAX_SERVER_ADDRESS; ++iAddr)
569 if (wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ] == 0)
571 AfsClass_IntToAddress (&m_ss.aAddresses[ m_ss.nAddresses++ ], wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ]);
574 lpCell->m_lServers->Update (this); // That update affected a hashlistkey
581 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
590 void SERVER::GetName (LPTSTR pszName)
592 SERVER::ShortenName (pszName, m_szName);
596 void SERVER::GetLongName (LPTSTR pszName)
598 lstrcpy (pszName, m_szName);
602 LPCELL SERVER::OpenCell (ULONG *pStatus)
604 return m_lpiCell->OpenCell (pStatus);
607 BOOL SERVER::GetStatus (LPSERVERSTATUS lpss, BOOL fNotify, ULONG *pStatus)
612 rc = RefreshStatus (fNotify, pStatus);
614 memcpy (lpss, &m_ss, sizeof(SERVERSTATUS));
619 short SERVER::GetGhostStatus (void)
625 PVOID SERVER::GetUserParam (void)
627 return GetIdentifier()->GetUserParam();
631 void SERVER::SetUserParam (PVOID pUserNew)
633 GetIdentifier()->SetUserParam (pUserNew);
637 void SERVER::ShortenName (LPTSTR pszTarget, LPTSTR pszSource, BOOL fForce)
639 lstrcpy (pszTarget, pszSource);
641 if (fForce || !fLongServerNames)
643 // If the name is really an IP address, don't shorten it.
645 BOOL fIsIPAddress = TRUE;
646 for (LPTSTR pch = pszTarget; *pch && fIsIPAddress; ++pch)
648 if (!isdigit(*pch) && !(*pch == TEXT('.')))
649 fIsIPAddress = FALSE;
654 if ((pszTarget = (LPTSTR)lstrchr (pszTarget, TEXT('.'))) != NULL)
655 *pszTarget = TEXT('\0');
661 BOOL SERVER::fIsMonitored (void)
667 BOOL SERVER::SetMonitor (BOOL fShouldMonitor, ULONG *pStatus)
672 if (m_fMonitor != fShouldMonitor)
675 if ((lpCell = m_lpiCell->OpenCell (&status)) == NULL)
679 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
681 if ((m_fMonitor = fShouldMonitor) == FALSE)
684 (lpCell->m_nServersUnmonitored)++;
686 else // (fMonitor == TRUE)
688 (lpCell->m_nServersUnmonitored)--;
690 rc = RefreshAll (&status);
693 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
705 * REFRESHALL __________________________________________________________________
707 * If a server is down, or doesn't have an VOS process running, it could
708 * take some time before we time out trying to talk to the server. During
709 * the course of a refresh, the first timeout-and-fail that we will hit is
710 * our call to wtaskVosPartitionGetBegin; since this call is very quick if
711 * it's going to be successful, we can safely perform this call once up-front
712 * to test to see if the server is listening at all. That test is performed
713 * on a separate thread, so that in the event the request times out, we can
714 * simply discard the thread and let it terminate on its own.
724 } REFRESHSECTION, *LPREFRESHSECTION;
726 static REFRESHSECTION *aRefSec = NULL;
727 static size_t cRefSec = 0;
728 static LPCRITICAL_SECTION pcsRefSec = NULL;
730 void AfsClass_InitRefreshSections (void)
732 if (pcsRefSec == NULL)
734 pcsRefSec = New (CRITICAL_SECTION);
735 InitializeCriticalSection (pcsRefSec);
740 void AfsClass_SkipRefresh (int idSection)
742 AfsClass_InitRefreshSections();
743 EnterCriticalSection (pcsRefSec);
745 if (aRefSec && (idSection < (int)cRefSec))
747 if (aRefSec[ idSection ].fInUse)
749 aRefSec[ idSection ].fCanceled = TRUE;
753 LeaveCriticalSection (pcsRefSec);
757 DWORD WINAPI SERVER::CanTalkToServer_ThreadProc (PVOID lp)
759 int idSection = (int)lp;
761 // Until we post a notification saying that we've entered
762 // a section, we don't need to worry about the aRefSec[] entry
763 // being invalid. Once that post is made, the user can skip
764 // the section at any time--so we'll have to check frequently,
765 // always under the pcsRefSec critical section.
767 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionStart, NULL, NULL, NULL, NULL, idSection, 0);
769 BOOL fAggregatesOK = FALSE;
770 BOOL fServicesOK = FALSE;
771 BOOL fContinue = TRUE;
773 // Try to get the BOS object for this server. Remember, there's
774 // a catch here: we can only assume that the aRefSec[idSection].lpServer
775 // pointer is valid so long as we're within the pcsRefSec critical
776 // section! (if we're in that critsec, we can verify that no one
777 // has canceled the operation--and if no one has, there is a thread
778 // hanging around which holds the library's critsec, which ensures
779 // the lpServer pointer won't have been freed.)
785 TCHAR szServer[ cchNAME ];
787 EnterCriticalSection (pcsRefSec);
788 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
792 hCell = aRefSec[ idSection ].hCell;
793 aRefSec[ idSection ].lpServer->GetLongName (szServer);
795 LeaveCriticalSection (pcsRefSec);
800 wp.wpBosServerOpen.hCell = hCell;
801 wp.wpBosServerOpen.pszServer = szServer;
804 fContinue = Worker_DoTask (wtaskBosServerOpen, &wp, &status);
806 EnterCriticalSection (pcsRefSec);
807 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
810 aRefSec[ idSection ].lpServer->m_lastStatus = status;
812 hBOS = wp.wpBosServerOpen.hServer;
813 LeaveCriticalSection (pcsRefSec);
818 WORKERPACKET wpBegin;
819 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
822 fContinue = Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status);
824 EnterCriticalSection (pcsRefSec);
825 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
828 aRefSec[ idSection ].lpServer->m_lastStatus = status;
829 LeaveCriticalSection (pcsRefSec);
834 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
835 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
837 // We can talk to BOS!
842 // If we couldn't talk to BOS, it's a sure bet the server is down--
843 // and regardless, if BOS isn't around, VOS isn't either. So
844 // we may not even have to test that.
849 wp.wpVosServerOpen.hCell = hCell;
850 wp.wpVosServerOpen.pszServer = szServer;
853 fContinue = Worker_DoTask (wtaskVosServerOpen, &wp, &status);
855 EnterCriticalSection (pcsRefSec);
856 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
859 aRefSec[ idSection ].lpServer->m_lastStatus = status;
861 hVOS = wp.wpVosServerOpen.hServer;
862 LeaveCriticalSection (pcsRefSec);
867 WORKERPACKET wpBegin;
868 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
869 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
872 fContinue = Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status);
874 EnterCriticalSection (pcsRefSec);
875 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
878 aRefSec[ idSection ].lpServer->m_lastStatus = status;
879 LeaveCriticalSection (pcsRefSec);
884 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
885 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
887 // We can talk to VOS!
888 fAggregatesOK = TRUE;
892 // Close the VOS and BOS objects we obtained.
897 wp.wpBosServerClose.hServer = hBOS;
898 Worker_DoTask (wtaskBosServerClose, &wp);
903 wp.wpVosServerClose.hServer = hVOS;
904 Worker_DoTask (wtaskVosServerClose, &wp);
907 // Return our entry in the RefSec array back to the pool.
908 // If the request was never canceled, there is another
909 // thread waiting to hear our results--update the server
910 // entry specified by RefSec before leaving.
912 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionEnd, NULL, NULL, NULL, NULL, idSection, 0);
914 EnterCriticalSection (pcsRefSec);
915 if ( (aRefSec[ idSection ].fInUse) && (!aRefSec[ idSection ].fCanceled) )
917 aRefSec[ idSection ].lpServer->m_fCanGetAggregates = fAggregatesOK;
918 aRefSec[ idSection ].lpServer->m_fCanGetServices = fServicesOK;
920 aRefSec[ idSection ].fInUse = FALSE;
921 LeaveCriticalSection (pcsRefSec);
926 BOOL SERVER::CanTalkToServer (ULONG *pStatus)
928 // Ensure the server exists in the cell at all--
929 // this call just updates the server's IP addresses
930 // etc (information it gets from the database servers)
931 // and doesn't require talking to the server itself.
933 if (!RefreshStatus (FALSE, pStatus))
936 // Find a new refsec array element to use...
938 AfsClass_InitRefreshSections();
939 EnterCriticalSection (pcsRefSec);
941 for (int idSection = 0; idSection < (int)cRefSec; ++idSection)
943 if (!aRefSec[ idSection ].fInUse)
946 if (idSection == (int)cRefSec)
948 if (!REALLOC (aRefSec, cRefSec, 1+idSection, 4))
951 *pStatus = GetLastError();
952 LeaveCriticalSection (pcsRefSec);
956 aRefSec[ idSection ].fInUse = TRUE;
957 aRefSec[ idSection ].fCanceled = FALSE;
958 aRefSec[ idSection ].lpServer = this;
959 aRefSec[ idSection ].hCell = NULL;
962 if ((lpCell = OpenCell()) != NULL)
964 aRefSec[ idSection ].hCell = lpCell->GetCellObject();
968 LeaveCriticalSection (pcsRefSec);
970 // Until we find out differently, assume that we won't be
971 // able to query VOS or BOS on this server.
973 m_fCanGetAggregates = FALSE;
974 m_fCanGetServices = FALSE;
977 // Fork a separate thread, on which to quickly try to talk
982 if ((hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)CanTalkToServer_ThreadProc, (PVOID)idSection, 0, &dwThreadID)) == NULL)
984 EnterCriticalSection (pcsRefSec);
985 aRefSec[ idSection ].fInUse = FALSE;
986 LeaveCriticalSection (pcsRefSec);
988 *pStatus = GetLastError();
991 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
993 // Wait for that thread to terminate, or for our
994 // newly-allocated RefSec entry to be marked Canceled.
996 for (DWORD dw = STILL_ACTIVE; dw == STILL_ACTIVE; )
998 EnterCriticalSection (pcsRefSec);
1000 GetExitCodeThread (hThread, &dw);
1001 if (dw == STILL_ACTIVE)
1003 if ( (aRefSec[ idSection ].fInUse) &&
1004 (aRefSec[ idSection ].lpServer == this) &&
1005 (aRefSec[ idSection ].fCanceled) )
1007 if (m_lastStatus == 0)
1008 m_lastStatus = ERROR_CANCELLED;
1013 LeaveCriticalSection (pcsRefSec);
1015 if (dw == STILL_ACTIVE)
1016 Sleep(100); // wait another brief instant
1019 // dw == 0 : user canceled operation (thread is still running!)
1020 // dw == 1 : thread completed successfully, and set fCanTalkTo* flags.
1022 // Note that the thread will clear aRefSec[idSection].fInUse when it
1023 // terminates (so, if dw!=-1, it has already done so).
1026 *pStatus = m_lastStatus;
1027 return (dw == 0) ? FALSE : TRUE;
1031 BOOL SERVER::RefreshAll (ULONG *pStatus, double dInit, double dFactor)
1036 if (m_fAggregatesOutOfDate || m_fServicesOutOfDate)
1038 if ((++cRefreshAllReq) == 1)
1040 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier(), 0);
1043 double perAGGREGATES = 65.0; // % of time spent finding aggs & sets
1044 double perSERVICES = 25.0; // % of time spent finding services
1045 double perVLDB = 10.0; // % of time spent finding VLDB info
1047 if (cRefreshAllReq >= 2) // being called as part of a cell-wide op?
1049 perAGGREGATES = 80.0; // % of time spent finding aggs & sets
1050 perSERVICES = 20.0; // % of time spent finding services
1051 perVLDB = 0.0; // we won't query VLDB stuff ourself.
1054 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
1056 if (!CanTalkToServer (&status)) // Determines fCanGetAggregates, fCanGetServices
1064 if (!m_fCanGetAggregates)
1067 m_fAggregatesOutOfDate = FALSE;
1071 size_t nAggregates = 0;
1072 size_t iAggregate = 0;
1074 for (LPAGGREGATE lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1077 lpAggregate->Close();
1082 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1084 ULONG perComplete = (ULONG)( ((double)perAGGREGATES / 100.0) * ((double)iAggregate * 100.0 / nAggregates) );
1085 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpAggregate->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1087 lpAggregate->RefreshFilesets (TRUE);
1088 lpAggregate->Close();
1095 if (!m_fCanGetServices)
1098 m_fServicesOutOfDate = FALSE;
1102 size_t nServices = 0;
1103 size_t iService = 0;
1105 for (LPSERVICE lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1113 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1115 ULONG perComplete = (ULONG)( (double)perAGGREGATES + ((double)perSERVICES / 100.0) * ((double)iService * 100.0 / nServices) );
1116 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpService->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1118 lpService->RefreshStatus (TRUE);
1126 if (cRefreshAllReq == 1) // not being called as part of a cell-wide op?
1129 if ((lpCell = OpenCell()) != NULL)
1131 lpCell->RefreshVLDB (GetIdentifier(), TRUE, NULL);
1137 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
1139 if ((--cRefreshAllReq) == 0)
1141 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd, GetIdentifier(), NULL, NULL, NULL, 100, m_lastStatus);
1145 if (rc && m_lastStatus)
1154 * AGGREGATES _________________________________________________________________
1158 LPAGGREGATE SERVER::OpenAggregate (LPTSTR pszName, ULONG *pStatus)
1160 if (!RefreshAggregates (TRUE, pStatus))
1163 LPAGGREGATE lpAggregate;
1164 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateName->GetFirstObject (pszName))) != NULL)
1171 LPAGGREGATE SERVER::OpenAggregate (ULONG dwID, ULONG *pStatus)
1173 if (!RefreshAggregates (TRUE, pStatus))
1176 LPAGGREGATE lpAggregate;
1177 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateID->GetFirstObject (&dwID))) != NULL)
1184 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1186 return AggregateFindFirst (phEnum, NULL, fNotify, pStatus);
1190 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1192 LPAGGREGATE lpAggregate = NULL;
1194 if (!RefreshAggregates (fNotify, pStatus))
1197 if (lpiFind != NULL)
1199 lpAggregate = lpiFind->OpenAggregate();
1202 else if ((*phEnum = m_lAggregates->FindFirst()) != NULL)
1204 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1208 if (!lpAggregate && pStatus)
1209 *pStatus = ERROR_FILE_NOT_FOUND;
1214 LPAGGREGATE SERVER::AggregateFindNext (HENUM *phEnum)
1216 LPAGGREGATE lpAggregate = NULL;
1220 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1222 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1231 void SERVER::AggregateFindClose (HENUM *phEnum)
1242 * SERVICES ___________________________________________________________________
1246 LPSERVICE SERVER::OpenService (LPTSTR pszName, ULONG *pStatus)
1248 if (!RefreshServices (TRUE, pStatus))
1251 LPSERVICE lpService;
1252 if ((lpService = (LPSERVICE)(m_lkServiceName->GetFirstObject (pszName))) != NULL)
1259 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1261 return ServiceFindFirst (phEnum, NULL, fNotify, pStatus);
1265 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1267 LPSERVICE lpService = NULL;
1269 if (!RefreshServices (fNotify, pStatus))
1272 if (lpiFind != NULL)
1274 lpService = lpiFind->OpenService();
1277 else if ((*phEnum = m_lServices->FindFirst()) != NULL)
1279 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1283 if (!lpService && pStatus)
1284 *pStatus = ERROR_FILE_NOT_FOUND;
1289 LPSERVICE SERVER::ServiceFindNext (HENUM *phEnum)
1291 LPSERVICE lpService = NULL;
1295 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1297 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1306 void SERVER::ServiceFindClose (HENUM *phEnum)
1317 * HASH KEYS __________________________________________________________________
1321 BOOL CALLBACK SERVER::KeyAggregateName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1323 return !lstrcmp (((LPAGGREGATE)pObject)->m_szName, (LPTSTR)pData);
1326 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1328 return SERVER::KeyAggregateName_HashData (pKey, ((LPAGGREGATE)pObject)->m_szName);
1331 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1333 return HashString ((LPTSTR)pData);
1337 BOOL CALLBACK SERVER::KeyAggregateID_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1339 return (((LPAGGREGATE)pObject)->m_as.dwID == *(ULONG*)pData);
1342 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1344 return SERVER::KeyAggregateID_HashData (pKey, &((LPAGGREGATE)pObject)->m_as.dwID);
1347 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashData (LPHASHLISTKEY pKey, PVOID pData)
1349 return (HASHVALUE)*(ULONG*)pData;
1353 BOOL CALLBACK SERVER::KeyServiceName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1355 return !lstrcmp (((LPSERVICE)pObject)->m_szName, (LPTSTR)pData);
1358 HASHVALUE CALLBACK SERVER::KeyServiceName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1360 return SERVER::KeyServiceName_HashData (pKey, ((LPSERVICE)pObject)->m_szName);
1363 HASHVALUE CALLBACK SERVER::KeyServiceName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1365 return HashString ((LPTSTR)pData);