407 lines
9.9 KiB
C++
407 lines
9.9 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1994.
|
||
|
//
|
||
|
// File: seglist.hxx
|
||
|
//
|
||
|
// Contents: List of CTableSegment objects.
|
||
|
//
|
||
|
// Classes: CTableSegList
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
// History: 1-15-95 srikants Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <tableseg.hxx>
|
||
|
#include <segmru.hxx>
|
||
|
|
||
|
#include <sglookup.hxx>
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CTableSegList
|
||
|
//
|
||
|
// Purpose: A List of CTableSegments
|
||
|
//
|
||
|
// History: 1-16-95 srikants Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
class CTableSegList : public CDoubleList
|
||
|
{
|
||
|
|
||
|
friend class CSegListMgr;
|
||
|
friend class CFwdTableSegIter;
|
||
|
friend class CBackTableSegIter;
|
||
|
|
||
|
public:
|
||
|
|
||
|
CTableSegList() : _cWindows(0), _cBuckets(0){}
|
||
|
|
||
|
~CTableSegList();
|
||
|
|
||
|
CTableSegment* GetTop() { return (CTableSegment *) _Top(); }
|
||
|
|
||
|
|
||
|
unsigned GetWindowsCount() const { return _cWindows; }
|
||
|
|
||
|
unsigned GetBucketsCount() const { return _cBuckets; }
|
||
|
|
||
|
unsigned GetSegmentsCount() const { return _cWindows + _cBuckets; }
|
||
|
|
||
|
CTableSegment * GetFirst()
|
||
|
{
|
||
|
return !IsEmpty() ? (CTableSegment *) _root.Next() : 0;
|
||
|
}
|
||
|
|
||
|
CTableSegment * GetLast()
|
||
|
{
|
||
|
return !IsEmpty() ? (CTableSegment *) _root.Prev() : 0;
|
||
|
}
|
||
|
|
||
|
CTableSegment * GetNext( CTableSegment * pNode )
|
||
|
{
|
||
|
Win4Assert( 0 != pNode );
|
||
|
if ( !IsLast( *pNode ) )
|
||
|
{
|
||
|
return (CTableSegment *) pNode->Next();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CTableSegment * GetPrev( CTableSegment * pNode )
|
||
|
{
|
||
|
Win4Assert( 0 != pNode );
|
||
|
if ( !IsFirst( *pNode ) )
|
||
|
{
|
||
|
return (CTableSegment *) pNode->Prev();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Push ( CTableSegment * pTableSeg )
|
||
|
{
|
||
|
Win4Assert( 0 != pTableSeg );
|
||
|
_Push ( pTableSeg );
|
||
|
_IncrementCount( *pTableSeg );
|
||
|
}
|
||
|
|
||
|
void Queue( CTableSegment * pTableSeg )
|
||
|
{
|
||
|
Win4Assert( 0 != pTableSeg );
|
||
|
_Queue ( pTableSeg );
|
||
|
_IncrementCount( *pTableSeg );
|
||
|
}
|
||
|
|
||
|
void InsertAfter ( CTableSegment * pBefore, CTableSegment * pNew );
|
||
|
|
||
|
void InsertBefore( CTableSegment * pAfter, CTableSegment * pNew );
|
||
|
|
||
|
CTableSegment * RemoveTop();
|
||
|
|
||
|
void RemoveFromList( CTableSegment * pNode );
|
||
|
|
||
|
CTableSegment * Replace( CDoubleIter &it, CTableSegment * pNew );
|
||
|
|
||
|
#ifdef CIEXTMODE
|
||
|
void CiExtDump(void *ciExtSelf);
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
|
||
|
unsigned _cWindows; // Count of windows
|
||
|
unsigned _cBuckets; // Count of buckets
|
||
|
|
||
|
BOOL _IsNodeInList( CTableSegment * pNode );
|
||
|
|
||
|
void _IncrementCount( const CTableSegment & node );
|
||
|
|
||
|
void _DecrementCount( const CTableSegment & node );
|
||
|
|
||
|
CDoubleLink & _GetRoot()
|
||
|
{
|
||
|
return _root;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CDoubleTableSegIter
|
||
|
//
|
||
|
// Purpose: Iterator over a table segment list.
|
||
|
//
|
||
|
// History: 25-Jul-95 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
class CDoubleTableSegIter : public CDoubleList::CDoubleIter
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CDoubleTableSegIter ( CDoubleLink* pSeg ) : CDoubleIter(pSeg) {}
|
||
|
CDoubleTableSegIter ( CDoubleTableSegIter& iter ) : CDoubleIter(iter) {}
|
||
|
|
||
|
CTableSegment* operator->() { return (CTableSegment*) _pLinkCur; }
|
||
|
CTableSegment* GetSegment() { return (CTableSegment*) _pLinkCur; }
|
||
|
|
||
|
CTableWindow * GetWindow();
|
||
|
CTableBucket * GetBucket();
|
||
|
|
||
|
};
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CFwdTableSegIter
|
||
|
//
|
||
|
// Purpose: Iterator over a table segment list.
|
||
|
//
|
||
|
// History: 15-Jan-95 SrikantS Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
class CTableWindow;
|
||
|
class CTableBucket;
|
||
|
|
||
|
class CFwdTableSegIter : public CDoubleTableSegIter
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CFwdTableSegIter ( CTableSegList& list )
|
||
|
: CDoubleTableSegIter(list._GetRoot().Next()) {}
|
||
|
// copy constructor
|
||
|
CFwdTableSegIter ( CFwdTableSegIter& iter) : CDoubleTableSegIter(iter) {}
|
||
|
|
||
|
};
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CBackTableSegIter
|
||
|
//
|
||
|
// Purpose: Iterator over a table segment list.
|
||
|
//
|
||
|
// History: 15-Jan-95 SrikantS Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
class CBackTableSegIter : public CDoubleTableSegIter
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CBackTableSegIter ( CTableSegList& list )
|
||
|
: CDoubleTableSegIter(list._GetRoot().Prev()) {}
|
||
|
|
||
|
};
|
||
|
|
||
|
inline BOOL IsSpecialWid( WORKID wid )
|
||
|
{
|
||
|
Win4Assert( WORKID_TBLBEFOREFIRST == ((WORKID) 0xfffffffb) );
|
||
|
Win4Assert( WORKID_TBLFIRST == ((WORKID) 0xfffffffc) );
|
||
|
Win4Assert( WORKID_TBLLAST == ((WORKID) 0xfffffffd) );
|
||
|
Win4Assert( WORKID_TBLAFTERLAST == ((WORKID) 0xfffffffe) );
|
||
|
|
||
|
return wid >= WORKID_TBLBEFOREFIRST &&
|
||
|
wid <= WORKID_TBLAFTERLAST;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CSegListMgr
|
||
|
//
|
||
|
// Purpose: Manages list of segments and caching of segments that are
|
||
|
// in use by the query or client threads.
|
||
|
//
|
||
|
// History: 4-11-95 srikants Created
|
||
|
//
|
||
|
// Notes: All operations that modify the physical structure of the
|
||
|
// segment list MUST go through this object.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
class CSegListMgr
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CSegListMgr( unsigned nSegsToCache )
|
||
|
: _pCachedPutRowSeg(0) , _clientSegs(nSegsToCache),
|
||
|
_bucketSegs(ULONG_MAX)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
~CSegListMgr();
|
||
|
|
||
|
void Push ( CTableSegment * pTableSeg )
|
||
|
{
|
||
|
_list.Push( pTableSeg );
|
||
|
_lookupArray.InsertBefore( 0, pTableSeg );
|
||
|
}
|
||
|
|
||
|
void InsertAfter ( CTableSegment * pBefore, CTableSegment * pNew )
|
||
|
{
|
||
|
_list.InsertAfter( pBefore, pNew );
|
||
|
_lookupArray.InsertAfter( pBefore, pNew );
|
||
|
|
||
|
_lookupArray.TestInSync( _list );
|
||
|
}
|
||
|
|
||
|
void InsertBefore( CTableSegment * pAfter, CTableSegment * pNew )
|
||
|
{
|
||
|
_list.InsertBefore( pAfter, pNew );
|
||
|
_lookupArray.InsertBefore( pAfter, pNew );
|
||
|
|
||
|
_lookupArray.TestInSync( _list );
|
||
|
}
|
||
|
|
||
|
CTableSegment * RemoveTop()
|
||
|
{
|
||
|
CTableSegment * pFirst = _list.RemoveTop();
|
||
|
_InvalidateIfCached( pFirst );
|
||
|
_lookupArray.RemoveEntry( pFirst );
|
||
|
|
||
|
_lookupArray.TestInSync( _list );
|
||
|
|
||
|
return pFirst;
|
||
|
}
|
||
|
|
||
|
void RemoveFromList( CTableSegment * pNode )
|
||
|
{
|
||
|
_list.RemoveFromList( pNode );
|
||
|
_InvalidateIfCached( pNode );
|
||
|
_lookupArray.RemoveEntry( pNode );
|
||
|
|
||
|
_lookupArray.TestInSync( _list );
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Replaces the node in the iterator with the new node in the iterator
|
||
|
// as well as the list.
|
||
|
//
|
||
|
CTableSegment * Replace( CDoubleList::CDoubleIter & iter, CTableSegment * pNew )
|
||
|
{
|
||
|
Win4Assert( 0 != pNew );
|
||
|
Win4Assert( !_list.AtEnd( iter ) );
|
||
|
|
||
|
CTableSegment * pCurrent = _list.Replace(iter, pNew);
|
||
|
_InvalidateIfCached( pCurrent );
|
||
|
_lookupArray.Replace( pCurrent, pNew );
|
||
|
|
||
|
_lookupArray.TestInSync( _list );
|
||
|
|
||
|
return pCurrent;
|
||
|
}
|
||
|
|
||
|
CTableSegment * Replace( CTableSegment * pOld, CTableSegList & list );
|
||
|
|
||
|
//
|
||
|
// Methods that operate on the cached segment pointers.
|
||
|
//
|
||
|
void SetCachedPutRowSeg( CTableSegment * pSeg )
|
||
|
{
|
||
|
_pCachedPutRowSeg = pSeg;
|
||
|
}
|
||
|
|
||
|
CTableSegment * GetCachedPutRowSeg()
|
||
|
{
|
||
|
return _pCachedPutRowSeg;
|
||
|
}
|
||
|
|
||
|
void SetInUseByClient( WORKID wid, CTableSegment * pSeg )
|
||
|
{
|
||
|
if ( widInvalid != wid &&
|
||
|
!IsSpecialWid(wid) )
|
||
|
{
|
||
|
_clientSegs.AddReplace( wid, pSeg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UpdateSegsInUse( CTableSegment * pSeg );
|
||
|
|
||
|
BOOL IsInUseByClient( CTableSegment * pSeg )
|
||
|
{
|
||
|
return _clientSegs.IsSegmentInUse( pSeg );
|
||
|
}
|
||
|
|
||
|
BOOL IsRecentlyUsed( CTableSegment * pSeg )
|
||
|
{
|
||
|
if ( pSeg == _pCachedPutRowSeg ||
|
||
|
_clientSegs.IsSegmentInUse( pSeg ) )
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
else if ( !_bucketSegs.IsEmpty() &&
|
||
|
_bucketSegs.IsSegmentInUse( pSeg ) )
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void SetInUseByBuckets( WORKID wid )
|
||
|
{
|
||
|
if ( widInvalid != wid &&
|
||
|
!IsSpecialWid(wid) )
|
||
|
{
|
||
|
_bucketSegs.AddReplace( wid, 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ClearInUseByBuckets( WORKID wid )
|
||
|
{
|
||
|
if ( widInvalid != wid &&
|
||
|
!IsSpecialWid(wid) )
|
||
|
{
|
||
|
_bucketSegs.Remove( wid );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CTableSegList & GetList()
|
||
|
{
|
||
|
return _list;
|
||
|
}
|
||
|
|
||
|
CSegmentArray & GetSegmentArray() { return _lookupArray; }
|
||
|
|
||
|
#ifdef CIEXTMODE
|
||
|
void CiExtDump(void *ciExtSelf);
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
|
||
|
CTableSegment * _pCachedPutRowSeg;
|
||
|
// Last segment into which a row was
|
||
|
// added.
|
||
|
|
||
|
CTableSegList _list; // List of table segments
|
||
|
|
||
|
CSegmentArray _lookupArray;
|
||
|
// Array used to to quick lookups on
|
||
|
// key
|
||
|
|
||
|
CMRUSegments _clientSegs;// List of segments most recently used
|
||
|
// by the client.
|
||
|
|
||
|
CMRUSegments _bucketSegs;// List of segments that are currently
|
||
|
// being converted to windows and so
|
||
|
// should be pinned as windows.
|
||
|
|
||
|
void _InvalidateIfCached( const CTableSegment * const pSeg );
|
||
|
void _UpdateSegsInUse( CWidSegMapList & list , CTableSegment * pSeg );
|
||
|
|
||
|
};
|
||
|
|