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.

230 lines
9.1 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////////////////
  2. // FILE: retrsink.h
  3. // PURPOSE: Lib for handling retries of failed outbound connections
  4. // HISTORY:
  5. // NimishK 05-14-98 Created
  6. ///////////////////////////////////////////////////////////////////////////////////////////////
  7. #ifndef __RETRSINK_H__
  8. #define __RETRSINK_H__
  9. #include <baseobj.h>
  10. //function used for retry callback
  11. typedef VOID (*RETRFN)(PVOID pvContext);
  12. #define CALLBACK_DOMAIN "!callback"
  13. ////////////////////////////
  14. //Temporary stuff, till we get this all into the event interface IDL file
  15. typedef struct RetryData
  16. {
  17. BOOL fRetryDelay;
  18. DWORD dwRetryDelay;
  19. } RETRY_DATA, *PRETRY_DATA;
  20. typedef struct RetryConfigData
  21. {
  22. DWORD dwRetryThreshold;
  23. DWORD dwGlitchRetrySeconds;
  24. DWORD dwFirstRetrySeconds;
  25. DWORD dwSecondRetrySeconds;
  26. DWORD dwThirdRetrySeconds;
  27. DWORD dwFourthRetrySeconds;
  28. } RETRYCONFIG, *PRETRYCONFIG;
  29. enum SINK_STATUS {EVT_IGNORED, EVT_HANDLED, SKIP_ALL};
  30. ///////////////////////////
  31. #define DOMAIN_ENTRY_RETRY 0x00000002
  32. #define DOMAIN_ENTRY_SCHED 0x00000004
  33. #define DOMAIN_ENTRY_FORCE_CONN 0x00000008
  34. #define DOMAIN_ENTRY_ETRNTURN 0x00000040
  35. //Forward declaration
  36. class CRETRY_HASH_ENTRY;
  37. class CRETRY_HASH_TABLE;
  38. class CRETRY_Q;
  39. ////////////////////////////////////////////////////////////////////////////////////////////////
  40. // class CSMTP_RETRY_HANDLER
  41. // This class provides the retry functionality that is needed when SMTP server fails to
  42. // send messages to the remote host.
  43. // It is considered the default retry handler - meaning in absence of any other entity
  44. // taking care of retries, this handler will do it. For additional information look up
  45. // docs on the ServerEvent framework for AQUEUE.
  46. // Whenever SMTP acks a connection, this handler gets called. If the connection failed, the
  47. // handler keeps track of the "NextHop" name that failed. It will disable the link corres-
  48. // ponding to the "NextHop" and reactivate it later based on the retry interval specified
  49. // the administrator.
  50. // The main components are - a "NextHop" name hash table to keep track of links we know
  51. // about, a queue with entries sorted by the retry time of a link and a dedicated thread
  52. // that will be responsible for retrying entries based on the queue
  53. // This class will be initialized during the ConnectionManager initialization and deiniti-
  54. // alized during ConnectionManager Deinit.
  55. // It gets signalled whenever there is change in the config data ( retry interval )
  56. //
  57. ///////////////////////////////////////////////////////////////////////////////////////////////
  58. class CSMTP_RETRY_HANDLER :
  59. public IConnectionRetrySink,
  60. public CBaseObject
  61. {
  62. // CSMTP_RETRY_HANDLER
  63. public:
  64. CSMTP_RETRY_HANDLER()
  65. {
  66. m_RetryEvent = NULL;
  67. m_fHandlerShuttingDown = FALSE;
  68. }
  69. ~CSMTP_RETRY_HANDLER()
  70. {
  71. TraceFunctEnterEx((LPARAM)this, "~CSMTP_RETRY_HANDLER");
  72. TraceFunctLeaveEx((LPARAM)this);
  73. }
  74. //Init / denit called during ConnMan inits
  75. HRESULT HrInitialize(IN IConnectionRetryManager *pIConnectionRetryManager);
  76. HRESULT HrDeInitialize(void);
  77. //Config data change notifier - called by ConnMan whenver relevant
  78. //data in metabase changes
  79. void UpdateRetryData(PRETRYCONFIG pRetryConfig)
  80. {
  81. m_dwRetryThreshold = pRetryConfig->dwRetryThreshold;
  82. m_dwGlitchRetrySeconds = pRetryConfig->dwGlitchRetrySeconds;
  83. m_dwFirstRetrySeconds = pRetryConfig->dwFirstRetrySeconds;
  84. m_dwSecondRetrySeconds = pRetryConfig->dwSecondRetrySeconds;
  85. m_dwThirdRetrySeconds = pRetryConfig->dwThirdRetrySeconds;
  86. m_dwFourthRetrySeconds = pRetryConfig->dwFourthRetrySeconds;
  87. //Update all the queue entries with the new config data.
  88. //
  89. UpdateAllEntries();
  90. }
  91. //Wait for dedicated thread to exit during Deinit
  92. void WaitForQThread(void)
  93. {
  94. DWORD ThreadExit;
  95. ThreadExit = WaitForSingleObject(m_ThreadHandle,INFINITE);
  96. }
  97. //Wait for all ConnectionReleased threads to go away
  98. //during deinit
  99. void WaitForShutdown(void)
  100. {
  101. DWORD ThreadExit;
  102. ThreadExit = WaitForSingleObject(m_ShutdownEvent,INFINITE);
  103. }
  104. //Set event to control the dedicated thread
  105. void SetQueueEvent(void)
  106. {
  107. _ASSERT(m_RetryEvent != NULL);
  108. SetEvent(m_RetryEvent);
  109. }
  110. //wrapper for calls to enable/disable a link using IConnectionRetryManager
  111. //Called by Dedicated thread or connection release thread
  112. BOOL ReleaseForRetry(IN char * szHashedDomainName);
  113. BOOL HoldForRetry(IN char * szHashedDomainName);
  114. CRETRY_HASH_TABLE* GetTablePtr(){return m_pRetryHash;}
  115. CRETRY_Q* GetQueuePtr(){return m_pRetryQueue;}
  116. HANDLE GetRetryEventHandle(void) const {return m_RetryEvent;}
  117. BOOL IsShuttingDown(void){ return m_fHandlerShuttingDown;}
  118. void SetShuttingDown(void){ m_fHandlerShuttingDown = TRUE;}
  119. //Called by the RetryThreadRoutine whenever it comes across a link entry that
  120. // can be retried. Currently does not do much. Only Enables the link
  121. void ProcessEntry(CRETRY_HASH_ENTRY* pRHEntry);
  122. //The dedicated thread that keeps track of next link to be retried and wakes up and
  123. //does that
  124. static DWORD WINAPI RetryThreadRoutine(void * ThisPtr);
  125. //Aqueue DLL wide ( cross instance ) init deinit
  126. static DWORD dwInstanceCount;
  127. //Will call back after the appropriate time has elapsed.
  128. HRESULT SetCallbackTime(IN RETRFN pCallbackFn,
  129. IN PVOID pvContext,
  130. IN DWORD dwCallbackMinutes);
  131. public: //IConnectionRetrySink
  132. STDMETHOD(QueryInterface)(REFIID riid, LPVOID * ppvObj) {return E_NOTIMPL;};
  133. STDMETHOD_(ULONG, AddRef)(void) {return CBaseObject::AddRef();};
  134. STDMETHOD_(ULONG, Release)(void) {return CBaseObject::Release();};
  135. //Will be called by ConnectionManger every time a connection is released
  136. STDMETHOD(ConnectionReleased)(
  137. IN DWORD cbDomainName,
  138. IN CHAR szDomainName[],
  139. IN DWORD dwDomainInfoFlags,
  140. IN DWORD dwScheduleID,
  141. IN GUID guidRouting,
  142. IN DWORD dwConnectionStatus,
  143. IN DWORD cFailedMessages,
  144. IN DWORD cTriedMessages,
  145. IN DWORD cConsecutiveConnectionFailures,
  146. OUT BOOL* pfAllowImmediateRetry,
  147. OUT FILETIME *pftNextRetryTime);
  148. private :
  149. CRETRY_HASH_TABLE *m_pRetryHash;
  150. CRETRY_Q *m_pRetryQueue;
  151. DWORD m_dwRetryMilliSec; // Retry interval based on config data
  152. IConnectionRetryManager *m_pIRetryManager; // Interface to enable/disable link
  153. HANDLE m_RetryEvent; // Retry Release timeout event
  154. HANDLE m_ShutdownEvent; // Shutdown event
  155. HANDLE m_ThreadHandle; // Retry Thread handle
  156. BOOL m_fHandlerShuttingDown; // Shutdown flag
  157. BOOL m_fConfigDataUpdated;
  158. LONG m_ThreadsInRetry; // Number of ConnectionManager threads
  159. DWORD m_dwRetryThreshold;
  160. DWORD m_dwGlitchRetrySeconds;
  161. DWORD m_dwFirstRetrySeconds;
  162. DWORD m_dwSecondRetrySeconds;
  163. DWORD m_dwThirdRetrySeconds;
  164. DWORD m_dwFourthRetrySeconds;
  165. //Calculates the time a link needs to be released for retry.
  166. //The time is based on the current time and the configured interval and
  167. //the history of connection failures for this particular host
  168. FILETIME CalculateRetryTime(DWORD cFailedConnections, FILETIME* InsertedTime);
  169. //Insert or remove domains from the retry handler ( hash table and the queue )
  170. //based on the Connection released call
  171. BOOL InsertDomain(char * szDomainName,
  172. IN DWORD cbDomainName, //String length (in bytes) of domain name
  173. IN DWORD dwConnectionStatus, //eConnectionStatus
  174. IN DWORD dwScheduleID,
  175. IN GUID *pguidRouting,
  176. IN DWORD cConnectionFailureCount,
  177. IN DWORD cTriedMessages, //# of untried messages in queue
  178. IN DWORD cFailedMessages, //# of failed message for *this* connection
  179. OUT FILETIME *pftNextRetry //next retry
  180. );
  181. BOOL RemoveDomain(char * szDomainName);
  182. BOOL UpdateAllEntries(void);
  183. #ifdef DEBUG
  184. public :
  185. void DumpAll(void);
  186. #endif
  187. };
  188. #endif