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.

319 lines
8.0 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: queue.hxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 01-05-96 Rohanp Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #ifndef __QUEUE_H__
  18. #define __QUEUE_H__
  19. const DWORD SMTP_QUEUE_TYPE = 0;
  20. enum QUEUE_TYPE {LOCALQ, REMOTEQ, RETRYQ};
  21. enum QUEUE_OPCODE {PROCESS_QUEUE, TERMINATE_QUEUE};
  22. enum QUEUE_POSITION {QUEUE_TAIL, QUEUE_HEAD};
  23. enum QUEUE_SIG {SIGNAL, NONSIGNAL};
  24. // The PERSIST_QUEUE_ENTRY is the wrapper for the message in the queue,
  25. // containing creation and last access time for messages, as well as
  26. // Identifiers, flags, and retrys. Actual queue elements will be derived
  27. // from PERSIST_QUEUE_ENTRY
  28. //forward declaration
  29. class PERSIST_QUEUE;
  30. class SMTP_SERVER_INSTANCE;
  31. class PERSIST_QUEUE_ENTRY
  32. {
  33. private:
  34. QUEUE_OPCODE m_OpCode;
  35. PERSIST_QUEUE * m_ParentQ;
  36. SMTP_SERVER_INSTANCE * m_pInstance;
  37. protected:
  38. LONGLONG m_ExpireTime; // Time to delete object
  39. LONGLONG m_LastAccess; // Time of last access
  40. DWORD m_QueueId; // Unique ID
  41. DWORD m_RefId; // Sub-ref ID for duplicates
  42. DWORD m_Flags; // Flags
  43. DWORD m_Retries; // Number of retries
  44. public:
  45. LIST_ENTRY m_QEntry; // List pointers
  46. PERSIST_QUEUE_ENTRY(SMTP_SERVER_INSTANCE * pInstance)
  47. {
  48. m_OpCode = PROCESS_QUEUE;
  49. m_ParentQ = NULL;
  50. m_ExpireTime = (LONGLONG) 0;
  51. m_LastAccess = (LONGLONG) 0;
  52. m_QueueId = 0;
  53. m_RefId = 0;
  54. m_Flags = 0;
  55. m_Retries = 0;
  56. m_pInstance = pInstance;
  57. }
  58. SMTP_SERVER_INSTANCE * QuerySmtpInstance( VOID ) const
  59. { _ASSERT(m_pInstance != NULL); return m_pInstance; }
  60. BOOL IsSmtpInstance( VOID ) const
  61. { return m_pInstance != NULL; }
  62. VOID SetSmtpInstance( IN SMTP_SERVER_INSTANCE * pInstance )
  63. { _ASSERT(m_pInstance == NULL); m_pInstance = pInstance; }
  64. void SetExpireTime(LONGLONG ExpireTime) {m_ExpireTime = ExpireTime;}
  65. LONGLONG GetExpireTime (void) const{return m_ExpireTime;}
  66. void SetLastAccessTime(LONGLONG LastTime) {m_LastAccess = LastTime;}
  67. LONGLONG GetLastAccessTime(void) const {return m_LastAccess;}
  68. void SetOpCode (QUEUE_OPCODE OpCode){m_OpCode = OpCode;}
  69. void SetParentQ (PERSIST_QUEUE *ParentQ){m_ParentQ = ParentQ;}
  70. PERSIST_QUEUE * GetParentQ (void)const {return m_ParentQ;}
  71. QUEUE_OPCODE GetOpCode (void) const {return m_OpCode;}
  72. LIST_ENTRY & QueryListEntry(void) {return ( m_QEntry);}
  73. virtual void BeforeDelete(void){}
  74. virtual ~PERSIST_QUEUE_ENTRY(){}
  75. };
  76. typedef PERSIST_QUEUE_ENTRY * PQUEUE_ENTRY;
  77. //
  78. // A PERSIST_QUEUE is the convenient abstraction to hold all of the messages that
  79. // we're trying to deliver. Threads wait on the queue throught the m_QEvent handle.
  80. // This thread is used to dispatch various entries as they become available
  81. // either through magically appearing in the queue from somewhere else, or
  82. // through the timeout (RetryInterval).
  83. // All times in the queue are FILETIMES
  84. //QHEADER is the part of the queue that will be written to disk.
  85. //it is the header.
  86. struct QHEADER
  87. {
  88. DWORD TypeOfEntry;
  89. DWORD Entries; // Number of entries
  90. DWORD Flags; // Flags
  91. DWORD RetryInterval; // Retry interval for messages
  92. DWORD StoreInterval; // Flush to store interval
  93. LONGLONG LastStore; // Time of last store
  94. };
  95. class PERSIST_QUEUE
  96. {
  97. private :
  98. QHEADER m_QData;
  99. HANDLE m_QEvent; // Queue event
  100. DWORD m_NumThreads;
  101. HANDLE m_ThreadHandle[64]; // Thread handle
  102. CRITICAL_SECTION m_CritSec; // Guard
  103. LIST_ENTRY m_QHead; // List pointers
  104. SMTP_SERVER_INSTANCE * m_ParentInst;
  105. BOOL InitializeQueue(void);
  106. public:
  107. PERSIST_QUEUE (SMTP_SERVER_INSTANCE * pSmtpInst) //initialize stuff that can't fail
  108. {
  109. TraceFunctEnterEx((LPARAM)this, "PERSIST_QUEUE::PERSIST_QUEUE");
  110. _ASSERT(pSmtpInst != NULL);
  111. m_QEvent = NULL;
  112. m_ParentInst = pSmtpInst;
  113. m_NumThreads = 1;
  114. //Init or critical section. This protects the queue
  115. InitializeCriticalSection(&m_CritSec);
  116. //Init the heaad of the queue
  117. InitializeListHead(&m_QHead);
  118. TraceFunctLeaveEx((LPARAM)this);
  119. }
  120. void SetNumThreads (DWORD NumThreads)
  121. {
  122. m_NumThreads = NumThreads;
  123. }
  124. virtual ~PERSIST_QUEUE ()
  125. {
  126. TraceFunctEnterEx((LPARAM)this, "~PERSIST_QUEUE");
  127. //FlushQueueEvents();
  128. if(m_QEvent != NULL)
  129. CloseHandle(m_QEvent);
  130. WaitForQThread();
  131. DWORD Loop = 0;
  132. for (Loop = 0; Loop < m_NumThreads; Loop++)
  133. {
  134. if(m_ThreadHandle[Loop] != NULL)
  135. CloseHandle(m_ThreadHandle[Loop]);
  136. }
  137. DeleteCriticalSection (&m_CritSec);
  138. TraceFunctLeaveEx((LPARAM)this);
  139. }
  140. void WaitForQThread(void)
  141. {
  142. DWORD WhichEvent;
  143. WhichEvent = WaitForMultipleObjects(m_NumThreads, m_ThreadHandle, TRUE, INFINITE);
  144. }
  145. void SetQueueEvent(void)
  146. {
  147. _ASSERT(m_QEvent != NULL);
  148. _ASSERT(m_ParentInst != NULL);
  149. SetEvent(m_QEvent);
  150. }
  151. virtual PQUEUE_ENTRY PopQEntry(void)
  152. {
  153. PLIST_ENTRY plEntry = NULL;
  154. PQUEUE_ENTRY pqEntry = NULL;
  155. _ASSERT(m_ParentInst != NULL);
  156. //get the first item off the queue
  157. plEntry = RemoveHeadList (&m_QHead);
  158. pqEntry = CONTAINING_RECORD(plEntry, PERSIST_QUEUE_ENTRY, m_QEntry);
  159. //decrement the number of entries in the queue
  160. --m_QData.Entries;
  161. return pqEntry;
  162. }
  163. SMTP_SERVER_INSTANCE * GetParentInst(void)const {return m_ParentInst;}
  164. void LockQ () {EnterCriticalSection (&m_CritSec);}
  165. void UnLockQ() {LeaveCriticalSection (&m_CritSec);}
  166. virtual void DropRetryCounter(void) {}
  167. virtual void BumpRetryCounter(void) {}
  168. virtual DWORD GetRetryMinutes(void) {return INFINITE;}
  169. HANDLE GetQueueThreadHandle(void) const {return NULL;}
  170. HANDLE GetQueueEventHandle(void) const {return m_QEvent;}
  171. static PERSIST_QUEUE * CreateQueue(QUEUE_TYPE Qtype, SMTP_SERVER_INSTANCE * pSmtpInst);
  172. LIST_ENTRY & QueryListHead(void) {return ( m_QHead);}
  173. DWORD GetNumEntries(void) const {return m_QData.Entries;}
  174. BOOL IsQueueEmpty(void) const {return IsListEmpty(&m_QHead);}
  175. virtual BOOL ProcessQueueEvents(ISMTPConnection *pISMTPConnection);
  176. virtual BOOL IsAtLeastOneValidUser (void){return TRUE;}
  177. static DWORD WINAPI QueueThreadRoutine(void * ThisPtr);
  178. void FlushQueueEvents(void);
  179. /*++
  180. Name :
  181. PERSIST_QUEUE::InsertEntry
  182. Description:
  183. This function inserts an element into the queue.
  184. It always inserts aat the tail
  185. Arguments:
  186. pEntry - Element to insert into the queue
  187. Returns:
  188. always TRUE
  189. --*/
  190. virtual BOOL InsertEntry(IN OUT PERSIST_QUEUE_ENTRY * pEntry, QUEUE_SIG Qsig = SIGNAL, QUEUE_POSITION Qpos = QUEUE_TAIL)
  191. {
  192. _ASSERT( pEntry != NULL);
  193. _ASSERT(m_ParentInst != NULL);
  194. //get the lock the protects the queue
  195. LockQ();
  196. //increment number of entries in the queue
  197. ++m_QData.Entries;
  198. //Insert into the list of mail contexts.
  199. if(Qpos == QUEUE_TAIL)
  200. {
  201. InsertTailList( &m_QHead, &pEntry->QueryListEntry());
  202. }
  203. else
  204. {
  205. InsertHeadList( &m_QHead, &pEntry->QueryListEntry());
  206. }
  207. if(Qsig == SIGNAL)
  208. SetEvent (m_QEvent);
  209. //release the lock and return
  210. UnLockQ();
  211. return TRUE;
  212. }
  213. /*++
  214. Name :
  215. PERSIST_QUEUE::RemoveEntry
  216. Description:
  217. This function deletes an entry from the queue
  218. Arguments:
  219. pEntry - Element to insert into the queue
  220. Returns:
  221. --*/
  222. void RemoveEntry(IN OUT PERSIST_QUEUE_ENTRY * pEntry)
  223. {
  224. _ASSERT( pEntry != NULL);
  225. _ASSERT(m_ParentInst != NULL);
  226. LockQ();
  227. //decrement number of entries in the queue
  228. --m_QData.Entries;
  229. // Remove from list of connections
  230. RemoveEntryList( &pEntry->QueryListEntry());
  231. UnLockQ();
  232. }
  233. };
  234. typedef PERSIST_QUEUE * PQUEUE;
  235. BOOL OpenQueueFile (char * FileName, char * InputBuffer, HANDLE* QFHandle, char * Sender);
  236. HANDLE GetDuplicateMailQHandle (HANDLE QFileHandle);
  237. #endif