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.

556 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 2000.
  5. //
  6. // File: tblbuket.cxx
  7. //
  8. // Contents: Implementation of the bucket in large table.
  9. //
  10. // Classes: CTableBucket
  11. // CBucketRowIter
  12. // CBucketRowCompare
  13. //
  14. // History: 2-14-95 srikants Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "pch.cxx"
  18. #pragma hdrstop
  19. #include <query.hxx>
  20. #include <objcur.hxx>
  21. #include "tblbuket.hxx"
  22. #include "tabledbg.hxx"
  23. #include "tblwindo.hxx"
  24. #include "colcompr.hxx"
  25. //+---------------------------------------------------------------------------
  26. //
  27. // Function: CTableBucket constructor
  28. //
  29. // Arguments: [pSortSet] - Pointer to the sort set.
  30. // [masterColSet] - Reference tot he master column set.
  31. // [segId] - Segment Id of the this segment
  32. //
  33. // History: 2-15-95 srikants Created
  34. //
  35. // Notes:
  36. //
  37. //----------------------------------------------------------------------------
  38. CTableBucket::CTableBucket( CSortSet const & sortSet,
  39. CTableKeyCompare & comparator,
  40. CColumnMasterSet & masterColSet,
  41. ULONG segId )
  42. : CTableSegment( CTableSegment::eBucket, segId, sortSet, comparator ),
  43. _minWid(0), _maxWid(0),
  44. _fSorted(TRUE),
  45. _widArray( CTableSegment::cBucketRowLimit+20 )
  46. ,_pLargeTable(0)
  47. {
  48. _fStoreRank = ( 0 != masterColSet.Find( pidRank ) );
  49. _fStoreHitCount = ( 0 != masterColSet.Find( pidHitCount ) );
  50. CColumnMasterDesc * pDesc = masterColSet.Find(pidPath);
  51. _pPathCompressor = pDesc ? pDesc->GetCompressor() : 0;
  52. }
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Function: PutRow
  56. //
  57. // Synopsis: Add/Replaces a row in the bucket
  58. //
  59. // Arguments: [obj] - Reference to the retriever for the row
  60. // [eRowType] - Type of the row.
  61. //
  62. // Returns: FALSE always (why?)
  63. //
  64. // History: 2-15-95 srikants Created
  65. //
  66. // Notes:
  67. //
  68. //----------------------------------------------------------------------------
  69. BOOL CTableBucket::PutRow( CRetriever & obj, CTableRowKey & currKey )
  70. {
  71. WORKID wid = obj.WorkId();
  72. PROPVARIANT vRank;
  73. if ( _fStoreRank )
  74. {
  75. ULONG cbRank = sizeof vRank;
  76. obj.GetPropertyValue( pidRank, &vRank, &cbRank );
  77. Win4Assert( VT_I4 == vRank.vt );
  78. }
  79. PROPVARIANT vHitCount;
  80. if ( _fStoreHitCount )
  81. {
  82. ULONG cbHitCount = sizeof vHitCount;
  83. obj.GetPropertyValue( pidHitCount, &vHitCount, &cbHitCount );
  84. Win4Assert( VT_I4 == vHitCount.vt );
  85. }
  86. BOOL fNew = _AddWorkId( wid, vRank.lVal, vHitCount.lVal );
  87. // Update Low and High Keys
  88. currKey.MakeReady();
  89. if ( _comparator.Compare( currKey, _lowKey ) < 0 )
  90. _lowKey = currKey;
  91. int iCmp = _comparator.Compare( currKey, _highKey );
  92. if ( iCmp > 0 )
  93. _highKey = currKey;
  94. else if ( iCmp < 0 )
  95. _fSorted = FALSE;
  96. return FALSE;
  97. }
  98. //+---------------------------------------------------------------------------
  99. //
  100. // Function: _AddWorkId
  101. //
  102. // Synopsis: Add/Replace the given workid to the table. It appends the
  103. // new workid to the end of the widArray and updates the
  104. // hash table.
  105. //
  106. // Arguments: [wid] - The wid to be added.
  107. // [lRank] - Rank for the hit
  108. // [lHitCount] - HitCount for the hit
  109. //
  110. // Returns: TRUE if this is a brand new wid.
  111. // FALSE if the wid already existed.
  112. //
  113. // History: 2-15-95 srikants Created
  114. //
  115. // Notes:
  116. //
  117. //----------------------------------------------------------------------------
  118. BOOL CTableBucket::_AddWorkId(
  119. WORKID wid,
  120. LONG lRank,
  121. LONG lHitCount )
  122. {
  123. if ( 0 == _hTable.Count() )
  124. {
  125. _minWid = _maxWid = wid;
  126. }
  127. else if ( wid < _minWid )
  128. {
  129. _minWid = wid;
  130. }
  131. else if ( wid > _maxWid )
  132. {
  133. _maxWid = wid;
  134. }
  135. CWidValueHashEntry entry( wid );
  136. BOOL fFound = _hTable.LookUpWorkId( entry );
  137. if ( !fFound )
  138. {
  139. //
  140. // The wid doesn't already exist. We have to append it to
  141. // the end of the wid array
  142. //
  143. unsigned pos = _widArray.Count();
  144. _widArray.Add( wid, pos );
  145. entry.SetValue( pos );
  146. if ( _fStoreRank )
  147. _aRank[ pos ] = lRank;
  148. if ( _fStoreHitCount )
  149. _aHitCount[ pos ] = lHitCount;
  150. //
  151. // Add the workid to the hash table.
  152. //
  153. _hTable.AddEntry( entry );
  154. }
  155. else
  156. {
  157. Win4Assert( entry.Value() < _widArray.Size() );
  158. Win4Assert( _widArray.Get( entry.Value() ) == wid );
  159. }
  160. return !fFound;
  161. }
  162. //+---------------------------------------------------------------------------
  163. //
  164. // Function: RemoveRow
  165. //
  166. // Synopsis: Removes the specified row (if present) from the table.
  167. //
  168. // Arguments: [varUnique] - The row to be removed
  169. //
  170. // History: 2-17-95 srikants Created
  171. //
  172. // Notes: NEWFEATURE/BROKENCODE: vikasman - _highKey & _lowKey not being
  173. // updated here !! But we don't expect RemoveRow to be called
  174. //
  175. //----------------------------------------------------------------------------
  176. BOOL CTableBucket::RemoveRow(
  177. PROPVARIANT const & varUnique,
  178. WORKID & widNext,
  179. CI_TBL_CHAPT & chapt )
  180. {
  181. widNext = widInvalid; // until categorization supports buckets
  182. chapt = chaptInvalid;
  183. Win4Assert(varUnique.vt == VT_I4);
  184. WORKID wid = (WORKID) varUnique.lVal;
  185. CWidValueHashEntry entry( wid );
  186. BOOL fFound = _hTable.LookUpWorkId( entry );
  187. if ( fFound )
  188. {
  189. Win4Assert( entry.Value() < _widArray.Size() );
  190. Win4Assert( _widArray.Get( entry.Value() ) == wid );
  191. //
  192. // Set the value to widInvalid in the widArray.
  193. //
  194. _widArray.Get( entry.Value() ) = widDeleted;
  195. _hTable.DeleteWorkId( wid );
  196. //
  197. // While deletions don't really destroy the sort order, the
  198. // widArray will no longer have workids in order because we don't
  199. // compact the widarray on deletions. Compaction is memory intensive
  200. // as well we have to fix the hash table.
  201. //
  202. _fSorted = FALSE;
  203. }
  204. return fFound;
  205. }
  206. //+---------------------------------------------------------------------------
  207. //
  208. // Function: SortOrder
  209. //
  210. // Synopsis:
  211. //
  212. // Returns:
  213. //
  214. // Modifies:
  215. //
  216. // History: 2-17-95 srikants Created
  217. //
  218. // Notes:
  219. //
  220. //----------------------------------------------------------------------------
  221. CSortSet const & CTableBucket::SortOrder()
  222. {
  223. Win4Assert( !"Must not be called" );
  224. return *((CSortSet *) 0);
  225. }
  226. //+---------------------------------------------------------------------------
  227. //
  228. // Function: IsGettingFull
  229. //
  230. // Synopsis: Checks if the bucket is getting too full.
  231. //
  232. // Returns: TRUE if getting full. FALSE o/w
  233. //
  234. // History: 3-20-95 srikants Created
  235. //
  236. // Notes:
  237. //
  238. //----------------------------------------------------------------------------
  239. BOOL CTableBucket::IsGettingFull()
  240. {
  241. return _hTable.Count() >= CTableSink::cBucketRowLimit;
  242. }
  243. //+---------------------------------------------------------------------------
  244. //
  245. // Function: WorkIdAtOffset
  246. //
  247. // Synopsis: Returns the workid at the specified offset, if one can
  248. // be found. windInvalid o/w
  249. //
  250. // Arguments: [offset] - The offset at which the wid is needed.
  251. //
  252. // Returns: If the bucket is sorted and the offset is within the
  253. // limits of the bucket, it will be the workid at that offset.
  254. // O/W, it will be widInvalid.
  255. //
  256. // History: 3-20-95 srikants Created
  257. //
  258. // Notes:
  259. //
  260. //----------------------------------------------------------------------------
  261. WORKID CTableBucket::WorkIdAtOffset( ULONG offset ) const
  262. {
  263. WORKID wid = widInvalid;
  264. if ( IsSorted() && ( offset < _widArray.Count() ))
  265. {
  266. wid = _widArray.Get(offset);
  267. }
  268. return wid;
  269. }
  270. //+---------------------------------------------------------------------------
  271. //
  272. // Function: RowOffset
  273. //
  274. // Synopsis: Gives the row offset of the workid, if possible.
  275. //
  276. // Arguments: [wid] - The workid to look up.
  277. // [rOffset] - On output, it will have the offset of the
  278. // row.
  279. //
  280. // Returns: TRUE if the wid could be located and the bucket is sorted.
  281. // FALSE o/w
  282. //
  283. // History: 3-20-95 srikants Created
  284. //
  285. // Notes:
  286. //
  287. //----------------------------------------------------------------------------
  288. BOOL CTableBucket::RowOffset( WORKID wid, ULONG & rOffset )
  289. {
  290. BOOL fRet = FALSE;
  291. if ( _fSorted )
  292. {
  293. CWidValueHashEntry entry( wid );
  294. if ( _hTable.LookUpWorkId( entry ) )
  295. {
  296. fRet = TRUE;
  297. rOffset = entry.Value();
  298. Win4Assert( _widArray.Get( rOffset ) == wid );
  299. }
  300. }
  301. return fRet;
  302. }
  303. //+---------------------------------------------------------------------------
  304. //
  305. // Function: WorkIdToPath
  306. //
  307. // Synopsis: Used in downlevel for bucket->window conversion. Given a
  308. // workid, it returns the path associated with the wid.
  309. //
  310. // Arguments: [wid] - The wid to convert to a path.
  311. // [outVarnt] - The variant that will contain the path.
  312. // [cbVarnt] - Length of the variant
  313. //
  314. // Returns: TRUE if successfully retrieved.
  315. // FALSE o/w
  316. //
  317. // History: 3-29-95 srikants Created
  318. //
  319. // Notes:
  320. //
  321. //----------------------------------------------------------------------------
  322. BOOL CTableBucket::WorkIdToPath( WORKID wid,
  323. CInlineVariant & outVarnt, ULONG & cbVarnt )
  324. {
  325. Win4Assert( 0 != _pLargeTable );
  326. Win4Assert( 0 != _pPathCompressor );
  327. CLock lock( _pLargeTable->GetMutex() );
  328. CTableVariant pathVarnt;
  329. XCompressFreeVariant xpvarnt;
  330. BOOL fStatus = FALSE;
  331. if ( GVRSuccess ==
  332. _pPathCompressor->GetData( &pathVarnt, VT_LPWSTR, wid, pidPath ) )
  333. {
  334. xpvarnt.Set( _pPathCompressor, &pathVarnt );
  335. //
  336. // Copy the data from the variant to the buffer.
  337. //
  338. const ULONG cbHeader = sizeof(CInlineVariant);
  339. ULONG cbVarData = pathVarnt.VarDataSize();
  340. ULONG cbTotal = cbVarData + cbHeader;
  341. if ( cbVarnt >= cbTotal )
  342. {
  343. CVarBufferAllocator bufAlloc( outVarnt.GetVarBuffer(), cbVarData );
  344. bufAlloc.SetBase(0);
  345. pathVarnt.Copy( &outVarnt, bufAlloc, (USHORT) cbVarData, 0 );
  346. fStatus = TRUE;
  347. }
  348. cbVarnt = cbTotal;
  349. }
  350. return fStatus;
  351. }
  352. #if DBG==1
  353. //+---------------------------------------------------------------------------
  354. //
  355. // Function: _CheckIfTooBig
  356. //
  357. // Synopsis:
  358. //
  359. // Returns:
  360. //
  361. // Modifies:
  362. //
  363. // History: 4-14-95 srikants Created
  364. //
  365. // Notes:
  366. //
  367. //----------------------------------------------------------------------------
  368. void CTableBucket::_CheckIfTooBig()
  369. {
  370. if ( _hTable.Count() > CTableSink::cBucketRowLimit )
  371. {
  372. tbDebugOut(( DEB_ERROR,
  373. "Bucket 0x%X is getting too full 0x%X Rows. Still adding. \n",
  374. GetSegId(), _hTable.Count() ));
  375. }
  376. }
  377. #endif // DBG==1
  378. //+---------------------------------------------------------------------------
  379. //
  380. // Function: WorkId
  381. //
  382. // Synopsis: Returns the current workid in the retriever.
  383. //
  384. // History: 3-20-95 srikants Created
  385. //
  386. // Notes:
  387. //
  388. //----------------------------------------------------------------------------
  389. WORKID CBucketRowIter::WorkId()
  390. {
  391. WORKID wid = widInvalid;
  392. //
  393. // Skip over the deleted wids
  394. //
  395. while ( !_AtEnd() && ( (wid=_Get()) == widDeleted ) )
  396. _Next();
  397. if ( !_AtEnd() )
  398. {
  399. Win4Assert( widInvalid != wid );
  400. if ( _fRetrievePath )
  401. {
  402. _pwszPath[0] = 0;
  403. _cwcCurrPath = 1;
  404. ULONG cbVarnt = cbPathVarnt;
  405. BOOL fStatus = _bucket.WorkIdToPath( wid, _pathVarnt, cbVarnt );
  406. Win4Assert( fStatus );
  407. Win4Assert( cbVarnt >= sizeof(CTableVariant) );
  408. _cwcCurrPath = (cbVarnt-sizeof(CTableVariant))/sizeof(WCHAR);
  409. }
  410. return wid;
  411. }
  412. else
  413. {
  414. return widInvalid;
  415. }
  416. }
  417. //+---------------------------------------------------------------------------
  418. //
  419. // Function: NextWorkId
  420. //
  421. // Synopsis: Positions to the next workid in the iterator
  422. //
  423. // Returns: The next work id.
  424. //
  425. // History: 3-20-95 srikants Created
  426. //
  427. // Notes:
  428. //
  429. //----------------------------------------------------------------------------
  430. WORKID CBucketRowIter::NextWorkId()
  431. {
  432. Win4Assert ( !_AtEnd() );
  433. _Next();
  434. return WorkId();
  435. }
  436. //+---------------------------------------------------------------------------
  437. //
  438. // Function: Path
  439. //
  440. // Synopsis: Retrieves the path of the current wid.
  441. //
  442. // History: 3-29-95 srikants Created
  443. //
  444. // Notes:
  445. //
  446. //----------------------------------------------------------------------------
  447. WCHAR const * CBucketRowIter::Path()
  448. {
  449. return _pwszPath;
  450. }
  451. //+---------------------------------------------------------------------------
  452. //
  453. // Function: PathSize
  454. //
  455. // Synopsis: Returns the size of the path in bytes excluding the
  456. // null termination
  457. //
  458. // Returns: The size of the path in BYTES WITHOUT the null termination
  459. //
  460. // History: 3-29-95 srikants Created
  461. //
  462. // Notes:
  463. //
  464. //----------------------------------------------------------------------------
  465. unsigned CBucketRowIter::PathSize()
  466. {
  467. Win4Assert( _cwcCurrPath > 0 );
  468. //
  469. // Don't include the trailing zero
  470. //
  471. return (_cwcCurrPath-1)*sizeof(WCHAR);
  472. }