876 lines
23 KiB
C++
876 lines
23 KiB
C++
/*++
|
|
|
|
Copyright (C) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
MAINTOBJ.CPP
|
|
|
|
Abstract:
|
|
|
|
Maintenance object for keeping track of CComLink objects.
|
|
|
|
History:
|
|
|
|
a-davj 24-Sep-97 Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "wmishared.h"
|
|
|
|
DWORD ClientMaintThread ( LPDWORD pParam ) ;
|
|
|
|
//***************************************************************************
|
|
//
|
|
// LockOut::LockOut
|
|
// LockOut::~LockOut
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor and destructor
|
|
//
|
|
//***************************************************************************
|
|
|
|
LockOut::LockOut(CRITICAL_SECTION & cs)
|
|
{
|
|
m_cs = &cs;
|
|
EnterCriticalSection(m_cs);
|
|
}
|
|
|
|
LockOut::~LockOut()
|
|
{
|
|
LeaveCriticalSection(m_cs);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::MaintObj
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
//
|
|
//***************************************************************************
|
|
|
|
MaintObj :: MaintObj ( BOOL a_Client )
|
|
{
|
|
InitializeCriticalSection ( & m_cs ) ;
|
|
|
|
m_ChangeEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|
m_ClientThreadStartedEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|
m_ClientThreadHandle = NULL;
|
|
|
|
m_ClientRole = a_Client;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::~MaintObj
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
MaintObj :: ~MaintObj ()
|
|
{
|
|
// If this object is supplying the thread, as is the case in a client,
|
|
// the thread should be terminated as a result of the global termiation
|
|
// event already being set. However, threads being threads, give it
|
|
// some time to die gracefully before resorting to a termination.
|
|
|
|
if ( m_ClientThreadHandle )
|
|
{
|
|
DWORD dwRes = WbemWaitForSingleObject ( m_ClientThreadHandle , 2000 ) ;
|
|
if ( dwRes == WAIT_TIMEOUT )
|
|
{
|
|
TerminateThread ( m_ClientThreadHandle , 1 ) ;
|
|
}
|
|
|
|
CloseHandle ( m_ClientThreadHandle ) ;
|
|
}
|
|
|
|
DeleteCriticalSection ( & m_cs ) ;
|
|
|
|
if ( m_ChangeEvent )
|
|
CloseHandle ( m_ChangeEvent ) ;
|
|
|
|
if ( m_ClientThreadStartedEvent )
|
|
CloseHandle ( m_ClientThreadStartedEvent ) ;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::AddComLink
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Called when it is time to add a new CComLink object to the list of things
|
|
// being maintained.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pComLink Pointer to the object to be added to the list
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT MaintObj :: AddComLink ( CComLink *a_ComLink )
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
// Add the object pointer to the CComLink list
|
|
|
|
a_ComLink->AddRef2 ( NULL , NONE , DONOTHING ) ;
|
|
|
|
ComEntry *t_ComLinkNode = new ComEntry ( a_ComLink ) ;
|
|
if ( t_ComLinkNode == NULL )
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
HANDLE t_StreamHandle = a_ComLink->GetStreamHandle () ;
|
|
|
|
HRESULT scRet = m_ComLinkContainer.Add ( t_ComLinkNode ) ;
|
|
if ( SUCCEEDED ( scRet ) )
|
|
{
|
|
// Some comlinks use events to indicate time to read. If this is one
|
|
// of these, add it to the list.
|
|
|
|
if ( t_StreamHandle )
|
|
{
|
|
EventEntry * t_EventNode = new EventEntry ( t_StreamHandle );
|
|
m_EventContainer.Add ( t_EventNode ) ;
|
|
}
|
|
}
|
|
|
|
// If ComLinks has transitioned to one ( actually really need to test for transition from 0 to 1 )
|
|
// or event handle has been removed then update worket thread.
|
|
|
|
if ( m_ComLinkContainer.Size () == 1 || t_StreamHandle )
|
|
{
|
|
SetEvent ( m_ChangeEvent ) ;
|
|
}
|
|
|
|
return scRet;
|
|
}
|
|
|
|
void MaintObj::Indicate ( CComLink *a_ComLink )
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
// Find the entry in the list an immediatly delete it
|
|
|
|
int t_Index ;
|
|
ComEntry *t_ComEntryNode = FindEntry ( a_ComLink, t_Index ) ;
|
|
if ( t_ComEntryNode == NULL )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
m_ComLinkContainer.RemoveAt ( t_Index ) ;
|
|
delete t_ComEntryNode ;
|
|
|
|
a_ComLink->Release2 ( NULL , NONE ) ;
|
|
}
|
|
|
|
void MaintObj::UnLockedIndicate ( CComLink *a_ComLink )
|
|
{
|
|
// Find the entry in the list an immediatly delete it
|
|
|
|
int t_Index ;
|
|
ComEntry *t_ComEntryNode = UnLockedFindEntry ( a_ComLink, t_Index ) ;
|
|
if ( t_ComEntryNode == NULL )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
m_ComLinkContainer.RemoveAt ( t_Index ) ;
|
|
delete t_ComEntryNode ;
|
|
|
|
a_ComLink->Release3 ( NULL , NONE ) ;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::ShutDownComlink
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Called when a comlink should be terminated. Note that the actual
|
|
// deletion is done in the maintenace loop since we dont want the CComLink
|
|
// object to delete itself in a member function.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pComLink Pointer to the object to be added to the list
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT MaintObj::ShutDownComlink ( CComLink *a_ComLink )
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
HRESULT scRet = UnLockedShutDownComlink ( a_ComLink ) ;
|
|
return scRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::ShutDownComlink
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Called when a comlink should be terminated. Note that the actual
|
|
// deletion is done in the maintenace loop since we dont want the CComLink
|
|
// object to delete itself in a member function.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pComLink Pointer to the object to be added to the list
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT MaintObj::UnLockedShutDownComlink ( CComLink *a_ComLink )
|
|
{
|
|
HRESULT scRet = S_OK;
|
|
|
|
// Find the entry in the list an immediatly delete it
|
|
|
|
int t_Index ;
|
|
HANDLE t_StreamHandle = NULL;
|
|
ComEntry *t_ComEntryNode = UnLockedFindEntry ( a_ComLink, t_Index ) ;
|
|
if ( t_ComEntryNode != NULL )
|
|
{
|
|
m_ComLinkContainer.RemoveAt ( t_Index ) ;
|
|
delete t_ComEntryNode ;
|
|
|
|
t_StreamHandle = a_ComLink->GetStreamHandle ();
|
|
|
|
a_ComLink->UnLockedShutdown () ;
|
|
|
|
a_ComLink->Release3 ( NULL , NONE ) ;
|
|
}
|
|
|
|
// some comlinks have an event for reading which needs to be deleted.
|
|
// These cannot be deleted immediatly since the maintenance thread is
|
|
// currently waiting on these. So, mark it for deletion instead.
|
|
|
|
if ( t_StreamHandle )
|
|
{
|
|
int t_Size = m_EventContainer.Size() ;
|
|
for ( int t_Index = 0; t_Index < t_Size ; t_Index ++ )
|
|
{
|
|
EventEntry *t_EventNode = ( EventEntry * ) m_EventContainer [ t_Index ] ;
|
|
if(t_EventNode && ( t_EventNode->m_AsynchronousEventHandle == t_StreamHandle ) )
|
|
{
|
|
t_EventNode->m_DeleteASAP = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If ComLinks has transitioned to zero or event handle has been removed then update worket thread.
|
|
|
|
if ( m_ComLinkContainer.Size () == 0 || t_StreamHandle )
|
|
{
|
|
SetEvent ( m_ChangeEvent ) ;
|
|
}
|
|
|
|
return scRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::StartClientThreadIfNeeded
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Only used by clients since the server uses the main thread. This is
|
|
// called when the locator determines that a non dcom connection is
|
|
// being make.
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT MaintObj::StartClientThreadIfNeeded ()
|
|
{
|
|
DWORD dwRes = WbemWaitForSingleObject ( m_ClientThreadStartedEvent , 0 ) ;
|
|
if( dwRes == WAIT_OBJECT_0 )
|
|
{
|
|
// Thread has already been started, one per process.
|
|
|
|
return S_FALSE ;
|
|
}
|
|
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
DWORD t_ThreadId;
|
|
|
|
m_ClientThreadHandle = CreateThread (
|
|
|
|
NULL ,
|
|
0 ,
|
|
( LPTHREAD_START_ROUTINE ) ClientMaintThread ,
|
|
( LPVOID ) m_ClientThreadStartedEvent ,
|
|
0,
|
|
&t_ThreadId
|
|
) ;
|
|
|
|
if ( ! m_ClientThreadHandle )
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
DWORD t_Timeout = GetTimeout () ;
|
|
dwRes = WbemWaitForSingleObject ( m_ClientThreadStartedEvent , t_Timeout ) ;
|
|
if ( dwRes == WAIT_OBJECT_0 )
|
|
{
|
|
return S_OK ;
|
|
}
|
|
else
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::ShutDownAllComlinks
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT MaintObj::ShutDownAllComlinks ()
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
UnLockedShutDownAllComlinks () ;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::ShutDownAllComlinks
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT MaintObj::UnLockedShutDownAllComlinks ()
|
|
{
|
|
while ( m_ComLinkContainer.Size () > 0 )
|
|
{
|
|
ComEntry *t_ComLinkNode = (ComEntry *) m_ComLinkContainer [ 0 ] ;
|
|
CComLink*t_ComLink = t_ComLinkNode->m_ComLink ;
|
|
|
|
UnLockedShutDownComlink ( t_ComLink ) ;
|
|
}
|
|
|
|
// Should be zero by the time we get here
|
|
|
|
int t_Size = m_EventContainer.Size () ;
|
|
for ( int t_Index = 0 ; t_Index < t_Size ; t_Index ++ )
|
|
{
|
|
EventEntry *t_EntryNode = ( EventEntry * ) m_EventContainer [ t_Index ];
|
|
if ( t_EntryNode )
|
|
{
|
|
delete t_EntryNode ;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::CheckForHungConnections()
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Called periodically by the server maintenace thread to eliminate any
|
|
// clients which have died or gone away without releasing properly.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT MaintObj :: CheckForHungConnections ()
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
DWORD t_RegistryTimeout = GetTimeout () ;
|
|
|
|
int t_Size = m_ComLinkContainer.Size () ;
|
|
for ( int t_Index = t_Size-1; t_Index >= 0; t_Index --)
|
|
{
|
|
ComEntry *t_ComLinkNode = ( ComEntry * ) m_ComLinkContainer [ t_Index ] ;
|
|
if ( t_ComLinkNode )
|
|
{
|
|
CComLink *t_ComLink = t_ComLinkNode->m_ComLink ;
|
|
if( t_ComLink )
|
|
{
|
|
DWORD t_LastActivity = GetCurrentTime () - t_ComLink->GetTimeOfLastRead () ;
|
|
|
|
// If now hearbeats have been received for some time, then
|
|
// start the termination process. Note that does the shut down
|
|
// if there are not any active calls being processed at this time.
|
|
|
|
if ( t_LastActivity > t_RegistryTimeout )
|
|
{
|
|
t_ComLink->StartTermination () ;
|
|
|
|
// If there are no busy threads then shutdown comlink. There seems to be a hole in this logic !!!!!
|
|
|
|
if ( gThrdPool.Busy () == FALSE )
|
|
{
|
|
ShutDownComlink ( t_ComLink ) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::SendHeartBeats()
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Sends a periodic "Keep Alive" message to the partner.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT MaintObj :: SendHeartBeats ()
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
int t_Size = m_ComLinkContainer.Size () ;
|
|
for( int t_Index = 0; t_Index < t_Size ; t_Index ++ )
|
|
{
|
|
ComEntry *t_ComLinkNode = ( ComEntry * ) m_ComLinkContainer [ t_Index ] ;
|
|
if ( t_ComLinkNode )
|
|
{
|
|
CComLink *t_ComLink = t_ComLinkNode->m_ComLink ;
|
|
if ( t_ComLink )
|
|
{
|
|
t_ComLink->StrobeConnection () ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::FindEntry()
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Finds a particular CComLink in the list, returns a pointer and the index
|
|
// is set.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pComLink CComLink object pointer
|
|
// iFind set to the index in our array.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// Pointer to ComEntry object. Note that iFind is set via reference
|
|
//
|
|
//***************************************************************************
|
|
|
|
ComEntry *MaintObj :: UnLockedFindEntry ( CComLink *a_ComLink , int &a_Index )
|
|
{
|
|
a_Index = -1 ;
|
|
|
|
int t_Size = m_ComLinkContainer.Size();
|
|
|
|
for( int t_Index = 0; t_Index < t_Size; t_Index ++ )
|
|
{
|
|
ComEntry *t_ComLinkNode = ( ComEntry * ) m_ComLinkContainer [ t_Index ] ;
|
|
if ( a_ComLink == t_ComLinkNode->m_ComLink )
|
|
{
|
|
a_Index = t_Index ;
|
|
return t_ComLinkNode ;
|
|
}
|
|
}
|
|
|
|
return NULL ;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::FindEntry()
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Finds a particular CComLink in the list, returns a pointer and the index
|
|
// is set.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pComLink CComLink object pointer
|
|
// iFind set to the index in our array.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// Pointer to ComEntry object. Note that iFind is set via reference
|
|
//
|
|
//***************************************************************************
|
|
|
|
ComEntry *MaintObj :: FindEntry ( CComLink *a_ComLink , int &a_Index )
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
return UnLockedFindEntry ( a_ComLink , a_Index ) ;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::GetSocketComLink()
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Given a socket number, this finds the CComLink object which is using
|
|
// this socket.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// s Socket number
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// CComlink object, NULL if not found.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CComLink *MaintObj :: GetSocketComLink ( SOCKET s )
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
int t_Size = m_ComLinkContainer.Size () ;
|
|
for( int t_Index = 0 ; t_Index < t_Size ; t_Index ++ )
|
|
{
|
|
ComEntry *t_ComLinkNode = ( ComEntry * ) m_ComLinkContainer [ t_Index ] ;
|
|
if ( t_ComLinkNode )
|
|
{
|
|
CComLink *t_ComLink = t_ComLinkNode->m_ComLink ;
|
|
|
|
if ( t_ComLink && t_ComLink->GetSocketHandle () == s )
|
|
{
|
|
return t_ComLink ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::GetEvents()
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// This is called by the maintenace thread an it returns a list of events
|
|
// to wait on and sets the time between pings. Note that the handle list
|
|
// includes the termination event, the change in state event, as well as
|
|
// any asynchronous read events.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// ghTerminate Terminate event
|
|
// piNum Set to the number of events returned
|
|
// pdwRest Set to the time between pings
|
|
// bServer True if being called by the server. Note that
|
|
// this currently isnt relevant.
|
|
// RETURN VALUE:
|
|
//
|
|
// pointer to a handle array. Note that the CALLER SHOULD FREE THIS when
|
|
// it is either done, or needs a fresh list.
|
|
//
|
|
//***************************************************************************
|
|
|
|
HANDLE *MaintObj::GetEvents (
|
|
|
|
HANDLE a_Terminate,
|
|
int &a_EventContainerSize ,
|
|
DWORD &a_EventTimeout
|
|
)
|
|
{
|
|
// note that this is called by the maintenance thread in responce
|
|
// to the change event being set.
|
|
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
// Figure out how long to delay
|
|
|
|
DWORD t_ComLinkCount = m_ComLinkContainer.Size();
|
|
if ( t_ComLinkCount )
|
|
{
|
|
DWORD t_RegistryTimeout = GetTimeout () / STROBES_PER_TIMEOUT_PERIOD ;
|
|
a_EventTimeout = t_RegistryTimeout ;
|
|
}
|
|
else
|
|
{
|
|
a_EventTimeout = INFINITE;
|
|
}
|
|
|
|
// find out how many events need to be watched for the comlinks
|
|
|
|
int t_Size = m_EventContainer.Size() ;
|
|
int t_NumberOfAsyncEvents = 0 ;
|
|
int t_NumberToDelete = 0 ;
|
|
|
|
for ( int t_Index = 0; t_Index < t_Size ; t_Index ++ )
|
|
{
|
|
EventEntry *t_AsyncEntry = ( EventEntry * ) m_EventContainer [ t_Index ] ;
|
|
if ( t_AsyncEntry )
|
|
{
|
|
if ( t_AsyncEntry->m_DeleteASAP )
|
|
{
|
|
t_NumberToDelete ++ ;
|
|
}
|
|
else
|
|
{
|
|
t_NumberOfAsyncEvents ++ ;
|
|
}
|
|
}
|
|
}
|
|
|
|
a_EventContainerSize = t_NumberOfAsyncEvents + 2 ;
|
|
HANDLE *t_EventContainer = new HANDLE [ a_EventContainerSize ] ;
|
|
t_EventContainer[0] = a_Terminate;
|
|
t_EventContainer[1] = m_ChangeEvent;
|
|
|
|
// Add each comlink event entry to the list
|
|
|
|
int t_ContainerIndex = 2;
|
|
for ( t_Index = 0; t_Index < t_Size ; t_Index ++ )
|
|
{
|
|
EventEntry *t_AsyncEntry = ( EventEntry * ) m_EventContainer [ t_Index ] ;
|
|
if ( t_AsyncEntry )
|
|
{
|
|
if ( t_AsyncEntry->m_DeleteASAP == FALSE )
|
|
{
|
|
t_EventContainer [ t_ContainerIndex ] = t_AsyncEntry->m_AsynchronousEventHandle ;
|
|
t_ContainerIndex ++ ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( t_NumberToDelete != 0 )
|
|
{
|
|
// Delete any unused event objects
|
|
|
|
for ( t_Index = t_Size - 1 ; t_Index >= 0; t_Index -- )
|
|
{
|
|
EventEntry *t_AsyncEntry = ( EventEntry * ) m_EventContainer [ t_Index ] ;
|
|
if ( t_AsyncEntry )
|
|
{
|
|
if ( t_AsyncEntry->m_DeleteASAP )
|
|
{
|
|
m_EventContainer.RemoveAt ( t_Index ) ;
|
|
delete t_AsyncEntry ;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_EventContainer.Compress () ;
|
|
}
|
|
|
|
ResetEvent ( m_ChangeEvent ) ;
|
|
|
|
return t_EventContainer ;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// MaintObj::ServiceEvent()
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Called by the maintenance thread when one of the events used by CComLinks
|
|
// to indicate read ready data is set.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// hEvent Event that was set.
|
|
//
|
|
//***************************************************************************
|
|
|
|
void MaintObj :: ServiceEvent ( HANDLE a_Event )
|
|
{
|
|
LockOut lock ( m_cs ) ;
|
|
|
|
int t_Size = m_ComLinkContainer.Size () ;
|
|
|
|
for ( int t_Index = 0 ; t_Index < t_Size ; t_Index ++ )
|
|
{
|
|
ComEntry *t_ComLinkNode = ( ComEntry * ) m_ComLinkContainer [ t_Size ];
|
|
if ( t_ComLinkNode )
|
|
{
|
|
CComLink *t_ComLink = t_ComLinkNode->m_ComLink ;
|
|
if ( a_Event == t_ComLink->GetStreamHandle () )
|
|
{
|
|
t_ComLink->ProcessEvent () ;
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
|
|
ResetEvent ( a_Event ) ; //hmm, never found it, reset so we dont go into infinite loop
|
|
}
|
|
|
|
BOOL MaintObj :: ClientRole ()
|
|
{
|
|
return m_ClientRole ;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DWORD ClientMaintThread
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Periodically pings the connection and thus detects when the connection
|
|
// has died.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pParam points to the comlink object that is to be watched.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// N/A
|
|
//***************************************************************************
|
|
|
|
DWORD ClientMaintThread ( LPDWORD pParam )
|
|
{
|
|
DWORD t_EventTimeout = 0 ;
|
|
|
|
// Do some initial work and signal when we are ready.
|
|
|
|
HANDLE t_ThreadStartedEvent = ( HANDLE ) pParam ;
|
|
SetEvent ( t_ThreadStartedEvent ) ;
|
|
|
|
int t_EventContainerSize ;
|
|
|
|
HANDLE *t_EventContainer = gMaintObj.GetEvents ( g_Terminate , t_EventContainerSize , t_EventTimeout ) ;
|
|
|
|
while(1)
|
|
{
|
|
DWORD dwRet = MsgWaitForMultipleObjects ( t_EventContainerSize , t_EventContainer , FALSE, t_EventTimeout , QS_ALLINPUT ) ;
|
|
|
|
// Check for termination, if that is the case free up and exit.
|
|
// ============================================================
|
|
|
|
if ( dwRet == 0xffffffff )
|
|
{
|
|
DWORD t_GetLastError = GetLastError () ;
|
|
}
|
|
else if ( dwRet == WAIT_OBJECT_0 )
|
|
{
|
|
// Ok, delete the comlink objects and exit!
|
|
|
|
delete [] t_EventContainer;
|
|
|
|
gMaintObj.ShutDownAllComlinks () ;
|
|
ExitThread(0);
|
|
}
|
|
else if ( dwRet == ( WAIT_OBJECT_0 + 1 ) )
|
|
{
|
|
// There has been a change in either the number of connections, or
|
|
// the number of active connections.
|
|
|
|
delete [] t_EventContainer ;
|
|
t_EventContainer = gMaintObj.GetEvents ( g_Terminate , t_EventContainerSize , t_EventTimeout ) ;
|
|
}
|
|
else if ( ( dwRet >= ( WAIT_OBJECT_0 + t_EventContainerSize ) ) && ( dwRet < ( WAIT_OBJECT_0 + t_EventContainerSize ) ) )
|
|
{
|
|
gMaintObj.ServiceEvent ( t_EventContainer [ dwRet - WAIT_OBJECT_0 ] ) ;
|
|
}
|
|
else if ( dwRet == WAIT_TIMEOUT )
|
|
{
|
|
|
|
// time period elapsed
|
|
|
|
DEBUGTRACE((LOG,"\nHeart Beat"));
|
|
|
|
if ( gMaintObj.ClientRole () )
|
|
{
|
|
gMaintObj.SendHeartBeats ();
|
|
}
|
|
|
|
DEBUGTRACE((LOG,"\nHung Connections"));
|
|
|
|
gMaintObj.CheckForHungConnections () ;
|
|
|
|
DEBUGTRACE((LOG,"\nCompleted Check for Hung Connections"));
|
|
|
|
}
|
|
else
|
|
{
|
|
MSG t_Message ;
|
|
BOOL t_Status = PeekMessage ( &t_Message , NULL , 0 , 0 , PM_REMOVE ) ;
|
|
if ( t_Status )
|
|
{
|
|
TranslateMessage ( &t_Message ) ;
|
|
DispatchMessage ( &t_Message ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|