6 #include <WINNT/afsclass.h>
11 * DEFINITIONS ________________________________________________________________
15 // Each SERVER object maintains a list of aggregates and a list
16 // of services; those lists have hashtables placed across their
17 // names (and, for aggregates, their IDs) for faster lookup.
18 // The default table size in a HASHLIST is 1000 elements--that's
19 // too large for a list of aggregates or services on a server,
20 // as it's enough to handle up to 30,000 objects before the table
21 // would need to resize iteself (see the documentation in
22 // hashlist.cpp for info). Instead, we choose a more reasonable
23 // default table size.
25 #define cKEYAGGREGATENAME_TABLESIZE 100
26 #define cKEYAGGREGATEID_TABLESIZE 100
28 #define cKEYSERVICENAME_TABLESIZE 50
32 * VARIABLES __________________________________________________________________
38 * PROTOTYPES _________________________________________________________________
44 * ROUTINES ___________________________________________________________________
49 SERVER::SERVER (LPCELL lpCellParent, LPTSTR pszName)
51 m_lpiCell = lpCellParent->GetIdentifier();
53 lstrcpy (m_szName, pszName);
64 m_fCanGetAggregates = TRUE;
65 m_fAggregatesOutOfDate = TRUE;
66 m_lAggregates = New (HASHLIST);
67 m_lAggregates->SetCriticalSection (AfsClass_GetCriticalSection());
68 m_lkAggregateName = m_lAggregates->CreateKey ("Aggregate Name", SERVER::KeyAggregateName_Compare, SERVER::KeyAggregateName_HashObject, SERVER::KeyAggregateName_HashData, cKEYAGGREGATENAME_TABLESIZE);
69 m_lkAggregateID = m_lAggregates->CreateKey ("Aggregate ID", SERVER::KeyAggregateID_Compare, SERVER::KeyAggregateID_HashObject, SERVER::KeyAggregateID_HashData, cKEYAGGREGATEID_TABLESIZE);
71 m_fCanGetServices = TRUE;
72 m_fServicesOutOfDate = TRUE;
73 m_lServices = New (HASHLIST);
74 m_lServices->SetCriticalSection (AfsClass_GetCriticalSection());
75 m_lkServiceName = m_lServices->CreateKey ("Service Name", SERVER::KeyServiceName_Compare, SERVER::KeyServiceName_HashObject, SERVER::KeyServiceName_HashData, cKEYSERVICENAME_TABLESIZE);
83 m_fStatusOutOfDate = TRUE;
84 memset (&m_ss, 0x00, sizeof(SERVERSTATUS));
88 SERVER::~SERVER (void)
93 if ((lpCell = m_lpiCell->OpenCell()) != NULL)
95 (lpCell->m_nServersUnmonitored)--;
101 m_lpiThis->m_cRef --;
104 Delete (m_lAggregates);
105 Delete (m_lServices);
109 void SERVER::FreeAll (void)
127 void SERVER::FreeAggregates (void)
129 for (LPENUM pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
131 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
132 m_lAggregates->Remove (lpAggregate);
133 Delete (lpAggregate);
138 void SERVER::FreeServices (void)
140 for (LPENUM pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
142 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
143 m_lServices->Remove (lpService);
149 void SERVER::SendDeleteNotifications (void)
151 for (LPENUM pEnum = m_lAggregates->FindFirst(); pEnum; pEnum = pEnum->FindNext())
153 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
154 lpAggregate->SendDeleteNotifications ();
157 for (pEnum = m_lServices->FindFirst(); pEnum; pEnum = pEnum->FindNext())
159 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
160 lpService->SendDeleteNotifications();
163 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
167 void SERVER::Close (void)
173 LPIDENT SERVER::GetIdentifier (void)
175 if (m_lpiThis == NULL)
177 if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
178 m_lpiThis = New2 (IDENT,(this));
179 m_lpiThis->m_cRef ++;
186 PVOID SERVER::OpenBosObject (PVOID *phCell, ULONG *pStatus)
190 if ((m_lpCellBOS = m_lpiCell->OpenCell (pStatus)) != NULL)
192 if ((m_hCellBOS = m_lpCellBOS->GetCellObject (pStatus)) != NULL)
194 TCHAR szCell[ cchNAME ];
195 m_lpiCell->GetCellName (szCell);
198 wp.wpBosServerOpen.hCell = m_hCellBOS;
199 wp.wpBosServerOpen.pszServer = m_szName;
200 if (Worker_DoTask (wtaskBosServerOpen, &wp, pStatus))
201 m_hBOS = wp.wpBosServerOpen.hServer;
206 m_lpCellBOS->Close();
216 *phCell = m_hCellBOS;
223 BOOL SERVER::CloseBosObject (ULONG *pStatus)
227 if ((m_cReqBOS > 0) && ((--m_cReqBOS) == 0))
232 wp.wpBosServerClose.hServer = m_hBOS;
233 if (!Worker_DoTask (wtaskBosServerClose, &wp, pStatus))
237 if (m_lpCellBOS != NULL)
239 m_lpCellBOS->Close();
248 PVOID SERVER::OpenVosObject (PVOID *phCell, ULONG *pStatus)
253 if ((lpCell = m_lpiCell->OpenCell (pStatus)) != NULL)
255 m_hCellVOS = lpCell->GetCellObject (pStatus);
260 if (m_hCellVOS && !m_hVOS)
262 TCHAR szCell[ cchNAME ];
263 m_lpiCell->GetCellName (szCell);
266 wp.wpVosServerOpen.hCell = m_hCellVOS;
267 wp.wpVosServerOpen.pszServer = m_szName;
268 if (Worker_DoTask (wtaskVosServerOpen, &wp, pStatus))
269 m_hVOS = wp.wpVosServerOpen.hServer;
275 *phCell = m_hCellVOS;
282 BOOL SERVER::CloseVosObject (ULONG *pStatus)
286 if ((m_cReqVOS > 0) && ((--m_cReqVOS) == 0))
291 wp.wpVosServerClose.hServer = m_hVOS;
292 if (!Worker_DoTask (wtaskVosServerClose, &wp, pStatus))
304 void SERVER::Invalidate (void)
306 if (!m_fAggregatesOutOfDate || !m_fServicesOutOfDate || !m_fStatusOutOfDate)
308 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
310 m_fAggregatesOutOfDate = TRUE;
311 m_fServicesOutOfDate = TRUE;
312 m_fStatusOutOfDate = TRUE;
315 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
320 void SERVER::InvalidateStatus (void)
322 if (!m_fStatusOutOfDate)
324 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
326 m_fStatusOutOfDate = TRUE;
329 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
334 void SERVER::InvalidateServices (void)
336 if (!m_fServicesOutOfDate)
338 if (m_wGhost & GHOST_HAS_SERVER_ENTRY)
340 m_fServicesOutOfDate = TRUE;
343 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
348 BOOL SERVER::RefreshAggregates (BOOL fNotify, ULONG *pStatus)
353 if (m_fAggregatesOutOfDate)
355 m_fAggregatesOutOfDate = FALSE;
360 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin, GetIdentifier());
362 // First thing is to forget about what aggregates we think we have
365 for (LPENUM pEnum = m_lAggregates->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
367 LPAGGREGATE lpAggregate = (LPAGGREGATE)(pEnum->GetObject());
368 lpAggregate->SendDeleteNotifications();
369 m_lAggregates->Remove (lpAggregate);
370 Delete (lpAggregate);
373 // Next, the harder part: look through the server to find a list
378 if ((hVOS = OpenVosObject (&hCell, &status)) == NULL)
382 WORKERPACKET wpBegin;
383 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
384 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
386 if (!Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status))
393 wpNext.wpVosPartitionGetNext.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
394 if (!Worker_DoTask (wtaskVosPartitionGetNext, &wpNext, &status))
396 if (status == ADMITERATORDONE)
403 vos_partitionEntry_p pData = &wpNext.wpVosPartitionGetNext.Data;
405 LPTSTR pszName = AnsiToString (pData->name);
406 LPTSTR pszDevice = AnsiToString (pData->deviceName);
408 LPAGGREGATE lpAggregate = New2 (AGGREGATE,(this, pszName, pszDevice));
410 lpAggregate->m_as.dwID = lpAggregate->GetID();
412 FreeString (pszDevice, pData->deviceName);
413 FreeString (pszName, pData->name);
415 lpAggregate->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
416 lpAggregate->m_as.ckStorageTotal = pData->totalSpace;
417 lpAggregate->m_as.ckStorageFree = pData->totalFreeSpace;
418 m_lAggregates->Add (lpAggregate);
420 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpAggregate->GetIdentifier());
424 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
425 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
432 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd, GetIdentifier(), ((rc) ? 0 : status));
442 BOOL SERVER::RefreshServices (BOOL fNotify, ULONG *pStatus)
447 if (m_fServicesOutOfDate)
449 m_fServicesOutOfDate = FALSE;
454 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesBegin, GetIdentifier());
456 // First thing is to forget about what services we think we have now.
458 for (LPENUM pEnum = m_lServices->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
460 LPSERVICE lpService = (LPSERVICE)(pEnum->GetObject());
461 lpService->SendDeleteNotifications();
462 m_lServices->Remove (lpService);
466 // Next, the harder part: look through the server to find a list
471 if ((hBOS = OpenBosObject (&hCell, &status)) == NULL)
475 WORKERPACKET wpBegin;
476 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
477 if (!Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status))
481 LPSERVICE lpService = New2 (SERVICE,(this, TEXT("BOS")));
482 m_lServices->Add (lpService);
483 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
487 TCHAR szServiceName[ cchNAME ];
490 wpNext.wpBosProcessNameGetNext.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
491 wpNext.wpBosProcessNameGetNext.pszService = szServiceName;
493 if (!Worker_DoTask (wtaskBosProcessNameGetNext, &wpNext, &status))
495 if (status == ADMITERATORDONE)
502 lpService = New2 (SERVICE,(this, wpNext.wpBosProcessNameGetNext.pszService));
503 m_lServices->Add (lpService);
504 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpService->GetIdentifier());
508 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
509 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
516 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesEnd, GetIdentifier(), ((rc) ? 0 : status));
526 BOOL SERVER::RefreshStatus (BOOL fNotify, ULONG *pStatus)
531 if (m_fStatusOutOfDate)
533 m_fStatusOutOfDate = FALSE;
536 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
539 if ((lpCell = OpenCell (&status)) == NULL)
544 if ((hCell = lpCell->GetCellObject (&status)) == NULL)
549 wp.wpClientAFSServerGet.hCell = hCell;
550 wp.wpClientAFSServerGet.pszServer = m_szName;
552 if (!Worker_DoTask (wtaskClientAFSServerGet, &wp, &status))
558 for (size_t iAddr = 0; iAddr < AFS_MAX_SERVER_ADDRESS; ++iAddr)
560 if (wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ] == 0)
562 AfsClass_IntToAddress (&m_ss.aAddresses[ m_ss.nAddresses++ ], wp.wpClientAFSServerGet.Entry.serverAddress[ iAddr ]);
565 lpCell->m_lServers->Update (this); // That update affected a hashlistkey
572 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
581 void SERVER::GetName (LPTSTR pszName)
583 SERVER::ShortenName (pszName, m_szName);
587 void SERVER::GetLongName (LPTSTR pszName)
589 lstrcpy (pszName, m_szName);
593 LPCELL SERVER::OpenCell (ULONG *pStatus)
595 return m_lpiCell->OpenCell (pStatus);
598 BOOL SERVER::GetStatus (LPSERVERSTATUS lpss, BOOL fNotify, ULONG *pStatus)
603 rc = RefreshStatus (fNotify, pStatus);
605 memcpy (lpss, &m_ss, sizeof(SERVERSTATUS));
610 short SERVER::GetGhostStatus (void)
616 PVOID SERVER::GetUserParam (void)
618 return GetIdentifier()->GetUserParam();
622 void SERVER::SetUserParam (PVOID pUserNew)
624 GetIdentifier()->SetUserParam (pUserNew);
628 void SERVER::ShortenName (LPTSTR pszTarget, LPTSTR pszSource, BOOL fForce)
630 lstrcpy (pszTarget, pszSource);
632 if (fForce || !fLongServerNames)
634 // If the name is really an IP address, don't shorten it.
636 BOOL fIsIPAddress = TRUE;
637 for (LPTSTR pch = pszTarget; *pch && fIsIPAddress; ++pch)
639 if (!isdigit(*pch) && !(*pch == TEXT('.')))
640 fIsIPAddress = FALSE;
645 if ((pszTarget = (LPTSTR)lstrchr (pszTarget, TEXT('.'))) != NULL)
646 *pszTarget = TEXT('\0');
652 BOOL SERVER::fIsMonitored (void)
658 BOOL SERVER::SetMonitor (BOOL fShouldMonitor, ULONG *pStatus)
663 if (m_fMonitor != fShouldMonitor)
666 if ((lpCell = m_lpiCell->OpenCell (&status)) == NULL)
670 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
672 if ((m_fMonitor = fShouldMonitor) == FALSE)
675 (lpCell->m_nServersUnmonitored)++;
677 else // (fMonitor == TRUE)
679 (lpCell->m_nServersUnmonitored)--;
681 rc = RefreshAll (&status);
684 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
696 * REFRESHALL __________________________________________________________________
698 * If a server is down, or doesn't have an VOS process running, it could
699 * take some time before we time out trying to talk to the server. During
700 * the course of a refresh, the first timeout-and-fail that we will hit is
701 * our call to wtaskVosPartitionGetBegin; since this call is very quick if
702 * it's going to be successful, we can safely perform this call once up-front
703 * to test to see if the server is listening at all. That test is performed
704 * on a separate thread, so that in the event the request times out, we can
705 * simply discard the thread and let it terminate on its own.
715 } REFRESHSECTION, *LPREFRESHSECTION;
717 static REFRESHSECTION *aRefSec = NULL;
718 static size_t cRefSec = 0;
719 static LPCRITICAL_SECTION pcsRefSec = NULL;
721 void AfsClass_InitRefreshSections (void)
723 if (pcsRefSec == NULL)
725 pcsRefSec = New (CRITICAL_SECTION);
726 InitializeCriticalSection (pcsRefSec);
731 void AfsClass_SkipRefresh (int idSection)
733 AfsClass_InitRefreshSections();
734 EnterCriticalSection (pcsRefSec);
736 if (aRefSec && (idSection < (int)cRefSec))
738 if (aRefSec[ idSection ].fInUse)
740 aRefSec[ idSection ].fCanceled = TRUE;
744 LeaveCriticalSection (pcsRefSec);
748 DWORD WINAPI SERVER::CanTalkToServer_ThreadProc (PVOID lp)
750 int idSection = (int)lp;
752 // Until we post a notification saying that we've entered
753 // a section, we don't need to worry about the aRefSec[] entry
754 // being invalid. Once that post is made, the user can skip
755 // the section at any time--so we'll have to check frequently,
756 // always under the pcsRefSec critical section.
758 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionStart, NULL, NULL, NULL, NULL, idSection, 0);
760 BOOL fAggregatesOK = FALSE;
761 BOOL fServicesOK = FALSE;
762 BOOL fContinue = TRUE;
764 // Try to get the BOS object for this server. Remember, there's
765 // a catch here: we can only assume that the aRefSec[idSection].lpServer
766 // pointer is valid so long as we're within the pcsRefSec critical
767 // section! (if we're in that critsec, we can verify that no one
768 // has canceled the operation--and if no one has, there is a thread
769 // hanging around which holds the library's critsec, which ensures
770 // the lpServer pointer won't have been freed.)
776 TCHAR szServer[ cchNAME ];
778 EnterCriticalSection (pcsRefSec);
779 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
783 hCell = aRefSec[ idSection ].hCell;
784 aRefSec[ idSection ].lpServer->GetLongName (szServer);
786 LeaveCriticalSection (pcsRefSec);
791 wp.wpBosServerOpen.hCell = hCell;
792 wp.wpBosServerOpen.pszServer = szServer;
795 fContinue = Worker_DoTask (wtaskBosServerOpen, &wp, &status);
797 EnterCriticalSection (pcsRefSec);
798 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
801 aRefSec[ idSection ].lpServer->m_lastStatus = status;
803 hBOS = wp.wpBosServerOpen.hServer;
804 LeaveCriticalSection (pcsRefSec);
809 WORKERPACKET wpBegin;
810 wpBegin.wpBosProcessNameGetBegin.hServer = hBOS;
813 fContinue = Worker_DoTask (wtaskBosProcessNameGetBegin, &wpBegin, &status);
815 EnterCriticalSection (pcsRefSec);
816 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
819 aRefSec[ idSection ].lpServer->m_lastStatus = status;
820 LeaveCriticalSection (pcsRefSec);
825 wpDone.wpBosProcessNameGetDone.hEnum = wpBegin.wpBosProcessNameGetBegin.hEnum;
826 Worker_DoTask (wtaskBosProcessNameGetDone, &wpDone);
828 // We can talk to BOS!
833 // If we couldn't talk to BOS, it's a sure bet the server is down--
834 // and regardless, if BOS isn't around, VOS isn't either. So
835 // we may not even have to test that.
840 wp.wpVosServerOpen.hCell = hCell;
841 wp.wpVosServerOpen.pszServer = szServer;
844 fContinue = Worker_DoTask (wtaskVosServerOpen, &wp, &status);
846 EnterCriticalSection (pcsRefSec);
847 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
850 aRefSec[ idSection ].lpServer->m_lastStatus = status;
852 hVOS = wp.wpVosServerOpen.hServer;
853 LeaveCriticalSection (pcsRefSec);
858 WORKERPACKET wpBegin;
859 wpBegin.wpVosPartitionGetBegin.hCell = hCell;
860 wpBegin.wpVosPartitionGetBegin.hServer = hVOS;
863 fContinue = Worker_DoTask (wtaskVosPartitionGetBegin, &wpBegin, &status);
865 EnterCriticalSection (pcsRefSec);
866 if ( ((!aRefSec[ idSection ].fInUse) || (aRefSec[ idSection ].fCanceled)) )
869 aRefSec[ idSection ].lpServer->m_lastStatus = status;
870 LeaveCriticalSection (pcsRefSec);
875 wpDone.wpVosPartitionGetDone.hEnum = wpBegin.wpVosPartitionGetBegin.hEnum;
876 Worker_DoTask (wtaskVosPartitionGetDone, &wpDone);
878 // We can talk to VOS!
879 fAggregatesOK = TRUE;
883 // Close the VOS and BOS objects we obtained.
888 wp.wpBosServerClose.hServer = hBOS;
889 Worker_DoTask (wtaskBosServerClose, &wp);
894 wp.wpVosServerClose.hServer = hVOS;
895 Worker_DoTask (wtaskVosServerClose, &wp);
898 // Return our entry in the RefSec array back to the pool.
899 // If the request was never canceled, there is another
900 // thread waiting to hear our results--update the server
901 // entry specified by RefSec before leaving.
903 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionEnd, NULL, NULL, NULL, NULL, idSection, 0);
905 EnterCriticalSection (pcsRefSec);
906 if ( (aRefSec[ idSection ].fInUse) && (!aRefSec[ idSection ].fCanceled) )
908 aRefSec[ idSection ].lpServer->m_fCanGetAggregates = fAggregatesOK;
909 aRefSec[ idSection ].lpServer->m_fCanGetServices = fServicesOK;
911 aRefSec[ idSection ].fInUse = FALSE;
912 LeaveCriticalSection (pcsRefSec);
917 BOOL SERVER::CanTalkToServer (ULONG *pStatus)
919 // Ensure the server exists in the cell at all--
920 // this call just updates the server's IP addresses
921 // etc (information it gets from the database servers)
922 // and doesn't require talking to the server itself.
924 if (!RefreshStatus (FALSE, pStatus))
927 // Find a new refsec array element to use...
929 AfsClass_InitRefreshSections();
930 EnterCriticalSection (pcsRefSec);
932 for (int idSection = 0; idSection < (int)cRefSec; ++idSection)
934 if (!aRefSec[ idSection ].fInUse)
937 if (idSection == (int)cRefSec)
939 if (!REALLOC (aRefSec, cRefSec, 1+idSection, 4))
942 *pStatus = GetLastError();
943 LeaveCriticalSection (pcsRefSec);
947 aRefSec[ idSection ].fInUse = TRUE;
948 aRefSec[ idSection ].fCanceled = FALSE;
949 aRefSec[ idSection ].lpServer = this;
950 aRefSec[ idSection ].hCell = NULL;
953 if ((lpCell = OpenCell()) != NULL)
955 aRefSec[ idSection ].hCell = lpCell->GetCellObject();
959 LeaveCriticalSection (pcsRefSec);
961 // Until we find out differently, assume that we won't be
962 // able to query VOS or BOS on this server.
964 m_fCanGetAggregates = FALSE;
965 m_fCanGetServices = FALSE;
968 // Fork a separate thread, on which to quickly try to talk
973 if ((hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)CanTalkToServer_ThreadProc, (PVOID)idSection, 0, &dwThreadID)) == NULL)
975 EnterCriticalSection (pcsRefSec);
976 aRefSec[ idSection ].fInUse = FALSE;
977 LeaveCriticalSection (pcsRefSec);
979 *pStatus = GetLastError();
982 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
984 // Wait for that thread to terminate, or for our
985 // newly-allocated RefSec entry to be marked Canceled.
987 for (DWORD dw = STILL_ACTIVE; dw == STILL_ACTIVE; )
989 EnterCriticalSection (pcsRefSec);
991 GetExitCodeThread (hThread, &dw);
992 if (dw == STILL_ACTIVE)
994 if ( (aRefSec[ idSection ].fInUse) &&
995 (aRefSec[ idSection ].lpServer == this) &&
996 (aRefSec[ idSection ].fCanceled) )
998 if (m_lastStatus == 0)
999 m_lastStatus = ERROR_CANCELLED;
1004 LeaveCriticalSection (pcsRefSec);
1006 if (dw == STILL_ACTIVE)
1007 Sleep(100); // wait another brief instant
1010 // dw == 0 : user canceled operation (thread is still running!)
1011 // dw == 1 : thread completed successfully, and set fCanTalkTo* flags.
1013 // Note that the thread will clear aRefSec[idSection].fInUse when it
1014 // terminates (so, if dw!=-1, it has already done so).
1017 *pStatus = m_lastStatus;
1018 return (dw == 0) ? FALSE : TRUE;
1022 BOOL SERVER::RefreshAll (ULONG *pStatus, double dInit, double dFactor)
1027 if (m_fAggregatesOutOfDate || m_fServicesOutOfDate)
1029 if ((++cRefreshAllReq) == 1)
1031 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier(), 0);
1034 double perAGGREGATES = 65.0; // % of time spent finding aggs & sets
1035 double perSERVICES = 25.0; // % of time spent finding services
1036 double perVLDB = 10.0; // % of time spent finding VLDB info
1038 if (cRefreshAllReq >= 2) // being called as part of a cell-wide op?
1040 perAGGREGATES = 80.0; // % of time spent finding aggs & sets
1041 perSERVICES = 20.0; // % of time spent finding services
1042 perVLDB = 0.0; // we won't query VLDB stuff ourself.
1045 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
1047 if (!CanTalkToServer (&status)) // Determines fCanGetAggregates, fCanGetServices
1055 if (!m_fCanGetAggregates)
1058 m_fAggregatesOutOfDate = FALSE;
1062 size_t nAggregates = 0;
1063 size_t iAggregate = 0;
1065 for (LPAGGREGATE lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1068 lpAggregate->Close();
1073 for (lpAggregate = AggregateFindFirst (&hEnum); lpAggregate; lpAggregate = AggregateFindNext (&hEnum))
1075 ULONG perComplete = (ULONG)( ((double)perAGGREGATES / 100.0) * ((double)iAggregate * 100.0 / nAggregates) );
1076 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpAggregate->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1078 lpAggregate->RefreshFilesets (TRUE);
1079 lpAggregate->Close();
1086 if (!m_fCanGetServices)
1089 m_fServicesOutOfDate = FALSE;
1093 size_t nServices = 0;
1094 size_t iService = 0;
1096 for (LPSERVICE lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1104 for (lpService = ServiceFindFirst (&hEnum); lpService; lpService = ServiceFindNext (&hEnum))
1106 ULONG perComplete = (ULONG)( (double)perAGGREGATES + ((double)perSERVICES / 100.0) * ((double)iService * 100.0 / nServices) );
1107 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpService->GetIdentifier(), NULL, NULL, NULL, (ULONG)( 100.0 * dInit + dFactor * (double)perComplete ), 0);
1109 lpService->RefreshStatus (TRUE);
1117 if (cRefreshAllReq == 1) // not being called as part of a cell-wide op?
1120 if ((lpCell = OpenCell()) != NULL)
1122 lpCell->RefreshVLDB (GetIdentifier(), TRUE, NULL);
1128 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), m_lastStatus);
1130 if ((--cRefreshAllReq) == 0)
1132 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd, GetIdentifier(), NULL, NULL, NULL, 100, m_lastStatus);
1136 if (rc && m_lastStatus)
1145 * AGGREGATES _________________________________________________________________
1149 LPAGGREGATE SERVER::OpenAggregate (LPTSTR pszName, ULONG *pStatus)
1151 if (!RefreshAggregates (TRUE, pStatus))
1154 LPAGGREGATE lpAggregate;
1155 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateName->GetFirstObject (pszName))) != NULL)
1162 LPAGGREGATE SERVER::OpenAggregate (ULONG dwID, ULONG *pStatus)
1164 if (!RefreshAggregates (TRUE, pStatus))
1167 LPAGGREGATE lpAggregate;
1168 if ((lpAggregate = (LPAGGREGATE)(m_lkAggregateID->GetFirstObject (&dwID))) != NULL)
1175 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1177 return AggregateFindFirst (phEnum, NULL, fNotify, pStatus);
1181 LPAGGREGATE SERVER::AggregateFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1183 LPAGGREGATE lpAggregate = NULL;
1185 if (!RefreshAggregates (fNotify, pStatus))
1188 if (lpiFind != NULL)
1190 lpAggregate = lpiFind->OpenAggregate();
1193 else if ((*phEnum = m_lAggregates->FindFirst()) != NULL)
1195 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1199 if (!lpAggregate && pStatus)
1200 *pStatus = ERROR_FILE_NOT_FOUND;
1205 LPAGGREGATE SERVER::AggregateFindNext (HENUM *phEnum)
1207 LPAGGREGATE lpAggregate = NULL;
1211 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1213 lpAggregate = (LPAGGREGATE)( (*phEnum)->GetObject() );
1222 void SERVER::AggregateFindClose (HENUM *phEnum)
1233 * SERVICES ___________________________________________________________________
1237 LPSERVICE SERVER::OpenService (LPTSTR pszName, ULONG *pStatus)
1239 if (!RefreshServices (TRUE, pStatus))
1242 LPSERVICE lpService;
1243 if ((lpService = (LPSERVICE)(m_lkServiceName->GetFirstObject (pszName))) != NULL)
1250 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1252 return ServiceFindFirst (phEnum, NULL, fNotify, pStatus);
1256 LPSERVICE SERVER::ServiceFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1258 LPSERVICE lpService = NULL;
1260 if (!RefreshServices (fNotify, pStatus))
1263 if (lpiFind != NULL)
1265 lpService = lpiFind->OpenService();
1268 else if ((*phEnum = m_lServices->FindFirst()) != NULL)
1270 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1274 if (!lpService && pStatus)
1275 *pStatus = ERROR_FILE_NOT_FOUND;
1280 LPSERVICE SERVER::ServiceFindNext (HENUM *phEnum)
1282 LPSERVICE lpService = NULL;
1286 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1288 lpService = (LPSERVICE)( (*phEnum)->GetObject() );
1297 void SERVER::ServiceFindClose (HENUM *phEnum)
1308 * HASH KEYS __________________________________________________________________
1312 BOOL CALLBACK SERVER::KeyAggregateName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1314 return !lstrcmp (((LPAGGREGATE)pObject)->m_szName, (LPTSTR)pData);
1317 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1319 return SERVER::KeyAggregateName_HashData (pKey, ((LPAGGREGATE)pObject)->m_szName);
1322 HASHVALUE CALLBACK SERVER::KeyAggregateName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1324 return HashString ((LPTSTR)pData);
1328 BOOL CALLBACK SERVER::KeyAggregateID_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1330 return (((LPAGGREGATE)pObject)->m_as.dwID == *(ULONG*)pData);
1333 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1335 return SERVER::KeyAggregateID_HashData (pKey, &((LPAGGREGATE)pObject)->m_as.dwID);
1338 HASHVALUE CALLBACK SERVER::KeyAggregateID_HashData (LPHASHLISTKEY pKey, PVOID pData)
1340 return (HASHVALUE)*(ULONG*)pData;
1344 BOOL CALLBACK SERVER::KeyServiceName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
1346 return !lstrcmp (((LPSERVICE)pObject)->m_szName, (LPTSTR)pData);
1349 HASHVALUE CALLBACK SERVER::KeyServiceName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
1351 return SERVER::KeyServiceName_HashData (pKey, ((LPSERVICE)pObject)->m_szName);
1354 HASHVALUE CALLBACK SERVER::KeyServiceName_HashData (LPHASHLISTKEY pKey, PVOID pData)
1356 return HashString ((LPTSTR)pData);