|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: RCSTRMHD.HXX
//
// Contents: Header information for the Recoverable Storage Object.
// This header information must be updated atomically.
//
//
// Classes: CRcovStorageHdr
// SRcovStorageHdr
//
// History: 25-Jan-94 SrikantS Created.
//
//----------------------------------------------------------------------------
#pragma once
#include <pshpack4.h>
//+---------------------------------------------------------------------------
//
// Struct: CRcovStrmHdr,
//
// Purpose: Stream management header associated with each copy of the
// recoverable streams.
//
// History: 1-25-94 SrikantS Created
//
//----------------------------------------------------------------------------
//
// A stream can be "decommitted in the front" only in units of
// VACB_MAPPING_GRANULARITY which is 256K. So, we have to accumulate the bytes
// to be "shrinked" until we reach the 256K number. In the picture below, that
// region is "B". The region "A" is the part that has already been de-committed
// by OFS.
//
// The stream may look like this
//
// |-----//-------|--------|------------------|---------------|
// | A // A | B | C | D |
// |---//---------|--------|------------------|---------------|
//
// A = "Hole" - n * SHRINK_FROM_FRONT_PAGE_SIZE. This is the region which
// is de-committed as part of the "OFS ShrinkFromFront" operation.
//
// B = the committed region which is not visible to the user . These are the
// bytes being accumulated to be "decommitted" once we reach the magic
// SHRINK_FROM_FRONT_PAGE_SIZE. B is always < SHRINK_FROM_FRONT_PAGE_SIZE.
//
// A + B = _cbSkip
//
// C = _cbValid. This is the "user visible data".
//
// B + C + D = Committed Region. This is in units of 64K chunks because that
// is the mapping granularity in memory mapped files.
//
// When B reaches the size of "SHRINK_FROM_FRONT_PAGE_SIZE", it will be
// made into a "hole" as part of A.
//
class CRcovStrmHdr {
public:
ULONG _nRec; // Count of records in the stream.
ULONG _cbValid; // Number of valid bytes in the stream.
LONGLONG _cbSkip; // Number of bytes to be skipped in the front.
// Needed for shrink from front.
};
//
// Minimum size for doing a shrink from front. It is 256K but for now
// just make it the COMMON_PAGE_SIZE to do testing.
//
const SHRINK_FROM_FRONT_PAGE_SIZE = 262144; // VACB_MAPPING_GRANULARITY;
inline ULONG VACBPageOffset( const LONGLONG & cb ) { return lltoul( cb & (SHRINK_FROM_FRONT_PAGE_SIZE-1) ); }
inline LONGLONG llVACBPageRound( const LONGLONG & cb ) { return ( cb + (SHRINK_FROM_FRONT_PAGE_SIZE-1) ) & ~(SHRINK_FROM_FRONT_PAGE_SIZE-1); }
inline LONGLONG llVACBPageTrunc( const LONGLONG & cb ) { return( cb & ~(SHRINK_FROM_FRONT_PAGE_SIZE-1)); }
inline ULONG VACBPageTrunc( ULONG cb ) { return( cb & ~(SHRINK_FROM_FRONT_PAGE_SIZE-1)); }
//+---------------------------------------------------------------------------
//
// Struct: CRcovUsrHdr
//
// Purpose: User (stream client) header associated with each copy of the
// recoverable streams. This provides for atomic storage of any
// small header information that the client may want to
// store.
//
// History: 1-25-94 SrikantS Created
//
//----------------------------------------------------------------------------
struct CRcovUserHdr { enum { CB_USRHDR = 92 }; ULONG GetSize() { return sizeof(_abHdr); }
BYTE _abHdr[CB_USRHDR]; };
//
// RcovOpType : RecoverableOperationType - operations on the storage
// object that are transacted.
//
enum RcovOpType { opNone, // No operation is being performed
opRead, // Read operation - for read locking.
opAppend, // Appending to the current stream
opModify, // "Party-On" operation
opMetaData, // Operations on the metadata of the object.
opDirty // To indicate that the backup is just dirty and
// not know which specific operation
};
//+---------------------------------------------------------------------------
//
// Class: CRcovStorageHdr
//
// Purpose: Data format of the information stored in the atomic
// stream of the recoverable storage object. This header
// information keeps track of the current primary copy,
// the recovery operations on the backup (if necessary),
// etc.
//
// This structure MUST be stored atomically. The only
// user of this data must be the PRcovStream class.
//
// History: 1-25-94 SrikantS Created
//
// Notes: The total size of this must be < CB_TINYMAX because
// this stream must be stored as a TINY stream in OFS.
//
//----------------------------------------------------------------------------
class CRcovStorageHdr {
enum { SIGHDR1 = 0x46524853, SIGHDR2 = 0x49524853 };
public:
CRcovStorageHdr(ULONG ulVer) { Init(ulVer); }
CRcovStorageHdr( const void *pvHdr, ULONG cbHdr );
void Init( const void *pvHdr, ULONG cbHdr ); void Init(ULONG ulVer);
enum DataCopyNum { idxOne, idxTwo }; enum { NUMCOPIES = 2 }; BOOL IsValid(ULONG ulExpectedVer) const;
void SetRcovOp( RcovOpType op ) { _opCurr = op; }
BOOL IsInTransaction() const { return opNone != _opCurr; }
BOOL IsWritable() const { return (opNone != _opCurr) && (opRead != _opCurr) ; }
DataCopyNum GetPrimary() const { return _iPrimary; }
DataCopyNum GetBackup() const { return idxOne == _iPrimary ? idxTwo : idxOne; }
BOOL IsBackupClean() const { return opNone == _opCurr; }
void SyncBackup();
void SwitchPrimary();
void GetUserHdr( DataCopyNum nCopy, CRcovUserHdr & hdr ) const { hdr = _ahdrUser[nCopy]; }
void SetUserHdr( DataCopyNum nCopy, const CRcovUserHdr & hdr ) { _ahdrUser[nCopy] = hdr; }
ULONG GetCount( DataCopyNum nCopy ) const { return _ahdrStrm[nCopy]._nRec; }
void SetCount( DataCopyNum nCopy, ULONG nRec ) { _ahdrStrm[nCopy]._nRec = nRec; }
void IncrementCount( DataCopyNum nCopy, ULONG nDelta = 1 ) { _ahdrStrm[nCopy]._nRec += nDelta; }
void DecrementCount( DataCopyNum nCopy, ULONG nDelta = 1 ) { Win4Assert( nDelta <= _ahdrStrm[nCopy]._nRec ); _ahdrStrm[nCopy]._nRec -= nDelta; }
ULONG GetUserDataSize( DataCopyNum nCopy ) const;
void SetUserDataSize( DataCopyNum nCopy, ULONG cbNew );
ULONG GetFullSize( DataCopyNum nCopy ) const;
ULONG GetUserDataStart( DataCopyNum nCopy ) const;
void SetCbToSkip( DataCopyNum nCopy, const LONGLONG & cbSkip );
LONGLONG GetCbToSkip( DataCopyNum nCopy ) const;
LONGLONG GetHoleLength( DataCopyNum nCopy ) const;
ULONG GetVersion() const { return _version; }
void SetVersion( ULONG version ) { _version = version; }
ULONG GetFlags() const { return _flags; }
void SetFlags( ULONG flags ) { _flags = flags; }
#ifdef CIEXTMODE
void CiExtDump(void *ciExtSelf); #endif
private:
//
// DO NOT MOVE THE _version FIELD - IT MUST BE THE FIRST FOUR
// BYTES IN THE HEADER.
//
ULONG _version; // Version Number information
ULONG _flags; // Flags for use by the recoverable object.
DataCopyNum _iPrimary; // Current primary copy num.
RcovOpType _opCurr; // Operation that needs to be recovered.
CRcovStrmHdr _ahdrStrm[NUMCOPIES]; // Two copies of the stream header.
ULONG _sigHdr1; // Signature to check for overruns.
CRcovUserHdr _ahdrUser[NUMCOPIES]; // Two copies of the user defined header.
ULONG _sigHdr2; };
#include <poppack.h>
inline CRcovStorageHdr::CRcovStorageHdr( const void * pvBuf, ULONG cbData ) { Init( pvBuf, cbData ); }
inline void CRcovStorageHdr::Init( const void * pvBuf, ULONG cbData ) { Win4Assert( cbData == sizeof(CRcovStorageHdr) ); memcpy( this, pvBuf, sizeof(CRcovStorageHdr) ); }
//+---------------------------------------------------------------------------
//
// Function: SwitchPrimary
//
// Synopsis: Switches the current primary and backup stream
// indices.
//
// History: 2-10-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
inline void CRcovStorageHdr::SwitchPrimary( ) { _iPrimary = GetBackup();
}
//+---------------------------------------------------------------------------
//
// Function: SyncBackup
//
// Synopsis: Synchronizes the backup stream header with the primary
// stream header. It also marks that backup is clean.
//
// History: 1-25-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
inline void CRcovStorageHdr::SyncBackup() { DataCopyNum iBackup = GetBackup();
_ahdrUser[iBackup] = _ahdrUser[_iPrimary]; _ahdrStrm[iBackup] = _ahdrStrm[_iPrimary]; _opCurr = opNone; }
//+---------------------------------------------------------------------------
//
// Member: CRcovStorageHdr::GetUserDataSize
//
// Synopsis: Returns the size data that is visible to the user in the
// given stream.
//
// Arguments: [nCopy] -
//
// History: 9-13-95 srikants Created
//
// Notes: In the picture this is region marked "C"
//
//----------------------------------------------------------------------------
inline ULONG CRcovStorageHdr::GetUserDataSize( DataCopyNum nCopy ) const { return _ahdrStrm[nCopy]._cbValid; }
//+---------------------------------------------------------------------------
//
// Member: CRcovStorageHdr::SetUserDataSize
//
// Synopsis: Sets the size of the data that is visible to the user in
// the given stream.
//
// Arguments: [nCopy] -
// [cbNew] -
//
// History: 9-13-95 srikants Created
//
// Notes: In the picture this is region marked "C"
//
//----------------------------------------------------------------------------
inline void CRcovStorageHdr::SetUserDataSize( DataCopyNum nCopy, ULONG cbNew ) { _ahdrStrm[nCopy]._cbValid = cbNew; }
//+---------------------------------------------------------------------------
//
// Member: CRcovStorageHdr::GetFullSize
//
// Synopsis: Returns the size of the user visible part + the initial bytes
// which must be skipped. Note that this does NOT include the
// length of the "hole" in the front.
//
// Arguments: [nCopy] -
//
// History: 9-13-95 srikants Created
//
// Notes: In the picture, this is "B+C"
//
//----------------------------------------------------------------------------
inline ULONG CRcovStorageHdr::GetFullSize( DataCopyNum nCopy ) const { return GetUserDataStart( nCopy ) + _ahdrStrm[nCopy]._cbValid; }
//+---------------------------------------------------------------------------
//
// Member: CRcovStorageHdr::GetUserDataStart
//
// Synopsis: Returns the offset of the user data from the "hole" in the
// front. Note that this is NOT the offset from the beginning
// of the stream.
//
// Arguments: [nCopy] -
//
// History: 9-13-95 srikants Created
//
// Notes: In the picture, this is "B"
//
//----------------------------------------------------------------------------
inline ULONG CRcovStorageHdr::GetUserDataStart( DataCopyNum nCopy ) const { return VACBPageOffset( _ahdrStrm[nCopy]._cbSkip ); }
//+---------------------------------------------------------------------------
//
// Member: CRcovStorageHdr::GetCbToSkip
//
// Synopsis: The number of bytes from the front of the stream that are
// NOT visible to the user. This is from the beginning of the
// stream.
//
// Arguments: [nCopy] -
//
// History: 9-13-95 srikants Created
//
// Notes: In the picture, this is "A+B"
//
//----------------------------------------------------------------------------
inline LONGLONG CRcovStorageHdr::GetCbToSkip( DataCopyNum nCopy ) const { return _ahdrStrm[nCopy]._cbSkip; }
//+---------------------------------------------------------------------------
//
// Member: CRcovStorageHdr::SetCbToSkip
//
// Synopsis: Sets the number of bytes invisible to the user in the front.
//
// Arguments: [nCopy] -
// [cbSkip] -
//
// History: 9-13-95 srikants Created
//
// Notes: In the picture, this is "A+B"
//
//----------------------------------------------------------------------------
inline void CRcovStorageHdr::SetCbToSkip( DataCopyNum nCopy, const LONGLONG & cbSkip ) { _ahdrStrm[nCopy]._cbSkip = cbSkip; }
//+---------------------------------------------------------------------------
//
// Member: CRcovStorageHdr::GetHoleLength
//
// Synopsis: Returns the length of the "hole" in the front of the stream.
//
// Arguments: [nCopy] -
//
// History: 9-13-95 srikants Created
//
// Notes: In the picture, this is "A"
//
//----------------------------------------------------------------------------
inline LONGLONG CRcovStorageHdr::GetHoleLength( DataCopyNum nCopy ) const { return llVACBPageTrunc( _ahdrStrm[nCopy]._cbSkip ); }
//
// SRcovStorageHdr : Safe Pointer to CRcovStorageHdr.
//
class SRcovStorageHdr { public:
SRcovStorageHdr(ULONG ulVer) { _pRcovStorageHdr = new CRcovStorageHdr(ulVer); }
SRcovStorageHdr( void *pvHdr, ULONG cbHdr ) { _pRcovStorageHdr = new CRcovStorageHdr ( pvHdr, cbHdr ); END_CONSTRUCTION( SRcovStorageHdr ); }
~SRcovStorageHdr() { delete _pRcovStorageHdr; }
CRcovStorageHdr * operator->() { return _pRcovStorageHdr; }
private:
CRcovStorageHdr * _pRcovStorageHdr;
};
|