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.

337 lines
8.5 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2001.
  5. //
  6. // File: ORCURSOR.CXX
  7. //
  8. // Contents: Merge Cursor. Computes union of multiple cursors.
  9. //
  10. // Classes: COrCursor
  11. //
  12. // History: 26-Sep-91 BartoszM Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <orcursor.hxx>
  18. #include <curstk.hxx>
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Member: COrCursor::COrCursor, public
  22. //
  23. // Synopsis: Create a sursor that merges a number of cursors.
  24. //
  25. // Arguments: [cCursor] -- count of cursors
  26. // [curStack] -- cursors to be merged
  27. //
  28. // History: 26-Sep-91 BartoszM Created
  29. // 14-Jul-92 KyleP Use max function for Rank
  30. // 22-Feb-93 KyleP Avoid divide-by-zero
  31. //
  32. // Notes: The cursors and the array will be deleted by destructor.
  33. // The cursors have to come from one index
  34. //
  35. //----------------------------------------------------------------------------
  36. COrCursor::COrCursor( int cCursor, CCurStack& curStack )
  37. : _lMaxWeight( 0 ), _iCur( 0 ), _wid( widInvalid )
  38. {
  39. // Two step construction of the heap.
  40. // We have to make sure that all cursors have a valid key
  41. int count = 0;
  42. CCursor** aCursor = curStack.AcqStack();
  43. // remove empty cursors
  44. for ( int i = 0; i < cCursor; i++ )
  45. {
  46. Win4Assert ( aCursor[i] != 0 );
  47. if ( aCursor[i]->WorkId() == widInvalid )
  48. {
  49. delete aCursor[i];
  50. }
  51. else
  52. {
  53. _lMaxWeight = max( _lMaxWeight, aCursor[i]->GetWeight() );
  54. if ( count != i )
  55. aCursor[count++] = aCursor[i];
  56. else
  57. count++;
  58. }
  59. }
  60. //
  61. // Avoid divide-by-zero
  62. //
  63. if ( _lMaxWeight == 0 )
  64. _lMaxWeight = 1;
  65. _widHeap.MakeHeap ( count, aCursor );
  66. if ( !_widHeap.IsEmpty() )
  67. {
  68. CCursor & cursor = * _widHeap.Top();
  69. _wid = cursor.WorkId();
  70. _iid = cursor.IndexId();
  71. _pid = cursor.Pid();
  72. }
  73. }
  74. //+---------------------------------------------------------------------------
  75. //
  76. // Member: COrCursor::WorkId, public
  77. //
  78. // Synopsis: Get current work id.
  79. //
  80. // History: 26-Sep-91 BartoszM Created
  81. //
  82. //----------------------------------------------------------------------------
  83. WORKID COrCursor::WorkId()
  84. {
  85. return _wid;
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Member: COrCursor::NextWorkId, public
  90. //
  91. // Synopsis: Move to next work id
  92. //
  93. // Returns: Target work id or widInvalid if no more wid's for current key
  94. //
  95. // History: 26-Sep-91 BartoszM Created
  96. //
  97. //----------------------------------------------------------------------------
  98. WORKID COrCursor::NextWorkId()
  99. {
  100. if ( widInvalid == _wid )
  101. return widInvalid;
  102. WORKID widNew;
  103. do
  104. {
  105. _widHeap.Top()->NextWorkId();
  106. _widHeap.ReheapKey();
  107. widNew = _widHeap.Top()->WorkId();
  108. }
  109. while ( widNew == _wid );
  110. _wid = widNew;
  111. return _wid;
  112. }
  113. //+---------------------------------------------------------------------------
  114. //
  115. // Member: COrCursor::WorkIdCount, public
  116. //
  117. // Synopsis: return wid count
  118. //
  119. // History: 26-Sep-91 BartoszM Created
  120. //
  121. // Notes: 1. Sum up wid count of all cursors in widHeap
  122. //
  123. //----------------------------------------------------------------------------
  124. ULONG COrCursor::WorkIdCount()
  125. {
  126. Win4Assert (( FALSE && "OrCursor::WorkIdCount called" ));
  127. return(0);
  128. }
  129. //+---------------------------------------------------------------------------
  130. //
  131. // Member: COrCursor::HitCount, public
  132. //
  133. // Synopsis: return occurrence count
  134. //
  135. // History: 28-Feb-92 AmyA Created
  136. //
  137. // Notes: returns the occurrence count for the wid on top of _widHeap.
  138. //
  139. //----------------------------------------------------------------------------
  140. ULONG COrCursor::HitCount()
  141. {
  142. if ( widInvalid == _wid )
  143. return 0;
  144. ULONG hitCnt = 0;
  145. CCursor **vector = _widHeap.GetVector();
  146. int count = _widHeap.Count();
  147. for (int i=0; i < count; i++)
  148. {
  149. if ( vector[i]->WorkId() == _wid )
  150. hitCnt += vector[i]->HitCount();
  151. }
  152. return hitCnt;
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Member: COrCursor::RatioFinished, public
  157. //
  158. // Synopsis: return approximate ratio of documents processed to total
  159. // documents.
  160. //
  161. // Notes: The ratio, while approximate, should not return 1/1 until
  162. // all cursors are exhausted.
  163. //
  164. //----------------------------------------------------------------------------
  165. void COrCursor::RatioFinished (ULONG& denom, ULONG& num)
  166. {
  167. if ( widInvalid == _wid )
  168. {
  169. denom = num = 1;
  170. return;
  171. }
  172. CCursor **vector = _widHeap.GetVector();
  173. int count = _widHeap.Count();
  174. unsigned cValid = 1;
  175. denom = 0;
  176. num = 0;
  177. for (int i=0; i < count; i++)
  178. {
  179. ULONG d, n;
  180. vector[i]->RatioFinished(d, n);
  181. Win4Assert( n <= d && d > 0 );
  182. num += n;
  183. denom += d;
  184. Win4Assert( d <= denom ); // overflow?
  185. if (n == d)
  186. {
  187. WORKID widCurrent = vector[i]->WorkId();
  188. if (widCurrent != widInvalid && widCurrent != _wid)
  189. cValid++;
  190. }
  191. }
  192. if (num == denom && cValid > 1)
  193. denom++;
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Member: COrCursor::Rank, public
  198. //
  199. // Synopsis: returns a rank (turns the OrCursor into a Quorum Cursor)
  200. //
  201. // History: 13-Apr-92 AmyA Created
  202. // 23-Jun-92 MikeHew Added Weighting
  203. // 14-Jul-92 KyleP Use max function for Rank
  204. //
  205. // Notes: See "Automatic Text Processing", G. Salton, 10.4.2 for
  206. // a discussion of the weight formula.
  207. //
  208. //----------------------------------------------------------------------------
  209. LONG COrCursor::Rank()
  210. {
  211. if ( widInvalid == _wid )
  212. return 0;
  213. LONG lRank = 0;
  214. CCursor **vector = _widHeap.GetVector();
  215. int cCur = _widHeap.Count();
  216. for ( int i = 0; i < cCur; i++ )
  217. {
  218. if ( vector[i]->WorkId() == _wid )
  219. {
  220. LONG lNew = vector[i]->Rank() * vector[i]->GetWeight();
  221. lRank = max( lRank, lNew );
  222. }
  223. }
  224. //
  225. // Normalize weight.
  226. //
  227. lRank = lRank / _lMaxWeight;
  228. return ( lRank );
  229. }
  230. //+---------------------------------------------------------------------------
  231. //
  232. // Member: COrCursor::Hit, public
  233. //
  234. // Synopsis: Hits current child (indexed by _iCur)
  235. // Moves onto next child if empty.
  236. //
  237. // History: 07-Sep-92 MikeHew Created
  238. //
  239. // Notes: Hit() should not be called more than once, except by
  240. // NextHit()
  241. //
  242. //----------------------------------------------------------------------------
  243. LONG COrCursor::Hit()
  244. {
  245. int cCur = _widHeap.Count();
  246. CCursor ** aCur = _widHeap.GetVector();
  247. Win4Assert( _iCur < cCur );
  248. LONG rank = aCur[_iCur]->Hit();
  249. // if this cursor is empty, find one that's not
  250. while ( rank == rankInvalid &&
  251. ++_iCur < cCur )
  252. {
  253. rank = aCur[_iCur]->Hit();
  254. }
  255. return rank;
  256. }
  257. //+---------------------------------------------------------------------------
  258. //
  259. // Member: COrCursor::NextHit, public
  260. //
  261. // Synopsis: NextHits current child (indexed by _iCur)
  262. // If current child becomes empty, increments _iCur
  263. //
  264. // History: 07-Sep-92 MikeHew Created
  265. //
  266. // Notes: NextHit() should not be called after returning rankInvalid
  267. //
  268. //----------------------------------------------------------------------------
  269. LONG COrCursor::NextHit()
  270. {
  271. int cCur = _widHeap.Count();
  272. CCursor ** aCur = _widHeap.GetVector();
  273. Win4Assert( _iCur < cCur );
  274. LONG rank = aCur[_iCur]->NextHit();
  275. if ( rank == rankInvalid )
  276. {
  277. if ( ++_iCur < cCur )
  278. {
  279. return Hit();
  280. }
  281. }
  282. return rank;
  283. }