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

////////////////////////////////////////////////////////////////////////////////////////////////
// FILE: retrsink.h
// PURPOSE: Lib for handling retries of failed outbound connections
// HISTORY:
// NimishK 05-14-98 Created
///////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __RETRSINK_H__
#define __RETRSINK_H__
#include <baseobj.h>
//function used for retry callback
typedef VOID (*RETRFN)(PVOID pvContext);
#define CALLBACK_DOMAIN "!callback"
////////////////////////////
//Temporary stuff, till we get this all into the event interface IDL file
typedef struct RetryData
{
BOOL fRetryDelay;
DWORD dwRetryDelay;
} RETRY_DATA, *PRETRY_DATA;
typedef struct RetryConfigData
{
DWORD dwRetryThreshold;
DWORD dwGlitchRetrySeconds;
DWORD dwFirstRetrySeconds;
DWORD dwSecondRetrySeconds;
DWORD dwThirdRetrySeconds;
DWORD dwFourthRetrySeconds;
} RETRYCONFIG, *PRETRYCONFIG;
enum SINK_STATUS {EVT_IGNORED, EVT_HANDLED, SKIP_ALL};
///////////////////////////
#define DOMAIN_ENTRY_RETRY 0x00000002
#define DOMAIN_ENTRY_SCHED 0x00000004
#define DOMAIN_ENTRY_FORCE_CONN 0x00000008
#define DOMAIN_ENTRY_ETRNTURN 0x00000040
//Forward declaration
class CRETRY_HASH_ENTRY;
class CRETRY_HASH_TABLE;
class CRETRY_Q;
////////////////////////////////////////////////////////////////////////////////////////////////
// class CSMTP_RETRY_HANDLER
// This class provides the retry functionality that is needed when SMTP server fails to
// send messages to the remote host.
// It is considered the default retry handler - meaning in absence of any other entity
// taking care of retries, this handler will do it. For additional information look up
// docs on the ServerEvent framework for AQUEUE.
// Whenever SMTP acks a connection, this handler gets called. If the connection failed, the
// handler keeps track of the "NextHop" name that failed. It will disable the link corres-
// ponding to the "NextHop" and reactivate it later based on the retry interval specified
// the administrator.
// The main components are - a "NextHop" name hash table to keep track of links we know
// about, a queue with entries sorted by the retry time of a link and a dedicated thread
// that will be responsible for retrying entries based on the queue
// This class will be initialized during the ConnectionManager initialization and deiniti-
// alized during ConnectionManager Deinit.
// It gets signalled whenever there is change in the config data ( retry interval )
//
///////////////////////////////////////////////////////////////////////////////////////////////
class CSMTP_RETRY_HANDLER :
public IConnectionRetrySink,
public CBaseObject
{
// CSMTP_RETRY_HANDLER
public:
CSMTP_RETRY_HANDLER()
{
m_RetryEvent = NULL;
m_fHandlerShuttingDown = FALSE;
}
~CSMTP_RETRY_HANDLER()
{
TraceFunctEnterEx((LPARAM)this, "~CSMTP_RETRY_HANDLER");
TraceFunctLeaveEx((LPARAM)this);
}
//Init / denit called during ConnMan inits
HRESULT HrInitialize(IN IConnectionRetryManager *pIConnectionRetryManager);
HRESULT HrDeInitialize(void);
//Config data change notifier - called by ConnMan whenver relevant
//data in metabase changes
void UpdateRetryData(PRETRYCONFIG pRetryConfig)
{
m_dwRetryThreshold = pRetryConfig->dwRetryThreshold;
m_dwGlitchRetrySeconds = pRetryConfig->dwGlitchRetrySeconds;
m_dwFirstRetrySeconds = pRetryConfig->dwFirstRetrySeconds;
m_dwSecondRetrySeconds = pRetryConfig->dwSecondRetrySeconds;
m_dwThirdRetrySeconds = pRetryConfig->dwThirdRetrySeconds;
m_dwFourthRetrySeconds = pRetryConfig->dwFourthRetrySeconds;
//Update all the queue entries with the new config data.
//
UpdateAllEntries();
}
//Wait for dedicated thread to exit during Deinit
void WaitForQThread(void)
{
DWORD ThreadExit;
ThreadExit = WaitForSingleObject(m_ThreadHandle,INFINITE);
}
//Wait for all ConnectionReleased threads to go away
//during deinit
void WaitForShutdown(void)
{
DWORD ThreadExit;
ThreadExit = WaitForSingleObject(m_ShutdownEvent,INFINITE);
}
//Set event to control the dedicated thread
void SetQueueEvent(void)
{
_ASSERT(m_RetryEvent != NULL);
SetEvent(m_RetryEvent);
}
//wrapper for calls to enable/disable a link using IConnectionRetryManager
//Called by Dedicated thread or connection release thread
BOOL ReleaseForRetry(IN char * szHashedDomainName);
BOOL HoldForRetry(IN char * szHashedDomainName);
CRETRY_HASH_TABLE* GetTablePtr(){return m_pRetryHash;}
CRETRY_Q* GetQueuePtr(){return m_pRetryQueue;}
HANDLE GetRetryEventHandle(void) const {return m_RetryEvent;}
BOOL IsShuttingDown(void){ return m_fHandlerShuttingDown;}
void SetShuttingDown(void){ m_fHandlerShuttingDown = TRUE;}
//Called by the RetryThreadRoutine whenever it comes across a link entry that
// can be retried. Currently does not do much. Only Enables the link
void ProcessEntry(CRETRY_HASH_ENTRY* pRHEntry);
//The dedicated thread that keeps track of next link to be retried and wakes up and
//does that
static DWORD WINAPI RetryThreadRoutine(void * ThisPtr);
//Aqueue DLL wide ( cross instance ) init deinit
static DWORD dwInstanceCount;
//Will call back after the appropriate time has elapsed.
HRESULT SetCallbackTime(IN RETRFN pCallbackFn,
IN PVOID pvContext,
IN DWORD dwCallbackMinutes);
public: //IConnectionRetrySink
STDMETHOD(QueryInterface)(REFIID riid, LPVOID * ppvObj) {return E_NOTIMPL;};
STDMETHOD_(ULONG, AddRef)(void) {return CBaseObject::AddRef();};
STDMETHOD_(ULONG, Release)(void) {return CBaseObject::Release();};
//Will be called by ConnectionManger every time a connection is released
STDMETHOD(ConnectionReleased)(
IN DWORD cbDomainName,
IN CHAR szDomainName[],
IN DWORD dwDomainInfoFlags,
IN DWORD dwScheduleID,
IN GUID guidRouting,
IN DWORD dwConnectionStatus,
IN DWORD cFailedMessages,
IN DWORD cTriedMessages,
IN DWORD cConsecutiveConnectionFailures,
OUT BOOL* pfAllowImmediateRetry,
OUT FILETIME *pftNextRetryTime);
private :
CRETRY_HASH_TABLE *m_pRetryHash;
CRETRY_Q *m_pRetryQueue;
DWORD m_dwRetryMilliSec; // Retry interval based on config data
IConnectionRetryManager *m_pIRetryManager; // Interface to enable/disable link
HANDLE m_RetryEvent; // Retry Release timeout event
HANDLE m_ShutdownEvent; // Shutdown event
HANDLE m_ThreadHandle; // Retry Thread handle
BOOL m_fHandlerShuttingDown; // Shutdown flag
BOOL m_fConfigDataUpdated;
LONG m_ThreadsInRetry; // Number of ConnectionManager threads
DWORD m_dwRetryThreshold;
DWORD m_dwGlitchRetrySeconds;
DWORD m_dwFirstRetrySeconds;
DWORD m_dwSecondRetrySeconds;
DWORD m_dwThirdRetrySeconds;
DWORD m_dwFourthRetrySeconds;
//Calculates the time a link needs to be released for retry.
//The time is based on the current time and the configured interval and
//the history of connection failures for this particular host
FILETIME CalculateRetryTime(DWORD cFailedConnections, FILETIME* InsertedTime);
//Insert or remove domains from the retry handler ( hash table and the queue )
//based on the Connection released call
BOOL InsertDomain(char * szDomainName,
IN DWORD cbDomainName, //String length (in bytes) of domain name
IN DWORD dwConnectionStatus, //eConnectionStatus
IN DWORD dwScheduleID,
IN GUID *pguidRouting,
IN DWORD cConnectionFailureCount,
IN DWORD cTriedMessages, //# of untried messages in queue
IN DWORD cFailedMessages, //# of failed message for *this* connection
OUT FILETIME *pftNextRetry //next retry
);
BOOL RemoveDomain(char * szDomainName);
BOOL UpdateAllEntries(void);
#ifdef DEBUG
public :
void DumpAll(void);
#endif
};
#endif