311 lines
6 KiB
C++
311 lines
6 KiB
C++
#ifndef _WPRECYCLER_HXX_
|
|
#define _WPRECYCLER_HXX_
|
|
|
|
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name :
|
|
wprecycler.hxx
|
|
|
|
Abstract:
|
|
Definition of WP_RECYCLER. Object handles worker process recycling
|
|
- Memory based recycling
|
|
- Schedule based recycling
|
|
- Elapsed time based recycling
|
|
|
|
|
|
Author:
|
|
Jaroslav Dunajsky (JaroslaD) 07-Dec-2000
|
|
|
|
Environment:
|
|
Win32 - User Mode
|
|
|
|
Project:
|
|
W3DT.DLL
|
|
--*/
|
|
|
|
|
|
// memory usage will be monitored every 5 minutes - hardcoded value
|
|
const DWORD CHECK_MEMORY_TIME_PERIOD = 300000;
|
|
|
|
|
|
|
|
|
|
class WP_RECYCLER
|
|
{
|
|
|
|
public:
|
|
|
|
static
|
|
HRESULT
|
|
Initialize(
|
|
VOID
|
|
)
|
|
{
|
|
DBG_ASSERT(FALSE == sm_fCritSecInit);
|
|
InitializeCriticalSection( &WP_RECYCLER::sm_CritSec );
|
|
sm_fCritSecInit = TRUE;
|
|
return S_OK;
|
|
};
|
|
|
|
static
|
|
VOID
|
|
Terminate(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Terminate all recycling
|
|
|
|
Note:
|
|
Caller must assure that no more Start*() methods will be called
|
|
after Terminate() is called
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
--*/
|
|
|
|
{
|
|
TerminateScheduleBased();
|
|
TerminateTimeBased();
|
|
TerminateMemoryBased();
|
|
TerminateRequestBased();
|
|
|
|
DBG_ASSERT(TRUE == sm_fCritSecInit);
|
|
DeleteCriticalSection( &WP_RECYCLER::sm_CritSec );
|
|
sm_fCritSecInit = FALSE;
|
|
return ;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
StartScheduleBased(
|
|
IN const WCHAR * pwszScheduleTimes
|
|
);
|
|
|
|
static
|
|
VOID
|
|
TerminateScheduleBased(
|
|
VOID
|
|
);
|
|
|
|
static
|
|
VOID
|
|
WINAPI
|
|
TimerCallbackForScheduleBased(
|
|
PVOID pParam,
|
|
BOOLEAN TimerOrWaitFired
|
|
);
|
|
|
|
|
|
static
|
|
HRESULT
|
|
StartMemoryBased(
|
|
IN DWORD dwMaxVirtualMemoryKbUsage
|
|
);
|
|
|
|
static
|
|
VOID
|
|
TerminateMemoryBased(
|
|
VOID
|
|
);
|
|
|
|
static
|
|
VOID
|
|
WINAPI
|
|
TimerCallbackForMemoryBased(
|
|
PVOID pParam,
|
|
BOOLEAN TimerOrWaitFired
|
|
);
|
|
|
|
static
|
|
HRESULT
|
|
StartTimeBased(
|
|
IN DWORD dwPeriodicRestartTimeInMinutes
|
|
);
|
|
|
|
static
|
|
VOID
|
|
TerminateTimeBased(
|
|
VOID
|
|
);
|
|
|
|
static
|
|
VOID
|
|
WINAPI
|
|
TimerCallbackForTimeBased(
|
|
PVOID pParam,
|
|
BOOLEAN TimerOrWaitFired
|
|
);
|
|
|
|
static
|
|
HRESULT
|
|
StartRequestBased(
|
|
IN DWORD dwRequests
|
|
);
|
|
|
|
static
|
|
VOID
|
|
TerminateRequestBased(
|
|
VOID
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
IsRequestCountLimitReached(
|
|
IN DWORD dwCurrentRequests
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
if Request count limit has been reached then
|
|
this routine will inform WAS that process is ready
|
|
to be recycled
|
|
|
|
Note:
|
|
It is called for each request!!!
|
|
|
|
Arguments:
|
|
|
|
dwCurrentRequests - number of requests processed so far
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
|
|
--*/
|
|
|
|
{
|
|
if ( !WP_RECYCLER::sm_fIsStartedRequestBased )
|
|
{
|
|
return TRUE;
|
|
}
|
|
if ( dwCurrentRequests > sm_dwMaxValueForRequestBased )
|
|
{
|
|
IF_DEBUG( WPRECYCLER )
|
|
{
|
|
if ( dwCurrentRequests == sm_dwMaxValueForRequestBased + 1 )
|
|
{
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"WP_RECYCLER::CheckRequestBased - limit has been reached"
|
|
"- tell WAS to recycle\n" ));
|
|
}
|
|
}
|
|
WP_RECYCLER::SendRecyclingMsg( IPM_WP_RESTART_COUNT_REACHED );
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
NeedToSendRecyclingMsg(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
returns true if recycling request hasn't been sent yet
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
|
|
--*/
|
|
|
|
{
|
|
if( sm_RecyclingMsgSent == 1 )
|
|
{
|
|
return FALSE;
|
|
}
|
|
return InterlockedExchange( &sm_RecyclingMsgSent, 1 ) == 0;
|
|
|
|
}
|
|
|
|
|
|
static
|
|
VOID
|
|
SendRecyclingMsg(
|
|
IN enum IPM_WP_SHUTDOWN_MSG Reason
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
sends recycling request to WAS
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
if( WP_RECYCLER::NeedToSendRecyclingMsg() )
|
|
{
|
|
DBG_ASSERT( g_pwpContext != NULL );
|
|
hr = g_pwpContext->SendMsgToAdminProcess( Reason );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
DBGPRINTF((
|
|
DBG_CONTEXT,
|
|
"failed to send recycling request message to WAS: hr=0x%x\n",
|
|
hr));
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
private:
|
|
|
|
|
|
//
|
|
// We maintain separate timers so that in the case of change in
|
|
// parameter for one type of recycling we don't have to drop
|
|
// all scheduled events for all recycling types
|
|
//
|
|
|
|
static CRITICAL_SECTION sm_CritSec;
|
|
|
|
static HANDLE sm_hTimerForMemoryBased;
|
|
static BOOL sm_fIsStartedMemoryBased;
|
|
static SIZE_T sm_MaxValueForMemoryBased;
|
|
static HANDLE sm_hCurrentProcess;
|
|
|
|
static HANDLE sm_hTimerForTimeBased;
|
|
static BOOL sm_fIsStartedTimeBased;
|
|
|
|
static HANDLE sm_hTimerQueueForScheduleBased;
|
|
static BOOL sm_fIsStartedScheduleBased;
|
|
|
|
static BOOL sm_fIsStartedRequestBased;
|
|
static DWORD sm_dwMaxValueForRequestBased;
|
|
|
|
// indicate that message requesting process recycling
|
|
// has been sent already (we will send only one recycling request)
|
|
// even if multiple conditions are hit
|
|
//
|
|
static LONG sm_RecyclingMsgSent;
|
|
static BOOL sm_fCritSecInit;
|
|
|
|
WP_RECYCLER();
|
|
~WP_RECYCLER();
|
|
|
|
};
|
|
|
|
|
|
#endif
|