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
15 KiB
468 lines
15 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1994 - 1999.
|
|
//
|
|
// File: rowbuf.hxx
|
|
//
|
|
// Contents: Declaration of the row buffer classes, used for HROW
|
|
// buffering at the interface level.
|
|
//
|
|
// Classes: CRowBuffer
|
|
// CRowBufferSet
|
|
// CDeferredValue
|
|
// CRBRefCount
|
|
//
|
|
// History: 22 Nov 1994 AlanW Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#include <tblalloc.hxx>
|
|
#include <tablecol.hxx>
|
|
|
|
class CTableColumnSet;
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CDeferredValue
|
|
//
|
|
// Purpose: Holds a value that is not in the row buffer because the value
|
|
// was deferred. The row buffer must free these values because
|
|
// the client asked for them DBTYPE_BYREF or DBTYPE_VECTOR with
|
|
// DBMEMOWNER_PROVIDEROWNED, so they must exist until the
|
|
// HROW goes away.
|
|
//
|
|
// History: 4 Aug 1995 dlee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CDeferredValue
|
|
{
|
|
public:
|
|
CDeferredValue(
|
|
HROW hrow,
|
|
PROPVARIANT & var ) :
|
|
_hrow( hrow ),
|
|
_var( var )
|
|
{ }
|
|
|
|
CDeferredValue() : _hrow( 0 )
|
|
{ }
|
|
|
|
~CDeferredValue()
|
|
{ Release(); }
|
|
|
|
void operator= ( CDeferredValue & val )
|
|
{
|
|
_hrow = val._hrow;
|
|
_var = val._var;
|
|
val._hrow = 0;
|
|
}
|
|
|
|
HROW GetHRow() { return _hrow; }
|
|
|
|
void Release();
|
|
|
|
private:
|
|
PROPVARIANT _var; // data that is deferred
|
|
HROW _hrow; // hrow to which the allocation belongs
|
|
};
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CRBRefCount
|
|
//
|
|
// Purpose: An HROW reference count in a row buffer.
|
|
//
|
|
// Notes: The ref. count occupies a USHORT at the beginning of the
|
|
// memory for the row.
|
|
//
|
|
// History: 29 May 1997 AlanW Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
const unsigned maxRowRefCount = 0x3FFF;
|
|
const unsigned eHasByrefData = 0x4000; // GetData has handed out ptr in buffer
|
|
const unsigned eHasByrefCopy = 0x8000; // a copy of row exists with eHasByrefData
|
|
|
|
class CRBRefCount
|
|
{
|
|
public:
|
|
USHORT GetRefCount() const { return _usRef & maxRowRefCount; }
|
|
|
|
void SetRefCount( CRBRefCount & Ref )
|
|
{
|
|
_usRef = Ref._usRef;
|
|
}
|
|
|
|
void SetRefCount(unsigned cRef)
|
|
{
|
|
_usRef = (_usRef & ~maxRowRefCount) | cRef;
|
|
}
|
|
|
|
void IncRefCount()
|
|
{
|
|
unsigned cRef = GetRefCount();
|
|
if (cRef < maxRowRefCount)
|
|
cRef++;
|
|
SetRefCount( cRef );
|
|
}
|
|
|
|
void DecRefCount()
|
|
{
|
|
unsigned cRef = GetRefCount();
|
|
Win4Assert(cRef > 0);
|
|
if (cRef > 0)
|
|
cRef--;
|
|
SetRefCount( cRef );
|
|
}
|
|
|
|
void AddRefs( CRBRefCount & Ref )
|
|
{
|
|
unsigned cRef = GetRefCount();
|
|
if ( (cRef + Ref.GetRefCount()) < maxRowRefCount)
|
|
cRef += Ref.GetRefCount();
|
|
else
|
|
cRef = maxRowRefCount;
|
|
SetRefCount( cRef );
|
|
|
|
if ( Ref.HasByrefData() )
|
|
SetByrefData();
|
|
|
|
if ( Ref.HasByrefCopy() )
|
|
SetByrefCopy();
|
|
}
|
|
|
|
BOOL HasByrefData() { return (_usRef & eHasByrefData) != 0; }
|
|
BOOL HasByrefCopy() { return (_usRef & eHasByrefCopy) != 0; }
|
|
|
|
void SetByrefData() { _usRef |= eHasByrefData; }
|
|
void SetByrefCopy() { _usRef |= eHasByrefCopy; }
|
|
|
|
CRBRefCount( unsigned cRef = 0 ) :
|
|
_usRef( (WORD)cRef )
|
|
{ }
|
|
|
|
CRBRefCount( CRBRefCount & Ref ) :
|
|
_usRef( Ref._usRef )
|
|
{
|
|
}
|
|
|
|
private:
|
|
USHORT _usRef;
|
|
};
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CRowBuffer
|
|
//
|
|
// Purpose: A row buffer in the client process. This
|
|
// provides the interface to HROWs for OLE-DB.
|
|
//
|
|
// Interface:
|
|
//
|
|
// History: 11 Nov 99 KLam Changed cast in IsRowHChapt for Win64
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CRowBuffer
|
|
{
|
|
friend class CRowBufferSet;
|
|
|
|
public:
|
|
CRowBuffer(
|
|
CTableColumnSet& rColumns,
|
|
ULONG cbRowWidth,
|
|
ULONG cRows,
|
|
XPtr<CFixedVarAllocator> & rAlloc
|
|
);
|
|
|
|
~CRowBuffer();
|
|
|
|
SCODE Lookup(
|
|
unsigned iRow,
|
|
CTableColumnSet ** ppColumns,
|
|
void ** ppbRowData,
|
|
BOOL fValidate = TRUE
|
|
) const;
|
|
|
|
void AddRefRow(
|
|
HROW hRow,
|
|
unsigned iRow,
|
|
ULONG & rRefCount,
|
|
DBROWSTATUS & rRowStatus
|
|
);
|
|
|
|
BOOL ReleaseRow(
|
|
HROW hRow,
|
|
unsigned iRow,
|
|
ULONG & rRefCount,
|
|
DBROWSTATUS & rRowStatus
|
|
);
|
|
|
|
void ReferenceChapter(
|
|
BYTE * pbRow
|
|
);
|
|
|
|
void AddRefChapter(
|
|
unsigned iRow,
|
|
ULONG & rRefCount
|
|
);
|
|
|
|
void ReleaseChapter(
|
|
unsigned iRow,
|
|
ULONG & rRefCount
|
|
);
|
|
|
|
inline void InitRowRefcount(
|
|
unsigned iRow,
|
|
CRBRefCount & OtherRefs
|
|
);
|
|
|
|
CRBRefCount DereferenceRow(
|
|
unsigned iRow
|
|
);
|
|
|
|
HROW GetRowId(unsigned iRow) const;
|
|
|
|
ULONG GetRowWidth(void) const { return _cbRowWidth; }
|
|
|
|
ULONG GetRowCount(void) const { return _cRows; }
|
|
|
|
void SetRowIdOffset( ULONG obRowId ) { _obRowId = obRowId; }
|
|
|
|
void SetChapterVars( ULONG obChaptId, ULONG obChaptRefcnt )
|
|
{
|
|
_obChaptId = obChaptId;
|
|
_obChaptRefcount = obChaptRefcnt;
|
|
}
|
|
|
|
LONG RefCount(void) const { return _cReferences; }
|
|
|
|
void LokReference() { _cReferences++; }
|
|
|
|
void AddDeferredValue( CDeferredValue & val )
|
|
{
|
|
Win4Assert( ciIsValidPointer( _aDeferredValues.GetPointer() ) );
|
|
_aDeferredValues[ _aDeferredValues.Count() ] = val;
|
|
Win4Assert( ciIsValidPointer( _aDeferredValues.GetPointer() ) );
|
|
}
|
|
|
|
BOOL FindHRow( unsigned &riRow, HROW hRow, BOOL fFindByrefData = FALSE ) const;
|
|
|
|
BOOL FindHChapter( unsigned &riRow, HCHAPTER hChapter ) const;
|
|
|
|
BOOL IsRowHRow( unsigned iRow, HROW hRow ) const
|
|
{
|
|
BYTE* pbRow = _pbRowData + ( iRow * _cbRowWidth );
|
|
|
|
// refcount is the first USHORT in each row
|
|
|
|
return ( ( 0 != ((CRBRefCount *) pbRow)->GetRefCount() ) &&
|
|
( hRow == ( * (HROW UNALIGNED *) ( pbRow + _obRowId ) ) ) );
|
|
}
|
|
|
|
BOOL IsRowOkAndHRow( unsigned iRow, HROW hRow ) const
|
|
{
|
|
if ( iRow >= GetRowCount() )
|
|
return FALSE;
|
|
|
|
return IsRowHRow( iRow, hRow );
|
|
}
|
|
|
|
BOOL IsRowHChapt( unsigned iRow, HCHAPTER hChapt ) const
|
|
{
|
|
BYTE* pbRow = _pbRowData + ( iRow * _cbRowWidth );
|
|
|
|
// refcount is the first USHORT in each row
|
|
|
|
return ( ( 0 != ((CRBRefCount *) pbRow)->GetRefCount() ) &&
|
|
( hChapt == ( * (CI_TBL_CHAPT *) ( pbRow + _obChaptId ) ) ) );
|
|
}
|
|
|
|
BOOL IsRowOkAndHChapt( unsigned iRow, HCHAPTER hChapt ) const
|
|
{
|
|
if ( iRow >= GetRowCount() )
|
|
return FALSE;
|
|
|
|
return IsRowHChapt( iRow, hChapt );
|
|
}
|
|
|
|
CTableColumn * Find( PROPID propid ) const
|
|
{
|
|
if ( _fQuickPROPID && propid <= _Columns.Count() )
|
|
{
|
|
Win4Assert( 0 != propid );
|
|
return _Columns.Get( propid-1 );
|
|
}
|
|
else
|
|
{
|
|
return _Columns.Find( propid );
|
|
}
|
|
}
|
|
|
|
void SetByrefData( BYTE * pbRow ) {
|
|
CRBRefCount * pRefCount = (CRBRefCount *) pbRow;
|
|
pRefCount->SetByrefData();
|
|
}
|
|
|
|
private:
|
|
|
|
inline BOOL IsChaptered( ) const
|
|
{ return _obChaptId != 0xFFFFFFFF; }
|
|
|
|
inline BYTE* _IndexRow( unsigned iRow, int fVerifyRefcnt = TRUE ) const;
|
|
|
|
CRBRefCount & _GetRowRefCount( unsigned iRow ) const;
|
|
CRBRefCount & _GetChaptRefCount( unsigned iRow ) const;
|
|
|
|
LONG _cReferences; // number of referenced rows in buffer
|
|
ULONG _cRows; // number of rows in this buffer
|
|
ULONG _cbRowWidth; // size of each row
|
|
BYTE* _pbRowData; // pointer to row data
|
|
ULONG _obRowId; // offset to row ID
|
|
ULONG _obChaptId; // offset to chapter ID
|
|
ULONG _obChaptRefcount; // offset to chapter ref. count
|
|
XPtr<CFixedVarAllocator> _Alloc; // allocator holding row data
|
|
|
|
CTableColumnSet& _Columns; // column descriptions
|
|
|
|
// Optimization to speed up the lookup of PROPIDs
|
|
BOOL _fQuickPROPID; // Set to TRUE if PropIds can be looked
|
|
// up quickly
|
|
|
|
CDynArrayInPlaceNST<CDeferredValue> _aDeferredValues; // deferred byref data
|
|
};
|
|
|
|
|
|
DECL_DYNARRAY( CRowBufferArray, CRowBuffer )
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CRowBufferSet
|
|
//
|
|
// Purpose: A set of row buffers in the client process. This
|
|
// provides the interface to HROWs for OLE-DB.
|
|
//
|
|
// Interface:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CRowBufferSet : public CRowBufferArray
|
|
{
|
|
public:
|
|
CRowBufferSet(
|
|
BOOL fSequential,
|
|
ULONG obRowRefcount,
|
|
ULONG obRowId,
|
|
ULONG obChaptRefcount,
|
|
ULONG obChaptId
|
|
);
|
|
|
|
~CRowBufferSet();
|
|
|
|
CRowBuffer &Lookup(
|
|
HROW hRow,
|
|
CTableColumnSet ** ppColumns,
|
|
void ** ppbRowData
|
|
);
|
|
|
|
void Add(
|
|
XPtr<CRowBuffer> & pBuf,
|
|
BOOL fPossibleDuplicateHRows,
|
|
HROW * pahRows = 0
|
|
);
|
|
|
|
void AddRefRows(
|
|
DBCOUNTITEM cRows,
|
|
const HROW rghRows [],
|
|
DBREFCOUNT rgRefCounts[] = 0,
|
|
DBROWSTATUS rgRowStatus[] = 0
|
|
);
|
|
|
|
SCODE ReleaseRows(
|
|
DBCOUNTITEM cRows,
|
|
const HROW rghRows [],
|
|
DBREFCOUNT rgRefCounts[] = 0,
|
|
DBROWSTATUS rgRowStatus[] = 0
|
|
);
|
|
|
|
void CheckAllHrowsReleased( );
|
|
|
|
void AddRefChapter(
|
|
HCHAPTER hChapter,
|
|
ULONG * pcRefCount
|
|
);
|
|
|
|
void ReleaseChapter(
|
|
HCHAPTER hChapter,
|
|
ULONG * pcRefCount
|
|
);
|
|
|
|
CMutexSem & GetBufferLock( )
|
|
{ return _mutex; }
|
|
|
|
BOOL IsChaptered( ) const
|
|
{ return _obChaptId != 0xFFFFFFFF; }
|
|
|
|
#ifdef _WIN64
|
|
CFixedVarAllocator * GetArrayAlloc () { return &_ArrayAlloc; }
|
|
#endif
|
|
|
|
private:
|
|
void _LokAddRefRow(
|
|
HROW hRow,
|
|
ULONG & rRefCount,
|
|
DBROWSTATUS & rRowStatus
|
|
);
|
|
|
|
void _LokReleaseRow(
|
|
HROW hRow,
|
|
ULONG & rRefCount,
|
|
DBROWSTATUS & rRowStatus
|
|
);
|
|
|
|
inline BOOL IsHrowRowId( ) const
|
|
{ return ! _fSequential; }
|
|
|
|
CRowBuffer* _FindRowBuffer(
|
|
HROW hRow,
|
|
unsigned & iBuf,
|
|
unsigned & iRow
|
|
);
|
|
|
|
CRowBuffer* _FindRowBufferByChapter(
|
|
HCHAPTER hChapter,
|
|
unsigned & iBuf,
|
|
unsigned & iRow
|
|
);
|
|
|
|
BOOL _fSequential;
|
|
ULONG _obRowRefcount; // offset of row reference cnt in bufs
|
|
ULONG _obRowId; // offset of row identifier in buffers
|
|
ULONG _obChaptRefcount; // offset of chapter reference cnt in bufs
|
|
ULONG _obChaptId; // offset of chapter identifier in buffers
|
|
ULONG _cRowBufs; // Count of row buffers in this set
|
|
|
|
#ifdef _WIN64
|
|
CFixedVarAllocator _ArrayAlloc; // Used for arrays of pointers in 64c -> 32s
|
|
#endif
|
|
|
|
// Hints for the next lookup of an hrow
|
|
|
|
unsigned _iBufHint;
|
|
unsigned _iRowHint;
|
|
|
|
#if CIDBG
|
|
unsigned _cHintHits;
|
|
unsigned _cHintMisses;
|
|
#endif
|
|
|
|
CMutexSem _mutex; // serialize on buffer set operations
|
|
};
|
|
|