Leaked source code of windows server 2003
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.

613 lines
17 KiB

  1. //
  2. // asyncctx.h -- This file contains the class definitions for:
  3. // CSearchRequestBlock
  4. // CBatchLdapConnection
  5. // CBatchLdapConnectionCache
  6. // CStoreListResolveContext
  7. // CSingleSearchReinsertionRequest
  8. //
  9. // Created:
  10. // Feb 19, 1997 -- Milan Shah (milans)
  11. //
  12. // Changes:
  13. // jstamerj 1999/03/16 15:29:20: Heavily modified to batch requests
  14. // togethor across multiple message
  15. // categorizations
  16. // jstamerj 1999/03/22 12:44:01: Modified to support throttling via a
  17. // queue of CInsertionRequest objects
  18. //
  19. // dlongley 2001/10/22: Added CSingleSearchReinsertionRequest to force
  20. // abandoned and reissued searches to be throttled
  21. // via the CInsertionRequest object queue
  22. //
  23. #ifndef _ASYNCCTX_H_
  24. #define _ASYNCCTX_H_
  25. #include "ldapconn.h"
  26. #include "ccataddr.h"
  27. #include "simparray.h"
  28. #include "icatqueries.h"
  29. #include "icatasync.h"
  30. class CBatchLdapConnectionCache;
  31. class CCfgConnection;
  32. template <class T> class CEmailIDLdapStore;
  33. //
  34. // The MCIS3 LDAP server beta 1 does not correctly handle queries with more
  35. // than 4 legs in an OR clause. Because of this, we need to limit our search
  36. // query compression on a configurable basis. The global value,
  37. // nMaxSearchBlockSize constrains how many searches will be compressed into
  38. // a single search. The value is read from the registry key
  39. // szMaxSearchBlockSize. If it is not present, it defaults to
  40. // MAX_SEARCH_BLOCK_SIZE.
  41. //
  42. #define MAX_SEARCH_BLOCK_SIZE_KEY "System\\CurrentControlSet\\Services\\SMTPSVC\\Parameters"
  43. #define MAX_SEARCH_BLOCK_SIZE_VALUE "MaxSearchBlockSize"
  44. #define MAX_SEARCH_BLOCK_SIZE 20
  45. #define MAX_PENDING_SEARCHES_VALUE "MaxPendingSearches"
  46. #define MAX_PENDING_SEARCHES 60
  47. #define MAX_CONNECTION_RETRIES_VALUE "MaxConnectionRetries"
  48. #define MAX_CONNECTION_RETRIES 20
  49. class CBatchLdapConnectionCache;
  50. class CBatchLdapConnection;
  51. class CStoreListResolveContext;
  52. typedef VOID (*LPFNLIST_COMPLETION)(VOID *lpContext);
  53. typedef VOID (*LPSEARCHCOMPLETION)(
  54. CCatAddr *pCCatAddr,
  55. CStoreListResolveContext *pslrc,
  56. CBatchLdapConnection *pConn);
  57. //------------------------------------------------------------
  58. //
  59. // Class CSearchRequestBlock
  60. //
  61. //------------------------------------------------------------
  62. CatDebugClass(CSearchRequestBlock)
  63. {
  64. private:
  65. typedef struct _SearchRequest {
  66. CCatAddr *pCCatAddr;
  67. LPSEARCHCOMPLETION fnSearchCompletion;
  68. CStoreListResolveContext *pslrc;
  69. LPSTR pszSearchFilter;
  70. LPSTR pszDistinguishingAttribute;
  71. LPSTR pszDistinguishingAttributeValue;
  72. } SEARCH_REQUEST, *PSEARCH_REQUEST;
  73. #define SIGNATURE_CSEARCHREQUESTBLOCK (DWORD)'lBRS'
  74. #define SIGNATURE_CSEARCHREQUESTBLOCK_INVALID (DWORD)'lBRX'
  75. public:
  76. void * operator new(size_t size, DWORD dwNumRequests);
  77. CSearchRequestBlock(
  78. CBatchLdapConnection *pConn);
  79. ~CSearchRequestBlock();
  80. VOID InsertSearchRequest(
  81. ISMTPServer *pISMTPServer,
  82. ICategorizerParameters *pICatParams,
  83. CCatAddr *pCCatAddr,
  84. LPSEARCHCOMPLETION fnSearchCompletion,
  85. CStoreListResolveContext *pslrc,
  86. LPSTR pszSearchFilter,
  87. LPSTR pszDistinguishingAttribute,
  88. LPSTR pszDistinguishingAttributeValue);
  89. VOID DispatchBlock();
  90. HRESULT ReserveSlot()
  91. {
  92. if( ((DWORD)InterlockedIncrement((PLONG)&m_cBlockRequestsReserved)) > m_cBlockSize)
  93. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  94. else
  95. return S_OK;
  96. }
  97. HRESULT AddResults(
  98. DWORD dwNumResults,
  99. ICategorizerItemAttributes **rgpItemAttributes)
  100. {
  101. HRESULT hr;
  102. hr = m_csaItemAttr.AddArray(
  103. dwNumResults,
  104. rgpItemAttributes);
  105. if(SUCCEEDED(hr)) {
  106. //
  107. // AddRef all the interfaces we hold
  108. //
  109. for(DWORD dwCount = 0; dwCount < dwNumResults; dwCount++) {
  110. rgpItemAttributes[dwCount]->AddRef();
  111. }
  112. }
  113. return hr;
  114. }
  115. private:
  116. PSEARCH_REQUEST GetNextSearchRequest(DWORD *pdwIndex)
  117. {
  118. *pdwIndex = InterlockedIncrement((PLONG)&m_cBlockRequestsAllocated) - 1;
  119. _ASSERT(*pdwIndex < m_cBlockSize);
  120. return &(m_prgSearchRequests[*pdwIndex]);
  121. }
  122. VOID CompleteBlockWithError(HRESULT hr)
  123. {
  124. PutBlockHRESULT(hr);
  125. CallCompletions();
  126. }
  127. static VOID LDAPCompletion(
  128. LPVOID ctx,
  129. DWORD dwNumResults,
  130. ICategorizerItemAttributes **rgpICatItemAttributes,
  131. HRESULT hrStatus,
  132. BOOL fFinalCompletion);
  133. HRESULT HrTriggerBuildQueries();
  134. HRESULT HrTriggerSendQuery();
  135. static HRESULT HrBuildQueriesDefault(
  136. HRESULT HrStatus,
  137. PVOID pContext);
  138. static HRESULT HrSendQueryDefault(
  139. HRESULT HrStatus,
  140. PVOID pContext);
  141. static HRESULT HrSendQueryCompletion(
  142. HRESULT HrStatus,
  143. PVOID pContext);
  144. VOID CompleteSearchBlock(
  145. HRESULT hrStatus);
  146. HRESULT HrTriggerSortQueryResult(
  147. HRESULT hrStatus);
  148. static HRESULT HrSortQueryResultDefault(
  149. HRESULT hrStatus,
  150. PVOID pContext);
  151. VOID PutBlockHRESULT(
  152. HRESULT hr);
  153. VOID CallCompletions();
  154. VOID MatchItem(
  155. ICategorizerItem *pICatItem,
  156. ICategorizerItemAttributes *pICatItemAttr);
  157. DWORD DwNumBlockRequests()
  158. {
  159. return m_cBlockRequestsReadyForDispatch;
  160. }
  161. ISMTPServerEx * GetISMTPServerEx()
  162. {
  163. return m_pISMTPServerEx;
  164. }
  165. VOID LogAmbiguousEvent(ICategorizerItem *pItem);
  166. DWORD m_dwSignature;
  167. ISMTPServer *m_pISMTPServer;
  168. ISMTPServerEx *m_pISMTPServerEx;
  169. ICategorizerParameters *m_pICatParams;
  170. DWORD m_cBlockRequestsReserved;
  171. DWORD m_cBlockRequestsAllocated;
  172. DWORD m_cBlockRequestsReadyForDispatch;
  173. DWORD m_cBlockSize;
  174. LIST_ENTRY m_listentry;
  175. PSEARCH_REQUEST m_prgSearchRequests;
  176. ICategorizerItem **m_rgpICatItems;
  177. CBatchLdapConnection *m_pConn;
  178. LPSTR m_pszSearchFilter;
  179. CICategorizerQueriesIMP m_CICatQueries;
  180. CICategorizerAsyncContextIMP m_CICatAsyncContext;
  181. CSimpArray<ICategorizerItemAttributes *> m_csaItemAttr;
  182. friend class CBatchLdapConnection;
  183. friend class CICategorizerAsyncContextIMP;
  184. };
  185. //------------------------------------------------------------
  186. //
  187. // Class CBatchLdapConnection
  188. //
  189. //------------------------------------------------------------
  190. class CBatchLdapConnection :
  191. public CLdapConnectionCache::CCachedLdapConnection
  192. {
  193. private:
  194. #define SIGNATURE_CBATCHLDAPCONN (DWORD)'oCLB'
  195. #define SIGNATURE_CBATCHLDAPCONN_INVALID (DWORD)'oCLX'
  196. public:
  197. CBatchLdapConnection(
  198. LPSTR szHost,
  199. DWORD dwPort,
  200. LPSTR szNamingContext,
  201. LPSTR szAccount,
  202. LPSTR szPassword,
  203. LDAP_BIND_TYPE bt,
  204. CLdapConnectionCache *pCache) :
  205. CCachedLdapConnection(
  206. szHost,
  207. dwPort,
  208. szNamingContext,
  209. szAccount,
  210. szPassword,
  211. bt,
  212. pCache)
  213. {
  214. m_dwSignature = SIGNATURE_CBATCHLDAPCONN;
  215. m_pInsertionBlock = NULL;
  216. InitializeListHead(&m_listhead);
  217. InitializeSpinLock(&m_spinlock);
  218. m_cInsertionContext = 0;
  219. if(m_nMaxSearchBlockSize == 0)
  220. InitializeFromRegistry();
  221. InitializeSpinLock(&m_spinlock_insertionrequests);
  222. m_dwcPendingSearches = 0;
  223. m_fDPS_Was_Here = FALSE;
  224. InitializeListHead(&m_listhead_insertionrequests);
  225. InitializeListHead(&m_listhead_cancelnotifies);
  226. }
  227. ~CBatchLdapConnection()
  228. {
  229. _ASSERT(m_dwSignature == SIGNATURE_CBATCHLDAPCONN);
  230. m_dwSignature = SIGNATURE_CBATCHLDAPCONN_INVALID;
  231. _ASSERT(m_dwcPendingSearches == 0);
  232. }
  233. CLdapConnection *GetConnection()
  234. {
  235. return( this );
  236. }
  237. VOID GetInsertionContext()
  238. {
  239. AcquireSpinLock(&m_spinlock);
  240. m_cInsertionContext++;
  241. ReleaseSpinLock(&m_spinlock);
  242. }
  243. VOID ReleaseInsertionContext()
  244. {
  245. AcquireSpinLock(&m_spinlock);
  246. if((--m_cInsertionContext) == 0) {
  247. LIST_ENTRY listhead_dispatch;
  248. //
  249. // Remove all blocks from the insertion list and put them in the dispatch list
  250. //
  251. if(IsListEmpty(&m_listhead)) {
  252. // No blocks
  253. ReleaseSpinLock(&m_spinlock);
  254. InitializeListHead(&listhead_dispatch);
  255. } else {
  256. CopyMemory(&listhead_dispatch, &m_listhead, sizeof(LIST_ENTRY));
  257. listhead_dispatch.Blink->Flink = &listhead_dispatch;
  258. listhead_dispatch.Flink->Blink = &listhead_dispatch;
  259. InitializeListHead(&m_listhead);
  260. ReleaseSpinLock(&m_spinlock);
  261. //
  262. // Dispatch all the blocks
  263. //
  264. DispatchBlocks(&listhead_dispatch);
  265. }
  266. } else {
  267. ReleaseSpinLock(&m_spinlock);
  268. }
  269. }
  270. HRESULT HrInsertSearchRequest(
  271. ISMTPServer *pISMTPServer,
  272. ICategorizerParameters *pICatParams,
  273. CCatAddr *pCCatAddr,
  274. LPSEARCHCOMPLETION fnSearchCompletion,
  275. CStoreListResolveContext *pslrc,
  276. LPSTR pszSearchFilter,
  277. LPSTR pszDistinguishingAttribute,
  278. LPSTR pszDistinguishingAttributeValue);
  279. static VOID InitializeFromRegistry();
  280. VOID IncrementPendingSearches(DWORD dw = 1)
  281. {
  282. AcquireSpinLock(&m_spinlock_insertionrequests);
  283. m_dwcPendingSearches += dw;
  284. ReleaseSpinLock(&m_spinlock_insertionrequests);
  285. }
  286. VOID DecrementPendingSearches(DWORD dwcSearches = 1);
  287. HRESULT HrInsertInsertionRequest(
  288. CInsertionRequest *pCInsertionRequest);
  289. VOID CancelAllSearches(
  290. HRESULT hr = HRESULT_FROM_WIN32(ERROR_CANCELLED));
  291. private:
  292. CSearchRequestBlock *GetSearchRequestBlock();
  293. VOID RemoveSearchRequestBlockFromList(
  294. CSearchRequestBlock *pBlock)
  295. {
  296. AcquireSpinLock(&m_spinlock);
  297. RemoveEntryList(&(pBlock->m_listentry));
  298. ReleaseSpinLock(&m_spinlock);
  299. }
  300. VOID DispatchBlocks(PLIST_ENTRY listhead);
  301. public:
  302. static DWORD m_nMaxConnectionRetries;
  303. private:
  304. static DWORD m_nMaxSearchBlockSize;
  305. static DWORD m_nMaxPendingSearches;
  306. DWORD m_dwSignature;
  307. LIST_ENTRY m_listhead;
  308. SPIN_LOCK m_spinlock;
  309. LONG m_cInsertionContext;
  310. CSearchRequestBlock *m_pInsertionBlock;
  311. SPIN_LOCK m_spinlock_insertionrequests;
  312. DWORD m_dwcPendingSearches;
  313. DWORD m_dwcReservedSearches;
  314. LIST_ENTRY m_listhead_insertionrequests;
  315. typedef struct _tagCancelNotify {
  316. LIST_ENTRY le;
  317. HRESULT hrCancel;
  318. } CANCELNOTIFY, *PCANCELNOTIFY;
  319. // This list is also protected by m_spinlock_insertionrequests
  320. LIST_ENTRY m_listhead_cancelnotifies;
  321. CExShareLock m_cancellock;
  322. BOOL m_fDPS_Was_Here;
  323. friend class CSearchRequestBlock;
  324. };
  325. //------------------------------------------------------------
  326. //
  327. // class CBatchLdapConnectionCache
  328. //
  329. //------------------------------------------------------------
  330. class CBatchLdapConnectionCache :
  331. public CLdapConnectionCache
  332. {
  333. public:
  334. CBatchLdapConnectionCache(
  335. ISMTPServerEx *pISMTPServerEx) :
  336. CLdapConnectionCache(pISMTPServerEx)
  337. {
  338. }
  339. HRESULT GetConnection(
  340. CBatchLdapConnection **ppConn,
  341. LPSTR szHost,
  342. DWORD dwPort,
  343. LPSTR szNamingContext,
  344. LPSTR szAccount,
  345. LPSTR szPassword,
  346. LDAP_BIND_TYPE bt,
  347. PVOID pCreateContext = NULL)
  348. {
  349. return CLdapConnectionCache::GetConnection(
  350. (CLdapConnection **)ppConn,
  351. szHost,
  352. dwPort,
  353. szNamingContext,
  354. szAccount,
  355. szPassword,
  356. bt,
  357. pCreateContext);
  358. }
  359. CCachedLdapConnection *CreateCachedLdapConnection(
  360. LPSTR szHost,
  361. DWORD dwPort,
  362. LPSTR szNamingContext,
  363. LPSTR szAccount,
  364. LPSTR szPassword,
  365. LDAP_BIND_TYPE bt,
  366. PVOID pCreateContext)
  367. {
  368. CCachedLdapConnection *pret;
  369. pret = new CBatchLdapConnection(
  370. szHost,
  371. dwPort,
  372. szNamingContext,
  373. szAccount,
  374. szPassword,
  375. bt,
  376. this);
  377. if(pret)
  378. if(FAILED(pret->HrInitialize())) {
  379. pret->Release();
  380. pret = NULL;
  381. }
  382. return pret;
  383. }
  384. };
  385. //------------------------------------------------------------
  386. //
  387. // class CStoreListResolveContext
  388. //
  389. //------------------------------------------------------------
  390. CatDebugClass(CStoreListResolveContext)
  391. {
  392. public:
  393. CStoreListResolveContext(CEmailIDLdapStore<CCatAddr> *pStore);
  394. ~CStoreListResolveContext();
  395. VOID AddRef()
  396. {
  397. InterlockedIncrement((PLONG) &m_cRefs);
  398. }
  399. VOID Release()
  400. {
  401. if( InterlockedDecrement((PLONG) &m_cRefs) == 0 )
  402. delete this;
  403. }
  404. HRESULT HrInitialize(
  405. ISMTPServer *pISMTPServer,
  406. ICategorizerParameters *pICatParams);
  407. HRESULT HrLookupEntryAsync(
  408. CCatAddr *pCCatAddr);
  409. VOID Cancel();
  410. CCfgConnection *GetConnection();
  411. VOID GetInsertionContext();
  412. VOID ReleaseInsertionContext();
  413. HRESULT HrInsertInsertionRequest(
  414. CInsertionRequest *pCInsertionRequest);
  415. ISMTPServerEx * GetISMTPServerEx()
  416. {
  417. return m_pISMTPServerEx;
  418. }
  419. BOOL Canceled() {
  420. return m_fCanceled;
  421. }
  422. HRESULT HrInvalidateConnectionAndRetrieveNewConnection(
  423. CBatchLdapConnection *pConn,
  424. BOOL fIncrementRetryCount = TRUE);
  425. private:
  426. static VOID AsyncLookupCompletion(
  427. CCatAddr *pCCatAddr,
  428. CStoreListResolveContext *pslrc,
  429. CBatchLdapConnection *pConn);
  430. VOID LogSLRCFailover(
  431. IN DWORD dwcRetries,
  432. IN LPSTR pszOldHost,
  433. IN LPSTR pszNewHost);
  434. VOID LogSLRCFailure(
  435. IN DWORD dwcRetries,
  436. IN LPSTR pszHost);
  437. private:
  438. #define SIGNATURE_CSTORELISTRESOLVECONTEXT (DWORD)'CRLS'
  439. #define SIGNATURE_CSTORELISTRESOLVECONTEXT_INVALID (DWORD)'XRLS'
  440. DWORD m_cRefs;
  441. DWORD m_dwSignature;
  442. CCfgConnection *m_pConn;
  443. CRITICAL_SECTION m_cs;
  444. DWORD m_dwcInsertionContext;
  445. BOOL m_fCanceled;
  446. DWORD m_dwcRetries;
  447. DWORD m_dwcCompletedLookups;
  448. ISMTPServer *m_pISMTPServer;
  449. ISMTPServerEx *m_pISMTPServerEx;
  450. ICategorizerParameters *m_pICatParams;
  451. CEmailIDLdapStore<CCatAddr> *m_pStore;
  452. };
  453. inline CSearchRequestBlock::CSearchRequestBlock(
  454. CBatchLdapConnection *pConn) :
  455. m_CICatQueries( &m_pszSearchFilter )
  456. {
  457. _ASSERT(m_dwSignature == SIGNATURE_CSEARCHREQUESTBLOCK);
  458. m_pISMTPServer = NULL;
  459. m_pISMTPServerEx = NULL;
  460. m_pICatParams = NULL;
  461. m_pszSearchFilter = NULL;
  462. m_cBlockRequestsReserved = 0;
  463. m_cBlockRequestsAllocated = 0;
  464. m_cBlockRequestsReadyForDispatch = 0;
  465. m_pConn = pConn;
  466. m_pConn->AddRef();
  467. }
  468. //------------------------------------------------------------
  469. //
  470. // class CSingleSearchReinsertionRequest
  471. //
  472. //------------------------------------------------------------
  473. CatDebugClass(CSingleSearchReinsertionRequest),
  474. public CInsertionRequest
  475. {
  476. public:
  477. HRESULT HrInsertSearches(
  478. DWORD dwcSearches);
  479. VOID NotifyDeQueue(
  480. HRESULT hr);
  481. #define SIGNATURE_CSingleSearchReinsertionRequest (DWORD)'qRIS'
  482. #define SIGNATURE_CSingleSearchReinsertionRequest_INVALID (DWORD)'XRIS'
  483. CSingleSearchReinsertionRequest(
  484. CStoreListResolveContext *pslrc,
  485. CCatAddr *pCCatAddr)
  486. {
  487. m_dwSignature = SIGNATURE_CSingleSearchReinsertionRequest;
  488. m_hr = S_OK;
  489. m_dwcSearches = 0;
  490. m_pslrc = pslrc;
  491. m_pCCatAddr = pCCatAddr;
  492. m_pCCatAddr->AddRef();
  493. }
  494. ~CSingleSearchReinsertionRequest()
  495. {
  496. if(!m_dwcSearches)
  497. m_pCCatAddr->LookupCompletion();
  498. m_pCCatAddr->Release();
  499. _ASSERT(m_dwSignature == SIGNATURE_CSingleSearchReinsertionRequest);
  500. m_dwSignature = SIGNATURE_CSingleSearchReinsertionRequest_INVALID;
  501. }
  502. ISMTPServerEx *GetISMTPServerEx()
  503. {
  504. return m_pslrc->GetISMTPServerEx();
  505. }
  506. private:
  507. DWORD m_dwSignature;
  508. HRESULT m_hr;
  509. DWORD m_dwcSearches;
  510. CStoreListResolveContext *m_pslrc;
  511. CCatAddr *m_pCCatAddr;
  512. };
  513. #endif _ASYNCCTX_H_