|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: mmerglog.cxx
//
// Contents: Implementation of the master merge log.
//
// Classes: CMMergeLog, CNewMMergeLog, CMMergeIdxIter
//
// Functions:
//
// History: 3-30-94 srikants Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <eventlog.hxx>
#include "mmerglog.hxx"
IMPL_DYNARRAY_INPLACE(CIndexIdArray, CIndexId );
//+---------------------------------------------------------------------------
//
// Function: CMMergeIndexList constructor
//
// Synopsis: A dynamic index array.
//
// Arguments: [cShadowIndex] -- Initial guess of number of indexes likely
// to be added to the list.
//
// History: 4-20-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
CMMergeIndexList::CMMergeIndexList( ULONG cShadowIndex ) : _aShadowIndex( cShadowIndex ), _cShadowIndex(0), _sigIdxList(sigIdxList) { }
//+---------------------------------------------------------------------------
//
// Function: GetIndex
//
// Synopsis: Given the "offset" into the indexlist(array), it returns
// the "indexId" in that offset.
//
// Arguments: [iid] -- Output - will have the indexid.
// [nIdx] -- Offset into the array.
//
// Returns: if the specified offset is within the range. FALSE o/w.
//
// History: 4-20-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CMMergeIndexList::GetIndex( CIndexId & iid, ULONG nIdx ) { if ( nIdx >= _cShadowIndex ) { return(FALSE); }
iid = _aShadowIndex.Get(nIdx); return(TRUE); }
void CMMergeIndexList::AddIndex( CIndexId & iid ) { _aShadowIndex.Add( iid, _cShadowIndex ); _cShadowIndex++; }
//+---------------------------------------------------------------------------
//
// Function: Serialize
//
// Synopsis: Serializes the index list using the given write transaction.
//
// Arguments: [trans] -- Write transaction of which this is part of.
//
// History: 4-20-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CMMergeIndexList::Serialize( CRcovStrmWriteTrans & trans ) { //
// First write the signature and the count of shadow indexes.
//
ciAssert( _sigIdxList == sigIdxList ); trans.Empty();
trans.Append( this, OFFSET(CMMergeIndexList, _aShadowIndex) );
//
// Now append the shadow index ids that are participating in the
// master merge.
//
for ( ULONG i = 0; i < _cShadowIndex; i++ ) { CIndexId & iid = _aShadowIndex.Get(i); trans.Append( &iid, sizeof(CIndexId) ); }
}
void CMMergeIndexList::DeSerialize( CRcovStrmReadTrans & trans, PRcovStorageObj & obj ) { //
// Rewind and read the signature and count of shadow indexes
// participating in the master merge.
//
trans.Seek(0); ULONG cbValid = obj.GetHeader().GetUserDataSize( obj.GetHeader().GetPrimary() ); ULONG cbMin = OFFSET(CMMergeIndexList, _aShadowIndex);
if ( cbValid < cbMin ) { ciDebugOut(( DEB_ERROR, "Master Log Size is Invalid - 0x%X\n", cbValid ));
PStorage & storage = obj.GetStorage();
Win4Assert( !"Corrupt master merge log" );
storage.ReportCorruptComponent( L"MMergeIndexList1" );
THROW( CException( CI_CORRUPT_DATABASE ) ); }
//
// Read the signature and the count of shadow indexes participating
// in the master merge.
//
trans.Read( this, OFFSET(CMMergeIndexList, _aShadowIndex) ); if ( _sigIdxList != sigIdxList ) { ciDebugOut(( DEB_ERROR, "Master Log Signature Invalid 0x%X\n", _sigIdxList ));
PStorage & storage = obj.GetStorage();
Win4Assert( !"Corrupt master merge log" );
storage.ReportCorruptComponent( L"MMergeIndexList2" );
THROW( CException( CI_CORRUPT_DATABASE ) );
}
cbMin += sizeof(CIndexId) * _cShadowIndex; if ( cbValid < cbMin ) { ciDebugOut(( DEB_ERROR, "Master Log Size is Invalid - 0x%X\n", cbValid ));
PStorage & storage = obj.GetStorage();
Win4Assert( !"Corrupt master merge log" );
storage.ReportCorruptComponent( L"MMergeIndexList3" );
THROW( CException( CI_CORRUPT_DATABASE ) ); }
for ( ULONG i = 0; i < _cShadowIndex; i++ ) { CIndexId iid; trans.Read( &iid, sizeof(CIndexId) ); _aShadowIndex.Add(iid, i ); }
return; }
//+---------------------------------------------------------------------------
//
// Function: CNewMMergeLog - constructor
//
// Synopsis: Constructor for a new master merge log.
//
// Arguments: [objMMLog] -- The recoverable storage object for the master
// merge log.
//
// History: 4-20-94 srikants Created
//
//----------------------------------------------------------------------------
CNewMMergeLog::CNewMMergeLog( PRcovStorageObj & objMMLog ) :_fCommit(FALSE), _objMMLog(objMMLog), _trans(_objMMLog) { }
void CNewMMergeLog::DoCommit() { if ( _fCommit ) { _fCommit = FALSE; // To prevent cycles if there is a failure in
// the process of committing.
//
// Write the list of shadow indexes followed by the split key
//
_shadowIdxList.Serialize( _trans ); AppendEmptySplitKeys();
//
// Write the header information and commit the transaction.
//
WriteHeader(); _trans.Commit(); } }
CNewMMergeLog::~CNewMMergeLog() { if ( _fCommit ) { ciDebugOut(( DEB_ERROR, "aborting committed CNewMMergeLog!\n" )); } }
//+---------------------------------------------------------------------------
//
// Function: AppendEmptySplitKeys
//
// Synopsis: Appends empty split keys for the index list and key list.
//
// History: 4-20-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CNewMMergeLog::AppendEmptySplitKeys() { CMMergeSplitKey splitKey; CKeyBuf key; key.FillMin();
splitKey.SetKey( key );
ciAssert( _objMMLog.GetHeader().GetUserDataSize( _objMMLog.GetHeader().GetBackup() ) == _shadowIdxList.GetValidLength() );
_trans.Append( &splitKey, sizeof CMMergeSplitKey ); _trans.Append( &splitKey, sizeof CMMergeSplitKey ); }
//+---------------------------------------------------------------------------
//
// Function: WriteHeader
//
// Synopsis: Writes the header for the new master merge log.
//
// History: 4-20-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CNewMMergeLog::WriteHeader() { // STACKSTACK
XPtr<struct CRcovUserHdr> xHdr(new CRcovUserHdr); RtlZeroMemory( xHdr.GetPointer(), sizeof(CRcovUserHdr) );
ciDebugOut(( DEB_ITRACE, "Writing Header For New Master Log - cShadowIdx %d - oSplitKey %d\n", _shadowIdxList.GetShadowIndexCount(), _shadowIdxList.GetValidLength() )); ciDebugOut(( DEB_ITRACE, "WidMax Index 0x%X WidMax KeyList 0x%X\n", _widMaxIndex, _widMaxKeyList ));
CMMergeLogHdr * phdrMMLog = (CMMergeLogHdr *) xHdr.GetPointer();
phdrMMLog->Init(); phdrMMLog->SetShadowIndexCount(_shadowIdxList.GetShadowIndexCount()); phdrMMLog->SetSplitKeyOffset(_shadowIdxList.GetValidLength()); phdrMMLog->SetKeyListWidMax( _widMaxKeyList ); phdrMMLog->SetIndexWidMax( _widMaxIndex );
_objMMLog.GetHeader().SetUserHdr( _objMMLog.GetHeader().GetBackup(), xHdr.GetReference() ); }
//+---------------------------------------------------------------------------
//
// Function: CMMergeLog::CMMergeLog
//
// Synopsis: Constructor for an existing master merge log.
//
// Arguments: [objMMLog] -- Recoverable storage object for the master
// mergelog.
//
// History: 4-20-94 srikants Created
//
//----------------------------------------------------------------------------
CMMergeLog::CMMergeLog( PRcovStorageObj & objMMLog ) : _sigMMergeLog(eSigMMergeLog), _objMMLog(objMMLog) { //
// Create a read transaction for reading in the master log.
//
CRcovStrmReadTrans trans(_objMMLog); XPtr<struct CRcovUserHdr> xHdr(new CRcovUserHdr); CMMergeLogHdr * phdrMMLog = (CMMergeLogHdr *) xHdr.GetPointer();
_objMMLog.GetHeader().GetUserHdr( _objMMLog.GetHeader().GetPrimary(), xHdr.GetReference() );
_widMaxIndex = phdrMMLog->GetIndexWidMax(); _widMaxKeyList = phdrMMLog->GetKeyListWidMax();
ciDebugOut(( DEB_ITRACE, "DeSerialize MMLog Hdr - Index Max Wid 0x%X KeyList MaxWid 0x%X\n", _widMaxIndex, _widMaxKeyList ));
ciDebugOut(( DEB_ITRACE, "Seeking to 0x%X bytes to read split key\n", phdrMMLog->GetSplitKeyOffset() ));
//
// Read the index split key.
//
trans.Seek( phdrMMLog->GetSplitKeyOffset() ); trans.Read( &_idxSplitKey, sizeof(_idxSplitKey) ); Win4Assert( _idxSplitKey.IsValid() );
if ( !_idxSplitKey.IsValid() ) { PStorage & storage = objMMLog.GetStorage(); storage.ReportCorruptComponent( L"MMergeLogSplitKey" ); THROW( CException( CI_CORRUPT_DATABASE ) ); }
//
// Read the keylist split key.
//
trans.Read(&_keylstSplitKey, sizeof(_keylstSplitKey)); Win4Assert( _keylstSplitKey.IsValid() );
if ( !_keylstSplitKey.IsValid() ) { PStorage & storage = objMMLog.GetStorage(); storage.ReportCorruptComponent( L"MMergeLogKeylstSplitKey" ); THROW( CException( CI_CORRUPT_DATABASE ) ); } } //CMMergeLog
//+---------------------------------------------------------------------------
//
// Function: CheckPoint
//
// Synopsis: Writes out the state of master merge (as indicated in the
// master log object) to disk in an atomic fashion.
//
// History: 4-20-94 srikants Created
//
//----------------------------------------------------------------------------
void CMMergeLog::CheckPoint() { CRcovStrmWriteTrans trans(_objMMLog);
// STACKSTACK
XPtr<struct CRcovUserHdr> xHdr(new CRcovUserHdr); CMMergeLogHdr * phdrMMLog = (CMMergeLogHdr *) xHdr.GetPointer();
_objMMLog.GetHeader().GetUserHdr( _objMMLog.GetHeader().GetBackup(), xHdr.GetReference() );
phdrMMLog->SetIndexWidMax( _widMaxIndex ); phdrMMLog->SetKeyListWidMax( _widMaxKeyList );
ciDebugOut(( DEB_ITRACE, "Seeking to 0x%X bytes to write split key\n", phdrMMLog->GetSplitKeyOffset() ));
_objMMLog.GetHeader().SetUserHdr( _objMMLog.GetHeader().GetBackup(), xHdr.GetReference() );
//
// Write out the index split key.
//
trans.Seek( phdrMMLog->GetSplitKeyOffset() ); trans.Write( &_idxSplitKey, sizeof(_idxSplitKey) );
//
// Write out the keylist split key.
//
trans.Write( &_keylstSplitKey, sizeof(_keylstSplitKey) );
trans.Commit(); }
CMMergeIdxListIter::CMMergeIdxListIter( PRcovStorageObj & objMMLog ) : _objMMLog(objMMLog), _curr(0), _trans(_objMMLog) { _shadowIdxList.DeSerialize( _trans, _objMMLog ); }
BOOL CMMergeIdxListIter::Found( CIndexId & iid ) { for ( ULONG i = 0; i < _shadowIdxList.GetShadowIndexCount(); i++ ) { CIndexId iidCurr; _shadowIdxList.GetIndex( iidCurr , i ); if ( iid == iidCurr ) { return(TRUE); } }
return(FALSE); }
|