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.

545 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 2000
  5. //
  6. // File: PosCache.cxx
  7. //
  8. // Contents: Positionable cache
  9. //
  10. // Classes: CMiniPositionableCache
  11. //
  12. // History: 05-Jun-95 KyleP Created
  13. // 14-JAN-97 KrishnaN Undefined CI_INETSRV and related changes
  14. // 29-Mar-2000 KLam Fixed Bookmarks
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <pch.cxx>
  18. #pragma hdrstop
  19. #include "poscache.hxx"
  20. //+---------------------------------------------------------------------------
  21. //
  22. // Member: CMiniPositionableCache::CMiniPositionableCache, public
  23. //
  24. // Synopsis: Builds bindings to fetch bookmark.
  25. //
  26. // Arguments: [Index] -- Identifier. Not used internally.
  27. // [pRowsetScroll] -- Rowset used to fill cache.
  28. // [cBindings] -- Size of [pBindings].
  29. // [pBindings] -- Default binding.
  30. // [cbMaxLen] -- Max length of data fetched via [pBindings]
  31. // [iColumnBookmark] -- Ordinal of column containing bookmark.
  32. // [cbBookmark] -- Size of bookmark
  33. //
  34. // History: 05-Jun-95 KyleP Created.
  35. // 06-Jan-2000 KLam Fixed bindings
  36. //
  37. //----------------------------------------------------------------------------
  38. CMiniPositionableCache::CMiniPositionableCache( int Index,
  39. IRowsetScroll * pRowsetScroll,
  40. unsigned cBindings,
  41. DBBINDING * pBindings,
  42. unsigned cbMaxLen,
  43. DBORDINAL iColumnBookmark,
  44. DBBKMARK cbBookmark )
  45. : PMiniRowCache( Index,
  46. pRowsetScroll,
  47. cBindings,
  48. pBindings,
  49. cbMaxLen ),
  50. _pRowsetScroll( pRowsetScroll ),
  51. _fUsingBookmark( FALSE ),
  52. _haccBookmark( (HACCESSOR)0xFFFFFFFF ),
  53. _pbBookmark( (unsigned) ( sizeof(DBBKMARK) + cbBookmark + 1 )),
  54. _pbBookmarkSeek( (unsigned) (sizeof(DBBKMARK) + cbBookmark + 1 )),
  55. _hrowPrev( DB_NULL_HROW )
  56. {
  57. if ( iColumnBookmark != -1 )
  58. {
  59. _fUsingBookmark = TRUE;
  60. //
  61. // Setup accessor for bookmark.
  62. //
  63. DBBINDING bindBmk;
  64. RtlZeroMemory(&bindBmk, sizeof bindBmk);
  65. bindBmk.iOrdinal = iColumnBookmark;
  66. bindBmk.obValue = sizeof(DBLENGTH);
  67. bindBmk.obLength = 0;
  68. bindBmk.dwPart = DBPART_VALUE | DBPART_LENGTH;
  69. bindBmk.cbMaxLen = _pbBookmark.Count() - sizeof(DBLENGTH);
  70. bindBmk.wType = DBTYPE_BYTES;
  71. IAccessor * pia = 0;
  72. SCODE sc = _pRowsetScroll->QueryInterface( IID_IAccessor, (void **)&pia );
  73. if (SUCCEEDED( sc ))
  74. {
  75. sc = pia->CreateAccessor( DBACCESSOR_ROWDATA,
  76. 1,
  77. &bindBmk,
  78. 0,
  79. &_haccBookmark,
  80. 0);
  81. pia->Release();
  82. }
  83. if ( FAILED(sc) )
  84. {
  85. vqDebugOut(( DEB_ERROR,
  86. "CMiniPositionableCache: CreateAccessor returned 0x%x\n",
  87. sc ));
  88. THROW( CException( sc ) );
  89. }
  90. }
  91. //
  92. // Start with bookmark positioned at beginning of rowset (DBBMK_FIRST)
  93. //
  94. *(DBBKMARK *)_pbBookmark.GetPointer() = sizeof(BYTE);
  95. _pbBookmark[sizeof(DBBKMARK)] = DBBMK_FIRST;
  96. _oBookmark = 0;
  97. *(DBBKMARK *)_pbBookmarkSeek.GetPointer() = sizeof(BYTE);
  98. _pbBookmarkSeek[sizeof(DBBKMARK)] = DBBMK_FIRST;
  99. _xpbPrevRow.Set( new BYTE [_cbRow] );
  100. Next();
  101. }
  102. //+---------------------------------------------------------------------------
  103. //
  104. // Member: CMiniPositionableCache::~CMiniPositionableCache, public
  105. //
  106. // Synopsis: Destructor
  107. //
  108. // History: 05-Jun-95 KyleP Created.
  109. //
  110. //----------------------------------------------------------------------------
  111. CMiniPositionableCache::~CMiniPositionableCache()
  112. {
  113. if ( _haccBookmark != (HACCESSOR)0xFFFFFFFF )
  114. {
  115. IAccessor * pia = 0;
  116. _pRowsetScroll->QueryInterface( IID_IAccessor, (void **)&pia );
  117. Win4Assert(pia && "No Accessor!");
  118. pia->ReleaseAccessor( _haccBookmark, 0 );
  119. pia->Release();
  120. }
  121. }
  122. //+---------------------------------------------------------------------------
  123. //
  124. // Member: CMiniPositionableCache::Next, public
  125. //
  126. // Synopsis: Moves to next row
  127. //
  128. // Returns: Move status
  129. //
  130. // History: 05-Jun-95 KyleP Created.
  131. //
  132. //----------------------------------------------------------------------------
  133. PMiniRowCache::ENext CMiniPositionableCache::Next( int iDir /* = 1 */ )
  134. {
  135. //
  136. // If we had a row in cache, Just advance to it. Otherwise
  137. // fetch more rows from table.
  138. //
  139. _ihrow++;
  140. if ( _ihrow >= _chrow )
  141. {
  142. Win4Assert( iDir );
  143. iDir = iDir > 0 ? 1 : -1 ;
  144. //
  145. // Fetch more rows from table.
  146. //
  147. HROW * phrow = _ahrow.GetPointer();
  148. SCODE sc = _pRowsetScroll->GetRowsAt(
  149. 0, // Watch region handle
  150. 0, // Chapter
  151. *(DBBKMARK *)_pbBookmark.GetPointer(), // cbBookmark
  152. _pbBookmark.GetPointer() + sizeof(DBBKMARK), // pbBookmark
  153. _oBookmark, // Offset from bookmark
  154. _ahrow.Count() * iDir, // Rows requested
  155. &_chrow, // Rows received
  156. &phrow ); // HROWs stored here
  157. Win4Assert( DB_E_BADSTARTPOSITION != sc );
  158. vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", _chrow, _Index ));
  159. if ( FAILED(sc) )
  160. {
  161. vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAt\n", sc ));
  162. _chrow = 0;
  163. THROW( CException( sc ) );
  164. }
  165. else if ( 0 == _chrow && sc != DB_S_ENDOFROWSET )
  166. {
  167. return( PMiniRowCache::NotNow );
  168. }
  169. if ( _fUsingBookmark && _chrow > 0 )
  170. {
  171. //
  172. // Update current bookmark to last row fetched.
  173. //
  174. SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned) (_chrow-1)],
  175. _haccBookmark,
  176. _pbBookmark.GetPointer() );
  177. if ( FAILED(sc) )
  178. {
  179. vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
  180. THROW( CException( sc ) );
  181. }
  182. _oBookmark = 1;
  183. }
  184. else
  185. _oBookmark += _chrow;
  186. _ihrow = 0;
  187. }
  188. if( IsAtEnd() )
  189. {
  190. *(DBBKMARK *)_pbBookmark.GetPointer() = sizeof(BYTE);
  191. _pbBookmark[sizeof(DBBKMARK)] = DBBMK_LAST;
  192. return CMiniPositionableCache::EndOfRows;
  193. }
  194. LoadData();
  195. return CMiniPositionableCache::Ok;
  196. }
  197. //+---------------------------------------------------------------------------
  198. //
  199. // Member: CMiniPositionableCache::LoadPrevRowData, public
  200. //
  201. // Synopsis: Load the previous row data from the current top
  202. // position into _hrowPrev and _xpbPrevRow
  203. //
  204. // Returns: status
  205. //
  206. // History: 12-Sep-98 VikasMan Created
  207. //
  208. // Notes: The positioning of the cursor does not change in this call.
  209. // _hrwoPrev is set to DB_NULL_HROW if there is no previous row
  210. //
  211. //----------------------------------------------------------------------------
  212. PMiniRowCache::ENext CMiniPositionableCache::LoadPrevRowData()
  213. {
  214. DBCOUNTITEM chrow = 0;
  215. if ( _hrowPrev != DB_NULL_HROW )
  216. {
  217. _pRowsetScroll->ReleaseRows( 1, &_hrowPrev, 0, 0, 0 );
  218. _hrowPrev = DB_NULL_HROW;
  219. }
  220. HROW * phrowPrev = &_hrowPrev;
  221. SCODE sc = _pRowsetScroll->GetRowsAt(
  222. 0, // Watch region handle
  223. 0, // Chapter
  224. *(DBBKMARK *)_pbBookmark.GetPointer(), // cbBookmark
  225. _pbBookmark.GetPointer() + sizeof(DBBKMARK), // pbBookmark
  226. 0 - _chrow, // Offset from bookmark
  227. 1, // Rows requested
  228. &chrow, // Rows received
  229. &phrowPrev ); // HROWs stored here
  230. Win4Assert( DB_E_BADSTARTPOSITION != sc );
  231. vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", chrow, _Index ));
  232. if ( FAILED(sc) )
  233. {
  234. vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAt\n", sc ));
  235. _hrowPrev = DB_NULL_HROW;
  236. THROW( CException( sc ) );
  237. }
  238. else if ( 0 == chrow )
  239. {
  240. return ( sc == DB_S_ENDOFROWSET ?
  241. PMiniRowCache::EndOfRows : PMiniRowCache::NotNow );
  242. }
  243. if ( 1 == chrow )
  244. {
  245. Win4Assert( _hrowPrev != DB_NULL_HROW );
  246. // Load Data
  247. SCODE sc = _pRowset->GetData( _hrowPrev, _hacc, _xpbPrevRow.GetPointer() );
  248. if ( FAILED(sc) )
  249. {
  250. vqDebugOut(( DEB_ERROR, "PMiniRowCache: GetData returned 0x%x\n", sc ));
  251. THROW( CException( E_FAIL ) );
  252. }
  253. }
  254. return CMiniPositionableCache::Ok;
  255. }
  256. //+---------------------------------------------------------------------------
  257. //
  258. // Member: CMiniPositionableCache::MovePrev, public
  259. //
  260. // Synopsis: Move to the previous row
  261. //
  262. // Returns: status
  263. //
  264. // History: 12-Sep-98 VikasMan Created
  265. //
  266. // Notes: This function uses _hrowPrev to move to previous row. Use
  267. // LoadPrevRowData to fill up _hrowPrev and then call this function.
  268. //
  269. //
  270. //----------------------------------------------------------------------------
  271. PMiniRowCache::ENext CMiniPositionableCache::MovePrev()
  272. {
  273. if ( _ihrow > 0 )
  274. {
  275. _ihrow--;
  276. }
  277. else if ( _hrowPrev != DB_NULL_HROW )
  278. {
  279. if ( _chrow > 0 )
  280. {
  281. _pRowsetScroll->ReleaseRows( 1, &_ahrow[(unsigned)(_chrow - 1)], 0, 0, 0 );
  282. RtlMoveMemory( &_ahrow[1], &_ahrow[0], ( _chrow - 1 ) * sizeof( HROW ) );
  283. }
  284. else
  285. {
  286. SetCacheSize( _chrow = 1 );
  287. }
  288. _ahrow[0] = _hrowPrev;
  289. _hrowPrev = DB_NULL_HROW;
  290. RtlCopyMemory( _pbRow, _xpbPrevRow.GetPointer(), _cbRow );
  291. if ( _fUsingBookmark )
  292. {
  293. //
  294. // Update current bookmark to last row fetched.
  295. //
  296. SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned)(_chrow-1)],
  297. _haccBookmark,
  298. _pbBookmark.GetPointer() );
  299. if ( FAILED(sc) )
  300. {
  301. vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
  302. THROW( CException( sc ) );
  303. }
  304. _oBookmark = 1;
  305. }
  306. }
  307. return CMiniPositionableCache::Ok;
  308. }
  309. //+---------------------------------------------------------------------------
  310. //
  311. // Member: CMiniPositionableCache::Seek, public
  312. //
  313. // Synopsis: Seek forward from current position.
  314. //
  315. // Arguments: [lRows] -- Rows to move from last seek position.
  316. //
  317. // Returns: Move status
  318. //
  319. // History: 05-Jun-95 KyleP Created.
  320. //
  321. //----------------------------------------------------------------------------
  322. PMiniRowCache::ENext CMiniPositionableCache::Seek( DBROWOFFSET lRows )
  323. {
  324. FlushCache();
  325. memcpy( _pbBookmark.GetPointer(),
  326. _pbBookmarkSeek.GetPointer(),
  327. _pbBookmark.Count() );
  328. _oBookmark = lRows;
  329. vqDebugOut(( DEB_ITRACE, "%d: Seek %d\n", Index(), lRows ));
  330. return Next();
  331. }
  332. //+---------------------------------------------------------------------------
  333. //
  334. // Member: CMiniPositionableCache::Seek, public
  335. //
  336. // Synopsis: Seek to specified bookmark.
  337. //
  338. // Arguments: [cbBookmark] -- Size of [pbBookmark]
  339. // [pbBookmark] -- Bookmark
  340. //
  341. // Returns: Move status
  342. //
  343. // History: 05-Jun-95 KyleP Created.
  344. //
  345. //----------------------------------------------------------------------------
  346. PMiniRowCache::ENext CMiniPositionableCache::Seek( DBBKMARK cbBookmark, BYTE const * pbBookmark )
  347. {
  348. Win4Assert( _fUsingBookmark ||
  349. (cbBookmark == 1 && (*pbBookmark == DBBMK_FIRST || *pbBookmark == DBBMK_LAST) ) );
  350. FlushCache();
  351. #if CIDBG == 1
  352. if ( cbBookmark == 4 )
  353. vqDebugOut(( DEB_ITRACE, "%d: Seek 0x%x\n", Index(), *(ULONG UNALIGNED *)pbBookmark ));
  354. #endif
  355. //
  356. // Set up bookmark.
  357. //
  358. *(DBBKMARK *)_pbBookmark.GetPointer() = cbBookmark;
  359. memcpy( _pbBookmark.GetPointer() + sizeof(DBBKMARK),
  360. pbBookmark,
  361. (unsigned) cbBookmark );
  362. *(DBBKMARK *)_pbBookmarkSeek.GetPointer() = cbBookmark;
  363. memcpy( _pbBookmarkSeek.GetPointer() + sizeof(DBBKMARK),
  364. pbBookmark,
  365. (unsigned) cbBookmark );
  366. _oBookmark = 0;
  367. return Next();
  368. }
  369. //+---------------------------------------------------------------------------
  370. //
  371. // Member: CMiniPositionableCache::Seek, public
  372. //
  373. // Synopsis: Seek to specified approximate position.
  374. //
  375. // Arguments: [ulNumerator] -- Numerator.
  376. // [ulDenominator] -- Denominator.
  377. //
  378. // Returns: Move status
  379. //
  380. // History: 05-Jun-95 KyleP Created.
  381. //
  382. //----------------------------------------------------------------------------
  383. PMiniRowCache::ENext CMiniPositionableCache::Seek( DBCOUNTITEM ulNumerator, DBCOUNTITEM ulDenominator )
  384. {
  385. Win4Assert( _fUsingBookmark );
  386. FlushCache();
  387. vqDebugOut(( DEB_ITRACE, "%d: Seek %u/%u through.\n", Index(), ulNumerator, ulDenominator ));
  388. HROW * phrow = _ahrow.GetPointer();
  389. SCODE sc = _pRowsetScroll->GetRowsAtRatio( 0, // Watch region handle
  390. 0, // Chapter
  391. ulNumerator,
  392. ulDenominator,
  393. _ahrow.Count(), // Rows requested
  394. &_chrow, // Rows received
  395. &phrow ); // HROWs stored here
  396. vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", _chrow, _Index ));
  397. if ( FAILED(sc) )
  398. {
  399. vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAtRatio\n", sc ));
  400. _chrow = 0;
  401. THROW( CException( sc ) );
  402. }
  403. else if ( 0 == _chrow && sc != DB_S_ENDOFROWSET )
  404. {
  405. return( PMiniRowCache::NotNow );
  406. }
  407. if ( _chrow > 0 )
  408. {
  409. //
  410. // Update current bookmark to last row fetched.
  411. //
  412. SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned)(_chrow-1)],
  413. _haccBookmark,
  414. _pbBookmark.GetPointer() );
  415. if ( FAILED(sc) )
  416. {
  417. vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
  418. THROW( CException( sc ) );
  419. }
  420. memcpy( _pbBookmarkSeek.GetPointer(),
  421. _pbBookmark.GetPointer(),
  422. _pbBookmark.Count() );
  423. _oBookmark = 1;
  424. }
  425. _ihrow = 0;
  426. if( IsAtEnd() )
  427. {
  428. return CMiniPositionableCache::EndOfRows;
  429. }
  430. LoadData();
  431. return CMiniPositionableCache::Ok;
  432. }
  433. //+---------------------------------------------------------------------------
  434. //
  435. // Member: CMiniPositionableCache::FlushCache, public
  436. //
  437. // Synopsis: Clear the cache.
  438. //
  439. // History: 12-Sep-98 VikasMan Created
  440. //
  441. //----------------------------------------------------------------------------
  442. void CMiniPositionableCache::FlushCache()
  443. {
  444. if ( _hrowPrev != DB_NULL_HROW )
  445. {
  446. _pRowsetScroll->ReleaseRows( 1, &_hrowPrev, 0, 0, 0 );
  447. _hrowPrev = DB_NULL_HROW;
  448. }
  449. PMiniRowCache::FlushCache();
  450. }