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.

373 lines
9.5 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1998
  5. //
  6. // File: RowHeap.cxx
  7. //
  8. // Contents: Heap of rowsets.
  9. //
  10. // Classes: CRowHeap
  11. //
  12. // History: 05-Jun-95 KyleP Created
  13. // 14-JAN-97 KrishnaN Undefined CI_INETSRV and related changes
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. #include "rowheap.hxx"
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Member: CRowHeap::CRowHeap, public
  22. //
  23. // Synopsis: Constructor.
  24. //
  25. // Arguments: [cCursor] -- Max number of elements in heap.
  26. //
  27. // History: 05-Jun-95 KyleP Created.
  28. //
  29. //----------------------------------------------------------------------------
  30. CRowHeap::CRowHeap( unsigned cCursor )
  31. : _ahrowTop( cCursor ),
  32. _cCursor( cCursor )
  33. {
  34. END_CONSTRUCTION( CRowHeap );
  35. }
  36. //+---------------------------------------------------------------------------
  37. //
  38. // Member: CRowHeap::Init, public
  39. //
  40. // Synopsis: Create heap.
  41. //
  42. // Arguments: [pComparator] -- Used to compare elements.
  43. // [apCursor] -- Heap created from these.
  44. //
  45. // History: 05-Jun-95 KyleP Created.
  46. //
  47. //----------------------------------------------------------------------------
  48. void CRowHeap::Init( CRowComparator * pComparator,
  49. PMiniRowCache ** apCursor )
  50. {
  51. _pComparator = pComparator;
  52. _apCursor = apCursor;
  53. //
  54. // Move invalid cursors to end.
  55. //
  56. int cValid = _cCursor;
  57. for ( int i = 0; i < cValid; i++ )
  58. {
  59. if ( _apCursor[i]->IsAtEnd() )
  60. {
  61. cValid--;
  62. PMiniRowCache * pTemp = _apCursor[i];
  63. _apCursor[i] = _apCursor[cValid];
  64. _apCursor[cValid] = pTemp;
  65. i--;
  66. }
  67. }
  68. //
  69. // And create a heap out of the rest.
  70. //
  71. MakeHeap( cValid );
  72. }
  73. //+---------------------------------------------------------------------------
  74. //
  75. // Member: CRowHeap::ReInit, public
  76. //
  77. // Synopsis: Recreate heap.
  78. //
  79. // Arguments: [cValid] -- Number of valid cursors. Others to end.
  80. //
  81. // History: 05-Jun-95 KyleP Created.
  82. //
  83. //----------------------------------------------------------------------------
  84. void CRowHeap::ReInit( int cValid )
  85. {
  86. MakeHeap( cValid );
  87. }
  88. //+---------------------------------------------------------------------------
  89. //
  90. // Member: CRowHeap::Validate, public
  91. //
  92. // Synopsis: See notes.
  93. //
  94. // Returns: State of heap.
  95. //
  96. // History: 05-Jun-95 KyleP Created.
  97. //
  98. // Notes: There are times when iteration stopped because some cursor
  99. // couldn't continue (usually for block-limited rows, or
  100. // some error condition). When this situation occurs, Validate
  101. // must be called to reset the heap.
  102. //
  103. //----------------------------------------------------------------------------
  104. PMiniRowCache::ENext CRowHeap::Validate()
  105. {
  106. if ( !IsHeapEmpty() && Top()->IsAtEnd() )
  107. return Next();
  108. else
  109. return PMiniRowCache::Ok;
  110. }
  111. //+---------------------------------------------------------------------------
  112. //
  113. // Member: CRowHeap::AdjustCacheSize, public
  114. //
  115. // Synopsis: Adjust size of row cache(s).
  116. //
  117. // Arguments: [cRows] -- Total number of rows to cache.
  118. //
  119. // History: 05-Jun-95 KyleP Created.
  120. //
  121. //----------------------------------------------------------------------------
  122. void CRowHeap::AdjustCacheSize( ULONG cRows )
  123. {
  124. if ( Count() > 0 )
  125. {
  126. ULONG cRowsPerCursor = 1 + cRows / Count();
  127. if ( cRowsPerCursor != Top()->CacheSize() )
  128. {
  129. for ( int i = 0; i < _cCursor; i++ )
  130. _apCursor[i]->SetCacheSize( cRowsPerCursor );
  131. }
  132. }
  133. }
  134. //+---------------------------------------------------------------------------
  135. //
  136. // Member: CRowHeap::Next, public
  137. //
  138. // Synopsis: Move to next element.
  139. //
  140. // Returns: State of heap. Move occurred only if PMiniRowCache::Ok.
  141. //
  142. // History: 05-Jun-95 KyleP Created.
  143. //
  144. //----------------------------------------------------------------------------
  145. PMiniRowCache::ENext CRowHeap::Next( int iDir /* = 1 */ )
  146. {
  147. PMiniRowCache::ENext next = Top()->Next( iDir );
  148. if ( PMiniRowCache::NotNow == next )
  149. return next;
  150. if ( PMiniRowCache::EndOfRows == next )
  151. {
  152. RemoveTop();
  153. if ( IsHeapEmpty() )
  154. return next;
  155. next = PMiniRowCache::Ok;
  156. }
  157. _ahrowTop[Top()->Index()] = Top()->GetHROW();
  158. Reheap();
  159. return next;
  160. }
  161. //+---------------------------------------------------------------------------
  162. //
  163. // Member: CRowHeap::NthToTop, public
  164. //
  165. // Effects: Moves Nth element of heap to top.
  166. //
  167. // Arguments: [n] -- Nth element of heap.
  168. //
  169. // History: 23-Jun-95 KyleP Created.
  170. //
  171. // Notes: This is different from CRowHeap::Next, because the caches
  172. // themselves are not touched. It is used for approximate
  173. // positioning.
  174. //
  175. // This is a destructive function! Elements are removed from
  176. // the heap.
  177. //
  178. //----------------------------------------------------------------------------
  179. void CRowHeap::NthToTop( unsigned n )
  180. {
  181. for ( ; n > 0; n-- )
  182. {
  183. RemoveTop();
  184. Reheap();
  185. }
  186. }
  187. //+---------------------------------------------------------------------------
  188. //
  189. // Member: CRowHeap::Add, public
  190. //
  191. // Synopsis: Add element to heap.
  192. //
  193. // Arguments: [pCursor] -- Cursor to add.
  194. //
  195. // History: 05-Jun-95 KyleP Created.
  196. //
  197. //----------------------------------------------------------------------------
  198. void CRowHeap::Add( PMiniRowCache * pCursor )
  199. {
  200. //
  201. // Special case: empty cursor.
  202. //
  203. if ( pCursor->IsAtEnd() )
  204. {
  205. _ahrowTop[pCursor->Index()] = (HROW)-1;
  206. return;
  207. }
  208. _iEnd++;
  209. _ahrowTop[pCursor->Index()] = pCursor->GetHROW();
  210. //
  211. // Special case: empty heap.
  212. //
  213. if ( 0 == _iEnd )
  214. {
  215. _apCursor[0] = pCursor;
  216. return;
  217. }
  218. int child, parent;
  219. for ( child = _iEnd, parent = (_iEnd-1)/2;
  220. child > 0;
  221. child=parent, parent = (parent-1)/2)
  222. {
  223. if ( !_pComparator->IsLT( pCursor->GetData(),
  224. pCursor->DataLength(),
  225. pCursor->Index(),
  226. _apCursor[parent]->GetData(),
  227. _apCursor[parent]->DataLength(),
  228. _apCursor[parent]->Index() ) )
  229. break;
  230. _apCursor[child] = _apCursor[parent];
  231. }
  232. _apCursor[child] = pCursor;
  233. }
  234. //+---------------------------------------------------------------------------
  235. //
  236. // Member: CRowHeap::Reheap, private
  237. //
  238. // Synopsis: 'Heapify'. Called when top element (only!) has changed.
  239. //
  240. // History: 05-Jun-95 KyleP Created.
  241. //
  242. //----------------------------------------------------------------------------
  243. void CRowHeap::Reheap()
  244. {
  245. PMiniRowCache * root_item = _apCursor[0];
  246. int parent, child;
  247. for ( parent = 0, child = 1;
  248. child <= _iEnd;
  249. parent = child, child = 2 * child + 1 )
  250. {
  251. if ( child < _iEnd &&
  252. _pComparator->IsLT( _apCursor[child+1]->GetData(),
  253. _apCursor[child+1]->DataLength(),
  254. _apCursor[child+1]->Index(),
  255. _apCursor[child]->GetData(),
  256. _apCursor[child]->DataLength(),
  257. _apCursor[child]->Index() ) )
  258. {
  259. child++;
  260. }
  261. if ( !_pComparator->IsLT( _apCursor[child]->GetData(),
  262. _apCursor[child]->DataLength(),
  263. _apCursor[child]->Index(),
  264. root_item->GetData(),
  265. root_item->DataLength(),
  266. root_item->Index() ) )
  267. {
  268. break;
  269. }
  270. _apCursor[parent] = _apCursor[child];
  271. }
  272. _apCursor[parent] = root_item;
  273. # if CIDBG == 1
  274. AssertCursorArrayIsValid();
  275. # endif
  276. }
  277. //+---------------------------------------------------------------------------
  278. //
  279. // Member: CRowHeap::MakeHeap, private
  280. //
  281. // Synopsis: 'Heapify'. Called when all elements have changed.
  282. //
  283. // Arguments: [cValid] -- Number of valid cursors, all positioned toward
  284. // beginning of array.
  285. //
  286. // History: 05-Jun-95 KyleP Created.
  287. //
  288. //----------------------------------------------------------------------------
  289. void CRowHeap::MakeHeap( int cValid )
  290. {
  291. _iEnd = -1;
  292. for ( int i = 0; i < cValid; i++ )
  293. Add( _apCursor[i] );
  294. for ( i = cValid; i < _cCursor; i++ )
  295. _ahrowTop[_apCursor[i]->Index()] = (HROW)-1;
  296. # if CIDBG == 1
  297. AssertCursorArrayIsValid();
  298. # endif
  299. }
  300. #if CIDBG == 1
  301. void CRowHeap::AssertCursorArrayIsValid()
  302. {
  303. for ( int i = 0; i < _cCursor; i++ )
  304. for ( int j = i+1; j < _cCursor; j++ )
  305. {
  306. if ( _apCursor[i] == _apCursor[j] )
  307. {
  308. vqDebugOut(( DEB_ERROR,
  309. "Invalid rowheap: _apCursor[%d] (0x%x) == _apCursor[%d] (0x%x)\n",
  310. i, _apCursor[i],
  311. j, _apCursor[j] ));
  312. Win4Assert( _apCursor[i] != _apCursor[j] );
  313. }
  314. }
  315. }
  316. #endif // CIDBG == 1