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.

368 lines
9.3 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: PQueue.cxx
  7. //
  8. // Purpose: 'Pending' queue. Queue of pending notifications.
  9. //
  10. // Classes: CPendingQueue
  11. //
  12. // History: 30-Aug-95 KyleP Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include "pqueue.hxx"
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Member: CPendingQueue::CPendingQueue, public
  21. //
  22. // Synopsis: Constructor
  23. //
  24. // History: 01-Sep-95 KyleP Created
  25. //
  26. //----------------------------------------------------------------------------
  27. CPendingQueue::CPendingQueue()
  28. : _cUnique( 0 ),
  29. _iBottom( 0 ),
  30. _iTop( 0 ),
  31. _cDoc( 16 ),
  32. _aDoc(0)
  33. {
  34. _aDoc = new CPendingQueue::CDocItem[_cDoc];
  35. }
  36. //+---------------------------------------------------------------------------
  37. //
  38. // Member: CPendingQueue::~CPendingQueue, public
  39. //
  40. // Synopsis: Destructor
  41. //
  42. // History: 01-Sep-95 KyleP Created
  43. //
  44. //----------------------------------------------------------------------------
  45. CPendingQueue::~CPendingQueue()
  46. {
  47. Win4Assert( 0 == _iTop );
  48. delete [] _aDoc;
  49. }
  50. //+---------------------------------------------------------------------------
  51. //
  52. // Member: CPendingQueue::LokPrepare, public
  53. //
  54. // Synopsis: Allocate queue entry (to be filled in later).
  55. //
  56. // Arguments: [workid] -- Workid of entry
  57. //
  58. // Returns: Unique identifier for this entry.
  59. //
  60. // History: 01-Sep-95 KyleP Created
  61. //
  62. //----------------------------------------------------------------------------
  63. unsigned CPendingQueue::LokPrepare( WORKID wid )
  64. {
  65. //
  66. // May have to grow the array. This is a very rare operation.
  67. //
  68. if ( _iTop == _cDoc )
  69. {
  70. CPendingQueue::CDocItem * pTemp = _aDoc;
  71. #if CIDBG==1
  72. if ( _iTop >= 128 )
  73. {
  74. ciDebugOut(( DEB_WARN,
  75. "Too many active threads (0x%X) in cleanup\n", _iTop ));
  76. }
  77. #endif // CIDBG==1
  78. _cDoc *= 2;
  79. _aDoc = new CPendingQueue::CDocItem[_cDoc];
  80. RtlCopyMemory( _aDoc, pTemp, _cDoc / 2 * sizeof(_aDoc[0]) );
  81. delete [] pTemp;
  82. }
  83. unsigned iHint = _iTop;
  84. _aDoc[_iTop].wid = wid;
  85. _aDoc[_iTop].hint = _cUnique++;
  86. _aDoc[_iTop].fComplete = FALSE;
  87. _iTop++;
  88. return _aDoc[_iTop-1].hint;
  89. }
  90. //+---------------------------------------------------------------------------
  91. //
  92. // Member: CPendingQueue::LokComplete, public
  93. //
  94. // Synopsis: Fill in pre-reserved queue entry
  95. //
  96. // Arguments: [iHint] -- Unique id of entry.
  97. // [wid] -- Workid of entry.
  98. // [usn] -- USN.
  99. // [volumeId] -- Volume id
  100. // [partid] -- Partition Id
  101. // [action] -- Update/Delete
  102. //
  103. // Returns: TRUE if queue was empty except for this entry. Means this
  104. // entry wasn't added (and can be processed now). FALSE means
  105. // CPendingQueue::Remove must be called directly following return
  106. // from Complete.
  107. //
  108. // History: 01-Sep-95 KyleP Created
  109. //
  110. //----------------------------------------------------------------------------
  111. BOOL CPendingQueue::LokComplete( unsigned iHint,
  112. WORKID wid,
  113. USN usn,
  114. VOLUMEID volumeId,
  115. PARTITIONID partid,
  116. ULONG action )
  117. {
  118. if ( ULONG_MAX == iHint )
  119. {
  120. //
  121. // Special case for scan-update documents. There is no need for
  122. // preserving order of updates.
  123. //
  124. return TRUE;
  125. }
  126. Win4Assert( _iBottom == 0 );
  127. Win4Assert( _iTop > 0 );
  128. //
  129. // Special case: If this is the only pending document then don't bother to fill
  130. // in the struct, only to pull the values out. Remember, this is
  131. // called from Cleanup. Speed counts.
  132. //
  133. if( _iTop == 1 )
  134. {
  135. Win4Assert( _aDoc[0].wid == wid );
  136. Win4Assert( _aDoc[0].hint == iHint );
  137. _iTop--;
  138. return TRUE;
  139. }
  140. //
  141. // The entry may have moved down, but never up the queue.
  142. //
  143. for ( unsigned i = 0; _aDoc[i].hint != iHint; i++ )
  144. {
  145. Win4Assert( i < _iTop );
  146. continue; // NULL body
  147. }
  148. Win4Assert( _aDoc[i].wid == wid );
  149. _aDoc[i].usn = usn;
  150. _aDoc[i].volumeId = volumeId;
  151. _aDoc[i].partid = partid;
  152. _aDoc[i].action = action;
  153. _aDoc[i].fComplete = TRUE;
  154. return FALSE;
  155. }
  156. //+---------------------------------------------------------------------------
  157. //
  158. // Member: CPendingQueue::LokRemove, public
  159. //
  160. // Synopsis: Pop a completed entry from queue.
  161. //
  162. // Arguments: [wid] -- Workid of entry returned here.
  163. // [usn] -- USN returned here.
  164. // [volumeId] -- Volume id
  165. // [partid] -- Partition Id returned here.
  166. // [action] -- Update/Delete returned here.
  167. //
  168. // Returns: TRUE if an entry was available for removal. FALSE is queue
  169. // was empty, or bottom entry was not complete.
  170. //
  171. // History: 01-Sep-95 KyleP Created
  172. //
  173. //----------------------------------------------------------------------------
  174. BOOL CPendingQueue::LokRemove( WORKID & wid,
  175. USN & usn,
  176. VOLUMEID& volumeId,
  177. PARTITIONID & partid,
  178. ULONG & action )
  179. {
  180. //
  181. // All done. Empty queue.
  182. //
  183. if ( _iBottom == _iTop )
  184. {
  185. _iBottom = 0;
  186. _iTop = 0;
  187. return FALSE;
  188. }
  189. //
  190. // Out of completed entries.
  191. //
  192. if ( !_aDoc[_iBottom].fComplete )
  193. {
  194. RtlMoveMemory( _aDoc, &_aDoc[_iBottom], (_iTop - _iBottom) * sizeof(_aDoc[0]) );
  195. _iTop -= _iBottom;
  196. _iBottom = 0;
  197. return FALSE;
  198. }
  199. //
  200. // Got something!
  201. //
  202. wid = _aDoc[_iBottom].wid;
  203. usn = _aDoc[_iBottom].usn;
  204. volumeId = _aDoc[_iBottom].volumeId;
  205. partid = _aDoc[_iBottom].partid;
  206. action = _aDoc[_iBottom].action;
  207. _iBottom++;
  208. return TRUE;
  209. }
  210. //+---------------------------------------------------------------------------
  211. //
  212. // Member: CPendingQueue::LokCountCompleted, public
  213. //
  214. // Returns: Count of completed entries in queue.
  215. //
  216. // History: 01-Sep-95 KyleP Created
  217. //
  218. //----------------------------------------------------------------------------
  219. unsigned CPendingQueue::LokCountCompleted()
  220. {
  221. Win4Assert( _iBottom == 0 );
  222. unsigned cComplete = 0;
  223. for ( unsigned i = 0; i < _iTop; i++ )
  224. {
  225. if ( _aDoc[i].fComplete )
  226. cComplete++;
  227. }
  228. return cComplete;
  229. }
  230. //+---------------------------------------------------------------------------
  231. //
  232. // Member: CPendingQueue::LokGetCompleted, public
  233. //
  234. // Synopsis: Fetch wids of completed entries.
  235. //
  236. // Arguments: [awid] -- Wids returned here.
  237. //
  238. // History: 01-Sep-95 KyleP Created
  239. //
  240. // Notes: Assumes [awid] is big enough to hold CountCompleted() wids.
  241. //
  242. //----------------------------------------------------------------------------
  243. void CPendingQueue::LokGetCompleted( WORKID * awid )
  244. {
  245. Win4Assert( _iBottom == 0 );
  246. for ( unsigned i = 0; i < _iTop; i++ )
  247. {
  248. if ( _aDoc[i].fComplete )
  249. {
  250. *awid = _aDoc[i].wid;
  251. awid++;
  252. }
  253. }
  254. }
  255. //+---------------------------------------------------------------------------
  256. //
  257. // Member: CPendingQueue::LokFlushCompletedEntries
  258. //
  259. // Synopsis: Flushes any completed entries in the pending queue.
  260. //
  261. // History: 9-11-95 srikants Created
  262. //
  263. // Notes: Called as a result of an exception while removing the
  264. // entries.
  265. //
  266. // The "Incomplete" entries will get cleaned up as part of
  267. // the "UpdateDocument" calls from cleanup.
  268. //
  269. //----------------------------------------------------------------------------
  270. void CPendingQueue::LokFlushCompletedEntries()
  271. {
  272. ciDebugOut(( DEB_WARN,
  273. "CPendingQueue::Flushing Entries _iBottom=0x%X _iTop=0x%X\n",
  274. _iBottom, _iTop ));
  275. Win4Assert( 0 == _iBottom || _iBottom <= _iTop );
  276. while ( _iBottom < _iTop && _aDoc[_iBottom].fComplete )
  277. _iBottom++;
  278. if ( _iBottom == _iTop )
  279. {
  280. _iBottom = _iTop = 0;
  281. }
  282. else
  283. {
  284. RtlMoveMemory( _aDoc, &_aDoc[_iBottom], (_iTop - _iBottom) * sizeof(_aDoc[0]) );
  285. _iTop -= _iBottom;
  286. _iBottom = 0;
  287. }
  288. return;
  289. }
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Member: CPendingQueue::LokFlushAllEntries
  293. //
  294. // Synopsis: Flushes all entries in the pending queue.
  295. //
  296. // History: 06-10-95 KyleP Created
  297. //
  298. // Notes: Used during restart, after a call to EnableUsnUpdate.
  299. //
  300. //----------------------------------------------------------------------------
  301. void CPendingQueue::LokFlushAllEntries()
  302. {
  303. ciDebugOut(( DEB_WARN,
  304. "CPendingQueue::Flushing All Entries _iBottom=0x%X _iTop=0x%X\n",
  305. _iBottom, _iTop ));
  306. Win4Assert( 0 == _iBottom || _iBottom < _iTop );
  307. _iBottom = 0;
  308. _iTop = 0;
  309. _cUnique = 0;
  310. return;
  311. }