Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

626 lines
18 KiB

  1. /*-----------------------------------------------------------------------------
  2. Copyright (c) 1995-1997 Microsoft Corporation
  3. Module Name :
  4. waminfo.hxx
  5. Abstract:
  6. Header file for WAMINFO object.
  7. Author:
  8. David Kaplan ( DaveK ) 11-Mar-1997
  9. Environment:
  10. User Mode - Win32
  11. Project:
  12. W3 services DLL
  13. -----------------------------------------------------------------------------*/
  14. /*-----------------------------------------------------------------------------
  15. Forward references
  16. -----------------------------------------------------------------------------*/
  17. #include <lkrhash.h>
  18. #include <svmap.h>
  19. #include <issched.hxx>
  20. #ifndef __W3SVC_WAMINFO_HXX__
  21. #define __W3SVC_WAMINFO_HXX__
  22. #include "ptable.hxx"
  23. interface IWam;
  24. /*-----------------------------------------------------------------------------
  25. External definitions
  26. -----------------------------------------------------------------------------*/
  27. typedef
  28. LONG (WINAPI * PFN_INTERLOCKED_COMPARE_EXCHANGE)
  29. (
  30. LONG *Destination,
  31. LONG Exchange,
  32. LONG Comperand
  33. );
  34. extern PFN_INTERLOCKED_COMPARE_EXCHANGE g_pfnInterlockedCompareExchange;
  35. HRESULT
  36. CreateWamRequestInstance
  37. (
  38. HTTP_REQUEST * pHttpRequest,
  39. EXEC_DESCRIPTOR * pExec,
  40. const STR * pstrPath,
  41. CWamInfo * pWamInfo,
  42. WAM_REQUEST** ppWamRequestOut
  43. );
  44. /*-----------------------------------------------------------------------------
  45. WAM States Explaination
  46. WIS_START This state is set in WamInfo constructor, and changed to WIS_RUNNING
  47. if Init() succeeded. Therefore, a WamInfo in either hashtable or dyinglist
  48. can not have this state.
  49. WIS_RUNNING This state indicates the WAMINFO in the hashtable is ok to serving requests.
  50. WIS_REPAIR This state indicates a thread is currently repair WAMINFO after it detects the outproc
  51. Wam pointer is nolonger reachable via RPC(a crash). This state is only
  52. applied to WamInfoOutProc.
  53. WIS_PAUSE This state indicates the application is paused by metabase setting, therefore,
  54. the WamInfo should be deleted such that next request will refresh the metabase
  55. setting again.
  56. WIS_CPUPAUSE This state indicates the application is paused by Job object control. An application
  57. is in a zombie state that it does not have IWAM pointer(and other stuff) since the
  58. out-proc mtx process is terminated.
  59. WIS_SHUTDOWN This state indicates the WamInfo is in a shutdown stage. Therefore, any new requests
  60. need to be rejected.
  61. WIS_ERROR This state indicates the WamInfo is in some weired error state.(Currently, it is not
  62. being used).
  63. WIS_END This state indicates the WamInfo is in destructor mode.
  64. General rules to change the state:
  65. Use ChangeToState(oldstate, newstate), check whether the return value is same as oldstate.
  66. -----------------------------------------------------------------------------*/
  67. enum
  68. {
  69. WIS_START = 0,
  70. WIS_RUNNING,
  71. WIS_REPAIR,
  72. WIS_PAUSE,
  73. WIS_CPUPAUSE,
  74. WIS_ERROR,
  75. WIS_SHUTDOWN,
  76. WIS_END,
  77. WIS_MAX_STATE
  78. };
  79. /*-----------------------------------------------------------------------------
  80. class CWamInfo:
  81. One-to-One relation with Wam object.
  82. -----------------------------------------------------------------------------*/
  83. class CWamInfo
  84. {
  85. public:
  86. CWamInfo
  87. (
  88. const STR &strMetabasePath,
  89. BOOL fInProcess,
  90. BOOL fInPool,
  91. BOOL fEnableTryExcept,
  92. REFGUID clsidWam
  93. );
  94. virtual ~CWamInfo(void);
  95. void Reference(void);
  96. void Dereference(void);
  97. void RecycleLock(void);
  98. void RecycleUnlock(void);
  99. // ------------------------------------------------------------
  100. // WAM INFO's public functions
  101. // ------------------------------------------------------------
  102. HRESULT CreateWamInstance( DWORD dwContext );
  103. virtual HRESULT Init
  104. (
  105. WCHAR* wszPackageId,
  106. DWORD pidInetInfo
  107. );
  108. virtual HRESULT UnInit(void);
  109. virtual void LeaveOOPZone(WAM_REQUEST * pWamRequest, BOOL fRecord);
  110. virtual HRESULT GetStatistics
  111. (
  112. DWORD Level,
  113. LPWAM_STATISTICS_INFO pWamStatsInfo
  114. );
  115. virtual void LoopWaitForActiveRequests
  116. (
  117. INT cIgnoreRefs
  118. );
  119. virtual HRESULT StartShutdown
  120. (
  121. INT cIgnoreRefs
  122. ); // NOTE StartShutdown is non-virtual so derived class can use it
  123. virtual VOID NotifyGetInfoForName
  124. (
  125. IN LPCSTR pszServerVariable
  126. );
  127. virtual HRESULT DoProcessRequestCall
  128. (
  129. IN IWam * pIWam,
  130. IN WAM_REQUEST * pWamRequest,
  131. OUT BOOL * pfHandled
  132. );
  133. HRESULT ProcessAsyncIO
  134. (
  135. WAM_REQUEST* pWamRequest,
  136. #ifdef _WIN64
  137. UINT64 pWamExecInfoIn, // WamExecInfo *
  138. #else
  139. ULONG_PTR pWamExecInfoIn, // WamExecInfo *
  140. #endif
  141. DWORD dwStatus,
  142. DWORD cbWritten,
  143. LPBYTE lpOopReadData = NULL
  144. );
  145. HRESULT ProcessWamRequest
  146. (
  147. HTTP_REQUEST * pHttpRequest,
  148. EXEC_DESCRIPTOR * pExec,
  149. const STR * pstrPath,
  150. BOOL * pfHandled,
  151. BOOL * pfFinished
  152. );
  153. DWORD ChangeToState(DWORD dwState);
  154. DWORD ChangeToState(DWORD dwOldState, DWORD dwNewState);
  155. DWORD QueryState(void) const;
  156. DWORD QueryCurrentRequests(void) const;
  157. virtual VOID ClearMembers();
  158. IWam* QueryIWam(void) const;
  159. CProcessEntry* QueryProcessEntry(void) const;
  160. DWORD PidWam(void) const;
  161. DWORD FInProcess(void) const;
  162. HANDLE HWamProcess(void) const;
  163. const STR & QueryApplicationPath(void) const;
  164. BOOL FCurrentStateValid(void) const;
  165. LPCSTR CWamInfo::QueryKey() const;
  166. void Print(void) const;
  167. void Recycle
  168. (
  169. DWORD dwTimeInSec
  170. );
  171. DWORD QueryShutdownTimeLimit(void) const;
  172. protected:
  173. virtual HRESULT PreProcessWamRequest
  174. (
  175. IN WAM_REQUEST* pWamRequest,
  176. IN HTTP_REQUEST* pHttpRequest,
  177. OUT IWam** ppIWam,
  178. OUT BOOL* pfHandled
  179. );
  180. virtual HRESULT PostProcessRequest
  181. (
  182. IN HRESULT hrIn,
  183. IN WAM_REQUEST * pWamRequest
  184. );
  185. virtual HRESULT PreProcessAsyncIO
  186. (
  187. IN WAM_REQUEST * pWamRequest,
  188. OUT IWam ** ppIWam
  189. );
  190. public:
  191. LIST_ENTRY ListEntry; // Double link List node for linking to DyingList.
  192. LIST_ENTRY leProcess; // Double Link List node for linking to the process entry.
  193. BOOL m_fRecycled;
  194. DWORD m_dwRecycleSchedulerCookie;
  195. protected:
  196. DWORD m_dwSignature;
  197. IWam* m_pIWam;
  198. DWORD m_dwIWamGipCookie; // GIP cookie to get thread-valid pIWams
  199. CProcessEntry* m_pProcessEntry;
  200. LONG m_cRef;
  201. LONG m_cCurrentRequests;
  202. LONG m_cTotalRequests;
  203. DWORD m_dwState;
  204. BOOL m_fInProcess;
  205. BOOL m_fInPool;
  206. BOOL m_fEnableTryExcept;
  207. BOOL m_fShuttingDown;
  208. STR m_strApplicationPath;
  209. CLSID m_clsidWam;
  210. LONG m_cMaxRequests;
  211. DWORD m_dwShutdownTimeLimit;
  212. DWORD m_dwRecycleTime;
  213. static BOOL m_rgValidState[WIS_MAX_STATE];
  214. CRITICAL_SECTION m_csRecycleLock;
  215. };
  216. inline void CWamInfo::Reference(void)
  217. {
  218. // DBGPRINTF((DBG_CONTEXT, "CWamInfo %p AddRef, m_cRef %d\n", this, m_cRef+1));
  219. InterlockedIncrement(&m_cRef);
  220. }
  221. inline void CWamInfo::Dereference(void)
  222. {
  223. DBG_ASSERT(m_cRef > 0);
  224. // DBGPRINTF((DBG_CONTEXT, "CWamInfo %p Release, m_cRef %d\n", this, m_cRef-1));
  225. if ( 0 == InterlockedDecrement(&m_cRef) )
  226. {
  227. delete this;
  228. }
  229. }
  230. inline DWORD CWamInfo::PidWam() const
  231. {
  232. return( m_pProcessEntry->QueryProcessId());
  233. }
  234. inline HANDLE CWamInfo::HWamProcess() const
  235. {
  236. return( m_pProcessEntry->QueryProcessHandle() );
  237. }
  238. inline DWORD CWamInfo::FInProcess() const
  239. {
  240. return( m_fInProcess );
  241. }
  242. inline BOOL CWamInfo::FCurrentStateValid(void) const
  243. {
  244. return (m_rgValidState[m_dwState]);
  245. }
  246. inline DWORD CWamInfo::QueryState(void) const
  247. {
  248. return (m_dwState);
  249. }
  250. inline DWORD CWamInfo::QueryCurrentRequests(void) const
  251. {
  252. return (m_cCurrentRequests);
  253. }
  254. inline CProcessEntry* CWamInfo::QueryProcessEntry(void) const
  255. {
  256. return m_pProcessEntry;
  257. }
  258. inline DWORD CWamInfo::ChangeToState(DWORD eState)
  259. {
  260. return (DWORD)InterlockedExchange((LONG *)&m_dwState, eState);
  261. }
  262. inline DWORD CWamInfo::ChangeToState(DWORD eOldState, DWORD eNewState)
  263. {
  264. return (DWORD)(*g_pfnInterlockedCompareExchange)((LONG *)&m_dwState, (LONG)eNewState, (LONG)eOldState);
  265. }
  266. inline IWam* CWamInfo::QueryIWam(void) const
  267. {
  268. return m_pIWam;
  269. }
  270. inline const STR &
  271. CWamInfo::QueryApplicationPath(void) const
  272. {
  273. // returns the STR object containing the Application Root Path
  274. return ( m_strApplicationPath);
  275. }
  276. inline void CWamInfo::LeaveOOPZone(WAM_REQUEST * pWamRequest, BOOL fRecord)
  277. {
  278. // No Op.
  279. }
  280. inline HRESULT CWamInfo::PostProcessRequest
  281. (
  282. IN HRESULT hrIn,
  283. IN WAM_REQUEST * pWamRequest
  284. )
  285. {
  286. return NOERROR;
  287. }
  288. inline DWORD CWamInfo::QueryShutdownTimeLimit(void) const
  289. {
  290. return m_dwShutdownTimeLimit;
  291. }
  292. inline VOID CWamInfo::RecycleLock(void)
  293. {
  294. Reference();
  295. EnterCriticalSection( &m_csRecycleLock );
  296. }
  297. inline VOID CWamInfo::RecycleUnlock(void)
  298. {
  299. LeaveCriticalSection( &m_csRecycleLock );
  300. Dereference();
  301. }
  302. class CWamInfoHash
  303. : public CTypedHashTable<CWamInfoHash, CWamInfo, const char*>
  304. {
  305. public:
  306. static const char* ExtractKey(const CWamInfo* pWamInfo);
  307. static DWORD CalcKeyHash(const char* pszKey);
  308. static bool EqualKeys(const char* pszKey1, const char* pszKey2);
  309. static void AddRefRecord(CWamInfo* pWamInfo, int nIncr);
  310. CWamInfoHash
  311. (
  312. double maxload, // Bound on average chain length,
  313. size_t initsize, // Initial size of Hash Table
  314. size_t num_subtbls // #subordinate hash tables.
  315. )
  316. : CTypedHashTable<CWamInfoHash, CWamInfo, const char*>
  317. ("WamInfo", maxload, initsize, num_subtbls)
  318. {}
  319. };
  320. inline const char*
  321. CWamInfoHash::ExtractKey(const CWamInfo* pWamInfo)
  322. {
  323. return pWamInfo->QueryKey();
  324. }
  325. inline DWORD
  326. CWamInfoHash::CalcKeyHash(const char* pszKey)
  327. {
  328. return HashStringNoCase(pszKey);
  329. }
  330. inline bool
  331. CWamInfoHash::EqualKeys(const char* pszKey1, const char* pszKey2)
  332. {
  333. return (_stricmp(pszKey1, pszKey2) == 0);
  334. }
  335. inline void
  336. CWamInfoHash::AddRefRecord(CWamInfo* pWamInfo, int nIncr)
  337. {
  338. if (nIncr == 1)
  339. {
  340. pWamInfo->Reference();
  341. }
  342. else
  343. {
  344. pWamInfo->Dereference();
  345. }
  346. }
  347. //======================== CWamInfoOutProc ====================================
  348. /*-----------------------------------------------------------------------------
  349. // COOPWamReqList
  350. //
  351. // class that contains link list head for OOP Wam Requests of a WAM instance.
  352. //
  353. -----------------------------------------------------------------------------*/
  354. class COOPWamReqList
  355. {
  356. public:
  357. COOPWamReqList(void);
  358. ~COOPWamReqList(void);
  359. BOOL FTimeToCleanup(DWORD dwCurrentTime);
  360. BOOL FActive(void);
  361. void SetTimeStamp(void);
  362. LIST_ENTRY m_leRecoverListLink; // Link with other COOPWamReqList.
  363. LIST_ENTRY m_leOOPWamReqListHead; // Cleanup List Head
  364. private:
  365. DWORD m_dwTimeStamp; // TimeStamp for Cleanup Scheduler
  366. // (GetTickerCount)
  367. BOOL m_fActive; // FALSE if the corresponding Wam
  368. // crashed.
  369. };
  370. /*-----------------------------------------------------------------------------
  371. // COOPWamReqList::SetTimeStamp
  372. //
  373. // Set time stamp when Out Proc Wam crashes.
  374. -----------------------------------------------------------------------------*/
  375. inline void
  376. COOPWamReqList::SetTimeStamp(void)
  377. {
  378. m_dwTimeStamp = GetTickCount();
  379. m_fActive = FALSE;
  380. }
  381. /*-----------------------------------------------------------------------------
  382. //COOPWamReqList::FActive
  383. //
  384. //Return whether the list is Active or not(m_fActive).
  385. -----------------------------------------------------------------------------*/
  386. inline BOOL
  387. COOPWamReqList::FActive(void)
  388. {
  389. return m_fActive;
  390. }
  391. class CWamInfoOutProc : public CWamInfo
  392. {
  393. public:
  394. PLIST_ENTRY m_pCurrentListHead; // pointer to an OOPWamReq ListHead
  395. // with current valid OOP WAM.
  396. private:
  397. DWORD m_fInRepair; // flag indicates WamInfo in crash-recovery mode or not.
  398. DWORD m_fNoMoreRecovery; // flag indicates WamInfo failed to ReInitWam() or not.
  399. HANDLE m_hPermitOOPEvent; // Event that serve as a gate to OutofProc processing
  400. // Signaled when normal processing
  401. // Reset during the crash-recovery
  402. CRITICAL_SECTION m_csList; // Critical section for RecoverList.
  403. LIST_ENTRY m_rgRecoverListHead;// pointer to an Array of cleanup list
  404. DWORD m_dwThreshold; // Threshold for number of active cleanup list.
  405. DWORD m_dwWamVersion; // Current valid WAM verion number.
  406. DWORD m_cRecoverList; // # of active cleanup list in the system(started with 1)
  407. DWORD m_idScheduled; // Scheduler ID for Schedule a work item.
  408. BOOL m_fJobEnabled;
  409. PW3_SERVER_INSTANCE m_pwsiInstance;
  410. SV_CACHE_LIST m_svCache;
  411. public:
  412. CWamInfoOutProc
  413. (
  414. const STR & strMetabasePath,
  415. BOOL fInProcess,
  416. BOOL fInPool,
  417. BOOL fEnableTryExcept,
  418. REFGUID clsidWam,
  419. DWORD dwThreshold,
  420. PW3_SERVER_INSTANCE pwiInstance,
  421. BOOL fJobEnabled,
  422. DWORD dwPeriodicRestartRequests,
  423. DWORD dwPeriodicRestartTime,
  424. DWORD dwShutdownTimeLimit
  425. );
  426. virtual ~CWamInfoOutProc();
  427. HRESULT GetStatistics
  428. (
  429. DWORD Level,
  430. LPWAM_STATISTICS_INFO pWamStatsInfo
  431. );
  432. static void WINAPI CleanupScheduled(void *pContext);
  433. VOID ClearMembers();
  434. private:
  435. HRESULT PreProcessWamRequest
  436. (
  437. IN WAM_REQUEST* pWamRequest,
  438. IN HTTP_REQUEST* pHttpRequest,
  439. OUT IWam** ppIWam,
  440. OUT BOOL* pfHandled
  441. );
  442. HRESULT PostProcessRequest
  443. (
  444. IN HRESULT hrIn,
  445. IN WAM_REQUEST * pWamRequest
  446. );
  447. HRESULT PreProcessAsyncIO
  448. (
  449. IN WAM_REQUEST * pWamRequest,
  450. OUT IWam ** ppIWam
  451. );
  452. HRESULT Init
  453. (
  454. IN WCHAR* wszPackageId,
  455. IN DWORD pidInetInfo
  456. );
  457. HRESULT UnInit(void);
  458. VOID NotifyGetInfoForName
  459. (
  460. IN LPCSTR pszServerVariable
  461. );
  462. HRESULT DoProcessRequestCall
  463. (
  464. IN IWam * pIWam,
  465. IN WAM_REQUEST * pWamRequest,
  466. OUT BOOL * pfHandled
  467. );
  468. IWam * EnterOOPZone(WAM_REQUEST * pWamRequest, DWORD *pdwWamVersion, BOOL fRecord);
  469. void LeaveOOPZone(WAM_REQUEST * pWamRequest, BOOL fRecord);
  470. void LoopWaitForActiveRequests(INT cIgnoreRefs);
  471. BOOL FExceedCrashLimit(void);
  472. HRESULT Repair(void);
  473. HRESULT ReInitWam(void);
  474. BOOL FinalCleanup(void);
  475. BOOL CleanupAll(BOOL fScheduled);
  476. BOOL Cleanup(COOPWamReqList *pCleanupList);
  477. void LockList(void);
  478. void UnLockList(void);
  479. public:
  480. DWORD GetWamVersion(void);
  481. BOOL IsJobEnabled() {return m_fJobEnabled;};
  482. };
  483. inline BOOL
  484. CWamInfoOutProc::FExceedCrashLimit(void)
  485. {
  486. return (m_dwWamVersion >= m_dwThreshold || m_fNoMoreRecovery);
  487. }
  488. inline DWORD
  489. CWamInfoOutProc::GetWamVersion(void)
  490. {
  491. return ( m_dwWamVersion );
  492. }
  493. inline void
  494. CWamInfoOutProc::LockList(void)
  495. {
  496. EnterCriticalSection(&m_csList);
  497. }
  498. inline void
  499. CWamInfoOutProc::UnLockList(void)
  500. {
  501. LeaveCriticalSection(&m_csList);
  502. }
  503. #endif __W3SVC_WAMINFO_HXX__