|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 1998
//
// File: RowHeap.cxx
//
// Contents: Heap of rowsets.
//
// Classes: CRowHeap
//
// History: 05-Jun-95 KyleP Created
// 14-JAN-97 KrishnaN Undefined CI_INETSRV and related changes
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include "rowheap.hxx"
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::CRowHeap, public
//
// Synopsis: Constructor.
//
// Arguments: [cCursor] -- Max number of elements in heap.
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
CRowHeap::CRowHeap( unsigned cCursor ) : _ahrowTop( cCursor ), _cCursor( cCursor ) { END_CONSTRUCTION( CRowHeap ); }
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::Init, public
//
// Synopsis: Create heap.
//
// Arguments: [pComparator] -- Used to compare elements.
// [apCursor] -- Heap created from these.
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
void CRowHeap::Init( CRowComparator * pComparator, PMiniRowCache ** apCursor ) { _pComparator = pComparator; _apCursor = apCursor;
//
// Move invalid cursors to end.
//
int cValid = _cCursor;
for ( int i = 0; i < cValid; i++ ) { if ( _apCursor[i]->IsAtEnd() ) { cValid--; PMiniRowCache * pTemp = _apCursor[i]; _apCursor[i] = _apCursor[cValid]; _apCursor[cValid] = pTemp; i--; } }
//
// And create a heap out of the rest.
//
MakeHeap( cValid ); }
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::ReInit, public
//
// Synopsis: Recreate heap.
//
// Arguments: [cValid] -- Number of valid cursors. Others to end.
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
void CRowHeap::ReInit( int cValid ) { MakeHeap( cValid ); }
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::Validate, public
//
// Synopsis: See notes.
//
// Returns: State of heap.
//
// History: 05-Jun-95 KyleP Created.
//
// Notes: There are times when iteration stopped because some cursor
// couldn't continue (usually for block-limited rows, or
// some error condition). When this situation occurs, Validate
// must be called to reset the heap.
//
//----------------------------------------------------------------------------
PMiniRowCache::ENext CRowHeap::Validate() { if ( !IsHeapEmpty() && Top()->IsAtEnd() ) return Next(); else return PMiniRowCache::Ok; }
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::AdjustCacheSize, public
//
// Synopsis: Adjust size of row cache(s).
//
// Arguments: [cRows] -- Total number of rows to cache.
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
void CRowHeap::AdjustCacheSize( ULONG cRows ) { if ( Count() > 0 ) { ULONG cRowsPerCursor = 1 + cRows / Count();
if ( cRowsPerCursor != Top()->CacheSize() ) { for ( int i = 0; i < _cCursor; i++ ) _apCursor[i]->SetCacheSize( cRowsPerCursor ); } } }
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::Next, public
//
// Synopsis: Move to next element.
//
// Returns: State of heap. Move occurred only if PMiniRowCache::Ok.
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
PMiniRowCache::ENext CRowHeap::Next( int iDir /* = 1 */ ) { PMiniRowCache::ENext next = Top()->Next( iDir );
if ( PMiniRowCache::NotNow == next ) return next;
if ( PMiniRowCache::EndOfRows == next ) { RemoveTop(); if ( IsHeapEmpty() ) return next;
next = PMiniRowCache::Ok; }
_ahrowTop[Top()->Index()] = Top()->GetHROW();
Reheap();
return next; }
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::NthToTop, public
//
// Effects: Moves Nth element of heap to top.
//
// Arguments: [n] -- Nth element of heap.
//
// History: 23-Jun-95 KyleP Created.
//
// Notes: This is different from CRowHeap::Next, because the caches
// themselves are not touched. It is used for approximate
// positioning.
//
// This is a destructive function! Elements are removed from
// the heap.
//
//----------------------------------------------------------------------------
void CRowHeap::NthToTop( unsigned n ) { for ( ; n > 0; n-- ) { RemoveTop(); Reheap(); } }
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::Add, public
//
// Synopsis: Add element to heap.
//
// Arguments: [pCursor] -- Cursor to add.
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
void CRowHeap::Add( PMiniRowCache * pCursor ) { //
// Special case: empty cursor.
//
if ( pCursor->IsAtEnd() ) {
_ahrowTop[pCursor->Index()] = (HROW)-1;
return; }
_iEnd++;
_ahrowTop[pCursor->Index()] = pCursor->GetHROW();
//
// Special case: empty heap.
//
if ( 0 == _iEnd ) { _apCursor[0] = pCursor; return; }
int child, parent;
for ( child = _iEnd, parent = (_iEnd-1)/2; child > 0; child=parent, parent = (parent-1)/2) { if ( !_pComparator->IsLT( pCursor->GetData(), pCursor->DataLength(), pCursor->Index(), _apCursor[parent]->GetData(), _apCursor[parent]->DataLength(), _apCursor[parent]->Index() ) ) break; _apCursor[child] = _apCursor[parent]; }
_apCursor[child] = pCursor; }
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::Reheap, private
//
// Synopsis: 'Heapify'. Called when top element (only!) has changed.
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
void CRowHeap::Reheap() { PMiniRowCache * root_item = _apCursor[0];
int parent, child;
for ( parent = 0, child = 1; child <= _iEnd; parent = child, child = 2 * child + 1 ) { if ( child < _iEnd && _pComparator->IsLT( _apCursor[child+1]->GetData(), _apCursor[child+1]->DataLength(), _apCursor[child+1]->Index(), _apCursor[child]->GetData(), _apCursor[child]->DataLength(), _apCursor[child]->Index() ) ) { child++; }
if ( !_pComparator->IsLT( _apCursor[child]->GetData(), _apCursor[child]->DataLength(), _apCursor[child]->Index(), root_item->GetData(), root_item->DataLength(), root_item->Index() ) ) { break; }
_apCursor[parent] = _apCursor[child]; }
_apCursor[parent] = root_item;
# if CIDBG == 1
AssertCursorArrayIsValid(); # endif
}
//+---------------------------------------------------------------------------
//
// Member: CRowHeap::MakeHeap, private
//
// Synopsis: 'Heapify'. Called when all elements have changed.
//
// Arguments: [cValid] -- Number of valid cursors, all positioned toward
// beginning of array.
//
// History: 05-Jun-95 KyleP Created.
//
//----------------------------------------------------------------------------
void CRowHeap::MakeHeap( int cValid ) { _iEnd = -1;
for ( int i = 0; i < cValid; i++ ) Add( _apCursor[i] );
for ( i = cValid; i < _cCursor; i++ ) _ahrowTop[_apCursor[i]->Index()] = (HROW)-1;
# if CIDBG == 1
AssertCursorArrayIsValid(); # endif
}
#if CIDBG == 1
void CRowHeap::AssertCursorArrayIsValid() { for ( int i = 0; i < _cCursor; i++ ) for ( int j = i+1; j < _cCursor; j++ ) { if ( _apCursor[i] == _apCursor[j] ) { vqDebugOut(( DEB_ERROR, "Invalid rowheap: _apCursor[%d] (0x%x) == _apCursor[%d] (0x%x)\n", i, _apCursor[i], j, _apCursor[j] )); Win4Assert( _apCursor[i] != _apCursor[j] ); } } }
#endif // CIDBG == 1
|