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.

718 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1995.
  5. //
  6. // File: rowcomp.cxx
  7. //
  8. // Contents: Implementation of CRowIndex
  9. //
  10. // Classes: CRowCompareVariant
  11. //
  12. // History: 23 Aug 1994 dlee Created
  13. //
  14. // Notes: All of these routines assume the caller (in this case the
  15. // table window) is locked, so they don't do their own locking
  16. // to protect data.
  17. //
  18. //--------------------------------------------------------------------------
  19. #include "pch.cxx"
  20. #pragma hdrstop
  21. #include <bigtable.hxx>
  22. #include <tblalloc.hxx> // for CFixedVarAllocator
  23. #include <objcur.hxx>
  24. #include <compare.hxx>
  25. #include "tabledbg.hxx"
  26. #include "rowindex.hxx"
  27. #include "rowcomp.hxx"
  28. #include "tblwindo.hxx"
  29. #include "colcompr.hxx"
  30. //+-------------------------------------------------------------------------
  31. //
  32. // Member: CRowCompareVariant::CRowCompareVariant, public
  33. //
  34. // Synopsis: Constructor for comparator object. Basically just
  35. // invokes the PropSet comparator.
  36. //
  37. // Arguments: [TableWindow] -- table window object
  38. //
  39. // History: 29 Aug 1994 dlee Created
  40. //
  41. //--------------------------------------------------------------------------
  42. CRowCompareVariant::CRowCompareVariant(CTableWindow &TableWindow)
  43. : _TableWindow(TableWindow),
  44. _cProps(TableWindow.SortOrder().Count()),
  45. _aComparator(_cProps),
  46. _aVar1(_cProps),
  47. _aVar2(_cProps),
  48. _apVar1(_cProps),
  49. _apVar2(_cProps),
  50. _apColumn(_cProps),
  51. _aVarFlags1(_cProps),
  52. _aVarFlags2(_cProps),
  53. _pPathStore(0),
  54. _sharedBuf(TableWindow._sharedBuf),
  55. _xBuffer(),
  56. _widCached(widInvalid)
  57. {
  58. //
  59. // Initialize an array of pointers to the variants, which is what
  60. // the comparison routine wants (and needs because some variants are
  61. // larger than a variant -- their out of line data is in the same
  62. // block after the variant-proper data).
  63. //
  64. // Also make an array of sort column data
  65. //
  66. for (unsigned i = 0; i < _cProps; i++)
  67. {
  68. _aVarFlags1[i] = eNone;
  69. _aVarFlags2[i] = eNone;
  70. _apVar1[i] = &(_aVar1[i]);
  71. _apVar2[i] = &(_aVar2[i]);
  72. BOOL fFound = FALSE;
  73. SSortKey Key = _TableWindow.SortOrder().Get( i );
  74. _apColumn[i] = _TableWindow._Columns.Find( Key.pidColumn, fFound );
  75. Win4Assert(fFound);
  76. }
  77. _InitComparators( _TableWindow.SortOrder() );
  78. } //CRowCompareVariant
  79. //+-------------------------------------------------------------------------
  80. //
  81. // Member: CRowCompareVariant::~CRowCompareVariant, public
  82. //
  83. // Synopsis: Destructor for comparator object. Frees allocated variants
  84. // left around after an exception or those that are buffered
  85. // for variant set 1.
  86. //
  87. // History: 12 Sep 1994 dlee Created
  88. //
  89. //--------------------------------------------------------------------------
  90. CRowCompareVariant::~CRowCompareVariant()
  91. {
  92. _Cleanup1();
  93. _Cleanup2();
  94. } //~CRowCompareVariant
  95. //+-------------------------------------------------------------------------
  96. //
  97. // Member: CRowCompareVariant::_FreeVariant, private
  98. //
  99. // Synopsis: Frees allocated variant depending on its source
  100. //
  101. // Arguments: [pColumn] -- column needed to get compressor
  102. // [pVar] -- variant to free
  103. // [eSource] -- source of the variant allocation
  104. //
  105. // History: 12 Sep 1994 dlee Created
  106. //
  107. //--------------------------------------------------------------------------
  108. inline void CRowCompareVariant::_FreeVariant(
  109. CTableColumn * pColumn,
  110. CTableVariant * pVar,
  111. EVariantSource eSource)
  112. {
  113. switch (eSource)
  114. {
  115. case eCompressor :
  116. (pColumn->GetCompressor())->FreeVariant( pVar );
  117. break;
  118. case eNewx :
  119. delete pVar;
  120. break;
  121. case eBuffer:
  122. _xBuffer.Release();
  123. break;
  124. default :
  125. Win4Assert(! "CRowCompareVariant::_FreeVariant() bad");
  126. break;
  127. }
  128. } //_FreeVariant
  129. //+-------------------------------------------------------------------------
  130. //
  131. // Member: CRowCompareVariant::_Cleanup1, private
  132. //
  133. // Synopsis: Frees allocated variants
  134. //
  135. // History: 12 Sep 1994 dlee Created
  136. //
  137. //--------------------------------------------------------------------------
  138. inline void CRowCompareVariant::_Cleanup1()
  139. {
  140. for (unsigned i = 0; i < _cProps; i++)
  141. {
  142. if (eNone != _aVarFlags1[i])
  143. {
  144. _FreeVariant( _apColumn[i], _apVar1[i], _aVarFlags1[i] );
  145. _aVarFlags1[i] = eNone;
  146. _apVar1[i] = &(_aVar1[i]);
  147. }
  148. }
  149. } //_Cleanup1
  150. //+-------------------------------------------------------------------------
  151. //
  152. // Member: CRowCompareVariant::_Cleanup2, private
  153. //
  154. // Synopsis: Frees allocated variants
  155. //
  156. // History: 12 Sep 1994 dlee Created
  157. //
  158. //--------------------------------------------------------------------------
  159. inline void CRowCompareVariant::_Cleanup2()
  160. {
  161. for (unsigned i = 0; i < _cProps; i++)
  162. {
  163. if (eNone != _aVarFlags2[i])
  164. {
  165. _FreeVariant( _apColumn[i], _apVar2[i], _aVarFlags2[i] );
  166. _aVarFlags2[i] = eNone;
  167. // Don't have to restore this pointer -- never changes for 2
  168. Win4Assert( _apVar2[i] == &(_aVar2[i]) );
  169. //_apVar2[i] = &(_aVar2[i]);
  170. }
  171. }
  172. } //_Cleanup2
  173. //+-------------------------------------------------------------------------
  174. //
  175. // Member: CRowCompareVariant::_MakeVariant, private
  176. //
  177. // Synopsis: Makes variants from raw row data. Variants are needed
  178. // by the comparator.
  179. //
  180. // Arguments: [pColumn] -- column description
  181. // [pbRow] -- pointer to raw row data for row (source)
  182. // [pVar] -- variant pointer (destination)
  183. // [rSource] -- source of the variant's allocation,
  184. // only touched if not eNone
  185. //
  186. // History: 1 Sep 1994 dlee Created
  187. //
  188. //--------------------------------------------------------------------------
  189. void CRowCompareVariant::_MakeVariant(
  190. CTableColumn * pColumn,
  191. BYTE * pbRow,
  192. CTableVariant * pVar,
  193. EVariantSource & rSource)
  194. {
  195. pbRow += pColumn->GetValueOffset();
  196. if (pColumn->IsCompressedCol())
  197. {
  198. //
  199. // Get the compressed data into a variant. Ignore the return
  200. // code. Assume that if GetData() is unable to find data it sets
  201. // the variant to VT_EMPTY, which the comparator is expecting.
  202. //
  203. (pColumn->GetCompressor())->GetData( pVar,
  204. pColumn->GetStoredType(),
  205. pColumn->GetValueSize() ?
  206. * ((ULONG *) pbRow) : 0,
  207. pColumn->PropId );
  208. rSource = eCompressor;
  209. }
  210. else
  211. {
  212. // Create variants from non-compressed data
  213. Win4Assert( pColumn->IsValueStored() );
  214. pVar->Init( pColumn->GetStoredType(),
  215. pbRow,
  216. pColumn->GetValueSize() );
  217. // Convert out of line data from offset to pointer
  218. pVar->OffsetsToPointers( _TableWindow._DataAllocator );
  219. }
  220. } //_MakeVariant
  221. //+-------------------------------------------------------------------------
  222. //
  223. // Member: CRowCompareVariant::_MakeVariant, private
  224. //
  225. // Synopsis: Makes variants from raw row data. Variants are needed
  226. // by the comparator. Always puts variants in Var1, never
  227. // in Var2.
  228. //
  229. // Arguments: [pColumn] -- column description
  230. // [rObject] -- object accessor for variant construction
  231. // [iProp] -- index of variant to which data is written
  232. //
  233. // Notes: inline -- only called once
  234. //
  235. // History: 1 Sep 1994 dlee Created
  236. //
  237. //--------------------------------------------------------------------------
  238. inline void CRowCompareVariant::_MakeVariant(
  239. CTableColumn * pColumn,
  240. CRetriever & rObject,
  241. unsigned iProp)
  242. {
  243. ULONG cbBuf = sizeof CTableVariant;
  244. GetValueResult eGvr = rObject.GetPropertyValue( pColumn->PropId,
  245. _apVar1[iProp],
  246. &cbBuf );
  247. //
  248. // If the data won't fit in a normal variant, either use the built-in
  249. // buffer or allocate a large one which will be freed after the
  250. // comparison.
  251. //
  252. if (eGvr == GVRNotEnoughSpace)
  253. {
  254. CTableVariant *pvar;
  255. if (!_xBuffer.InUse() && maxcbBuffer >= cbBuf)
  256. {
  257. if (0 == _xBuffer.GetPointer())
  258. _xBuffer.Init(maxcbBuffer);
  259. else
  260. _xBuffer.AddRef();
  261. pvar = (CTableVariant *) _xBuffer.GetPointer();
  262. _aVarFlags1[iProp] = eBuffer;
  263. }
  264. else
  265. {
  266. pvar = (CTableVariant*) new BYTE[cbBuf];
  267. _aVarFlags1[iProp] = eNewx;
  268. }
  269. eGvr = rObject.GetPropertyValue( pColumn->PropId, pvar, &cbBuf );
  270. _apVar1[iProp] = pvar;
  271. }
  272. if ( GVRNotAvailable == eGvr ||
  273. GVRSharingViolation == eGvr )
  274. {
  275. // No value for this property -- make an empty variant
  276. _apVar1[iProp]->vt = VT_EMPTY;
  277. }
  278. else if ( GVRSuccess != eGvr )
  279. {
  280. THROW( CException( CRetriever::NtStatusFromGVR(eGvr)) );
  281. }
  282. } //_MakeVariant
  283. //+---------------------------------------------------------------------------
  284. //
  285. // Function: _InitComparators
  286. //
  287. // Synopsis: Initializes the comparators methods for each of the columns
  288. // which need to be compared.
  289. //
  290. // Arguments: [sortSet] - The columns that need to be sorted on.
  291. //
  292. // History: 5-11-95 srikants Created
  293. //
  294. // Notes:
  295. //
  296. //----------------------------------------------------------------------------
  297. void CRowCompareVariant::_InitComparators( CSortSet const & sortSet )
  298. {
  299. for ( unsigned i = 0; i < _cProps; i++ )
  300. {
  301. _aComparator[i].Init( sortSet.Get(i).dwOrder );
  302. if ( 0 == _pPathStore && 0 != _apColumn[i]->GetCompressor() )
  303. {
  304. _pPathStore = _apColumn[i]->GetCompressor()->GetPathStore();
  305. if ( 0 != _pPathStore )
  306. {
  307. Win4Assert( _apColumn[i]->PropId == pidName ||
  308. _apColumn[i]->PropId == pidPath ||
  309. _apColumn[i]->PropId == pidWorkId );
  310. }
  311. }
  312. }
  313. }
  314. //+---------------------------------------------------------------------------
  315. //
  316. // Function: _GetPathId
  317. //
  318. // Synopsis: Returns the "pathId" stored in the row that the path compressor
  319. // can understand.
  320. //
  321. // Arguments: [col] - The column description.
  322. // [pbRow] - Row in the window.
  323. //
  324. // Returns: PATHID in the row.
  325. //
  326. // History: 5-11-95 srikants Created
  327. //
  328. // Notes:
  329. //
  330. //----------------------------------------------------------------------------
  331. PATHID CRowCompareVariant::_GetPathId( const CTableColumn & col , BYTE * pbRow )
  332. {
  333. return _TableWindow.RowWorkid( pbRow );
  334. }
  335. //+---------------------------------------------------------------------------
  336. //
  337. // Function: _MakeVariant
  338. //
  339. // Synopsis: Creates a variant and is optimized to use the sharedBuf
  340. // if possible.
  341. //
  342. // Arguments: [iCol] - Index of the column
  343. // [sharedBuf] - Global shared buffer
  344. // [obj] - The object retriever
  345. //
  346. // Returns: A pointer to the variant (if successful)
  347. //
  348. // History: 5-22-95 srikants Created
  349. //
  350. // Notes: This is optimized to avoid doing a memory allocation in
  351. // case the column is bigger than a simple variant. It
  352. // will use the global shared memory (sharedBuf) if it has
  353. // been acquired by the caller.
  354. //
  355. //----------------------------------------------------------------------------
  356. // inline
  357. PROPVARIANT * CRowCompareVariant::_MakeVariant( unsigned iCol,
  358. XUseSharedBuffer &sharedBuf,
  359. CRetriever & obj )
  360. {
  361. PROPVARIANT * pVarnt = 0;
  362. if ( sharedBuf.IsAcquired() )
  363. {
  364. //
  365. // The shared buffer has been acquired by the caller and so we
  366. // can use it to get the variant.
  367. //
  368. pVarnt = (PROPVARIANT *) sharedBuf.LokGetBuffer();
  369. ULONG cbBuf = sharedBuf.LokGetSize();
  370. ULONG propId = _apColumn[iCol]->PropId;
  371. GetValueResult gvr = obj.GetPropertyValue( propId,
  372. pVarnt,
  373. &cbBuf );
  374. if ( GVRNotEnoughSpace == gvr )
  375. {
  376. pVarnt = 0;
  377. }
  378. else if ( GVRNotAvailable == gvr ||
  379. GVRSharingViolation == gvr )
  380. {
  381. // No value for this property -- make an empty variant
  382. _apVar1[iCol]->vt = VT_EMPTY;
  383. pVarnt = _apVar1[iCol];
  384. }
  385. else if ( GVRSuccess != gvr )
  386. {
  387. THROW( CException( CRetriever::NtStatusFromGVR(gvr) ) );
  388. }
  389. }
  390. if ( 0 == pVarnt )
  391. {
  392. //
  393. // Either the sharedBuf was not acquired by the caller or the
  394. // buffer is not enough to hold the data.
  395. //
  396. if ( eNone == _aVarFlags1[iCol] )
  397. {
  398. _MakeVariant( _apColumn[iCol], obj, iCol );
  399. }
  400. pVarnt = _apVar1[iCol];
  401. }
  402. Win4Assert( 0 != pVarnt );
  403. return pVarnt;
  404. }
  405. //+---------------------------------------------------------------------------
  406. //
  407. // Function: _FastCompare
  408. //
  409. // Synopsis: A fast comparator for two rows in the window. It does a
  410. // quick compare on pidWorkId, pidPath and pidName.
  411. //
  412. // Arguments: [iCol] - Index of the column to be compared.
  413. // [pbRow1] - Pointer to the window row 1
  414. // [pbRow2] - Pointer to the window row 2
  415. // [iComp] - (OUTPUT) result of comparison.
  416. //
  417. // 0 - if equal
  418. // +1 - if row1 > row2
  419. // -1 - if row1 < row2
  420. //
  421. // Returns: TRUE if a fast compare was done. FALSE o/w
  422. //
  423. // History: 5-11-95 srikants Created
  424. //
  425. // Notes:
  426. //
  427. //----------------------------------------------------------------------------
  428. // inline
  429. BOOL CRowCompareVariant::_FastCompare( unsigned iCol,
  430. BYTE *pbRow1, BYTE *pbRow2,
  431. int & iComp )
  432. {
  433. ULONG propId = _apColumn[iCol]->PropId;
  434. switch ( propId )
  435. {
  436. case pidWorkId:
  437. {
  438. WORKID widRow1 = _TableWindow.RowWorkid( pbRow1 );
  439. WORKID widRow2 = _TableWindow.RowWorkid( pbRow2 );
  440. iComp = widRow1 - widRow2;
  441. }
  442. break;
  443. case pidName:
  444. case pidPath:
  445. if ( 0 == _apColumn[iCol]->GetCompressor() )
  446. return FALSE;
  447. Win4Assert( _apColumn[iCol]->GetValueSize() == sizeof(PATHID) );
  448. {
  449. PATHID pathid1 = _GetPathId( *_apColumn[iCol], pbRow1 );
  450. PATHID pathid2 = _GetPathId( *_apColumn[iCol], pbRow2 );
  451. iComp = _pPathStore->Compare( pathid1, pathid2, propId );
  452. }
  453. break;
  454. default:
  455. return FALSE;
  456. }
  457. return TRUE;
  458. }
  459. //+---------------------------------------------------------------------------
  460. //
  461. // Function: _FastCompare
  462. //
  463. // Synopsis: Same as above except that it compares an object retriever to
  464. // a row in the window.
  465. //
  466. // Arguments: [iCol] -
  467. // [obj] -
  468. // [pbRow2] -
  469. // [iComp] -
  470. //
  471. // Returns: TRUE if a fast compare was done; FALSE o/w
  472. //
  473. // Modifies:
  474. //
  475. // History: 5-11-95 srikants Created
  476. //
  477. // Notes:
  478. //
  479. //----------------------------------------------------------------------------
  480. // inline
  481. BOOL CRowCompareVariant::_FastCompare( unsigned iCol,
  482. CRetriever & obj,
  483. XUseSharedBuffer & sharedBuf,
  484. BYTE * pbRow2,
  485. int & iComp )
  486. {
  487. ULONG propId = _apColumn[iCol]->PropId;
  488. switch ( propId )
  489. {
  490. case pidWorkId:
  491. {
  492. WORKID widRow1 = obj.WorkId();
  493. WORKID widRow2 = _TableWindow.RowWorkid( pbRow2 );
  494. iComp = widRow1 - widRow2;
  495. }
  496. break;
  497. case pidName:
  498. case pidPath:
  499. if ( 0 == _apColumn[iCol]->GetCompressor() )
  500. return FALSE;
  501. Win4Assert( _apColumn[iCol]->GetValueSize() == sizeof(PATHID) );
  502. {
  503. PATHID pathid2 = _GetPathId( *_apColumn[iCol], pbRow2 );
  504. PROPVARIANT * pVarnt = _MakeVariant( iCol, sharedBuf, obj );
  505. iComp = _pPathStore->Compare( *pVarnt, pathid2, propId );
  506. }
  507. break;
  508. default:
  509. return FALSE;
  510. }
  511. return TRUE;
  512. }
  513. //+---------------------------------------------------------------------------
  514. //
  515. // Function: Compare
  516. //
  517. // Synopsis: Compares two rows in the window.
  518. //
  519. // Arguments: [oRow1] - Offset of row1
  520. // [oRow2] - Offset of row2
  521. //
  522. // Returns: 0 if the rows are the same,
  523. // positive column # of first column of row1 greater than row2
  524. // negative column # of first column of row1 less than row2
  525. //
  526. // History: 5-11-95 srikants Created
  527. //
  528. // Notes:
  529. //
  530. //----------------------------------------------------------------------------
  531. int CRowCompareVariant::Compare( TBL_OFF oRow1, TBL_OFF oRow2 )
  532. {
  533. BYTE *pbRow1 = (BYTE *) _TableWindow.
  534. _DataAllocator.FixedPointer( oRow1 );
  535. BYTE *pbRow2 = (BYTE *) _TableWindow.
  536. _DataAllocator.FixedPointer( oRow2 );
  537. WORKID widRow1 = _TableWindow.RowWorkid( pbRow1 );
  538. WORKID widRow2 = _TableWindow.RowWorkid( pbRow2 );
  539. if ( widRow1 != _widCached )
  540. {
  541. _Cleanup1();
  542. _widCached = widRow1;
  543. }
  544. int iComp = 0 ;
  545. for ( unsigned i = 0; ( 0 == iComp ) && (i < _cProps) ; i++ )
  546. {
  547. if ( _FastCompare( i, pbRow1, pbRow2, iComp ) )
  548. {
  549. iComp *= _aComparator[i].GetDirMult();
  550. }
  551. else
  552. {
  553. if ( eNone == _aVarFlags1[i] )
  554. {
  555. _MakeVariant( _apColumn[i], pbRow1, _apVar1[i], _aVarFlags1[i] );
  556. }
  557. _MakeVariant( _apColumn[i], pbRow2, _apVar2[i], _aVarFlags2[i] );
  558. iComp = _aComparator[i].Compare( _apVar1[i], _apVar2[i] );
  559. }
  560. }
  561. _Cleanup2();
  562. if ( 0 == iComp )
  563. return 0;
  564. else if ( iComp > 0 )
  565. return i;
  566. else
  567. return - (int) i;
  568. } //Compare
  569. //+---------------------------------------------------------------------------
  570. //
  571. // Function: CompareObject
  572. //
  573. // Synopsis: Compares an object retriever to a row in the window.
  574. //
  575. // Arguments: [obj] -
  576. // [oRow2] -
  577. //
  578. // Returns:
  579. //
  580. // History: 5-11-95 srikants Created
  581. //
  582. // Notes:
  583. //
  584. //----------------------------------------------------------------------------
  585. int CRowCompareVariant::CompareObject( CRetriever & obj , TBL_OFF oRow2 )
  586. {
  587. BYTE *pbRow2 = (BYTE *) _TableWindow.
  588. _DataAllocator.FixedPointer( oRow2 );
  589. WORKID widRow1 = obj.WorkId();
  590. if ( widRow1 != _widCached )
  591. {
  592. _Cleanup1();
  593. _widCached = widRow1;
  594. }
  595. XUseSharedBuffer xSharedBuf(_sharedBuf, FALSE);
  596. if ( !_sharedBuf.IsInUse() )
  597. {
  598. xSharedBuf.LokAcquire();
  599. }
  600. int iComp = 0;
  601. for ( unsigned i = 0; ( 0 == iComp ) && (i < _cProps) ; i++ )
  602. {
  603. if ( _FastCompare( i, obj, xSharedBuf, pbRow2, iComp ) )
  604. {
  605. iComp *= _aComparator[i].GetDirMult();
  606. }
  607. else
  608. {
  609. if ( eNone == _aVarFlags1[i] )
  610. {
  611. _MakeVariant( _apColumn[i], obj, i );
  612. }
  613. _MakeVariant( _apColumn[i], pbRow2, _apVar2[i], _aVarFlags2[i] );
  614. iComp = _aComparator[i].Compare( _apVar1[i], _apVar2[i] );
  615. }
  616. }
  617. _Cleanup2();
  618. if ( 0 == iComp )
  619. return 0;
  620. else if ( iComp > 0 )
  621. return i;
  622. else
  623. return - (int) i;
  624. } //CompareObject