windows-nt/Source/XPSP1/NT/inetsrv/query/distrib/poscache.cxx
2020-09-26 16:20:57 +08:00

546 lines
16 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 2000
//
// File: PosCache.cxx
//
// Contents: Positionable cache
//
// Classes: CMiniPositionableCache
//
// History: 05-Jun-95 KyleP Created
// 14-JAN-97 KrishnaN Undefined CI_INETSRV and related changes
// 29-Mar-2000 KLam Fixed Bookmarks
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include "poscache.hxx"
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::CMiniPositionableCache, public
//
// Synopsis: Builds bindings to fetch bookmark.
//
// Arguments: [Index] -- Identifier. Not used internally.
// [pRowsetScroll] -- Rowset used to fill cache.
// [cBindings] -- Size of [pBindings].
// [pBindings] -- Default binding.
// [cbMaxLen] -- Max length of data fetched via [pBindings]
// [iColumnBookmark] -- Ordinal of column containing bookmark.
// [cbBookmark] -- Size of bookmark
//
// History: 05-Jun-95 KyleP Created.
// 06-Jan-2000 KLam Fixed bindings
//
//----------------------------------------------------------------------------
CMiniPositionableCache::CMiniPositionableCache( int Index,
IRowsetScroll * pRowsetScroll,
unsigned cBindings,
DBBINDING * pBindings,
unsigned cbMaxLen,
DBORDINAL iColumnBookmark,
DBBKMARK cbBookmark )
: PMiniRowCache( Index,
pRowsetScroll,
cBindings,
pBindings,
cbMaxLen ),
_pRowsetScroll( pRowsetScroll ),
_fUsingBookmark( FALSE ),
_haccBookmark( (HACCESSOR)0xFFFFFFFF ),
_pbBookmark( (unsigned) ( sizeof(DBBKMARK) + cbBookmark + 1 )),
_pbBookmarkSeek( (unsigned) (sizeof(DBBKMARK) + cbBookmark + 1 )),
_hrowPrev( DB_NULL_HROW )
{
if ( iColumnBookmark != -1 )
{
_fUsingBookmark = TRUE;
//
// Setup accessor for bookmark.
//
DBBINDING bindBmk;
RtlZeroMemory(&bindBmk, sizeof bindBmk);
bindBmk.iOrdinal = iColumnBookmark;
bindBmk.obValue = sizeof(DBLENGTH);
bindBmk.obLength = 0;
bindBmk.dwPart = DBPART_VALUE | DBPART_LENGTH;
bindBmk.cbMaxLen = _pbBookmark.Count() - sizeof(DBLENGTH);
bindBmk.wType = DBTYPE_BYTES;
IAccessor * pia = 0;
SCODE sc = _pRowsetScroll->QueryInterface( IID_IAccessor, (void **)&pia );
if (SUCCEEDED( sc ))
{
sc = pia->CreateAccessor( DBACCESSOR_ROWDATA,
1,
&bindBmk,
0,
&_haccBookmark,
0);
pia->Release();
}
if ( FAILED(sc) )
{
vqDebugOut(( DEB_ERROR,
"CMiniPositionableCache: CreateAccessor returned 0x%x\n",
sc ));
THROW( CException( sc ) );
}
}
//
// Start with bookmark positioned at beginning of rowset (DBBMK_FIRST)
//
*(DBBKMARK *)_pbBookmark.GetPointer() = sizeof(BYTE);
_pbBookmark[sizeof(DBBKMARK)] = DBBMK_FIRST;
_oBookmark = 0;
*(DBBKMARK *)_pbBookmarkSeek.GetPointer() = sizeof(BYTE);
_pbBookmarkSeek[sizeof(DBBKMARK)] = DBBMK_FIRST;
_xpbPrevRow.Set( new BYTE [_cbRow] );
Next();
}
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::~CMiniPositionableCache, public
//
// Synopsis: Destructor
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
CMiniPositionableCache::~CMiniPositionableCache()
{
if ( _haccBookmark != (HACCESSOR)0xFFFFFFFF )
{
IAccessor * pia = 0;
_pRowsetScroll->QueryInterface( IID_IAccessor, (void **)&pia );
Win4Assert(pia && "No Accessor!");
pia->ReleaseAccessor( _haccBookmark, 0 );
pia->Release();
}
}
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::Next, public
//
// Synopsis: Moves to next row
//
// Returns: Move status
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
PMiniRowCache::ENext CMiniPositionableCache::Next( int iDir /* = 1 */ )
{
//
// If we had a row in cache, Just advance to it. Otherwise
// fetch more rows from table.
//
_ihrow++;
if ( _ihrow >= _chrow )
{
Win4Assert( iDir );
iDir = iDir > 0 ? 1 : -1 ;
//
// Fetch more rows from table.
//
HROW * phrow = _ahrow.GetPointer();
SCODE sc = _pRowsetScroll->GetRowsAt(
0, // Watch region handle
0, // Chapter
*(DBBKMARK *)_pbBookmark.GetPointer(), // cbBookmark
_pbBookmark.GetPointer() + sizeof(DBBKMARK), // pbBookmark
_oBookmark, // Offset from bookmark
_ahrow.Count() * iDir, // Rows requested
&_chrow, // Rows received
&phrow ); // HROWs stored here
Win4Assert( DB_E_BADSTARTPOSITION != sc );
vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", _chrow, _Index ));
if ( FAILED(sc) )
{
vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAt\n", sc ));
_chrow = 0;
THROW( CException( sc ) );
}
else if ( 0 == _chrow && sc != DB_S_ENDOFROWSET )
{
return( PMiniRowCache::NotNow );
}
if ( _fUsingBookmark && _chrow > 0 )
{
//
// Update current bookmark to last row fetched.
//
SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned) (_chrow-1)],
_haccBookmark,
_pbBookmark.GetPointer() );
if ( FAILED(sc) )
{
vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
THROW( CException( sc ) );
}
_oBookmark = 1;
}
else
_oBookmark += _chrow;
_ihrow = 0;
}
if( IsAtEnd() )
{
*(DBBKMARK *)_pbBookmark.GetPointer() = sizeof(BYTE);
_pbBookmark[sizeof(DBBKMARK)] = DBBMK_LAST;
return CMiniPositionableCache::EndOfRows;
}
LoadData();
return CMiniPositionableCache::Ok;
}
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::LoadPrevRowData, public
//
// Synopsis: Load the previous row data from the current top
// position into _hrowPrev and _xpbPrevRow
//
// Returns: status
//
// History: 12-Sep-98 VikasMan Created
//
// Notes: The positioning of the cursor does not change in this call.
// _hrwoPrev is set to DB_NULL_HROW if there is no previous row
//
//----------------------------------------------------------------------------
PMiniRowCache::ENext CMiniPositionableCache::LoadPrevRowData()
{
DBCOUNTITEM chrow = 0;
if ( _hrowPrev != DB_NULL_HROW )
{
_pRowsetScroll->ReleaseRows( 1, &_hrowPrev, 0, 0, 0 );
_hrowPrev = DB_NULL_HROW;
}
HROW * phrowPrev = &_hrowPrev;
SCODE sc = _pRowsetScroll->GetRowsAt(
0, // Watch region handle
0, // Chapter
*(DBBKMARK *)_pbBookmark.GetPointer(), // cbBookmark
_pbBookmark.GetPointer() + sizeof(DBBKMARK), // pbBookmark
0 - _chrow, // Offset from bookmark
1, // Rows requested
&chrow, // Rows received
&phrowPrev ); // HROWs stored here
Win4Assert( DB_E_BADSTARTPOSITION != sc );
vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", chrow, _Index ));
if ( FAILED(sc) )
{
vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAt\n", sc ));
_hrowPrev = DB_NULL_HROW;
THROW( CException( sc ) );
}
else if ( 0 == chrow )
{
return ( sc == DB_S_ENDOFROWSET ?
PMiniRowCache::EndOfRows : PMiniRowCache::NotNow );
}
if ( 1 == chrow )
{
Win4Assert( _hrowPrev != DB_NULL_HROW );
// Load Data
SCODE sc = _pRowset->GetData( _hrowPrev, _hacc, _xpbPrevRow.GetPointer() );
if ( FAILED(sc) )
{
vqDebugOut(( DEB_ERROR, "PMiniRowCache: GetData returned 0x%x\n", sc ));
THROW( CException( E_FAIL ) );
}
}
return CMiniPositionableCache::Ok;
}
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::MovePrev, public
//
// Synopsis: Move to the previous row
//
// Returns: status
//
// History: 12-Sep-98 VikasMan Created
//
// Notes: This function uses _hrowPrev to move to previous row. Use
// LoadPrevRowData to fill up _hrowPrev and then call this function.
//
//
//----------------------------------------------------------------------------
PMiniRowCache::ENext CMiniPositionableCache::MovePrev()
{
if ( _ihrow > 0 )
{
_ihrow--;
}
else if ( _hrowPrev != DB_NULL_HROW )
{
if ( _chrow > 0 )
{
_pRowsetScroll->ReleaseRows( 1, &_ahrow[(unsigned)(_chrow - 1)], 0, 0, 0 );
RtlMoveMemory( &_ahrow[1], &_ahrow[0], ( _chrow - 1 ) * sizeof( HROW ) );
}
else
{
SetCacheSize( _chrow = 1 );
}
_ahrow[0] = _hrowPrev;
_hrowPrev = DB_NULL_HROW;
RtlCopyMemory( _pbRow, _xpbPrevRow.GetPointer(), _cbRow );
if ( _fUsingBookmark )
{
//
// Update current bookmark to last row fetched.
//
SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned)(_chrow-1)],
_haccBookmark,
_pbBookmark.GetPointer() );
if ( FAILED(sc) )
{
vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
THROW( CException( sc ) );
}
_oBookmark = 1;
}
}
return CMiniPositionableCache::Ok;
}
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::Seek, public
//
// Synopsis: Seek forward from current position.
//
// Arguments: [lRows] -- Rows to move from last seek position.
//
// Returns: Move status
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
PMiniRowCache::ENext CMiniPositionableCache::Seek( DBROWOFFSET lRows )
{
FlushCache();
memcpy( _pbBookmark.GetPointer(),
_pbBookmarkSeek.GetPointer(),
_pbBookmark.Count() );
_oBookmark = lRows;
vqDebugOut(( DEB_ITRACE, "%d: Seek %d\n", Index(), lRows ));
return Next();
}
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::Seek, public
//
// Synopsis: Seek to specified bookmark.
//
// Arguments: [cbBookmark] -- Size of [pbBookmark]
// [pbBookmark] -- Bookmark
//
// Returns: Move status
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
PMiniRowCache::ENext CMiniPositionableCache::Seek( DBBKMARK cbBookmark, BYTE const * pbBookmark )
{
Win4Assert( _fUsingBookmark ||
(cbBookmark == 1 && (*pbBookmark == DBBMK_FIRST || *pbBookmark == DBBMK_LAST) ) );
FlushCache();
#if CIDBG == 1
if ( cbBookmark == 4 )
vqDebugOut(( DEB_ITRACE, "%d: Seek 0x%x\n", Index(), *(ULONG UNALIGNED *)pbBookmark ));
#endif
//
// Set up bookmark.
//
*(DBBKMARK *)_pbBookmark.GetPointer() = cbBookmark;
memcpy( _pbBookmark.GetPointer() + sizeof(DBBKMARK),
pbBookmark,
(unsigned) cbBookmark );
*(DBBKMARK *)_pbBookmarkSeek.GetPointer() = cbBookmark;
memcpy( _pbBookmarkSeek.GetPointer() + sizeof(DBBKMARK),
pbBookmark,
(unsigned) cbBookmark );
_oBookmark = 0;
return Next();
}
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::Seek, public
//
// Synopsis: Seek to specified approximate position.
//
// Arguments: [ulNumerator] -- Numerator.
// [ulDenominator] -- Denominator.
//
// Returns: Move status
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
PMiniRowCache::ENext CMiniPositionableCache::Seek( DBCOUNTITEM ulNumerator, DBCOUNTITEM ulDenominator )
{
Win4Assert( _fUsingBookmark );
FlushCache();
vqDebugOut(( DEB_ITRACE, "%d: Seek %u/%u through.\n", Index(), ulNumerator, ulDenominator ));
HROW * phrow = _ahrow.GetPointer();
SCODE sc = _pRowsetScroll->GetRowsAtRatio( 0, // Watch region handle
0, // Chapter
ulNumerator,
ulDenominator,
_ahrow.Count(), // Rows requested
&_chrow, // Rows received
&phrow ); // HROWs stored here
vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", _chrow, _Index ));
if ( FAILED(sc) )
{
vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAtRatio\n", sc ));
_chrow = 0;
THROW( CException( sc ) );
}
else if ( 0 == _chrow && sc != DB_S_ENDOFROWSET )
{
return( PMiniRowCache::NotNow );
}
if ( _chrow > 0 )
{
//
// Update current bookmark to last row fetched.
//
SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned)(_chrow-1)],
_haccBookmark,
_pbBookmark.GetPointer() );
if ( FAILED(sc) )
{
vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
THROW( CException( sc ) );
}
memcpy( _pbBookmarkSeek.GetPointer(),
_pbBookmark.GetPointer(),
_pbBookmark.Count() );
_oBookmark = 1;
}
_ihrow = 0;
if( IsAtEnd() )
{
return CMiniPositionableCache::EndOfRows;
}
LoadData();
return CMiniPositionableCache::Ok;
}
//+---------------------------------------------------------------------------
//
// Member: CMiniPositionableCache::FlushCache, public
//
// Synopsis: Clear the cache.
//
// History: 12-Sep-98 VikasMan Created
//
//----------------------------------------------------------------------------
void CMiniPositionableCache::FlushCache()
{
if ( _hrowPrev != DB_NULL_HROW )
{
_pRowsetScroll->ReleaseRows( 1, &_hrowPrev, 0, 0, 0 );
_hrowPrev = DB_NULL_HROW;
}
PMiniRowCache::FlushCache();
}