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>
19 #include <WINNT/afsclass.h>
24 * DEFINITIONS ________________________________________________________________
28 // Each SERVER object maintains a list of aggregates and a list
29 // of services; those lists have hashtables placed across their
30 // names (and, for aggregates, their IDs) for faster lookup.
31 // The default table size in a HASHLIST is 1000 elements--that's
32 // too large for a list of aggregates or services on a server,
33 // as it's enough to handle up to 30,000 objects before the table
34 // would need to resize iteself (see the documentation in
35 // hashlist.cpp for info). Instead, we choose a more reasonable
36 // default table size.
38 #define cKEYAGGREGATENAME_TABLESIZE 100
39 #define cKEYAGGREGATEID_TABLESIZE 100
41 #define cKEYSERVICENAME_TABLESIZE 50
45 * VARIABLES __________________________________________________________________
51 * PROTOTYPES _________________________________________________________________
57 * ROUTINES ___________________________________________________________________
62 SERVER::SERVER (LPCELL lpCellParent
, LPTSTR pszName
)
64 m_lpiCell
= lpCellParent
->GetIdentifier();
66 lstrcpy (m_szName
, pszName
);
77 m_fCanGetAggregates
= TRUE
;
78 m_fAggregatesOutOfDate
= TRUE
;
79 m_lAggregates
= New (HASHLIST
);
80 m_lAggregates
->SetCriticalSection (AfsClass_GetCriticalSection());
81 m_lkAggregateName
= m_lAggregates
->CreateKey ("Aggregate Name", SERVER::KeyAggregateName_Compare
, SERVER::KeyAggregateName_HashObject
, SERVER::KeyAggregateName_HashData
, cKEYAGGREGATENAME_TABLESIZE
);
82 m_lkAggregateID
= m_lAggregates
->CreateKey ("Aggregate ID", SERVER::KeyAggregateID_Compare
, SERVER::KeyAggregateID_HashObject
, SERVER::KeyAggregateID_HashData
, cKEYAGGREGATEID_TABLESIZE
);
84 m_fCanGetServices
= TRUE
;
85 m_fServicesOutOfDate
= TRUE
;
86 m_lServices
= New (HASHLIST
);
87 m_lServices
->SetCriticalSection (AfsClass_GetCriticalSection());
88 m_lkServiceName
= m_lServices
->CreateKey ("Service Name", SERVER::KeyServiceName_Compare
, SERVER::KeyServiceName_HashObject
, SERVER::KeyServiceName_HashData
, cKEYSERVICENAME_TABLESIZE
);
96 m_fVLDBOutOfDate
= FALSE
; /* FIXME: added because it was missing */
97 m_fStatusOutOfDate
= TRUE
;
98 memset (&m_ss
, 0x00, sizeof(SERVERSTATUS
));
102 SERVER::~SERVER (void)
107 if ((lpCell
= m_lpiCell
->OpenCell()) != NULL
)
109 (lpCell
->m_nServersUnmonitored
)--;
115 m_lpiThis
->m_cRef
--;
118 Delete (m_lAggregates
);
119 Delete (m_lServices
);
123 void SERVER::FreeAll (void)
141 void SERVER::FreeAggregates (void)
143 for (LPENUM pEnum
= m_lAggregates
->FindLast(); pEnum
; pEnum
= pEnum
->FindPrevious())
145 LPAGGREGATE lpAggregate
= (LPAGGREGATE
)(pEnum
->GetObject());
146 m_lAggregates
->Remove (lpAggregate
);
147 Delete (lpAggregate
);
152 void SERVER::FreeServices (void)
154 for (LPENUM pEnum
= m_lServices
->FindLast(); pEnum
; pEnum
= pEnum
->FindPrevious())
156 LPSERVICE lpService
= (LPSERVICE
)(pEnum
->GetObject());
157 m_lServices
->Remove (lpService
);
163 void SERVER::SendDeleteNotifications (void)
166 for (pEnum
= m_lAggregates
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
168 LPAGGREGATE lpAggregate
= (LPAGGREGATE
)(pEnum
->GetObject());
169 lpAggregate
->SendDeleteNotifications ();
172 for (pEnum
= m_lServices
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
174 LPSERVICE lpService
= (LPSERVICE
)(pEnum
->GetObject());
175 lpService
->SendDeleteNotifications();
178 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy
, GetIdentifier());
182 void SERVER::Close (void)
188 LPIDENT
SERVER::GetIdentifier (void)
190 if (m_lpiThis
== NULL
)
192 if ((m_lpiThis
= IDENT::FindIdent (this)) == NULL
)
193 m_lpiThis
= New2 (IDENT
,(this));
194 m_lpiThis
->m_cRef
++;
201 PVOID
SERVER::OpenBosObject (PVOID
*phCell
, ULONG
*pStatus
)
205 if ((m_lpCellBOS
= m_lpiCell
->OpenCell (pStatus
)) != NULL
)
207 if ((m_hCellBOS
= m_lpCellBOS
->GetCellObject (pStatus
)) != NULL
)
209 TCHAR szCell
[ cchNAME
];
210 m_lpiCell
->GetCellName (szCell
);
213 wp
.wpBosServerOpen
.hCell
= m_hCellBOS
;
214 wp
.wpBosServerOpen
.pszServer
= m_szName
;
215 if (Worker_DoTask (wtaskBosServerOpen
, &wp
, pStatus
))
216 m_hBOS
= wp
.wpBosServerOpen
.hServer
;
221 m_lpCellBOS
->Close();
231 *phCell
= m_hCellBOS
;
238 BOOL
SERVER::CloseBosObject (ULONG
*pStatus
)
242 if ((m_cReqBOS
> 0) && ((--m_cReqBOS
) == 0))
247 wp
.wpBosServerClose
.hServer
= m_hBOS
;
248 if (!Worker_DoTask (wtaskBosServerClose
, &wp
, pStatus
))
252 if (m_lpCellBOS
!= NULL
)
254 m_lpCellBOS
->Close();
263 PVOID
SERVER::OpenVosObject (PVOID
*phCell
, ULONG
*pStatus
)
268 if ((lpCell
= m_lpiCell
->OpenCell (pStatus
)) != NULL
)
270 m_hCellVOS
= lpCell
->GetCellObject (pStatus
);
275 if (m_hCellVOS
&& !m_hVOS
)
277 TCHAR szCell
[ cchNAME
];
278 m_lpiCell
->GetCellName (szCell
);
281 wp
.wpVosServerOpen
.hCell
= m_hCellVOS
;
282 wp
.wpVosServerOpen
.pszServer
= m_szName
;
283 if (Worker_DoTask (wtaskVosServerOpen
, &wp
, pStatus
))
284 m_hVOS
= wp
.wpVosServerOpen
.hServer
;
290 *phCell
= m_hCellVOS
;
297 BOOL
SERVER::CloseVosObject (ULONG
*pStatus
)
301 if ((m_cReqVOS
> 0) && ((--m_cReqVOS
) == 0))
306 wp
.wpVosServerClose
.hServer
= m_hVOS
;
307 if (!Worker_DoTask (wtaskVosServerClose
, &wp
, pStatus
))
319 void SERVER::Invalidate (void)
321 if (!m_fAggregatesOutOfDate
|| !m_fServicesOutOfDate
|| !m_fStatusOutOfDate
)
323 if (m_wGhost
& GHOST_HAS_SERVER_ENTRY
)
325 m_fAggregatesOutOfDate
= TRUE
;
326 m_fServicesOutOfDate
= TRUE
;
327 m_fStatusOutOfDate
= TRUE
;
330 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate
, GetIdentifier());
335 void SERVER::InvalidateStatus (void)
337 if (!m_fStatusOutOfDate
)
339 if (m_wGhost
& GHOST_HAS_SERVER_ENTRY
)
341 m_fStatusOutOfDate
= TRUE
;
344 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate
, GetIdentifier());
349 void SERVER::InvalidateServices (void)
351 if (!m_fServicesOutOfDate
)
353 if (m_wGhost
& GHOST_HAS_SERVER_ENTRY
)
355 m_fServicesOutOfDate
= TRUE
;
358 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate
, GetIdentifier());
363 BOOL
SERVER::RefreshAggregates (BOOL fNotify
, ULONG
*pStatus
)
368 if (m_fAggregatesOutOfDate
)
370 m_fAggregatesOutOfDate
= FALSE
;
375 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin
, GetIdentifier());
377 // First thing is to forget about what aggregates we think we have
381 for (pEnum
= m_lAggregates
->FindLast(); pEnum
; pEnum
= pEnum
->FindPrevious())
383 LPAGGREGATE lpAggregate
= (LPAGGREGATE
)(pEnum
->GetObject());
384 lpAggregate
->SendDeleteNotifications();
385 m_lAggregates
->Remove (lpAggregate
);
386 Delete (lpAggregate
);
389 // Next, the harder part: look through the server to find a list
394 if ((hVOS
= OpenVosObject (&hCell
, &status
)) == NULL
)
398 WORKERPACKET wpBegin
;
399 wpBegin
.wpVosPartitionGetBegin
.hCell
= hCell
;
400 wpBegin
.wpVosPartitionGetBegin
.hServer
= hVOS
;
402 if (!Worker_DoTask (wtaskVosPartitionGetBegin
, &wpBegin
, &status
))
409 wpNext
.wpVosPartitionGetNext
.hEnum
= wpBegin
.wpVosPartitionGetBegin
.hEnum
;
410 if (!Worker_DoTask (wtaskVosPartitionGetNext
, &wpNext
, &status
))
412 if (status
== ADMITERATORDONE
)
419 vos_partitionEntry_p pData
= &wpNext
.wpVosPartitionGetNext
.Data
;
421 LPTSTR pszName
= AnsiToString (pData
->name
);
422 LPTSTR pszDevice
= AnsiToString (pData
->deviceName
);
424 LPAGGREGATE lpAggregate
= New2 (AGGREGATE
,(this, pszName
, pszDevice
));
426 lpAggregate
->m_as
.dwID
= lpAggregate
->GetID();
428 FreeString (pszDevice
, pData
->deviceName
);
429 FreeString (pszName
, pData
->name
);
431 lpAggregate
->m_wGhost
|= GHOST_HAS_SERVER_ENTRY
;
432 lpAggregate
->m_as
.ckStorageTotal
= pData
->totalSpace
;
433 lpAggregate
->m_as
.ckStorageFree
= pData
->totalFreeSpace
;
434 m_lAggregates
->Add (lpAggregate
);
436 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpAggregate
->GetIdentifier());
440 wpDone
.wpVosPartitionGetDone
.hEnum
= wpBegin
.wpVosPartitionGetBegin
.hEnum
;
441 Worker_DoTask (wtaskVosPartitionGetDone
, &wpDone
);
448 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd
, GetIdentifier(), ((rc
) ? 0 : status
));
458 BOOL
SERVER::RefreshServices (BOOL fNotify
, ULONG
*pStatus
)
463 if (m_fServicesOutOfDate
)
465 m_fServicesOutOfDate
= FALSE
;
470 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesBegin
, GetIdentifier());
472 // First thing is to forget about what services we think we have now.
475 for (pEnum
= m_lServices
->FindLast(); pEnum
; pEnum
= pEnum
->FindPrevious())
477 LPSERVICE lpService
= (LPSERVICE
)(pEnum
->GetObject());
478 lpService
->SendDeleteNotifications();
479 m_lServices
->Remove (lpService
);
483 // Next, the harder part: look through the server to find a list
488 if ((hBOS
= OpenBosObject (&hCell
, &status
)) == NULL
)
492 WORKERPACKET wpBegin
;
493 wpBegin
.wpBosProcessNameGetBegin
.hServer
= hBOS
;
494 if (!Worker_DoTask (wtaskBosProcessNameGetBegin
, &wpBegin
, &status
))
498 LPSERVICE lpService
= New2 (SERVICE
,(this, TEXT("BOS")));
499 m_lServices
->Add (lpService
);
500 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpService
->GetIdentifier());
504 TCHAR szServiceName
[ cchNAME
];
507 wpNext
.wpBosProcessNameGetNext
.hEnum
= wpBegin
.wpBosProcessNameGetBegin
.hEnum
;
508 wpNext
.wpBosProcessNameGetNext
.pszService
= szServiceName
;
510 if (!Worker_DoTask (wtaskBosProcessNameGetNext
, &wpNext
, &status
))
512 if (status
== ADMITERATORDONE
)
519 lpService
= New2 (SERVICE
,(this, wpNext
.wpBosProcessNameGetNext
.pszService
));
520 m_lServices
->Add (lpService
);
521 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpService
->GetIdentifier());
525 wpDone
.wpBosProcessNameGetDone
.hEnum
= wpBegin
.wpBosProcessNameGetBegin
.hEnum
;
526 Worker_DoTask (wtaskBosProcessNameGetDone
, &wpDone
);
533 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServicesEnd
, GetIdentifier(), ((rc
) ? 0 : status
));
543 BOOL
SERVER::RefreshStatus (BOOL fNotify
, ULONG
*pStatus
)
548 if (m_fStatusOutOfDate
)
550 m_fStatusOutOfDate
= FALSE
;
553 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin
, GetIdentifier());
556 if ((lpCell
= OpenCell (&status
)) == NULL
)
561 if ((hCell
= lpCell
->GetCellObject (&status
)) == NULL
)
566 wp
.wpClientAFSServerGet
.hCell
= hCell
;
567 wp
.wpClientAFSServerGet
.pszServer
= m_szName
;
569 if (!Worker_DoTask (wtaskClientAFSServerGet
, &wp
, &status
))
575 for (size_t iAddr
= 0; iAddr
< AFS_MAX_SERVER_ADDRESS
; ++iAddr
)
577 if (wp
.wpClientAFSServerGet
.Entry
.serverAddress
[ iAddr
] == 0)
579 AfsClass_IntToAddress (&m_ss
.aAddresses
[ m_ss
.nAddresses
++ ], wp
.wpClientAFSServerGet
.Entry
.serverAddress
[ iAddr
]);
582 lpCell
->m_lServers
->Update (this); // That update affected a hashlistkey
589 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd
, GetIdentifier(), ((rc
) ? 0 : status
));
598 void SERVER::GetName (LPTSTR pszName
)
600 SERVER::ShortenName (pszName
, m_szName
);
604 void SERVER::GetLongName (LPTSTR pszName
)
606 lstrcpy (pszName
, m_szName
);
610 LPCELL
SERVER::OpenCell (ULONG
*pStatus
)
612 return m_lpiCell
->OpenCell (pStatus
);
615 BOOL
SERVER::GetStatus (LPSERVERSTATUS lpss
, BOOL fNotify
, ULONG
*pStatus
)
620 rc
= RefreshStatus (fNotify
, pStatus
);
622 memcpy (lpss
, &m_ss
, sizeof(SERVERSTATUS
));
627 short SERVER::GetGhostStatus (void)
633 PVOID
SERVER::GetUserParam (void)
635 return GetIdentifier()->GetUserParam();
639 void SERVER::SetUserParam (PVOID pUserNew
)
641 GetIdentifier()->SetUserParam (pUserNew
);
645 void SERVER::ShortenName (LPTSTR pszTarget
, LPTSTR pszSource
, BOOL fForce
)
647 lstrcpy (pszTarget
, pszSource
);
649 if (fForce
|| !fLongServerNames
)
651 // If the name is really an IP address, don't shorten it.
653 BOOL fIsIPAddress
= TRUE
;
654 for (LPTSTR pch
= pszTarget
; *pch
&& fIsIPAddress
; ++pch
)
656 if (!isdigit(*pch
) && !(*pch
== TEXT('.')))
657 fIsIPAddress
= FALSE
;
662 if ((pszTarget
= (LPTSTR
)lstrchr (pszTarget
, TEXT('.'))) != NULL
)
663 *pszTarget
= TEXT('\0');
669 BOOL
SERVER::fIsMonitored (void)
675 BOOL
SERVER::SetMonitor (BOOL fShouldMonitor
, ULONG
*pStatus
)
680 if (m_fMonitor
!= fShouldMonitor
)
683 if ((lpCell
= m_lpiCell
->OpenCell (&status
)) == NULL
)
687 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin
, GetIdentifier());
689 if ((m_fMonitor
= fShouldMonitor
) == FALSE
)
692 (lpCell
->m_nServersUnmonitored
)++;
694 else // (fMonitor == TRUE)
696 (lpCell
->m_nServersUnmonitored
)--;
698 rc
= RefreshAll (&status
);
701 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd
, GetIdentifier(), m_lastStatus
);
713 * REFRESHALL __________________________________________________________________
715 * If a server is down, or doesn't have an VOS process running, it could
716 * take some time before we time out trying to talk to the server. During
717 * the course of a refresh, the first timeout-and-fail that we will hit is
718 * our call to wtaskVosPartitionGetBegin; since this call is very quick if
719 * it's going to be successful, we can safely perform this call once up-front
720 * to test to see if the server is listening at all. That test is performed
721 * on a separate thread, so that in the event the request times out, we can
722 * simply discard the thread and let it terminate on its own.
732 } REFRESHSECTION
, *LPREFRESHSECTION
;
734 static REFRESHSECTION
*aRefSec
= NULL
;
735 static size_t cRefSec
= 0;
736 static LPCRITICAL_SECTION pcsRefSec
= NULL
;
738 void AfsClass_InitRefreshSections (void)
740 if (pcsRefSec
== NULL
)
742 pcsRefSec
= New (CRITICAL_SECTION
);
743 InitializeCriticalSection (pcsRefSec
);
748 void AfsClass_SkipRefresh (int idSection
)
750 AfsClass_InitRefreshSections();
751 EnterCriticalSection (pcsRefSec
);
753 if (aRefSec
&& (idSection
< (int)cRefSec
))
755 if (aRefSec
[ idSection
].fInUse
)
757 aRefSec
[ idSection
].fCanceled
= TRUE
;
761 LeaveCriticalSection (pcsRefSec
);
765 DWORD WINAPI
SERVER::CanTalkToServer_ThreadProc (PVOID lp
)
767 int idSection
= PtrToInt(lp
);
769 // Until we post a notification saying that we've entered
770 // a section, we don't need to worry about the aRefSec[] entry
771 // being invalid. Once that post is made, the user can skip
772 // the section at any time--so we'll have to check frequently,
773 // always under the pcsRefSec critical section.
775 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionStart
, NULL
, NULL
, NULL
, NULL
, idSection
, 0);
777 BOOL fAggregatesOK
= FALSE
;
778 BOOL fServicesOK
= FALSE
;
779 BOOL fContinue
= TRUE
;
781 // Try to get the BOS object for this server. Remember, there's
782 // a catch here: we can only assume that the aRefSec[idSection].lpServer
783 // pointer is valid so long as we're within the pcsRefSec critical
784 // section! (if we're in that critsec, we can verify that no one
785 // has canceled the operation--and if no one has, there is a thread
786 // hanging around which holds the library's critsec, which ensures
787 // the lpServer pointer won't have been freed.)
793 TCHAR szServer
[ cchNAME
];
795 EnterCriticalSection (pcsRefSec
);
796 if ( ((!aRefSec
[ idSection
].fInUse
) || (aRefSec
[ idSection
].fCanceled
)) )
800 hCell
= aRefSec
[ idSection
].hCell
;
801 aRefSec
[ idSection
].lpServer
->GetLongName (szServer
);
803 LeaveCriticalSection (pcsRefSec
);
808 wp
.wpBosServerOpen
.hCell
= hCell
;
809 wp
.wpBosServerOpen
.pszServer
= szServer
;
812 fContinue
= Worker_DoTask (wtaskBosServerOpen
, &wp
, &status
);
814 EnterCriticalSection (pcsRefSec
);
815 if ( ((!aRefSec
[ idSection
].fInUse
) || (aRefSec
[ idSection
].fCanceled
)) )
818 aRefSec
[ idSection
].lpServer
->m_lastStatus
= status
;
820 hBOS
= wp
.wpBosServerOpen
.hServer
;
821 LeaveCriticalSection (pcsRefSec
);
826 WORKERPACKET wpBegin
;
827 wpBegin
.wpBosProcessNameGetBegin
.hServer
= hBOS
;
830 fContinue
= Worker_DoTask (wtaskBosProcessNameGetBegin
, &wpBegin
, &status
);
832 EnterCriticalSection (pcsRefSec
);
833 if ( ((!aRefSec
[ idSection
].fInUse
) || (aRefSec
[ idSection
].fCanceled
)) )
836 aRefSec
[ idSection
].lpServer
->m_lastStatus
= status
;
837 LeaveCriticalSection (pcsRefSec
);
842 wpDone
.wpBosProcessNameGetDone
.hEnum
= wpBegin
.wpBosProcessNameGetBegin
.hEnum
;
843 Worker_DoTask (wtaskBosProcessNameGetDone
, &wpDone
);
845 // We can talk to BOS!
850 // If we couldn't talk to BOS, it's a sure bet the server is down--
851 // and regardless, if BOS isn't around, VOS isn't either. So
852 // we may not even have to test that.
857 wp
.wpVosServerOpen
.hCell
= hCell
;
858 wp
.wpVosServerOpen
.pszServer
= szServer
;
861 fContinue
= Worker_DoTask (wtaskVosServerOpen
, &wp
, &status
);
863 EnterCriticalSection (pcsRefSec
);
864 if ( ((!aRefSec
[ idSection
].fInUse
) || (aRefSec
[ idSection
].fCanceled
)) )
867 aRefSec
[ idSection
].lpServer
->m_lastStatus
= status
;
869 hVOS
= wp
.wpVosServerOpen
.hServer
;
870 LeaveCriticalSection (pcsRefSec
);
875 WORKERPACKET wpBegin
;
876 wpBegin
.wpVosPartitionGetBegin
.hCell
= hCell
;
877 wpBegin
.wpVosPartitionGetBegin
.hServer
= hVOS
;
880 fContinue
= Worker_DoTask (wtaskVosPartitionGetBegin
, &wpBegin
, &status
);
882 EnterCriticalSection (pcsRefSec
);
883 if ( ((!aRefSec
[ idSection
].fInUse
) || (aRefSec
[ idSection
].fCanceled
)) )
886 aRefSec
[ idSection
].lpServer
->m_lastStatus
= status
;
887 LeaveCriticalSection (pcsRefSec
);
892 wpDone
.wpVosPartitionGetDone
.hEnum
= wpBegin
.wpVosPartitionGetBegin
.hEnum
;
893 Worker_DoTask (wtaskVosPartitionGetDone
, &wpDone
);
895 // We can talk to VOS!
896 fAggregatesOK
= TRUE
;
900 // Close the VOS and BOS objects we obtained.
905 wp
.wpBosServerClose
.hServer
= hBOS
;
906 Worker_DoTask (wtaskBosServerClose
, &wp
);
911 wp
.wpVosServerClose
.hServer
= hVOS
;
912 Worker_DoTask (wtaskVosServerClose
, &wp
);
915 // Return our entry in the RefSec array back to the pool.
916 // If the request was never canceled, there is another
917 // thread waiting to hear our results--update the server
918 // entry specified by RefSec before leaving.
920 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllSectionEnd
, NULL
, NULL
, NULL
, NULL
, idSection
, 0);
922 EnterCriticalSection (pcsRefSec
);
923 if ( (aRefSec
[ idSection
].fInUse
) && (!aRefSec
[ idSection
].fCanceled
) )
925 aRefSec
[ idSection
].lpServer
->m_fCanGetAggregates
= fAggregatesOK
;
926 aRefSec
[ idSection
].lpServer
->m_fCanGetServices
= fServicesOK
;
928 aRefSec
[ idSection
].fInUse
= FALSE
;
929 LeaveCriticalSection (pcsRefSec
);
934 BOOL
SERVER::CanTalkToServer (ULONG
*pStatus
)
936 // Ensure the server exists in the cell at all--
937 // this call just updates the server's IP addresses
938 // etc (information it gets from the database servers)
939 // and doesn't require talking to the server itself.
941 if (!RefreshStatus (FALSE
, pStatus
))
944 // Find a new refsec array element to use...
946 AfsClass_InitRefreshSections();
947 EnterCriticalSection (pcsRefSec
);
950 for (idSection
= 0; idSection
< (int)cRefSec
; ++idSection
)
952 if (!aRefSec
[ idSection
].fInUse
)
955 if (idSection
== (int)cRefSec
)
957 if (!REALLOC (aRefSec
, cRefSec
, 1+idSection
, 4))
960 *pStatus
= GetLastError();
961 LeaveCriticalSection (pcsRefSec
);
965 aRefSec
[ idSection
].fInUse
= TRUE
;
966 aRefSec
[ idSection
].fCanceled
= FALSE
;
967 aRefSec
[ idSection
].lpServer
= this;
968 aRefSec
[ idSection
].hCell
= NULL
;
971 if ((lpCell
= OpenCell()) != NULL
)
973 aRefSec
[ idSection
].hCell
= lpCell
->GetCellObject();
977 LeaveCriticalSection (pcsRefSec
);
979 // Until we find out differently, assume that we won't be
980 // able to query VOS or BOS on this server.
982 m_fCanGetAggregates
= FALSE
;
983 m_fCanGetServices
= FALSE
;
986 // Fork a separate thread, on which to quickly try to talk
991 if ((hThread
= CreateThread (NULL
, 0, (LPTHREAD_START_ROUTINE
)CanTalkToServer_ThreadProc
, IntToPtr(idSection
), 0, &dwThreadID
)) == NULL
)
993 EnterCriticalSection (pcsRefSec
);
994 aRefSec
[ idSection
].fInUse
= FALSE
;
995 LeaveCriticalSection (pcsRefSec
);
997 *pStatus
= GetLastError();
1000 SetThreadPriority (hThread
, THREAD_PRIORITY_BELOW_NORMAL
);
1002 // Wait for that thread to terminate, or for our
1003 // newly-allocated RefSec entry to be marked Canceled.
1006 for (dw
= STILL_ACTIVE
; dw
== STILL_ACTIVE
; )
1008 EnterCriticalSection (pcsRefSec
);
1010 GetExitCodeThread (hThread
, &dw
);
1011 if (dw
== STILL_ACTIVE
)
1013 if ( (aRefSec
[ idSection
].fInUse
) &&
1014 (aRefSec
[ idSection
].lpServer
== this) &&
1015 (aRefSec
[ idSection
].fCanceled
) )
1017 if (m_lastStatus
== 0)
1018 m_lastStatus
= ERROR_CANCELLED
;
1023 LeaveCriticalSection (pcsRefSec
);
1025 if (dw
== STILL_ACTIVE
)
1026 Sleep(100); // wait another brief instant
1029 // dw == 0 : user canceled operation (thread is still running!)
1030 // dw == 1 : thread completed successfully, and set fCanTalkTo* flags.
1032 // Note that the thread will clear aRefSec[idSection].fInUse when it
1033 // terminates (so, if dw!=-1, it has already done so).
1036 *pStatus
= m_lastStatus
;
1037 return (dw
== 0) ? FALSE
: TRUE
;
1041 BOOL
SERVER::RefreshAll (ULONG
*pStatus
, double dInit
, double dFactor
)
1046 if (m_fAggregatesOutOfDate
|| m_fServicesOutOfDate
)
1048 if ((++cRefreshAllReq
) == 1)
1050 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin
, GetIdentifier(), 0);
1053 double perAGGREGATES
= 65.0; // % of time spent finding aggs & sets
1054 double perSERVICES
= 25.0; // % of time spent finding services
1055 double perVLDB
= 10.0; // % of time spent finding VLDB info
1057 if (cRefreshAllReq
>= 2) // being called as part of a cell-wide op?
1059 perAGGREGATES
= 80.0; // % of time spent finding aggs & sets
1060 perSERVICES
= 20.0; // % of time spent finding services
1061 perVLDB
= 0.0; // we won't query VLDB stuff ourself.
1064 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin
, GetIdentifier());
1066 if (!CanTalkToServer (&status
)) // Determines fCanGetAggregates, fCanGetServices
1074 if (!m_fCanGetAggregates
)
1077 m_fAggregatesOutOfDate
= FALSE
;
1081 size_t nAggregates
= 0;
1082 size_t iAggregate
= 0;
1084 LPAGGREGATE lpAggregate
;
1085 for (lpAggregate
= AggregateFindFirst (&hEnum
); lpAggregate
; lpAggregate
= AggregateFindNext (&hEnum
))
1088 lpAggregate
->Close();
1093 for (lpAggregate
= AggregateFindFirst (&hEnum
); lpAggregate
; lpAggregate
= AggregateFindNext (&hEnum
))
1095 ULONG perComplete
= (ULONG
)( ((double)perAGGREGATES
/ 100.0) * ((double)iAggregate
* 100.0 / nAggregates
) );
1096 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate
, lpAggregate
->GetIdentifier(), NULL
, NULL
, NULL
, (ULONG
)( 100.0 * dInit
+ dFactor
* (double)perComplete
), 0);
1098 lpAggregate
->RefreshFilesets (TRUE
);
1099 lpAggregate
->Close();
1106 if (!m_fCanGetServices
)
1109 m_fServicesOutOfDate
= FALSE
;
1113 size_t nServices
= 0;
1114 size_t iService
= 0;
1116 LPSERVICE lpService
;
1117 for (lpService
= ServiceFindFirst (&hEnum
); lpService
; lpService
= ServiceFindNext (&hEnum
))
1125 for (lpService
= ServiceFindFirst (&hEnum
); lpService
; lpService
= ServiceFindNext (&hEnum
))
1127 ULONG perComplete
= (ULONG
)( (double)perAGGREGATES
+ ((double)perSERVICES
/ 100.0) * ((double)iService
* 100.0 / nServices
) );
1128 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate
, lpService
->GetIdentifier(), NULL
, NULL
, NULL
, (ULONG
)( 100.0 * dInit
+ dFactor
* (double)perComplete
), 0);
1130 lpService
->RefreshStatus (TRUE
);
1138 if (cRefreshAllReq
== 1) // not being called as part of a cell-wide op?
1141 if ((lpCell
= OpenCell()) != NULL
)
1143 lpCell
->RefreshVLDB (GetIdentifier(), TRUE
, NULL
);
1149 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd
, GetIdentifier(), m_lastStatus
);
1151 if ((--cRefreshAllReq
) == 0)
1153 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd
, GetIdentifier(), NULL
, NULL
, NULL
, 100, m_lastStatus
);
1157 if (rc
&& m_lastStatus
)
1166 * AGGREGATES _________________________________________________________________
1170 LPAGGREGATE
SERVER::OpenAggregate (LPTSTR pszName
, ULONG
*pStatus
)
1172 if (!RefreshAggregates (TRUE
, pStatus
))
1175 LPAGGREGATE lpAggregate
;
1176 if ((lpAggregate
= (LPAGGREGATE
)(m_lkAggregateName
->GetFirstObject (pszName
))) != NULL
)
1183 LPAGGREGATE
SERVER::OpenAggregate (ULONG dwID
, ULONG
*pStatus
)
1185 if (!RefreshAggregates (TRUE
, pStatus
))
1188 LPAGGREGATE lpAggregate
;
1189 if ((lpAggregate
= (LPAGGREGATE
)(m_lkAggregateID
->GetFirstObject (&dwID
))) != NULL
)
1196 LPAGGREGATE
SERVER::AggregateFindFirst (HENUM
*phEnum
, BOOL fNotify
, ULONG
*pStatus
)
1198 return AggregateFindFirst (phEnum
, NULL
, fNotify
, pStatus
);
1202 LPAGGREGATE
SERVER::AggregateFindFirst (HENUM
*phEnum
, LPIDENT lpiFind
, BOOL fNotify
, ULONG
*pStatus
)
1204 LPAGGREGATE lpAggregate
= NULL
;
1206 if (!RefreshAggregates (fNotify
, pStatus
))
1209 if (lpiFind
!= NULL
)
1211 lpAggregate
= lpiFind
->OpenAggregate();
1214 else if ((*phEnum
= m_lAggregates
->FindFirst()) != NULL
)
1216 lpAggregate
= (LPAGGREGATE
)( (*phEnum
)->GetObject() );
1220 if (!lpAggregate
&& pStatus
)
1221 *pStatus
= ERROR_FILE_NOT_FOUND
;
1226 LPAGGREGATE
SERVER::AggregateFindNext (HENUM
*phEnum
)
1228 LPAGGREGATE lpAggregate
= NULL
;
1232 if ((*phEnum
= (*phEnum
)->FindNext()) != NULL
)
1234 lpAggregate
= (LPAGGREGATE
)( (*phEnum
)->GetObject() );
1243 void SERVER::AggregateFindClose (HENUM
*phEnum
)
1254 * SERVICES ___________________________________________________________________
1258 LPSERVICE
SERVER::OpenService (LPTSTR pszName
, ULONG
*pStatus
)
1260 if (!RefreshServices (TRUE
, pStatus
))
1263 LPSERVICE lpService
;
1264 if ((lpService
= (LPSERVICE
)(m_lkServiceName
->GetFirstObject (pszName
))) != NULL
)
1271 LPSERVICE
SERVER::ServiceFindFirst (HENUM
*phEnum
, BOOL fNotify
, ULONG
*pStatus
)
1273 return ServiceFindFirst (phEnum
, NULL
, fNotify
, pStatus
);
1277 LPSERVICE
SERVER::ServiceFindFirst (HENUM
*phEnum
, LPIDENT lpiFind
, BOOL fNotify
, ULONG
*pStatus
)
1279 LPSERVICE lpService
= NULL
;
1281 if (!RefreshServices (fNotify
, pStatus
))
1284 if (lpiFind
!= NULL
)
1286 lpService
= lpiFind
->OpenService();
1289 else if ((*phEnum
= m_lServices
->FindFirst()) != NULL
)
1291 lpService
= (LPSERVICE
)( (*phEnum
)->GetObject() );
1295 if (!lpService
&& pStatus
)
1296 *pStatus
= ERROR_FILE_NOT_FOUND
;
1301 LPSERVICE
SERVER::ServiceFindNext (HENUM
*phEnum
)
1303 LPSERVICE lpService
= NULL
;
1307 if ((*phEnum
= (*phEnum
)->FindNext()) != NULL
)
1309 lpService
= (LPSERVICE
)( (*phEnum
)->GetObject() );
1318 void SERVER::ServiceFindClose (HENUM
*phEnum
)
1329 * HASH KEYS __________________________________________________________________
1333 BOOL CALLBACK
SERVER::KeyAggregateName_Compare (LPHASHLISTKEY pKey
, PVOID pObject
, PVOID pData
)
1335 return !lstrcmp (((LPAGGREGATE
)pObject
)->m_szName
, (LPTSTR
)pData
);
1338 HASHVALUE CALLBACK
SERVER::KeyAggregateName_HashObject (LPHASHLISTKEY pKey
, PVOID pObject
)
1340 return SERVER::KeyAggregateName_HashData (pKey
, ((LPAGGREGATE
)pObject
)->m_szName
);
1343 HASHVALUE CALLBACK
SERVER::KeyAggregateName_HashData (LPHASHLISTKEY pKey
, PVOID pData
)
1345 return HashString ((LPTSTR
)pData
);
1349 BOOL CALLBACK
SERVER::KeyAggregateID_Compare (LPHASHLISTKEY pKey
, PVOID pObject
, PVOID pData
)
1351 return (((LPAGGREGATE
)pObject
)->m_as
.dwID
== *(ULONG
*)pData
);
1354 HASHVALUE CALLBACK
SERVER::KeyAggregateID_HashObject (LPHASHLISTKEY pKey
, PVOID pObject
)
1356 return SERVER::KeyAggregateID_HashData (pKey
, &((LPAGGREGATE
)pObject
)->m_as
.dwID
);
1359 HASHVALUE CALLBACK
SERVER::KeyAggregateID_HashData (LPHASHLISTKEY pKey
, PVOID pData
)
1361 return (HASHVALUE
)*(ULONG
*)pData
;
1365 BOOL CALLBACK
SERVER::KeyServiceName_Compare (LPHASHLISTKEY pKey
, PVOID pObject
, PVOID pData
)
1367 return !lstrcmp (((LPSERVICE
)pObject
)->m_szName
, (LPTSTR
)pData
);
1370 HASHVALUE CALLBACK
SERVER::KeyServiceName_HashObject (LPHASHLISTKEY pKey
, PVOID pObject
)
1372 return SERVER::KeyServiceName_HashData (pKey
, ((LPSERVICE
)pObject
)->m_szName
);
1375 HASHVALUE CALLBACK
SERVER::KeyServiceName_HashData (LPHASHLISTKEY pKey
, PVOID pData
)
1377 return HashString ((LPTSTR
)pData
);