mirror of https://github.com/tongzx/nt5src
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.
418 lines
11 KiB
418 lines
11 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1998.
|
|
//
|
|
// File: mmerglog.hxx
|
|
//
|
|
// Contents: Master Log manipulation class.
|
|
//
|
|
// Classes: CMMergeLog, CNewMMergeLog, CMMergeIdxListIter
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 3-30-94 srikants Created
|
|
//
|
|
// Note : The Primary/Backup Streams in the master log have the
|
|
// following format.
|
|
//
|
|
// 4 Bytes - sigIdxList ("MMIL")
|
|
// 4 Bytes - Number of shadow indexes participating in the
|
|
// master merge.
|
|
// 4n Bytes- Where n is the number of shadow indexes in the
|
|
// master merge.
|
|
//
|
|
// This will be the index split key.
|
|
//
|
|
// 4 Bytes - sigSplitKey ("MMSK")
|
|
// 4 Bytes - Number of valid bytes in the SplitKey.
|
|
// MAXKEYSIZE Bytes - The index SplitKey.
|
|
// 4 Bytes - Property Id of the SplitKey.
|
|
// 4 Bytes - PageNumber
|
|
// 4 Bytes - Offset within Page Number
|
|
//
|
|
// This will be the keylist split key.
|
|
//
|
|
// 4 Bytes - sigSplitKey("MMSK")
|
|
// 4 Bytes - Number of valid bytes in the SplitKey.
|
|
// MAXKEYSIZE Bytes - The keylist SplitKey.
|
|
// 4 Bytes - Property id of the split key.
|
|
// 4 Bytes - PageNumber
|
|
// 4 Bytes - Offset within Page Number
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#include <prcstob.hxx>
|
|
#include <idxids.hxx>
|
|
#include <rcstxact.hxx>
|
|
#include <bitoff.hxx>
|
|
|
|
#ifndef OFFSET
|
|
#define OFFSET( CClass, mem ) ((int) (ULONG_PTR)&((CClass *)0)->mem)
|
|
#endif // OFFSET
|
|
|
|
#include <pshpack4.h>
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CMMergeLogHdr
|
|
//
|
|
// Purpose: Header information stored in the user header portion of
|
|
// the MasterMergeLog.
|
|
//
|
|
// History: 3-31-94 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CMMergeLogHdr
|
|
{
|
|
enum { sigHdr = 0x44484d4d }; // "MMHD" in ascii.
|
|
|
|
public:
|
|
|
|
void Init()
|
|
{
|
|
_sigHdr1 = _sigHdr2 = sigHdr;
|
|
_cShadowIndex = _oSplitKey = 0;
|
|
_widMaxIndex = _widMaxKeyList = widInvalid;
|
|
}
|
|
|
|
ULONG GetShadowIndexCount() const { return _cShadowIndex; }
|
|
void SetShadowIndexCount( ULONG cShadowIndex )
|
|
{ _cShadowIndex = cShadowIndex; }
|
|
|
|
ULONG GetSplitKeyOffset() const { return _oSplitKey; }
|
|
void SetSplitKeyOffset( ULONG oSplitKey ) { _oSplitKey = oSplitKey; }
|
|
|
|
BOOL IsValid() { return _sigHdr1 == sigHdr && _sigHdr2 == sigHdr ; }
|
|
|
|
WORKID GetIndexWidMax() const { return _widMaxIndex; }
|
|
void SetIndexWidMax( WORKID widMax ) { _widMaxIndex = widMax; }
|
|
|
|
WORKID GetKeyListWidMax() const { return _widMaxKeyList; }
|
|
void SetKeyListWidMax( WORKID widMax ) { _widMaxKeyList = widMax; }
|
|
|
|
private:
|
|
|
|
ULONG _sigHdr1; // Signature - must be sigHdr
|
|
ULONG _cShadowIndex; // Number of shadow indexes in the merge.
|
|
ULONG _oSplitKey; // Offset of the split key in the stream.
|
|
ULONG _sigHdr2; // Signature - must be sigHdr
|
|
ULONG _widMaxIndex; // Maximum workid in the new index.
|
|
ULONG _widMaxKeyList; // Maximum workid in the key list.
|
|
};
|
|
|
|
DECL_DYNARRAY_INPLACE( CIndexIdArray, CIndexId );
|
|
|
|
class CMMergeLog;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CMMergeIndexList
|
|
//
|
|
// Purpose: Class for managing the list of indexes participating in a
|
|
// master merge.
|
|
//
|
|
// History: 3-31-94 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CMMergeIndexList
|
|
{
|
|
enum { sigIdxList = 0x4c494d4d }; // "MMIL" in ascii.
|
|
|
|
public:
|
|
|
|
CMMergeIndexList( ULONG cShadowIndex = 64 );
|
|
|
|
void Serialize( CRcovStrmWriteTrans & trans );
|
|
void DeSerialize( CRcovStrmReadTrans & trans, PRcovStorageObj & obj );
|
|
|
|
void AddIndex( CIndexId & iid );
|
|
|
|
ULONG GetShadowIndexCount() const { return _cShadowIndex; }
|
|
BOOL GetIndex( CIndexId & iid, ULONG nIdx );
|
|
|
|
ULONG GetValidLength() const
|
|
{
|
|
return( OFFSET(CMMergeIndexList, _aShadowIndex) +
|
|
_cShadowIndex * sizeof(CIndexId) );
|
|
}
|
|
|
|
private:
|
|
|
|
ULONG _sigIdxList; // Must be sigIdxList.
|
|
ULONG _cShadowIndex; // Count of the number of shadow indixes.
|
|
CIndexIdArray _aShadowIndex; // Array of shadow indexes.
|
|
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CMMergeSplitKey
|
|
//
|
|
// Purpose: Class for managing the "SplitKey" in the Master Log.
|
|
//
|
|
// History: 3-31-94 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CMMergeSplitKey
|
|
{
|
|
enum { sigSplitKey = 0x4b534d4d }; // "MMSK" in ascii.
|
|
|
|
public:
|
|
|
|
CMMergeSplitKey()
|
|
{
|
|
_sigSplitKey = sigSplitKey; _cbKey = 0; _pid = 0;
|
|
_bitOffBegin.Init(0,0);
|
|
_bitOffEnd.Init(0,0);
|
|
}
|
|
|
|
void GetKey( CKeyBuf & key );
|
|
|
|
void GetOffset( BitOffset & bitOffBegin, BitOffset & bitOffEnd )
|
|
{
|
|
bitOffBegin = _bitOffBegin;
|
|
bitOffEnd = _bitOffEnd;
|
|
}
|
|
|
|
void SetKey( const CKeyBuf & key );
|
|
|
|
void SetOffset( const BitOffset & bitOffBegin,
|
|
const BitOffset & bitOffEnd )
|
|
{
|
|
_bitOffBegin = bitOffBegin;
|
|
_bitOffEnd = bitOffEnd;
|
|
}
|
|
|
|
ULONG GetCount() { return _cbKey; }
|
|
|
|
BOOL IsValid() { return sigSplitKey == _sigSplitKey; }
|
|
|
|
private:
|
|
|
|
ULONG _sigSplitKey;
|
|
ULONG _cbKey;
|
|
BYTE _buf[MAXKEYSIZE];
|
|
PROPID _pid;
|
|
BitOffset _bitOffBegin;
|
|
BitOffset _bitOffEnd;
|
|
};
|
|
|
|
inline void CMMergeSplitKey::GetKey( CKeyBuf & key )
|
|
{
|
|
key.SetCount( _cbKey );
|
|
key.SetPid( _pid );
|
|
ciAssert( _cbKey <= MAXKEYSIZE );
|
|
memcpy( key.GetWritableBuf(), _buf, _cbKey );
|
|
}
|
|
|
|
inline void CMMergeSplitKey::SetKey( const CKeyBuf & key )
|
|
{
|
|
_pid = key.Pid();
|
|
_cbKey = key.Count();
|
|
ciAssert( _cbKey <= MAXKEYSIZE );
|
|
memcpy( _buf, key.GetBuf(), _cbKey );
|
|
}
|
|
|
|
#include <poppack.h>
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CNewMMergeLog
|
|
//
|
|
// Purpose: Class used to create a new Master Log before starting a
|
|
// master merge.
|
|
//
|
|
// History: 3-31-94 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CNewMMergeLog
|
|
{
|
|
public:
|
|
|
|
CNewMMergeLog( PRcovStorageObj & obj );
|
|
~CNewMMergeLog();
|
|
|
|
void AddPersistentIndex( CIndexId & iid )
|
|
{
|
|
_shadowIdxList.AddIndex( iid );
|
|
}
|
|
|
|
void SetKeyListWidMax( WORKID widMax ) { _widMaxKeyList = widMax; }
|
|
void SetIndexWidMax( WORKID widMax ) { _widMaxIndex = widMax; }
|
|
void Commit() { _fCommit = TRUE; }
|
|
void DoCommit();
|
|
|
|
private:
|
|
|
|
BOOL _fCommit;
|
|
PRcovStorageObj & _objMMLog;
|
|
CRcovStrmWriteTrans _trans;
|
|
CMMergeIndexList _shadowIdxList;
|
|
WORKID _widMaxKeyList;
|
|
WORKID _widMaxIndex;
|
|
|
|
void SerializeIndexList();
|
|
void AppendEmptySplitKeys();
|
|
void WriteHeader();
|
|
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CMMergeLog
|
|
//
|
|
// Purpose: The Master Merge Log class used during master merge to
|
|
// manage serializing/de-serializing the split key.
|
|
//
|
|
// History: 3-31-94 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
const LONGLONG eSigMMergeLog = 0x474f4c4752454d4di64; // "MMERGLOG"
|
|
|
|
class CMMergeLog
|
|
{
|
|
|
|
public:
|
|
|
|
CMMergeLog( PRcovStorageObj & objMMLog );
|
|
|
|
void GetIdxSplitKeyInfo( CKeyBuf & splitKey,
|
|
BitOffset & bitOffBegin,
|
|
BitOffset & bitOffEnd )
|
|
{
|
|
_idxSplitKey.GetKey( splitKey );
|
|
_idxSplitKey.GetOffset( bitOffBegin, bitOffEnd );
|
|
}
|
|
|
|
WORKID GetIndexWidMax() const { return _widMaxIndex; }
|
|
|
|
void SetIdxSplitKeyInfo( const CKeyBuf & splitKey,
|
|
const BitOffset & bitOffBegin,
|
|
const BitOffset & bitOffEnd )
|
|
{
|
|
_idxSplitKey.SetKey( splitKey );
|
|
_idxSplitKey.SetOffset( bitOffBegin, bitOffEnd );
|
|
|
|
ciDebugOut(( DEB_ITRACE, "Current split key is '%ws'\n",
|
|
splitKey.GetStr() ));
|
|
}
|
|
|
|
void SetIndexWidMax( WORKID widMax ) { _widMaxIndex = widMax; }
|
|
|
|
void GetKeyListSplitKeyInfo( CKeyBuf & splitKey,
|
|
BitOffset & bitOffBegin,
|
|
BitOffset & bitOffEnd
|
|
)
|
|
{
|
|
_keylstSplitKey.GetKey(splitKey);
|
|
_keylstSplitKey.GetOffset(bitOffBegin, bitOffEnd );
|
|
}
|
|
|
|
WORKID GetKeyListWidMax() const { return _widMaxKeyList; }
|
|
|
|
void SetKeyListSplitKeyInfo( const CKeyBuf & splitKey,
|
|
const BitOffset & bitOffBegin,
|
|
const BitOffset & bitOffEnd
|
|
)
|
|
{
|
|
_keylstSplitKey.SetKey( splitKey );
|
|
_keylstSplitKey.SetOffset( bitOffBegin, bitOffEnd );
|
|
}
|
|
|
|
void SetKeyListWidMax( WORKID widMax ) { _widMaxKeyList = widMax; }
|
|
|
|
void CheckPoint();
|
|
|
|
#ifdef CIEXTMODE
|
|
void CiExtDump(void *ciExtSelf);
|
|
#endif
|
|
|
|
private:
|
|
|
|
const LONGLONG _sigMMergeLog;
|
|
|
|
PRcovStorageObj & _objMMLog; // MasterMerge Log Object.
|
|
|
|
CMMergeSplitKey _idxSplitKey;
|
|
// The "SplitKey" between the current
|
|
// master and the old master.
|
|
|
|
CMMergeSplitKey _keylstSplitKey;
|
|
// Split key for the key list.
|
|
|
|
WORKID _widMaxIndex; // Maximum workid in the new index.
|
|
WORKID _widMaxKeyList; // Maximum workid in the key list
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CMMergeIdxListIter
|
|
//
|
|
// Purpose: Iterator to iterate through the list of participating
|
|
// shadow indexes in the master merge.
|
|
//
|
|
// History: 3-31-94 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CMMergeIdxListIter
|
|
{
|
|
public:
|
|
|
|
CMMergeIdxListIter( PRcovStorageObj & objMMLog );
|
|
|
|
BOOL Found( CIndexId & iid );
|
|
ULONG Count() { return _shadowIdxList.GetShadowIndexCount(); }
|
|
|
|
BOOL AtEnd()
|
|
{
|
|
return _curr >= _shadowIdxList.GetShadowIndexCount();
|
|
}
|
|
|
|
void GetIndex( CIndexId & iid );
|
|
void Advance() { _curr++; }
|
|
void GetFirstIndex( CIndexId & iid )
|
|
{
|
|
_curr = 0;
|
|
GetIndex( iid );
|
|
}
|
|
|
|
private:
|
|
|
|
ULONG _curr; // The current index being returned.
|
|
PRcovStorageObj & _objMMLog; // Recoverable storage object.
|
|
CRcovStrmReadTrans _trans; // Read transaction.
|
|
CMMergeIndexList _shadowIdxList;
|
|
// The list of shadow indexes.
|
|
|
|
};
|
|
|
|
inline void CMMergeIdxListIter::GetIndex( CIndexId & iid )
|
|
{
|
|
Win4Assert( !AtEnd() );
|
|
_shadowIdxList.GetIndex( iid, _curr );
|
|
}
|
|
|
|
|
|
|
|
|