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.

468 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1999.
  5. //
  6. // File: rowbuf.hxx
  7. //
  8. // Contents: Declaration of the row buffer classes, used for HROW
  9. // buffering at the interface level.
  10. //
  11. // Classes: CRowBuffer
  12. // CRowBufferSet
  13. // CDeferredValue
  14. // CRBRefCount
  15. //
  16. // History: 22 Nov 1994 AlanW Created
  17. //
  18. //--------------------------------------------------------------------------
  19. #pragma once
  20. #include <tblalloc.hxx>
  21. #include <tablecol.hxx>
  22. class CTableColumnSet;
  23. //+-------------------------------------------------------------------------
  24. //
  25. // Class: CDeferredValue
  26. //
  27. // Purpose: Holds a value that is not in the row buffer because the value
  28. // was deferred. The row buffer must free these values because
  29. // the client asked for them DBTYPE_BYREF or DBTYPE_VECTOR with
  30. // DBMEMOWNER_PROVIDEROWNED, so they must exist until the
  31. // HROW goes away.
  32. //
  33. // History: 4 Aug 1995 dlee Created
  34. //
  35. //--------------------------------------------------------------------------
  36. class CDeferredValue
  37. {
  38. public:
  39. CDeferredValue(
  40. HROW hrow,
  41. PROPVARIANT & var ) :
  42. _hrow( hrow ),
  43. _var( var )
  44. { }
  45. CDeferredValue() : _hrow( 0 )
  46. { }
  47. ~CDeferredValue()
  48. { Release(); }
  49. void operator= ( CDeferredValue & val )
  50. {
  51. _hrow = val._hrow;
  52. _var = val._var;
  53. val._hrow = 0;
  54. }
  55. HROW GetHRow() { return _hrow; }
  56. void Release();
  57. private:
  58. PROPVARIANT _var; // data that is deferred
  59. HROW _hrow; // hrow to which the allocation belongs
  60. };
  61. //+-------------------------------------------------------------------------
  62. //
  63. // Class: CRBRefCount
  64. //
  65. // Purpose: An HROW reference count in a row buffer.
  66. //
  67. // Notes: The ref. count occupies a USHORT at the beginning of the
  68. // memory for the row.
  69. //
  70. // History: 29 May 1997 AlanW Created
  71. //
  72. //--------------------------------------------------------------------------
  73. const unsigned maxRowRefCount = 0x3FFF;
  74. const unsigned eHasByrefData = 0x4000; // GetData has handed out ptr in buffer
  75. const unsigned eHasByrefCopy = 0x8000; // a copy of row exists with eHasByrefData
  76. class CRBRefCount
  77. {
  78. public:
  79. USHORT GetRefCount() const { return _usRef & maxRowRefCount; }
  80. void SetRefCount( CRBRefCount & Ref )
  81. {
  82. _usRef = Ref._usRef;
  83. }
  84. void SetRefCount(unsigned cRef)
  85. {
  86. _usRef = (_usRef & ~maxRowRefCount) | cRef;
  87. }
  88. void IncRefCount()
  89. {
  90. unsigned cRef = GetRefCount();
  91. if (cRef < maxRowRefCount)
  92. cRef++;
  93. SetRefCount( cRef );
  94. }
  95. void DecRefCount()
  96. {
  97. unsigned cRef = GetRefCount();
  98. Win4Assert(cRef > 0);
  99. if (cRef > 0)
  100. cRef--;
  101. SetRefCount( cRef );
  102. }
  103. void AddRefs( CRBRefCount & Ref )
  104. {
  105. unsigned cRef = GetRefCount();
  106. if ( (cRef + Ref.GetRefCount()) < maxRowRefCount)
  107. cRef += Ref.GetRefCount();
  108. else
  109. cRef = maxRowRefCount;
  110. SetRefCount( cRef );
  111. if ( Ref.HasByrefData() )
  112. SetByrefData();
  113. if ( Ref.HasByrefCopy() )
  114. SetByrefCopy();
  115. }
  116. BOOL HasByrefData() { return (_usRef & eHasByrefData) != 0; }
  117. BOOL HasByrefCopy() { return (_usRef & eHasByrefCopy) != 0; }
  118. void SetByrefData() { _usRef |= eHasByrefData; }
  119. void SetByrefCopy() { _usRef |= eHasByrefCopy; }
  120. CRBRefCount( unsigned cRef = 0 ) :
  121. _usRef( (WORD)cRef )
  122. { }
  123. CRBRefCount( CRBRefCount & Ref ) :
  124. _usRef( Ref._usRef )
  125. {
  126. }
  127. private:
  128. USHORT _usRef;
  129. };
  130. //+-------------------------------------------------------------------------
  131. //
  132. // Class: CRowBuffer
  133. //
  134. // Purpose: A row buffer in the client process. This
  135. // provides the interface to HROWs for OLE-DB.
  136. //
  137. // Interface:
  138. //
  139. // History: 11 Nov 99 KLam Changed cast in IsRowHChapt for Win64
  140. //
  141. //--------------------------------------------------------------------------
  142. class CRowBuffer
  143. {
  144. friend class CRowBufferSet;
  145. public:
  146. CRowBuffer(
  147. CTableColumnSet& rColumns,
  148. ULONG cbRowWidth,
  149. ULONG cRows,
  150. XPtr<CFixedVarAllocator> & rAlloc
  151. );
  152. ~CRowBuffer();
  153. SCODE Lookup(
  154. unsigned iRow,
  155. CTableColumnSet ** ppColumns,
  156. void ** ppbRowData,
  157. BOOL fValidate = TRUE
  158. ) const;
  159. void AddRefRow(
  160. HROW hRow,
  161. unsigned iRow,
  162. ULONG & rRefCount,
  163. DBROWSTATUS & rRowStatus
  164. );
  165. BOOL ReleaseRow(
  166. HROW hRow,
  167. unsigned iRow,
  168. ULONG & rRefCount,
  169. DBROWSTATUS & rRowStatus
  170. );
  171. void ReferenceChapter(
  172. BYTE * pbRow
  173. );
  174. void AddRefChapter(
  175. unsigned iRow,
  176. ULONG & rRefCount
  177. );
  178. void ReleaseChapter(
  179. unsigned iRow,
  180. ULONG & rRefCount
  181. );
  182. inline void InitRowRefcount(
  183. unsigned iRow,
  184. CRBRefCount & OtherRefs
  185. );
  186. CRBRefCount DereferenceRow(
  187. unsigned iRow
  188. );
  189. HROW GetRowId(unsigned iRow) const;
  190. ULONG GetRowWidth(void) const { return _cbRowWidth; }
  191. ULONG GetRowCount(void) const { return _cRows; }
  192. void SetRowIdOffset( ULONG obRowId ) { _obRowId = obRowId; }
  193. void SetChapterVars( ULONG obChaptId, ULONG obChaptRefcnt )
  194. {
  195. _obChaptId = obChaptId;
  196. _obChaptRefcount = obChaptRefcnt;
  197. }
  198. LONG RefCount(void) const { return _cReferences; }
  199. void LokReference() { _cReferences++; }
  200. void AddDeferredValue( CDeferredValue & val )
  201. {
  202. Win4Assert( ciIsValidPointer( _aDeferredValues.GetPointer() ) );
  203. _aDeferredValues[ _aDeferredValues.Count() ] = val;
  204. Win4Assert( ciIsValidPointer( _aDeferredValues.GetPointer() ) );
  205. }
  206. BOOL FindHRow( unsigned &riRow, HROW hRow, BOOL fFindByrefData = FALSE ) const;
  207. BOOL FindHChapter( unsigned &riRow, HCHAPTER hChapter ) const;
  208. BOOL IsRowHRow( unsigned iRow, HROW hRow ) const
  209. {
  210. BYTE* pbRow = _pbRowData + ( iRow * _cbRowWidth );
  211. // refcount is the first USHORT in each row
  212. return ( ( 0 != ((CRBRefCount *) pbRow)->GetRefCount() ) &&
  213. ( hRow == ( * (HROW UNALIGNED *) ( pbRow + _obRowId ) ) ) );
  214. }
  215. BOOL IsRowOkAndHRow( unsigned iRow, HROW hRow ) const
  216. {
  217. if ( iRow >= GetRowCount() )
  218. return FALSE;
  219. return IsRowHRow( iRow, hRow );
  220. }
  221. BOOL IsRowHChapt( unsigned iRow, HCHAPTER hChapt ) const
  222. {
  223. BYTE* pbRow = _pbRowData + ( iRow * _cbRowWidth );
  224. // refcount is the first USHORT in each row
  225. return ( ( 0 != ((CRBRefCount *) pbRow)->GetRefCount() ) &&
  226. ( hChapt == ( * (CI_TBL_CHAPT *) ( pbRow + _obChaptId ) ) ) );
  227. }
  228. BOOL IsRowOkAndHChapt( unsigned iRow, HCHAPTER hChapt ) const
  229. {
  230. if ( iRow >= GetRowCount() )
  231. return FALSE;
  232. return IsRowHChapt( iRow, hChapt );
  233. }
  234. CTableColumn * Find( PROPID propid ) const
  235. {
  236. if ( _fQuickPROPID && propid <= _Columns.Count() )
  237. {
  238. Win4Assert( 0 != propid );
  239. return _Columns.Get( propid-1 );
  240. }
  241. else
  242. {
  243. return _Columns.Find( propid );
  244. }
  245. }
  246. void SetByrefData( BYTE * pbRow ) {
  247. CRBRefCount * pRefCount = (CRBRefCount *) pbRow;
  248. pRefCount->SetByrefData();
  249. }
  250. private:
  251. inline BOOL IsChaptered( ) const
  252. { return _obChaptId != 0xFFFFFFFF; }
  253. inline BYTE* _IndexRow( unsigned iRow, int fVerifyRefcnt = TRUE ) const;
  254. CRBRefCount & _GetRowRefCount( unsigned iRow ) const;
  255. CRBRefCount & _GetChaptRefCount( unsigned iRow ) const;
  256. LONG _cReferences; // number of referenced rows in buffer
  257. ULONG _cRows; // number of rows in this buffer
  258. ULONG _cbRowWidth; // size of each row
  259. BYTE* _pbRowData; // pointer to row data
  260. ULONG _obRowId; // offset to row ID
  261. ULONG _obChaptId; // offset to chapter ID
  262. ULONG _obChaptRefcount; // offset to chapter ref. count
  263. XPtr<CFixedVarAllocator> _Alloc; // allocator holding row data
  264. CTableColumnSet& _Columns; // column descriptions
  265. // Optimization to speed up the lookup of PROPIDs
  266. BOOL _fQuickPROPID; // Set to TRUE if PropIds can be looked
  267. // up quickly
  268. CDynArrayInPlaceNST<CDeferredValue> _aDeferredValues; // deferred byref data
  269. };
  270. DECL_DYNARRAY( CRowBufferArray, CRowBuffer )
  271. //+-------------------------------------------------------------------------
  272. //
  273. // Class: CRowBufferSet
  274. //
  275. // Purpose: A set of row buffers in the client process. This
  276. // provides the interface to HROWs for OLE-DB.
  277. //
  278. // Interface:
  279. //
  280. //--------------------------------------------------------------------------
  281. class CRowBufferSet : public CRowBufferArray
  282. {
  283. public:
  284. CRowBufferSet(
  285. BOOL fSequential,
  286. ULONG obRowRefcount,
  287. ULONG obRowId,
  288. ULONG obChaptRefcount,
  289. ULONG obChaptId
  290. );
  291. ~CRowBufferSet();
  292. CRowBuffer &Lookup(
  293. HROW hRow,
  294. CTableColumnSet ** ppColumns,
  295. void ** ppbRowData
  296. );
  297. void Add(
  298. XPtr<CRowBuffer> & pBuf,
  299. BOOL fPossibleDuplicateHRows,
  300. HROW * pahRows = 0
  301. );
  302. void AddRefRows(
  303. DBCOUNTITEM cRows,
  304. const HROW rghRows [],
  305. DBREFCOUNT rgRefCounts[] = 0,
  306. DBROWSTATUS rgRowStatus[] = 0
  307. );
  308. SCODE ReleaseRows(
  309. DBCOUNTITEM cRows,
  310. const HROW rghRows [],
  311. DBREFCOUNT rgRefCounts[] = 0,
  312. DBROWSTATUS rgRowStatus[] = 0
  313. );
  314. void CheckAllHrowsReleased( );
  315. void AddRefChapter(
  316. HCHAPTER hChapter,
  317. ULONG * pcRefCount
  318. );
  319. void ReleaseChapter(
  320. HCHAPTER hChapter,
  321. ULONG * pcRefCount
  322. );
  323. CMutexSem & GetBufferLock( )
  324. { return _mutex; }
  325. BOOL IsChaptered( ) const
  326. { return _obChaptId != 0xFFFFFFFF; }
  327. #ifdef _WIN64
  328. CFixedVarAllocator * GetArrayAlloc () { return &_ArrayAlloc; }
  329. #endif
  330. private:
  331. void _LokAddRefRow(
  332. HROW hRow,
  333. ULONG & rRefCount,
  334. DBROWSTATUS & rRowStatus
  335. );
  336. void _LokReleaseRow(
  337. HROW hRow,
  338. ULONG & rRefCount,
  339. DBROWSTATUS & rRowStatus
  340. );
  341. inline BOOL IsHrowRowId( ) const
  342. { return ! _fSequential; }
  343. CRowBuffer* _FindRowBuffer(
  344. HROW hRow,
  345. unsigned & iBuf,
  346. unsigned & iRow
  347. );
  348. CRowBuffer* _FindRowBufferByChapter(
  349. HCHAPTER hChapter,
  350. unsigned & iBuf,
  351. unsigned & iRow
  352. );
  353. BOOL _fSequential;
  354. ULONG _obRowRefcount; // offset of row reference cnt in bufs
  355. ULONG _obRowId; // offset of row identifier in buffers
  356. ULONG _obChaptRefcount; // offset of chapter reference cnt in bufs
  357. ULONG _obChaptId; // offset of chapter identifier in buffers
  358. ULONG _cRowBufs; // Count of row buffers in this set
  359. #ifdef _WIN64
  360. CFixedVarAllocator _ArrayAlloc; // Used for arrays of pointers in 64c -> 32s
  361. #endif
  362. // Hints for the next lookup of an hrow
  363. unsigned _iBufHint;
  364. unsigned _iRowHint;
  365. #if CIDBG
  366. unsigned _cHintHits;
  367. unsigned _cHintMisses;
  368. #endif
  369. CMutexSem _mutex; // serialize on buffer set operations
  370. };