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 <afsconfig.h>
15 #include <afs/param.h>
20 #include <WINNT/afsclass.h>
25 * DEFINITIONS ________________________________________________________________
29 // Each SERVER object maintains a list of aggregates and a list
30 // of services; those lists have hashtables placed across their
31 // names (and, for aggregates, their IDs) for faster lookup.
32 // The default table size in a HASHLIST is 1000 elements--that's
33 // too large for a list of aggregates or services on a server,
34 // as it's enough to handle up to 30,000 objects before the table
35 // would need to resize iteself (see the documentation in
36 // hashlist.cpp for info). Instead, we choose a more reasonable
37 // default table size.
39 #define cKEYAGGREGATENAME_TABLESIZE 100
40 #define cKEYAGGREGATEID_TABLESIZE 100
42 #define cKEYSERVICENAME_TABLESIZE 50
46 * VARIABLES __________________________________________________________________
52 * PROTOTYPES _________________________________________________________________
58 * ROUTINES ___________________________________________________________________
63 SERVER::SERVER (LPCELL lpCellParent, LPTSTR pszName)
65 m_lpiCell = lpCellParent->GetIdentifier();
67 lstrcpy (m_szName, pszName);
78 m_fCanGetAggregates = TRUE;
79 m_fAggregatesOutOfDate = TRUE;
80 m_lAggregates = New (HASHLIST);
81 m_lAggregates->SetCriticalSection (AfsClass_GetCriticalSection());
82 m_lkAggregateName = m_lAggregates->CreateKey ("Aggregate Name", SERVER::KeyAggregateName_Compare, SERVER::KeyAggregateName_HashObject, SERVER::KeyAggregateName_HashData, cKEYAGGREGATENAME_TABLESIZE);
83 m_lkAggregateID = m_lAggregates->CreateKey ("Aggregate ID", SERVER::KeyAggregateID_Compare, SERVER::KeyAggregateID_HashObject, SERVER::KeyAggregateID_HashData, cKEYAGGREGATEID_TABLESIZE);
85 m_fCanGetServices = TRUE;
86 m_fServicesOutOfDate = TRUE;
87 m_lServices = New (HASHLIST);
88 m_lServices->SetCriticalSection (AfsClass_GetCriticalSection());
89 m_lkServiceName = m_lServices->CreateKey ("Service Name", SERVER::KeyServiceName_Compare, SERVER::KeyServiceName_HashObject, SERVER::KeyServiceName_HashData, cKEYSERVICENAME_TABLESIZE);
97 m_fVLDBOutOfDate = FALSE; /* FIXME: added because it was missing */
98 m_fStatusOutOfDate = TRUE;
99 memset (&m_ss, 0x00, sizeof(SERVERSTATUS));
103 SERVER::~SERVER (void)
108 if ((lpCell = m_lpiCell->OpenCell()) != NULL)
110 (lpCell->m_nServersUnmonitored)--;
116 m_lpiThis->m_cRef --;
119 Delete (m_lAggregates);
120 Delete (m_lServices);
124 void SERVER::FreeAll (void)
142 void SERVER::FreeAggregates (void)
144 for (LPENUM pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
146 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
147 m_lAggregates->Remove (lpAggregate);
148 Delete (lpAggregate);
153 void SERVER::FreeServices (void)
155 for (LPENUM pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
157 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
158 m_lServices->Remove (lpService);
164 void SERVER::SendDeleteNotifications (void)
167 for (pEnum = m_lAggregates->FindFirst(); pEnum; pEnum = pEnum->FindNext())
169 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
170 lpAggregate->SendDeleteNotifications ();
173 for (pEnum = m_lServices->FindFirst(); pEnum; pEnum = pEnum->FindNext())
175 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
176 lpService->SendDeleteNotifications();
179 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
183 void SERVER::Close (void)
189 LPIDENT SERVER::GetIdentifier (void)
191 if (m_lpiThis == NULL)
193 if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
194 m_lpiThis = New2 (IDENT,(this));
195 m_lpiThis->m_cRef ++;
202 PVOID SERVER::OpenBosObject (PVOID *phCell, ULONG *pStatus)
206 if ((m_lpCellBOS = m_lpiCell->OpenCell (pStatus)) != NULL)
208 if ((m_hCellBOS = m_lpCellBOS->GetCellObject (pStatus)) != NULL)
210 TCHAR szCell[ cchNAME ];
211 m_lpiCell->GetCellName (szCell);
214 wp.wpBosServerOpen.hCell = m_hCellBOS;
215 wp.wpBosServerOpen.pszServer = m_szName;
216 if (Worker_DoTask (wtaskBosServerOpen, &wp, pStatus))
217 m_hBOS = wp.wpBosServerOpen.hServer;
222 m_lpCellBOS->Close();
232 *phCell = m_hCellBOS;
239 BOOL SERVER::CloseBosObject (ULONG *pStatus)
243 if ((m_cReqBOS > 0) && ((--m_cReqBOS) == 0))
248 wp.wpBosServerClose.hServer = m_hBOS;
249 if (!Worker_DoTask (wtaskBosServerClose, &wp, pStatus))
253 if (m_lpCellBOS != NULL)
255 m_lpCellBOS->Close();
264 PVOID SERVER::OpenVosObject (PVOID *phCell, ULONG *pStatus)
269 if ((lpCell = m_lpiCell->OpenCell (pStatus)) != NULL)
271 m_hCellVOS = lpCell->GetCellObject (pStatus);
276 if (m_hCellVOS && !m_hVOS)
278 TCHAR szCell[ cchNAME ];
279 m_lpiCell->GetCellName (szCell);
282 wp.wpVosServerOpen.hCell = m_hCellVOS;
283 wp.wpVosServerOpen.pszServer = m_szName;
284 if (Worker_DoTask (wtaskVosServerOpen, &wp, pStatus))
285 m_hVOS = wp.wpVosServerOpen.hServer;
291 *phCell = m_hCellVOS;
298 BOOL SERVER::CloseVosObject (ULONG *pStatus)
302 if ((m_cReqVOS > 0) && ((--m_cReqVOS) == 0))
307 wp.wpVosServerClose.hServer = m_hVOS;
308 if (!Worker_DoTask (wtaskVosServerClose, &wp, pStatus))
320 void SERVER::Invalidate (void)
322 if (!m_fAggregatesOutOfDate || !m_fServicesOutOfDate || !m_fStatusOutOfDate)
324 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
326 m_fAggregatesOutOfDate = TRUE;
327 m_fServicesOutOfDate = TRUE;
328 m_fStatusOutOfDate = TRUE;
331 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
336 void SERVER::InvalidateStatus (void)
338 if (!m_fStatusOutOfDate)
340 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
342 m_fStatusOutOfDate = TRUE;
345 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
350 void SERVER::InvalidateServices (void)
352 if (!m_fServicesOutOfDate)
354 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
356 m_fServicesOutOfDate = TRUE;
359 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
364 BOOL SERVER::RefreshAggregates (BOOL fNotify, ULONG *pStatus)
369 if (m_fAggregatesOutOfDate)
371 m_fAggregatesOutOfDate = FALSE;
376 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin, GetIdentifier());
378 // First thing is to forget about what aggregates we think we have
382 for (pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
384 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
385 lpAggregate->SendDeleteNotifications();
386 m_lAggregates->Remove (lpAggregate);
387 Delete (lpAggregate);
390 // Next, the harder part: look through the server to find a list
395 if ((hVOS = OpenVosObject (&hCell, &status)) == NULL)
399 WORKERPACKET wpBegin;
400 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
401 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
403 if (!Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status))
410 wpNext.wpVosPartitionGetNext.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
411 if (!Worker_DoTask (wtaskVosPartitionGetNext, &wpNext, &status))
413 if (status == ADMITERATORDONE)
420 vos_partitionEntry_p pData = &wpNext.wpVosPartitionGetNext.Data;
422 LPTSTR pszName = AnsiToString (pData->name);
423 LPTSTR pszDevice = AnsiToString (pData->deviceName);
425 LPAGGREGATE lpAggregate = New2 (AGGREGATE,(this, pszName, pszDevice));
427 lpAggregate->m_as.dwID = lpAggregate->GetID();
429 FreeString (pszDevice, pData->deviceName);
430 FreeString (pszName, pData->name);
432 lpAggregate->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
433 lpAggregate->m_as.ckStorageTotal = pData->totalSpace;
434 lpAggregate->m_as.ckStorageFree = pData->totalFreeSpace;
435 m_lAggregates->Add (lpAggregate);
437 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpAggregate->GetIdentifier());
441 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
442 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
449 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd, GetIdentifier(), ((rc) ? 0 : status));
459 BOOL SERVER::RefreshServices (BOOL fNotify, ULONG *pStatus)
464 if (m_fServicesOutOfDate)
466 m_fServicesOutOfDate = FALSE;
471 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesBegin, GetIdentifier());
473 // First thing is to forget about what services we think we have now.
476 for (pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
478 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
479 lpService->SendDeleteNotifications();
480 m_lServices->Remove (lpService);
484 // Next, the harder part: look through the server to find a list
489 if ((hBOS = OpenBosObject (&hCell, &status)) == NULL)
493 WORKERPACKET wpBegin;
494 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
495 if (!Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status))
499 LPSERVICE lpService = New2 (SERVICE,(this, TEXT("BOS")));
500 m_lServices->Add (lpService);
501 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
505 TCHAR szServiceName[ cchNAME ];
508 wpNext.wpBosProcessNameGetNext.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
509 wpNext.wpBosProcessNameGetNext.pszService = szServiceName;
511 if (!Worker_DoTask (wtaskBosProcessNameGetNext, &wpNext, &status))
513 if (status == ADMITERATORDONE)
520 lpService = New2 (SERVICE,(this, wpNext.wpBosProcessNameGetNext.pszService));
521 m_lServices->Add (lpService);
522 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
526 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
527 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
534 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesEnd, GetIdentifier(), ((rc) ? 0 : status));
544 BOOL SERVER::RefreshStatus (BOOL fNotify, ULONG *pStatus)
549 if (m_fStatusOutOfDate)
551 m_fStatusOutOfDate = FALSE;
554 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
557 if ((lpCell = OpenCell (&status)) == NULL)
562 if ((hCell = lpCell->GetCellObject (&status)) == NULL)
567 wp.wpClientAFSServerGet.hCell = hCell;
568 wp.wpClientAFSServerGet.pszServer = m_szName;
570 if (!Worker_DoTask (wtaskClientAFSServerGet, &wp, &status))
576 for (size_t iAddr = 0; iAddr < AFS_MAX_SERVER_ADDRESS; ++iAddr)
578 if (wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ] == 0)
580 AfsClass_IntToAddress (&m_ss.aAddresses[ m_ss.nAddresses++ ], wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ]);
583 lpCell->m_lServers->Update (this); // That update affected a hashlistkey
590 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
599 void SERVER::GetName (LPTSTR pszName)
601 SERVER::ShortenName (pszName, m_szName);
605 void SERVER::GetLongName (LPTSTR pszName)
607 lstrcpy (pszName, m_szName);
611 LPCELL SERVER::OpenCell (ULONG *pStatus)
613 return m_lpiCell->OpenCell (pStatus);
616 BOOL SERVER::GetStatus (LPSERVERSTATUS lpss, BOOL fNotify, ULONG *pStatus)
621 rc = RefreshStatus (fNotify, pStatus);
623 memcpy (lpss, &m_ss, sizeof(SERVERSTATUS));
628 short SERVER::GetGhostStatus (void)
634 PVOID SERVER::GetUserParam (void)
636 return GetIdentifier()->GetUserParam();
640 void SERVER::SetUserParam (PVOID pUserNew)
642 GetIdentifier()->SetUserParam (pUserNew);
646 void SERVER::ShortenName (LPTSTR pszTarget, LPTSTR pszSource, BOOL fForce)
648 lstrcpy (pszTarget, pszSource);
650 if (fForce || !fLongServerNames)
652 // If the name is really an IP address, don't shorten it.
654 BOOL fIsIPAddress = TRUE;
655 for (LPTSTR pch = pszTarget; *pch && fIsIPAddress; ++pch)
657 if (!isdigit(*pch) && !(*pch == TEXT('.')))
658 fIsIPAddress = FALSE;
663 if ((pszTarget = (LPTSTR)lstrchr (pszTarget, TEXT('.'))) != NULL)
664 *pszTarget = TEXT('\0');
670 BOOL SERVER::fIsMonitored (void)
676 BOOL SERVER::SetMonitor (BOOL fShouldMonitor, ULONG *pStatus)
681 if (m_fMonitor != fShouldMonitor)
684 if ((lpCell = m_lpiCell->OpenCell (&status)) == NULL)
688 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
690 if ((m_fMonitor = fShouldMonitor) == FALSE)
693 (lpCell->m_nServersUnmonitored)++;
695 else // (fMonitor == TRUE)
697 (lpCell->m_nServersUnmonitored)--;
699 rc = RefreshAll (&status);
702 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
714 * REFRESHALL __________________________________________________________________
716 * If a server is down, or doesn't have an VOS process running, it could
717 * take some time before we time out trying to talk to the server. During
718 * the course of a refresh, the first timeout-and-fail that we will hit is
719 * our call to wtaskVosPartitionGetBegin; since this call is very quick if
720 * it's going to be successful, we can safely perform this call once up-front
721 * to test to see if the server is listening at all. That test is performed
722 * on a separate thread, so that in the event the request times out, we can
723 * simply discard the thread and let it terminate on its own.
733 } REFRESHSECTION, *LPREFRESHSECTION;
735 static REFRESHSECTION *aRefSec = NULL;
736 static size_t cRefSec = 0;
737 static LPCRITICAL_SECTION pcsRefSec = NULL;
739 void AfsClass_InitRefreshSections (void)
741 if (pcsRefSec == NULL)
743 pcsRefSec = New (CRITICAL_SECTION);
744 InitializeCriticalSection (pcsRefSec);
749 void AfsClass_SkipRefresh (int idSection)
751 AfsClass_InitRefreshSections();
752 EnterCriticalSection (pcsRefSec);
754 if (aRefSec && (idSection < (int)cRefSec))
756 if (aRefSec[ idSection ].fInUse)
758 aRefSec[ idSection ].fCanceled = TRUE;
762 LeaveCriticalSection (pcsRefSec);
766 DWORD WINAPI SERVER::CanTalkToServer_ThreadProc (PVOID lp)
768 int idSection = PtrToInt(lp);
770 // Until we post a notification saying that we've entered
771 // a section, we don't need to worry about the aRefSec[] entry
772 // being invalid. Once that post is made, the user can skip
773 // the section at any time--so we'll have to check frequently,
774 // always under the pcsRefSec critical section.
776 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionStart, NULL, NULL, NULL, NULL, idSection, 0);
778 BOOL fAggregatesOK = FALSE;
779 BOOL fServicesOK = FALSE;
780 BOOL fContinue = TRUE;
782 // Try to get the BOS object for this server. Remember, there's
783 // a catch here: we can only assume that the aRefSec[idSection].lpServer
784 // pointer is valid so long as we're within the pcsRefSec critical
785 // section! (if we're in that critsec, we can verify that no one
786 // has canceled the operation--and if no one has, there is a thread
787 // hanging around which holds the library's critsec, which ensures
788 // the lpServer pointer won't have been freed.)
794 TCHAR szServer[ cchNAME ];
796 EnterCriticalSection (pcsRefSec);
797 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
801 hCell = aRefSec[ idSection ].hCell;
802 aRefSec[ idSection ].lpServer->GetLongName (szServer);
804 LeaveCriticalSection (pcsRefSec);
809 wp.wpBosServerOpen.hCell = hCell;
810 wp.wpBosServerOpen.pszServer = szServer;
813 fContinue = Worker_DoTask (wtaskBosServerOpen, &wp, &status);
815 EnterCriticalSection (pcsRefSec);
816 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
819 aRefSec[ idSection ].lpServer->m_lastStatus = status;
821 hBOS = wp.wpBosServerOpen.hServer;
822 LeaveCriticalSection (pcsRefSec);
827 WORKERPACKET wpBegin;
828 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
831 fContinue = Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status);
833 EnterCriticalSection (pcsRefSec);
834 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
837 aRefSec[ idSection ].lpServer->m_lastStatus = status;
838 LeaveCriticalSection (pcsRefSec);
843 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
844 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
846 // We can talk to BOS!
851 // If we couldn't talk to BOS, it's a sure bet the server is down--
852 // and regardless, if BOS isn't around, VOS isn't either. So
853 // we may not even have to test that.
858 wp.wpVosServerOpen.hCell = hCell;
859 wp.wpVosServerOpen.pszServer = szServer;
862 fContinue = Worker_DoTask (wtaskVosServerOpen, &wp, &status);
864 EnterCriticalSection (pcsRefSec);
865 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
868 aRefSec[ idSection ].lpServer->m_lastStatus = status;
870 hVOS = wp.wpVosServerOpen.hServer;
871 LeaveCriticalSection (pcsRefSec);
876 WORKERPACKET wpBegin;
877 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
878 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
881 fContinue = Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status);
883 EnterCriticalSection (pcsRefSec);
884 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
887 aRefSec[ idSection ].lpServer->m_lastStatus = status;
888 LeaveCriticalSection (pcsRefSec);
893 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
894 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
896 // We can talk to VOS!
897 fAggregatesOK = TRUE;
901 // Close the VOS and BOS objects we obtained.
906 wp.wpBosServerClose.hServer = hBOS;
907 Worker_DoTask (wtaskBosServerClose, &wp);
912 wp.wpVosServerClose.hServer = hVOS;
913 Worker_DoTask (wtaskVosServerClose, &wp);
916 // Return our entry in the RefSec array back to the pool.
917 // If the request was never canceled, there is another
918 // thread waiting to hear our results--update the server
919 // entry specified by RefSec before leaving.
921 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionEnd, NULL, NULL, NULL, NULL, idSection, 0);
923 EnterCriticalSection (pcsRefSec);
924 if ( (aRefSec[ idSection ].fInUse) && (!aRefSec[ idSection ].fCanceled) )
926 aRefSec[ idSection ].lpServer->m_fCanGetAggregates = fAggregatesOK;
927 aRefSec[ idSection ].lpServer->m_fCanGetServices = fServicesOK;
929 aRefSec[ idSection ].fInUse = FALSE;
930 LeaveCriticalSection (pcsRefSec);
935 BOOL SERVER::CanTalkToServer (ULONG *pStatus)
937 // Ensure the server exists in the cell at all--
938 // this call just updates the server's IP addresses
939 // etc (information it gets from the database servers)
940 // and doesn't require talking to the server itself.
942 if (!RefreshStatus (FALSE, pStatus))
945 // Find a new refsec array element to use...
947 AfsClass_InitRefreshSections();
948 EnterCriticalSection (pcsRefSec);
951 for (idSection = 0; idSection < (int)cRefSec; ++idSection)
953 if (!aRefSec[ idSection ].fInUse)
956 if (idSection == (int)cRefSec)
958 if (!REALLOC (aRefSec, cRefSec, 1+idSection, 4))
961 *pStatus = GetLastError();
962 LeaveCriticalSection (pcsRefSec);
966 aRefSec[ idSection ].fInUse = TRUE;
967 aRefSec[ idSection ].fCanceled = FALSE;
968 aRefSec[ idSection ].lpServer = this;
969 aRefSec[ idSection ].hCell = NULL;
972 if ((lpCell = OpenCell()) != NULL)
974 aRefSec[ idSection ].hCell = lpCell->GetCellObject();
978 LeaveCriticalSection (pcsRefSec);
980 // Until we find out differently, assume that we won't be
981 // able to query VOS or BOS on this server.
983 m_fCanGetAggregates = FALSE;
984 m_fCanGetServices = FALSE;
987 // Fork a separate thread, on which to quickly try to talk
992 if ((hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)CanTalkToServer_ThreadProc, IntToPtr(idSection), 0, &dwThreadID)) == NULL)
994 EnterCriticalSection (pcsRefSec);
995 aRefSec[ idSection ].fInUse = FALSE;
996 LeaveCriticalSection (pcsRefSec);
998 *pStatus = GetLastError();
1001 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
1003 // Wait for that thread to terminate, or for our
1004 // newly-allocated RefSec entry to be marked Canceled.
1007 for (dw = STILL_ACTIVE; dw == STILL_ACTIVE; )
1009 EnterCriticalSection (pcsRefSec);
1011 GetExitCodeThread (hThread, &dw);
1012 if (dw == STILL_ACTIVE)
1014 if ( (aRefSec[ idSection ].fInUse) &&
1015 (aRefSec[ idSection ].lpServer == this) &&
1016 (aRefSec[ idSection ].fCanceled) )
1018 if (m_lastStatus == 0)
1019 m_lastStatus = ERROR_CANCELLED;
1024 LeaveCriticalSection (pcsRefSec);
1026 if (dw == STILL_ACTIVE)
1027 Sleep(100); // wait another brief instant
1030 // dw == 0 : user canceled operation (thread is still running!)
1031 // dw == 1 : thread completed successfully, and set fCanTalkTo* flags.
1033 // Note that the thread will clear aRefSec[idSection].fInUse when it
1034 // terminates (so, if dw!=-1, it has already done so).
1037 *pStatus = m_lastStatus;
1038 return (dw == 0) ? FALSE : TRUE;
1042 BOOL SERVER::RefreshAll (ULONG *pStatus, double dInit, double dFactor)
1047 if (m_fAggregatesOutOfDate || m_fServicesOutOfDate)
1049 if ((++cRefreshAllReq) == 1)
1051 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier(), 0);
1054 double perAGGREGATES = 65.0; // % of time spent finding aggs & sets
1055 double perSERVICES = 25.0; // % of time spent finding services
1056 double perVLDB = 10.0; // % of time spent finding VLDB info
1058 if (cRefreshAllReq >= 2) // being called as part of a cell-wide op?
1060 perAGGREGATES = 80.0; // % of time spent finding aggs & sets
1061 perSERVICES = 20.0; // % of time spent finding services
1062 perVLDB = 0.0; // we won't query VLDB stuff ourself.
1065 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
1067 if (!CanTalkToServer (&status)) // Determines fCanGetAggregates, fCanGetServices
1075 if (!m_fCanGetAggregates)
1078 m_fAggregatesOutOfDate = FALSE;
1082 size_t nAggregates = 0;
1083 size_t iAggregate = 0;
1085 LPAGGREGATE lpAggregate;
1086 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1089 lpAggregate->Close();
1094 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1096 ULONG perComplete = (ULONG)( ((double)perAGGREGATES / 100.0) * ((double)iAggregate * 100.0 / nAggregates) );
1097 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpAggregate->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1099 lpAggregate->RefreshFilesets (TRUE);
1100 lpAggregate->Close();
1107 if (!m_fCanGetServices)
1110 m_fServicesOutOfDate = FALSE;
1114 size_t nServices = 0;
1115 size_t iService = 0;
1117 LPSERVICE lpService;
1118 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1126 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1128 ULONG perComplete = (ULONG)( (double)perAGGREGATES + ((double)perSERVICES / 100.0) * ((double)iService * 100.0 / nServices) );
1129 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpService->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1131 lpService->RefreshStatus (TRUE);
1139 if (cRefreshAllReq == 1) // not being called as part of a cell-wide op?
1142 if ((lpCell = OpenCell()) != NULL)
1144 lpCell->RefreshVLDB (GetIdentifier(), TRUE, NULL);
1150 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
1152 if ((--cRefreshAllReq) == 0)
1154 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd, GetIdentifier(), NULL, NULL, NULL, 100, m_lastStatus);
1158 if (rc && m_lastStatus)
1167 * AGGREGATES _________________________________________________________________
1171 LPAGGREGATE SERVER::OpenAggregate (LPTSTR pszName, ULONG *pStatus)
1173 if (!RefreshAggregates (TRUE, pStatus))
1176 LPAGGREGATE lpAggregate;
1177 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateName->GetFirstObject (pszName))) != NULL)
1184 LPAGGREGATE SERVER::OpenAggregate (ULONG dwID, ULONG *pStatus)
1186 if (!RefreshAggregates (TRUE, pStatus))
1189 LPAGGREGATE lpAggregate;
1190 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateID->GetFirstObject (&dwID))) != NULL)
1197 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1199 return AggregateFindFirst (phEnum, NULL, fNotify, pStatus);
1203 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1205 LPAGGREGATE lpAggregate = NULL;
1207 if (!RefreshAggregates (fNotify, pStatus))
1210 if (lpiFind != NULL)
1212 lpAggregate = lpiFind->OpenAggregate();
1215 else if ((*phEnum = m_lAggregates->FindFirst()) != NULL)
1217 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1221 if (!lpAggregate && pStatus)
1222 *pStatus = ERROR_FILE_NOT_FOUND;
1227 LPAGGREGATE SERVER::AggregateFindNext (HENUM *phEnum)
1229 LPAGGREGATE lpAggregate = NULL;
1233 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1235 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1244 void SERVER::AggregateFindClose (HENUM *phEnum)
1255 * SERVICES ___________________________________________________________________
1259 LPSERVICE SERVER::OpenService (LPTSTR pszName, ULONG *pStatus)
1261 if (!RefreshServices (TRUE, pStatus))
1264 LPSERVICE lpService;
1265 if ((lpService = (LPSERVICE)(m_lkServiceName->GetFirstObject (pszName))) != NULL)
1272 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1274 return ServiceFindFirst (phEnum, NULL, fNotify, pStatus);
1278 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1280 LPSERVICE lpService = NULL;
1282 if (!RefreshServices (fNotify, pStatus))
1285 if (lpiFind != NULL)
1287 lpService = lpiFind->OpenService();
1290 else if ((*phEnum = m_lServices->FindFirst()) != NULL)
1292 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1296 if (!lpService && pStatus)
1297 *pStatus = ERROR_FILE_NOT_FOUND;
1302 LPSERVICE SERVER::ServiceFindNext (HENUM *phEnum)
1304 LPSERVICE lpService = NULL;
1308 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1310 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1319 void SERVER::ServiceFindClose (HENUM *phEnum)
1330 * HASH KEYS __________________________________________________________________
1334 BOOL CALLBACK SERVER::KeyAggregateName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1336 return !lstrcmp (((LPAGGREGATE)pObject)->m_szName, (LPTSTR)pData);
1339 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1341 return SERVER::KeyAggregateName_HashData (pKey, ((LPAGGREGATE)pObject)->m_szName);
1344 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1346 return HashString ((LPTSTR)pData);
1350 BOOL CALLBACK SERVER::KeyAggregateID_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1352 return (((LPAGGREGATE)pObject)->m_as.dwID == *(ULONG*)pData);
1355 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1357 return SERVER::KeyAggregateID_HashData (pKey, &((LPAGGREGATE)pObject)->m_as.dwID);
1360 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashData (LPHASHLISTKEY pKey, PVOID pData)
1362 return (HASHVALUE)*(ULONG*)pData;
1366 BOOL CALLBACK SERVER::KeyServiceName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1368 return !lstrcmp (((LPSERVICE)pObject)->m_szName, (LPTSTR)pData);
1371 HASHVALUE CALLBACK SERVER::KeyServiceName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1373 return SERVER::KeyServiceName_HashData (pKey, ((LPSERVICE)pObject)->m_szName);
1376 HASHVALUE CALLBACK SERVER::KeyServiceName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1378 return HashString ((LPTSTR)pData);