|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1998.
//
// File: RCSTXACT.HXX
//
// Contents: Recoverable Stream Transactions.
//
// Classes: CRcovStrmTrans
// CRcovStrmReadTrans
// CRcovStrmWriteTrans
// CRcovStrmAppendTrans
// CRcovStrmMDTrans
//
//
// History: 25-Jan-94 SrikantS Created.
//
//----------------------------------------------------------------------------
#pragma once
#include <prcstob.hxx>
#include <xact.hxx>
//+---------------------------------------------------------------------------
//
// Class: SOpenRcovObj
//
// Purpose: An unwindable object to guarantee that the open streams in a
// recoverable object are closed.
//
// History: 1-16-95 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
class SOpenRcovObj { public:
SOpenRcovObj( PRcovStorageObj & obj ) : _obj(obj) { }
~SOpenRcovObj() { //
// None of these methods on PRcovStorageObj can throw
//
if ( _obj.IsOpen(CRcovStorageHdr::idxOne) ) { _obj.Close(CRcovStorageHdr::idxOne); }
if ( _obj.IsOpen(CRcovStorageHdr::idxTwo) ) { _obj.Close(CRcovStorageHdr::idxTwo); } }
private:
PRcovStorageObj & _obj; };
//+---------------------------------------------------------------------------
//
// Class: CRcovStrmTrans ()
//
// Purpose: Base class for the Recoverable Stream transactions.
//
// History: 2-02-94 srikants Created
//
// Notes: This object must not be created directly. Classes for
// read transaction, write transaction, etc must be
// derived from this class.
//
//----------------------------------------------------------------------------
const DWORD ENDOFSTRM = 0xFFFFFFFF;
class CRcovStrmTrans : public CTransaction { public:
BOOL Seek( ULONG offset );
void Advance( ULONG cb );
void Backup( ULONG cb );
ULONG Read( void *pvBuf, ULONG cbToRead );
BOOL AtEnd();
protected:
CRcovStrmTrans( PRcovStorageObj &obj , RcovOpType op );
void CommitPh1(); void CommitPh2();
void Write( const void *pvBuf, ULONG cbToWrite );
void Unmap( CRcovStorageHdr::DataCopyNum nCopy );
void SetStrmSize( CRcovStorageHdr::DataCopyNum nCopy, ULONG cbNew );
void Grow( CRcovStorageHdr::DataCopyNum nCopy, ULONG cbDelta );
void CopyToBack( ULONG oSrc, ULONG oDst, ULONG cbToCopy );
void CleanupAndSynchronize();
void _Seek( ULONG offset );
ULONG _GetCommittedStrmSize( PMmStream & strm, CRcovStorageHdr::DataCopyNum nCopy );
ULONG _GetCommittedStrmSize( CRcovStorageHdr::DataCopyNum nCopy );
PRcovStorageObj & GetRcovObj() { return _obj; }
CRcovStorageHdr & GetStorageHdr() { return _hdr; }
void EmptyBackupStream();
CRcovStorageHdr::DataCopyNum _iPrim, _iBack, _iCurr;
private:
PRcovStorageObj & _obj;
CRcovStorageHdr & _hdr;
SOpenRcovObj _sObj; // Safe pointer to always close the
// streams on a failure (even in the
// constructor).
//
// This keeps track of the range of bytes mapped in memory and the
// current offset for both the primary copy and the backup copy.
//
class CStrmInfo { public:
CStrmInfo() { Reset(); _oCurrent = 0; }
void Reset() { _oMapLow = _oMapHigh = ENDOFSTRM; }
//
// All of the offsets below are WRT to the beginning of the
// "committed" region, ie, after the "hole" in the front.
//
ULONG _oMapLow; // Offset of the lowest mapped byte.
ULONG _oMapHigh; // Offset of the highest mapped byte.
ULONG _oCurrent; // Current offset.
} _aStrmInfo[2];
void SetCurrentStrm( CRcovStorageHdr::DataCopyNum nCopy ) { _iCurr = nCopy; }
BOOL IsMapped( ULONG offset ); };
//+---------------------------------------------------------------------------
//
// Function: IsMapped
//
// Synopsis: Checks whether the specified offset is mapped in the
// current stream or not.
//
// Arguments: [offset] -- Byte offset to check for mapping.
//
// Returns: TRUE if that byte is mapped; FALSE otherwise.
//
// History: 2-02-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
inline BOOL CRcovStrmTrans::IsMapped( ULONG offset ) { return ( ENDOFSTRM != _aStrmInfo[_iCurr]._oMapLow && offset >= _aStrmInfo[_iCurr]._oMapLow && offset <= _aStrmInfo[_iCurr]._oMapHigh ) ; }
//+---------------------------------------------------------------------------
//
// Member: CRcovStrmTrans::AtEnd
//
// Synopsis: Checks if the data access is at the end of the stream.
//
// Returns: TRUE if at end; FALSE o/w
//
// History: 2-02-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
inline BOOL CRcovStrmTrans::AtEnd() { return (_aStrmInfo[_iCurr]._oCurrent == ENDOFSTRM) || (_aStrmInfo[_iCurr]._oCurrent >= _hdr.GetFullSize(_iCurr)); }
inline ULONG CRcovStrmTrans::_GetCommittedStrmSize( PMmStream & strm, CRcovStorageHdr::DataCopyNum nCopy ) { return lltoul( strm.Size() - _hdr.GetHoleLength( nCopy ) ); }
inline ULONG CRcovStrmTrans::_GetCommittedStrmSize( CRcovStorageHdr::DataCopyNum nCopy ) { PMmStream & strm = _obj.GetMmStream( nCopy ); return _GetCommittedStrmSize( strm, nCopy ); }
//+---------------------------------------------------------------------------
//
// Class: CRcovStrmReadTrans ()
//
// Purpose: Read Transaction for a Recoverable Stream.
//
// History: 2-02-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
class CRcovStrmReadTrans : public CRcovStrmTrans { public:
CRcovStrmReadTrans( PRcovStorageObj &obj ); ~CRcovStrmReadTrans(); };
inline CRcovStrmReadTrans::CRcovStrmReadTrans( PRcovStorageObj & obj ) : CRcovStrmTrans( obj, opRead ) { Commit(); }
inline CRcovStrmReadTrans::~CRcovStrmReadTrans() { if ( XActCommit == CTransaction::_status ) { CTransaction::_status = XActAbort;
Unmap( _iPrim ); GetRcovObj().Close(_iPrim); CTransaction::Commit();
} }
//+---------------------------------------------------------------------------
//
// Class: CRcovStrmWriteTrans ()
//
// Purpose: Write transaction for a Recoverable Stream. This
// is a expensive transaction mode which allows any
// kind of writing on the stream.
//
// History: 2-02-94 srikants Created
//
// Notes: This transaction must be used only when there is a
// need to modify something in the middle of a stream.
// For appending to the stream, use the CRcovStrmAppendTrans
//
//----------------------------------------------------------------------------
class CRcovStrmWriteTrans : public CRcovStrmTrans { public:
CRcovStrmWriteTrans( PRcovStorageObj &obj );
void Empty(); void Append( const void *pvBuf, ULONG cbToAppend );
void Write( const void *pvBuf, ULONG cbToWrite ) { CRcovStrmTrans::Write( pvBuf, cbToWrite ); }
void Commit(); };
inline CRcovStrmWriteTrans::CRcovStrmWriteTrans( PRcovStorageObj & obj ) : CRcovStrmTrans( obj, opModify ) { }
inline void CRcovStrmWriteTrans::Append( const void *pvBuf, ULONG cbToAppend ) { Seek( ENDOFSTRM ); Write( pvBuf, cbToAppend ); }
//+---------------------------------------------------------------------------
//
// Class: CRcovStrmAppendTrans ()
//
// Purpose: Append transaction for a Recoverable Stream.
// Allows reading any where in the stream but writing
// is only to the end of the stream ( appending ).
// Optimized for append operation.
//
// History: 2-02-94 srikants Created
//
// Notes: Even though we don't want all the methods of CRcovStrmTrans
// be available to CRcovStrmAppendTrans users, we cannot
// selectively grant access to methods eg. declaring
// CRcovStrm::Read() say in the public section because
// of compiler limitations.
//
//----------------------------------------------------------------------------
class CRcovStrmAppendTrans : public CRcovStrmTrans { public:
CRcovStrmAppendTrans( PRcovStorageObj &obj );
void Append( const void *pvBuf, ULONG cbToAppend, BOOL fIncrementCount = TRUE );
void Commit(); };
inline void CRcovStrmAppendTrans::Append( const void *pvBuf, ULONG cbToAppend, BOOL fIncrementCount ) { Seek( ENDOFSTRM ); Write( pvBuf, cbToAppend );
if ( fIncrementCount ) GetStorageHdr().IncrementCount(_iBack); }
//+---------------------------------------------------------------------------
//
// Class: CRcovStrmMDTrans ()
//
// Purpose: Transaced operations on Meta Data for a recoverable
// stream.
//
// History: 2-02-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
class CRcovStrmMDTrans : public CRcovStrmTrans {
public:
enum MDOp { mdopSetSize, mdopGrow, mdopFrontShrink, mdopBackCompact };
CRcovStrmMDTrans( PRcovStorageObj &obj, MDOp op, ULONG cb );
void Commit();
private:
void SetSize( ULONG cbNew ); void Grow( ULONG cbDelta ); void ShrinkFromFront( ULONG cbDelta ); void CompactFromEnd( ULONG cbDelta ); void IncreaseBytesToSkip( ULONG cbDelta );
void CopyShrinkFromFront( ULONG cbNew, ULONG cbDelta );
MDOp _op; ULONG _cbOp;
};
//+---------------------------------------------------------------------------
//
// Class: CCopyRcovObject
//
// Purpose: Copies the given source recoverable object's data to the
// destination source object.
//
// History: 3-17-97 srikants Created
//
//----------------------------------------------------------------------------
class CCopyRcovObject {
public:
CCopyRcovObject( PRcovStorageObj & dst, PRcovStorageObj & src ) : _dst(dst), _src(src), _dstHdr(dst.GetHeader()), _srcHdr(src.GetHeader()) { _cbSrc = _srcHdr.GetUserDataSize( _srcHdr.GetPrimary() ); }
NTSTATUS DoIt();
private:
void _SetDstSize(); void _CopyData();
PRcovStorageObj & _dst; PRcovStorageObj & _src;
CRcovStorageHdr & _dstHdr; CRcovStorageHdr const & _srcHdr;
ULONG _cbSrc;
};
|