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.

352 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1997.
  5. //
  6. // File: PMComp.cxx
  7. //
  8. // Contents: Persistent index decompressor using during master merge
  9. //
  10. // Classes: CMPersDeComp
  11. //
  12. // History: 21-Apr-94 DwightKr Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include "mindex.hxx"
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Function: CMPersDeComp::CMPersDeComp
  21. //
  22. // Synopsis: Constructor for the persistent compressor capable of dealing
  23. // with two indexes representing the master index. This will
  24. // allow queries to transparently span both indexes.
  25. //
  26. // Arguments: [curDir] -- directory for the current (old) master index
  27. // [curIid] -- index Id of the current (old) master index
  28. // [curIndex] -- physical index of the current (old) master index
  29. // [newDir] -- directory for the new master index
  30. // [newIid] -- index Id of the new master index
  31. // [pKey] -- starting key to look for
  32. // [widMax] -- maximum workid in the new master index
  33. // [splitKey] -- key which seperates current & new master index
  34. // [mutex] -- mutex to control access to dirs during merge
  35. //
  36. // History: 4-10-94 DwightKr Created
  37. //
  38. //----------------------------------------------------------------------------
  39. CMPersDeComp::CMPersDeComp(
  40. PDirectory & curDir,
  41. INDEXID curIid,
  42. CPhysIndex & curIndex,
  43. WORKID curWidMax,
  44. PDirectory & newDir,
  45. INDEXID newIid,
  46. CPhysIndex & newIndex,
  47. const CKey * pKey,
  48. WORKID newWidMax,
  49. const CSplitKeyInfo & splitKeyInfo,
  50. CMutexSem & mutex ) :
  51. CKeyCursor(curIid, 0),
  52. _curDir(curDir),
  53. _curIid(curIid),
  54. _curIndex(curIndex),
  55. _curWidMax(curWidMax),
  56. _newDir(newDir),
  57. _newIid(newIid),
  58. _newIndex(newIndex),
  59. _newWidMax(newWidMax),
  60. _splitKeyInfo(splitKeyInfo),
  61. _pActiveCursor(0),
  62. _fUseNewIndex(FALSE),
  63. _mutex(mutex),
  64. _lastSplitKeyBuf( splitKeyInfo.GetKey() )
  65. {
  66. //
  67. // Note that _mutex is currently held when this constructor is called.
  68. //
  69. // Determine which index the query should start in. If the key is
  70. // less than or equal to the splitkey, start in the new master index.
  71. // Otherwise start in the current (old) master index.
  72. //
  73. BitOffset posKey;
  74. CKeyBuf keyInit;
  75. if ( pKey->Compare( _lastSplitKeyBuf ) <= 0 )
  76. {
  77. //
  78. // Save the offset of the splitKey so that the NextKey() operation
  79. // can quickly determine if we are about to fall off the logical
  80. // end of the index.
  81. //
  82. _newDir.Seek( _lastSplitKeyBuf, 0, _lastSplitKeyOffset );
  83. ciDebugOut(( DEB_PCOMP,
  84. "Constructor: splitkey '%.*ws' offset = 0x%x:0x%x\n",
  85. _lastSplitKeyBuf.StrLen(), _lastSplitKeyBuf.GetStr(),
  86. _lastSplitKeyOffset.Page(), _lastSplitKeyOffset.Offset() ));
  87. _fUseNewIndex = TRUE;
  88. _newDir.Seek( *pKey, &keyInit, posKey );
  89. _widMax = _newWidMax;
  90. _pActiveCursor = new CPersDeComp( _newDir, _newIid, _newIndex,
  91. posKey, keyInit,
  92. pKey, _newWidMax);
  93. }
  94. else
  95. {
  96. _curDir.Seek( *pKey, &keyInit, posKey );
  97. _widMax = _curWidMax;
  98. _pActiveCursor = new CPersDeComp( _curDir, _curIid, _curIndex,
  99. posKey, keyInit,
  100. pKey, _curWidMax );
  101. }
  102. // Update weights so Rank can be computed
  103. UpdateWeight();
  104. ciDebugOut(( DEB_PCOMP, "found key %.*ws at %lx:%lx\n",
  105. keyInit.StrLen(), keyInit.GetStr(),
  106. posKey.Page(), posKey.Offset() ));
  107. } //CMPersDeComp
  108. //+---------------------------------------------------------------------------
  109. //----------------------------------------------------------------------------
  110. CMPersDeComp::~CMPersDeComp()
  111. {
  112. delete _pActiveCursor;
  113. }
  114. //+---------------------------------------------------------------------------
  115. //----------------------------------------------------------------------------
  116. const CKeyBuf * CMPersDeComp::GetKey()
  117. {
  118. Win4Assert( _pActiveCursor );
  119. return _pActiveCursor->GetKey();
  120. }
  121. //+---------------------------------------------------------------------------
  122. //
  123. // Function: CMPersDeComp::GetNextKey()
  124. //
  125. // Synopsis: Obtains the next key from the logical master index.
  126. //
  127. // History: 4-10-94 DwightKr Created
  128. //
  129. // Notes: If we are using the new master index, and the current
  130. // key is the split key, then we have exhausted the new
  131. // master index, and the GetNextKey() operation should
  132. // transparently move to the current master index.
  133. //
  134. // We are comparing BitOffset's here rather than keys
  135. // because it is simplear and faster.
  136. //
  137. //----------------------------------------------------------------------------
  138. const CKeyBuf * CMPersDeComp::GetNextKey()
  139. {
  140. Win4Assert( _pActiveCursor );
  141. //
  142. // Grab the lock to protect access to split key info and the buffers
  143. // in the old index (so the master merge doesn't do a checkpoint
  144. // until after we create a cursor or move the cursor from one page to
  145. // the next. This is really expensive.
  146. //
  147. CLock lock( _mutex );
  148. //
  149. // If we are already using the old master index, then we don't need to
  150. // check the splitkey since we have already crossed over to the old index.
  151. //
  152. if ( !_fUseNewIndex )
  153. return _pActiveCursor->GetNextKey();
  154. //
  155. // We are using the new master index. If we are positioned at the split
  156. // key, the subsequent nextKey() operation will need to take us to
  157. // the old index. Determine if we are about to cross between indexes.
  158. //
  159. BitOffset currentKeyOffset;
  160. _pActiveCursor->GetOffset( currentKeyOffset );
  161. ciDebugOut(( DEB_PCOMP,
  162. "NextKey: splitkey offset = 0x%x:0x%x currentKeyOffset = 0x%x:0x%x\n",
  163. _lastSplitKeyOffset.Page(), _lastSplitKeyOffset.Offset(),
  164. currentKeyOffset.Page(), currentKeyOffset.Offset() ));
  165. if ( _lastSplitKeyOffset > currentKeyOffset )
  166. {
  167. const CKeyBuf *p = _pActiveCursor->GetNextKey();
  168. #if CIDBG == 1
  169. BitOffset boCur;
  170. _pActiveCursor->GetOffset( boCur );
  171. ciDebugOut(( DEB_PCOMP,
  172. "GetNextKey from new index = %.*ws offset = 0x%x:0x%x\n",
  173. p->StrLen(), p->GetStr(),
  174. boCur.Page(), boCur.Offset() ));
  175. #endif // CIDBG == 1
  176. return p;
  177. }
  178. //
  179. // We MAY have crossed over from the new index to the old index.
  180. // Check to see if the split key has moved to verify.
  181. //
  182. if ( !AreEqual( & _lastSplitKeyBuf, & (_splitKeyInfo.GetKey()) ) )
  183. {
  184. _lastSplitKeyBuf = _splitKeyInfo.GetKey();
  185. _newDir.Seek( _lastSplitKeyBuf, 0, _lastSplitKeyOffset );
  186. //
  187. // Check to see if we can continue using the new index since
  188. // the split key has moved.
  189. //
  190. if ( _lastSplitKeyOffset > currentKeyOffset )
  191. {
  192. ciDebugOut(( DEB_PCOMP, "sticking with new index due to split\n" ));
  193. return _pActiveCursor->GetNextKey();
  194. }
  195. }
  196. ciDebugOut(( DEB_PCOMP, "switching to old index given split key %.*ws\n",
  197. _lastSplitKeyBuf.StrLen(), _lastSplitKeyBuf.GetStr() ));
  198. //
  199. // Rebuild the key decompressor to point to the old index on the smallest
  200. // key >= the split key
  201. //
  202. _fUseNewIndex = FALSE;
  203. delete _pActiveCursor;
  204. _pActiveCursor = 0;
  205. BitOffset posKey;
  206. CKeyBuf keyInit;
  207. _curDir.Seek( _lastSplitKeyBuf, &keyInit, posKey );
  208. int iCompare = Compare( &keyInit, &_lastSplitKeyBuf );
  209. // If the split key isn't in the old index, use the next key
  210. if ( iCompare < 0 )
  211. _curDir.SeekNext( _lastSplitKeyBuf, &keyInit, posKey );
  212. ciDebugOut(( DEB_PCOMP, "found key >= (%d) split key = %.*ws at %lx:%lx\n",
  213. iCompare,
  214. keyInit.StrLen(), keyInit.GetStr(),
  215. posKey.Page(), posKey.Offset() ));
  216. // If we're out of keys then say so.
  217. if ( keyInit.IsMaxKey() )
  218. {
  219. ciDebugOut(( DEB_WARN, "at the end of the old index...\n" ));
  220. return 0;
  221. }
  222. _widMax = _curWidMax;
  223. CKey Key( keyInit );
  224. _pActiveCursor = new CPersDeComp( _curDir, _curIid, _curIndex,
  225. posKey, keyInit,
  226. &Key, _curWidMax );
  227. return _pActiveCursor->GetNextKey();
  228. } //GetNextKey
  229. //+---------------------------------------------------------------------------
  230. //----------------------------------------------------------------------------
  231. const CKeyBuf * CMPersDeComp::GetNextKey( BitOffset * pBitOff )
  232. {
  233. Win4Assert( _pActiveCursor );
  234. return _pActiveCursor->GetNextKey( pBitOff );
  235. }
  236. //+---------------------------------------------------------------------------
  237. //----------------------------------------------------------------------------
  238. WORKID CMPersDeComp::WorkId()
  239. {
  240. Win4Assert( _pActiveCursor );
  241. return _pActiveCursor->WorkId();
  242. }
  243. //+---------------------------------------------------------------------------
  244. //----------------------------------------------------------------------------
  245. WORKID CMPersDeComp::NextWorkId()
  246. {
  247. Win4Assert( _pActiveCursor );
  248. return _pActiveCursor->NextWorkId();
  249. }
  250. //+---------------------------------------------------------------------------
  251. //----------------------------------------------------------------------------
  252. ULONG CMPersDeComp::WorkIdCount()
  253. {
  254. Win4Assert( _pActiveCursor );
  255. return _pActiveCursor->WorkIdCount();
  256. }
  257. //+---------------------------------------------------------------------------
  258. //----------------------------------------------------------------------------
  259. OCCURRENCE CMPersDeComp::Occurrence()
  260. {
  261. Win4Assert( _pActiveCursor );
  262. return _pActiveCursor->Occurrence();
  263. }
  264. //+---------------------------------------------------------------------------
  265. //----------------------------------------------------------------------------
  266. OCCURRENCE CMPersDeComp::NextOccurrence()
  267. {
  268. Win4Assert( _pActiveCursor );
  269. return _pActiveCursor->NextOccurrence();
  270. }
  271. //+---------------------------------------------------------------------------
  272. //----------------------------------------------------------------------------
  273. OCCURRENCE CMPersDeComp::MaxOccurrence()
  274. {
  275. Win4Assert( _pActiveCursor );
  276. return _pActiveCursor->MaxOccurrence();
  277. }
  278. //+---------------------------------------------------------------------------
  279. //----------------------------------------------------------------------------
  280. ULONG CMPersDeComp::OccurrenceCount()
  281. {
  282. Win4Assert( _pActiveCursor );
  283. return _pActiveCursor->OccurrenceCount();
  284. }
  285. //+---------------------------------------------------------------------------
  286. //----------------------------------------------------------------------------
  287. ULONG CMPersDeComp::HitCount()
  288. {
  289. Win4Assert( _pActiveCursor );
  290. return _pActiveCursor->HitCount();
  291. }