627 lines
18 KiB
C++
627 lines
18 KiB
C++
/*-----------------------------------------------------------------------------
|
||
|
||
Copyright (c) 1995-1997 Microsoft Corporation
|
||
|
||
Module Name :
|
||
waminfo.hxx
|
||
|
||
Abstract:
|
||
Header file for WAMINFO object.
|
||
|
||
Author:
|
||
David Kaplan ( DaveK ) 11-Mar-1997
|
||
|
||
Environment:
|
||
User Mode - Win32
|
||
|
||
Project:
|
||
W3 services DLL
|
||
|
||
-----------------------------------------------------------------------------*/
|
||
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
Forward references
|
||
|
||
-----------------------------------------------------------------------------*/
|
||
|
||
#include <lkrhash.h>
|
||
#include <svmap.h>
|
||
#include <issched.hxx>
|
||
|
||
#ifndef __W3SVC_WAMINFO_HXX__
|
||
#define __W3SVC_WAMINFO_HXX__
|
||
#include "ptable.hxx"
|
||
|
||
interface IWam;
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
External definitions
|
||
|
||
-----------------------------------------------------------------------------*/
|
||
typedef
|
||
LONG (WINAPI * PFN_INTERLOCKED_COMPARE_EXCHANGE)
|
||
(
|
||
LONG *Destination,
|
||
LONG Exchange,
|
||
LONG Comperand
|
||
);
|
||
|
||
extern PFN_INTERLOCKED_COMPARE_EXCHANGE g_pfnInterlockedCompareExchange;
|
||
|
||
HRESULT
|
||
CreateWamRequestInstance
|
||
(
|
||
HTTP_REQUEST * pHttpRequest,
|
||
EXEC_DESCRIPTOR * pExec,
|
||
const STR * pstrPath,
|
||
CWamInfo * pWamInfo,
|
||
WAM_REQUEST** ppWamRequestOut
|
||
);
|
||
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
WAM States Explaination
|
||
|
||
WIS_START This state is set in WamInfo constructor, and changed to WIS_RUNNING
|
||
if Init() succeeded. Therefore, a WamInfo in either hashtable or dyinglist
|
||
can not have this state.
|
||
|
||
WIS_RUNNING This state indicates the WAMINFO in the hashtable is ok to serving requests.
|
||
|
||
WIS_REPAIR This state indicates a thread is currently repair WAMINFO after it detects the outproc
|
||
Wam pointer is nolonger reachable via RPC(a crash). This state is only
|
||
applied to WamInfoOutProc.
|
||
|
||
WIS_PAUSE This state indicates the application is paused by metabase setting, therefore,
|
||
the WamInfo should be deleted such that next request will refresh the metabase
|
||
setting again.
|
||
|
||
WIS_CPUPAUSE This state indicates the application is paused by Job object control. An application
|
||
is in a zombie state that it does not have IWAM pointer(and other stuff) since the
|
||
out-proc mtx process is terminated.
|
||
|
||
WIS_SHUTDOWN This state indicates the WamInfo is in a shutdown stage. Therefore, any new requests
|
||
need to be rejected.
|
||
|
||
WIS_ERROR This state indicates the WamInfo is in some weired error state.(Currently, it is not
|
||
being used).
|
||
|
||
WIS_END This state indicates the WamInfo is in destructor mode.
|
||
|
||
|
||
General rules to change the state:
|
||
|
||
Use ChangeToState(oldstate, newstate), check whether the return value is same as oldstate.
|
||
-----------------------------------------------------------------------------*/
|
||
enum
|
||
{
|
||
WIS_START = 0,
|
||
WIS_RUNNING,
|
||
WIS_REPAIR,
|
||
WIS_PAUSE,
|
||
WIS_CPUPAUSE,
|
||
WIS_ERROR,
|
||
WIS_SHUTDOWN,
|
||
WIS_END,
|
||
WIS_MAX_STATE
|
||
};
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
class CWamInfo:
|
||
|
||
One-to-One relation with Wam object.
|
||
-----------------------------------------------------------------------------*/
|
||
class CWamInfo
|
||
{
|
||
public:
|
||
|
||
CWamInfo
|
||
(
|
||
const STR &strMetabasePath,
|
||
BOOL fInProcess,
|
||
BOOL fInPool,
|
||
BOOL fEnableTryExcept,
|
||
REFGUID clsidWam
|
||
);
|
||
|
||
virtual ~CWamInfo(void);
|
||
|
||
void Reference(void);
|
||
void Dereference(void);
|
||
void RecycleLock(void);
|
||
void RecycleUnlock(void);
|
||
// ------------------------------------------------------------
|
||
// WAM INFO's public functions
|
||
// ------------------------------------------------------------
|
||
|
||
HRESULT CreateWamInstance( DWORD dwContext );
|
||
|
||
|
||
virtual HRESULT Init
|
||
(
|
||
WCHAR* wszPackageId,
|
||
DWORD pidInetInfo
|
||
);
|
||
|
||
virtual HRESULT UnInit(void);
|
||
|
||
virtual void LeaveOOPZone(WAM_REQUEST * pWamRequest, BOOL fRecord);
|
||
|
||
virtual HRESULT GetStatistics
|
||
(
|
||
DWORD Level,
|
||
LPWAM_STATISTICS_INFO pWamStatsInfo
|
||
);
|
||
|
||
virtual void LoopWaitForActiveRequests
|
||
(
|
||
INT cIgnoreRefs
|
||
);
|
||
|
||
virtual HRESULT StartShutdown
|
||
(
|
||
INT cIgnoreRefs
|
||
); // NOTE StartShutdown is non-virtual so derived class can use it
|
||
|
||
virtual VOID NotifyGetInfoForName
|
||
(
|
||
IN LPCSTR pszServerVariable
|
||
);
|
||
|
||
virtual HRESULT DoProcessRequestCall
|
||
(
|
||
IN IWam * pIWam,
|
||
IN WAM_REQUEST * pWamRequest,
|
||
OUT BOOL * pfHandled
|
||
);
|
||
|
||
HRESULT ProcessAsyncIO
|
||
(
|
||
WAM_REQUEST* pWamRequest,
|
||
#ifdef _WIN64
|
||
UINT64 pWamExecInfoIn, // WamExecInfo *
|
||
#else
|
||
ULONG_PTR pWamExecInfoIn, // WamExecInfo *
|
||
#endif
|
||
DWORD dwStatus,
|
||
DWORD cbWritten,
|
||
LPBYTE lpOopReadData = NULL
|
||
);
|
||
|
||
|
||
HRESULT ProcessWamRequest
|
||
(
|
||
HTTP_REQUEST * pHttpRequest,
|
||
EXEC_DESCRIPTOR * pExec,
|
||
const STR * pstrPath,
|
||
BOOL * pfHandled,
|
||
BOOL * pfFinished
|
||
);
|
||
|
||
DWORD ChangeToState(DWORD dwState);
|
||
DWORD ChangeToState(DWORD dwOldState, DWORD dwNewState);
|
||
DWORD QueryState(void) const;
|
||
DWORD QueryCurrentRequests(void) const;
|
||
virtual VOID ClearMembers();
|
||
|
||
IWam* QueryIWam(void) const;
|
||
CProcessEntry* QueryProcessEntry(void) const;
|
||
DWORD PidWam(void) const;
|
||
DWORD FInProcess(void) const;
|
||
HANDLE HWamProcess(void) const;
|
||
const STR & QueryApplicationPath(void) const;
|
||
BOOL FCurrentStateValid(void) const;
|
||
|
||
LPCSTR CWamInfo::QueryKey() const;
|
||
void Print(void) const;
|
||
|
||
void Recycle
|
||
(
|
||
DWORD dwTimeInSec
|
||
);
|
||
|
||
DWORD QueryShutdownTimeLimit(void) const;
|
||
|
||
protected:
|
||
virtual HRESULT PreProcessWamRequest
|
||
(
|
||
IN WAM_REQUEST* pWamRequest,
|
||
IN HTTP_REQUEST* pHttpRequest,
|
||
OUT IWam** ppIWam,
|
||
OUT BOOL* pfHandled
|
||
);
|
||
|
||
virtual HRESULT PostProcessRequest
|
||
(
|
||
IN HRESULT hrIn,
|
||
IN WAM_REQUEST * pWamRequest
|
||
);
|
||
|
||
virtual HRESULT PreProcessAsyncIO
|
||
(
|
||
IN WAM_REQUEST * pWamRequest,
|
||
OUT IWam ** ppIWam
|
||
);
|
||
|
||
public:
|
||
LIST_ENTRY ListEntry; // Double link List node for linking to DyingList.
|
||
LIST_ENTRY leProcess; // Double Link List node for linking to the process entry.
|
||
BOOL m_fRecycled;
|
||
DWORD m_dwRecycleSchedulerCookie;
|
||
|
||
protected:
|
||
DWORD m_dwSignature;
|
||
|
||
IWam* m_pIWam;
|
||
|
||
DWORD m_dwIWamGipCookie; // GIP cookie to get thread-valid pIWams
|
||
CProcessEntry* m_pProcessEntry;
|
||
LONG m_cRef;
|
||
LONG m_cCurrentRequests;
|
||
LONG m_cTotalRequests;
|
||
DWORD m_dwState;
|
||
BOOL m_fInProcess;
|
||
BOOL m_fInPool;
|
||
BOOL m_fEnableTryExcept;
|
||
BOOL m_fShuttingDown;
|
||
STR m_strApplicationPath;
|
||
CLSID m_clsidWam;
|
||
LONG m_cMaxRequests;
|
||
DWORD m_dwShutdownTimeLimit;
|
||
DWORD m_dwRecycleTime;
|
||
|
||
static BOOL m_rgValidState[WIS_MAX_STATE];
|
||
|
||
CRITICAL_SECTION m_csRecycleLock;
|
||
};
|
||
|
||
inline void CWamInfo::Reference(void)
|
||
{
|
||
// DBGPRINTF((DBG_CONTEXT, "CWamInfo %p AddRef, m_cRef %d\n", this, m_cRef+1));
|
||
InterlockedIncrement(&m_cRef);
|
||
}
|
||
|
||
inline void CWamInfo::Dereference(void)
|
||
{
|
||
DBG_ASSERT(m_cRef > 0);
|
||
// DBGPRINTF((DBG_CONTEXT, "CWamInfo %p Release, m_cRef %d\n", this, m_cRef-1));
|
||
if ( 0 == InterlockedDecrement(&m_cRef) )
|
||
{
|
||
delete this;
|
||
}
|
||
}
|
||
|
||
inline DWORD CWamInfo::PidWam() const
|
||
{
|
||
return( m_pProcessEntry->QueryProcessId());
|
||
}
|
||
|
||
inline HANDLE CWamInfo::HWamProcess() const
|
||
{
|
||
return( m_pProcessEntry->QueryProcessHandle() );
|
||
}
|
||
|
||
inline DWORD CWamInfo::FInProcess() const
|
||
{
|
||
return( m_fInProcess );
|
||
}
|
||
|
||
inline BOOL CWamInfo::FCurrentStateValid(void) const
|
||
{
|
||
return (m_rgValidState[m_dwState]);
|
||
}
|
||
|
||
inline DWORD CWamInfo::QueryState(void) const
|
||
{
|
||
return (m_dwState);
|
||
}
|
||
|
||
inline DWORD CWamInfo::QueryCurrentRequests(void) const
|
||
{
|
||
return (m_cCurrentRequests);
|
||
}
|
||
|
||
inline CProcessEntry* CWamInfo::QueryProcessEntry(void) const
|
||
{
|
||
return m_pProcessEntry;
|
||
}
|
||
|
||
inline DWORD CWamInfo::ChangeToState(DWORD eState)
|
||
{
|
||
return (DWORD)InterlockedExchange((LONG *)&m_dwState, eState);
|
||
}
|
||
|
||
inline DWORD CWamInfo::ChangeToState(DWORD eOldState, DWORD eNewState)
|
||
{
|
||
return (DWORD)(*g_pfnInterlockedCompareExchange)((LONG *)&m_dwState, (LONG)eNewState, (LONG)eOldState);
|
||
}
|
||
|
||
inline IWam* CWamInfo::QueryIWam(void) const
|
||
{
|
||
return m_pIWam;
|
||
}
|
||
|
||
inline const STR &
|
||
CWamInfo::QueryApplicationPath(void) const
|
||
{
|
||
// returns the STR object containing the Application Root Path
|
||
return ( m_strApplicationPath);
|
||
}
|
||
|
||
inline void CWamInfo::LeaveOOPZone(WAM_REQUEST * pWamRequest, BOOL fRecord)
|
||
{
|
||
// No Op.
|
||
}
|
||
|
||
inline HRESULT CWamInfo::PostProcessRequest
|
||
(
|
||
IN HRESULT hrIn,
|
||
IN WAM_REQUEST * pWamRequest
|
||
)
|
||
{
|
||
return NOERROR;
|
||
}
|
||
|
||
inline DWORD CWamInfo::QueryShutdownTimeLimit(void) const
|
||
{
|
||
return m_dwShutdownTimeLimit;
|
||
}
|
||
|
||
inline VOID CWamInfo::RecycleLock(void)
|
||
{
|
||
Reference();
|
||
EnterCriticalSection( &m_csRecycleLock );
|
||
}
|
||
|
||
inline VOID CWamInfo::RecycleUnlock(void)
|
||
{
|
||
LeaveCriticalSection( &m_csRecycleLock );
|
||
Dereference();
|
||
}
|
||
|
||
class CWamInfoHash
|
||
: public CTypedHashTable<CWamInfoHash, CWamInfo, const char*>
|
||
{
|
||
public:
|
||
static const char* ExtractKey(const CWamInfo* pWamInfo);
|
||
|
||
static DWORD CalcKeyHash(const char* pszKey);
|
||
|
||
static bool EqualKeys(const char* pszKey1, const char* pszKey2);
|
||
|
||
static void AddRefRecord(CWamInfo* pWamInfo, int nIncr);
|
||
|
||
CWamInfoHash
|
||
(
|
||
double maxload, // Bound on average chain length,
|
||
size_t initsize, // Initial size of Hash Table
|
||
size_t num_subtbls // #subordinate hash tables.
|
||
)
|
||
: CTypedHashTable<CWamInfoHash, CWamInfo, const char*>
|
||
("WamInfo", maxload, initsize, num_subtbls)
|
||
{}
|
||
};
|
||
|
||
inline const char*
|
||
CWamInfoHash::ExtractKey(const CWamInfo* pWamInfo)
|
||
{
|
||
return pWamInfo->QueryKey();
|
||
}
|
||
|
||
inline DWORD
|
||
CWamInfoHash::CalcKeyHash(const char* pszKey)
|
||
{
|
||
return HashStringNoCase(pszKey);
|
||
}
|
||
|
||
inline bool
|
||
CWamInfoHash::EqualKeys(const char* pszKey1, const char* pszKey2)
|
||
{
|
||
return (_stricmp(pszKey1, pszKey2) == 0);
|
||
}
|
||
|
||
inline void
|
||
CWamInfoHash::AddRefRecord(CWamInfo* pWamInfo, int nIncr)
|
||
{
|
||
if (nIncr == 1)
|
||
{
|
||
pWamInfo->Reference();
|
||
}
|
||
else
|
||
{
|
||
pWamInfo->Dereference();
|
||
}
|
||
}
|
||
|
||
//======================== CWamInfoOutProc ====================================
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
// COOPWamReqList
|
||
//
|
||
// class that contains link list head for OOP Wam Requests of a WAM instance.
|
||
//
|
||
-----------------------------------------------------------------------------*/
|
||
class COOPWamReqList
|
||
{
|
||
public:
|
||
COOPWamReqList(void);
|
||
~COOPWamReqList(void);
|
||
|
||
BOOL FTimeToCleanup(DWORD dwCurrentTime);
|
||
BOOL FActive(void);
|
||
void SetTimeStamp(void);
|
||
|
||
LIST_ENTRY m_leRecoverListLink; // Link with other COOPWamReqList.
|
||
LIST_ENTRY m_leOOPWamReqListHead; // Cleanup List Head
|
||
private:
|
||
DWORD m_dwTimeStamp; // TimeStamp for Cleanup Scheduler
|
||
// (GetTickerCount)
|
||
BOOL m_fActive; // FALSE if the corresponding Wam
|
||
// crashed.
|
||
};
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
// COOPWamReqList::SetTimeStamp
|
||
//
|
||
// Set time stamp when Out Proc Wam crashes.
|
||
-----------------------------------------------------------------------------*/
|
||
inline void
|
||
COOPWamReqList::SetTimeStamp(void)
|
||
{
|
||
m_dwTimeStamp = GetTickCount();
|
||
m_fActive = FALSE;
|
||
}
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
//COOPWamReqList::FActive
|
||
//
|
||
//Return whether the list is Active or not(m_fActive).
|
||
-----------------------------------------------------------------------------*/
|
||
inline BOOL
|
||
COOPWamReqList::FActive(void)
|
||
{
|
||
return m_fActive;
|
||
}
|
||
|
||
class CWamInfoOutProc : public CWamInfo
|
||
{
|
||
public:
|
||
PLIST_ENTRY m_pCurrentListHead; // pointer to an OOPWamReq ListHead
|
||
// with current valid OOP WAM.
|
||
private:
|
||
DWORD m_fInRepair; // flag indicates WamInfo in crash-recovery mode or not.
|
||
DWORD m_fNoMoreRecovery; // flag indicates WamInfo failed to ReInitWam() or not.
|
||
|
||
HANDLE m_hPermitOOPEvent; // Event that serve as a gate to OutofProc processing
|
||
// Signaled when normal processing
|
||
// Reset during the crash-recovery
|
||
CRITICAL_SECTION m_csList; // Critical section for RecoverList.
|
||
|
||
LIST_ENTRY m_rgRecoverListHead;// pointer to an Array of cleanup list
|
||
DWORD m_dwThreshold; // Threshold for number of active cleanup list.
|
||
DWORD m_dwWamVersion; // Current valid WAM verion number.
|
||
DWORD m_cRecoverList; // # of active cleanup list in the system(started with 1)
|
||
DWORD m_idScheduled; // Scheduler ID for Schedule a work item.
|
||
BOOL m_fJobEnabled;
|
||
PW3_SERVER_INSTANCE m_pwsiInstance;
|
||
|
||
SV_CACHE_LIST m_svCache;
|
||
|
||
public:
|
||
CWamInfoOutProc
|
||
(
|
||
const STR & strMetabasePath,
|
||
BOOL fInProcess,
|
||
BOOL fInPool,
|
||
BOOL fEnableTryExcept,
|
||
REFGUID clsidWam,
|
||
DWORD dwThreshold,
|
||
PW3_SERVER_INSTANCE pwiInstance,
|
||
BOOL fJobEnabled,
|
||
DWORD dwPeriodicRestartRequests,
|
||
DWORD dwPeriodicRestartTime,
|
||
DWORD dwShutdownTimeLimit
|
||
);
|
||
|
||
virtual ~CWamInfoOutProc();
|
||
|
||
HRESULT GetStatistics
|
||
(
|
||
DWORD Level,
|
||
LPWAM_STATISTICS_INFO pWamStatsInfo
|
||
);
|
||
|
||
static void WINAPI CleanupScheduled(void *pContext);
|
||
|
||
|
||
VOID ClearMembers();
|
||
|
||
private:
|
||
HRESULT PreProcessWamRequest
|
||
(
|
||
IN WAM_REQUEST* pWamRequest,
|
||
IN HTTP_REQUEST* pHttpRequest,
|
||
OUT IWam** ppIWam,
|
||
OUT BOOL* pfHandled
|
||
);
|
||
|
||
HRESULT PostProcessRequest
|
||
(
|
||
IN HRESULT hrIn,
|
||
IN WAM_REQUEST * pWamRequest
|
||
);
|
||
|
||
HRESULT PreProcessAsyncIO
|
||
(
|
||
IN WAM_REQUEST * pWamRequest,
|
||
OUT IWam ** ppIWam
|
||
);
|
||
|
||
HRESULT Init
|
||
(
|
||
IN WCHAR* wszPackageId,
|
||
IN DWORD pidInetInfo
|
||
);
|
||
|
||
HRESULT UnInit(void);
|
||
|
||
VOID NotifyGetInfoForName
|
||
(
|
||
IN LPCSTR pszServerVariable
|
||
);
|
||
|
||
HRESULT DoProcessRequestCall
|
||
(
|
||
IN IWam * pIWam,
|
||
IN WAM_REQUEST * pWamRequest,
|
||
OUT BOOL * pfHandled
|
||
);
|
||
|
||
IWam * EnterOOPZone(WAM_REQUEST * pWamRequest, DWORD *pdwWamVersion, BOOL fRecord);
|
||
void LeaveOOPZone(WAM_REQUEST * pWamRequest, BOOL fRecord);
|
||
|
||
void LoopWaitForActiveRequests(INT cIgnoreRefs);
|
||
|
||
BOOL FExceedCrashLimit(void);
|
||
HRESULT Repair(void);
|
||
HRESULT ReInitWam(void);
|
||
BOOL FinalCleanup(void);
|
||
BOOL CleanupAll(BOOL fScheduled);
|
||
BOOL Cleanup(COOPWamReqList *pCleanupList);
|
||
|
||
void LockList(void);
|
||
void UnLockList(void);
|
||
|
||
public:
|
||
DWORD GetWamVersion(void);
|
||
BOOL IsJobEnabled() {return m_fJobEnabled;};
|
||
};
|
||
|
||
inline BOOL
|
||
CWamInfoOutProc::FExceedCrashLimit(void)
|
||
{
|
||
return (m_dwWamVersion >= m_dwThreshold || m_fNoMoreRecovery);
|
||
}
|
||
|
||
inline DWORD
|
||
CWamInfoOutProc::GetWamVersion(void)
|
||
{
|
||
return ( m_dwWamVersion );
|
||
}
|
||
|
||
inline void
|
||
CWamInfoOutProc::LockList(void)
|
||
{
|
||
EnterCriticalSection(&m_csList);
|
||
}
|
||
|
||
inline void
|
||
CWamInfoOutProc::UnLockList(void)
|
||
{
|
||
LeaveCriticalSection(&m_csList);
|
||
}
|
||
|
||
#endif __W3SVC_WAMINFO_HXX__
|
||
|