874 lines
25 KiB
C++
874 lines
25 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1991 - 2000.
|
||
|
//
|
||
|
// File: IDXTAB.CXX
|
||
|
//
|
||
|
// Contents: Index Manager
|
||
|
//
|
||
|
// Classes: CIndexTable
|
||
|
//
|
||
|
// History: 22-Mar-91 BartoszM Created.
|
||
|
// 12-Feb-92 AmyA Hacked all methods for FAT.
|
||
|
// 01-Jul-93 BartoszM Rewrote to use memory mapped file
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <cistore.hxx>
|
||
|
#include <idxtab.hxx>
|
||
|
#include <eventlog.hxx>
|
||
|
#include <imprsnat.hxx>
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//----------------------------------------------------------------------------
|
||
|
CWriteIndexFile::CWriteIndexFile ( PRcovStorageObj & rcovObj ) :
|
||
|
_rcovObj(rcovObj),
|
||
|
_xact(rcovObj),
|
||
|
_iter(_xact, sizeof(CIndexRecord)),
|
||
|
_xactPtr(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CWriteIndexFile::BackUp()
|
||
|
{
|
||
|
ciAssert(_xactPtr > 0);
|
||
|
|
||
|
_xactPtr--;
|
||
|
_iter.Seek( _xactPtr );
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL CWriteIndexFile::ReadRecord ( CIndexRecord * pRecord )
|
||
|
{
|
||
|
ULONG ulRecCnt = _rcovObj.GetHeader().GetCount(_rcovObj.GetHeader().GetBackup());
|
||
|
|
||
|
if (_xactPtr >= ulRecCnt)
|
||
|
return(FALSE);
|
||
|
|
||
|
_iter.GetRec( pRecord );
|
||
|
_xactPtr++;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CWriteIndexFile::WriteRecord ( CIndexRecord* pRecord )
|
||
|
{
|
||
|
_iter.SetRec( pRecord );
|
||
|
_xactPtr++;
|
||
|
|
||
|
ULONG ulRecCnt = _rcovObj.GetHeader().GetCount(_rcovObj.GetHeader().GetBackup());
|
||
|
|
||
|
if (ulRecCnt < _xactPtr)
|
||
|
_rcovObj.GetHeader().SetCount(_rcovObj.GetHeader().GetBackup(), _xactPtr);
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CWriteIndexFile::IncrMMergeSeqNum
|
||
|
//
|
||
|
// Synopsis: Increments the master merge sequence number in the header.
|
||
|
//
|
||
|
// History: 3-21-97 srikants Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CWriteIndexFile::IncrMMergeSeqNum()
|
||
|
{
|
||
|
|
||
|
CRcovStorageHdr & storageHdr = _rcovObj.GetHeader();
|
||
|
|
||
|
CRcovUserHdr usrHdr;
|
||
|
CIndexTableUsrHdr * pIdxUsrHdr = (CIndexTableUsrHdr *) &usrHdr;
|
||
|
|
||
|
storageHdr.GetUserHdr( storageHdr.GetPrimary(), usrHdr );
|
||
|
ciDebugOut(( DEB_ITRACE, "Current MMerge Seq Num = %d \n",
|
||
|
pIdxUsrHdr->GetMMergeSeqNum() ));
|
||
|
|
||
|
pIdxUsrHdr->IncrMMergeSeqNum();
|
||
|
|
||
|
ciDebugOut(( DEB_ITRACE, "New MMerge Seq Num = %d \n",
|
||
|
pIdxUsrHdr->GetMMergeSeqNum() ));
|
||
|
|
||
|
storageHdr.SetUserHdr( storageHdr.GetBackup(), usrHdr );
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//----------------------------------------------------------------------------
|
||
|
CReadIndexFile::CReadIndexFile ( PRcovStorageObj & rcovObj ) :
|
||
|
_rcovObj(rcovObj),
|
||
|
_xact(rcovObj),
|
||
|
_iter(_xact, sizeof(CIndexRecord)),
|
||
|
_xactPtr(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CReadIndexFile::BackUp()
|
||
|
{
|
||
|
ciAssert(_xactPtr > 0);
|
||
|
|
||
|
_xactPtr--;
|
||
|
_iter.Seek( _xactPtr );
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL CReadIndexFile::ReadRecord ( CIndexRecord * pRecord )
|
||
|
{
|
||
|
ULONG ulRecCnt = _rcovObj.GetHeader().GetCount(_rcovObj.GetHeader().GetPrimary());
|
||
|
|
||
|
if (_xactPtr >= ulRecCnt)
|
||
|
return(FALSE);
|
||
|
|
||
|
_iter.GetRec( pRecord );
|
||
|
_xactPtr++;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CAddReplaceIndexRecord::CAddReplaceIndexRecord, public
|
||
|
//
|
||
|
// Synopsis: Rewinds the file pointer indFile, then reads in IndexRecords until
|
||
|
// either a record with INDEXID iid is found or EOF is reached.
|
||
|
//
|
||
|
// Notes: Whether or not a record with INDEXID iid is found can be
|
||
|
// determined by calling Found().
|
||
|
//
|
||
|
// History: 16-Mar-92 AmyA Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CAddReplaceIndexRecord::CAddReplaceIndexRecord ( CWriteIndexFile & indFile,
|
||
|
INDEXID iid )
|
||
|
: _indFile( indFile )
|
||
|
|
||
|
{
|
||
|
_indFile.Rewind();
|
||
|
|
||
|
do
|
||
|
{
|
||
|
_found = _indFile.ReadRecord ( this );
|
||
|
} while (_found && Iid() != iid);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CAddReplaceIndexRecord::Write()
|
||
|
//
|
||
|
// Synopsis: Writes the information from CIndexRecord out to the file--
|
||
|
// either replacing the record that was found in the constructor
|
||
|
// (if there was one found) or appending to the end of the file
|
||
|
// indicated by _indFile.
|
||
|
//
|
||
|
// History: 28-Feb-95 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
inline void CAddReplaceIndexRecord::WriteRecord()
|
||
|
{
|
||
|
if ( Found() )
|
||
|
{
|
||
|
_indFile.BackUp();
|
||
|
}
|
||
|
|
||
|
_indFile.WriteRecord( this );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::CIndexTable, public
|
||
|
//
|
||
|
// Synopsis: Constructor.
|
||
|
//
|
||
|
// History: 28-Mar-91 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CIndexTable::CIndexTable ( CiStorage& storage, CTransaction& xact )
|
||
|
: _storage(storage), _pRcovObj(0)
|
||
|
{
|
||
|
_pRcovObj = _storage.QueryIdxTableObject();
|
||
|
Win4Assert( 0 != _pRcovObj );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::~CIndexTable, public
|
||
|
//
|
||
|
// Synopsis: Destructor.
|
||
|
//
|
||
|
// History: 28-May-92 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CIndexTable::~CIndexTable ()
|
||
|
{
|
||
|
delete _pRcovObj;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTableIter::CIndexTableIter
|
||
|
//
|
||
|
// Synopsis: Constructor.
|
||
|
//
|
||
|
// History: 28-May-92 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CIndexTabIter::CIndexTabIter ( CIndexTable& idxTable )
|
||
|
: _idxTable(idxTable),
|
||
|
_indFile( idxTable.GetIndexTableObj() )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTabIter::Begin, public
|
||
|
//
|
||
|
// Synopsis: Position cursor at the beginning of table
|
||
|
//
|
||
|
// History: 28-Mar-91 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL CIndexTabIter::Begin ()
|
||
|
{
|
||
|
CNextIndexRecord rec(_indFile);
|
||
|
|
||
|
if (!rec.Found())
|
||
|
return FALSE;
|
||
|
|
||
|
_indFile.Rewind();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTabIter::NextRecord, public
|
||
|
//
|
||
|
// Synopsis: Called during startup. Reads next record
|
||
|
//
|
||
|
// Arguments: [indexRecord] -- record to be filled
|
||
|
//
|
||
|
// History: 28-Mar-91 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL CIndexTabIter::NextRecord ( CIndexRecord& indexRecord )
|
||
|
{
|
||
|
CNextIndexRecord rec(_indFile);
|
||
|
|
||
|
if (!rec.Found())
|
||
|
return(FALSE);
|
||
|
|
||
|
if ( rec.VersionStamp() < _idxTable._storage.GetStorageVersion() )
|
||
|
{
|
||
|
Win4Assert ( !"Corrupt index table" );
|
||
|
|
||
|
PStorage & storage = GetStorage();
|
||
|
|
||
|
storage.ReportCorruptComponent ( L"IndexTable1" );
|
||
|
|
||
|
THROW( CException ( STATUS_INTERNAL_DB_CORRUPTION ));
|
||
|
}
|
||
|
else if ( rec.VersionStamp() > _idxTable._storage.GetStorageVersion() )
|
||
|
{
|
||
|
ciAssert ( !"Unknown index format: upgrade index software" );
|
||
|
|
||
|
PStorage & storage = GetStorage();
|
||
|
|
||
|
storage.ReportCorruptComponent ( L"IndexTable2" );
|
||
|
|
||
|
THROW( CException ( STATUS_INTERNAL_DB_CORRUPTION ));
|
||
|
}
|
||
|
|
||
|
indexRecord._objectId = rec.ObjectId();
|
||
|
indexRecord._iid = rec.Iid();
|
||
|
indexRecord._type = rec.Type();
|
||
|
indexRecord._maxWorkId = rec.MaxWorkId();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTabIter::~CIndexTabIter, public
|
||
|
//
|
||
|
// Synopsis: Iteration finished
|
||
|
//
|
||
|
// History: 28-Mar-91 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CIndexTabIter::~CIndexTabIter()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::SwapIndexes, public
|
||
|
//
|
||
|
// Synopsis: Replaces old indexes with a new one after merge
|
||
|
//
|
||
|
// Arguments: [pIndexNew] -- new index
|
||
|
// [cIndexOld] -- count of old indexes to be removed
|
||
|
// [aIidOld] -- array of old index id's
|
||
|
//
|
||
|
// Notes: ResMan LOCKED
|
||
|
//
|
||
|
// History: 02-May-91 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CIndexTable::SwapIndexes ( CShadowMergeSwapInfo & info )
|
||
|
{
|
||
|
CIndexRecord & record = info._recNewIndex;
|
||
|
|
||
|
ciDebugOut (( DEB_ITRACE, "IndexManager: Adding index %lx, maxWid %ld\n",
|
||
|
record.Iid(), record.MaxWorkId() ));
|
||
|
|
||
|
CWriteIndexFile indFile( GetIndexTableObj() );
|
||
|
|
||
|
// Mark old indexes deleted
|
||
|
|
||
|
for ( unsigned i = 0; i < info._cIndexOld; i++ )
|
||
|
{
|
||
|
CIndexId idFull = info._aIidOld[i];
|
||
|
if ( idFull.IsPersistent())
|
||
|
{
|
||
|
CAddReplaceIndexRecord rec(indFile, info._aIidOld[i]);
|
||
|
if (!rec.Found())
|
||
|
{
|
||
|
//
|
||
|
// We have a persistent index which was not found in the
|
||
|
// index list. This must be an index corruption.
|
||
|
//
|
||
|
|
||
|
ciDebugOut(( DEB_ERROR, "Can't find index 0x%lx\n",
|
||
|
info._aIidOld[i] ));
|
||
|
Win4Assert( !"Corrupt index table" );
|
||
|
_storage.ReportCorruptComponent( L"IndexTable3" );
|
||
|
|
||
|
THROW( CException ( CI_CORRUPT_DATABASE ));
|
||
|
}
|
||
|
rec.SetType(itZombie); // And one more....
|
||
|
rec.WriteRecord();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add record for the new index.
|
||
|
//
|
||
|
|
||
|
if ( widInvalid != record.ObjectId() )
|
||
|
AddRecord ( indFile,
|
||
|
record.Iid(),
|
||
|
record.Type(),
|
||
|
record.MaxWorkId(),
|
||
|
record.ObjectId() );
|
||
|
|
||
|
//
|
||
|
// Replace the old fresh test entry with the new fresh test entry.
|
||
|
//
|
||
|
DeleteObject( indFile, partidDefault, itFreshLog, info._widOldFreshLog );
|
||
|
AddRecord( indFile, CIndexId( 0, partidDefault ), itFreshLog,
|
||
|
0, info._widNewFreshLog );
|
||
|
|
||
|
indFile.Commit();
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SwapIndexes
|
||
|
//
|
||
|
// Synopsis: This method marks the old indexes as "zombie" in the index
|
||
|
// table, deletes the MMLog, MMFreshLog and NewMasterIndex
|
||
|
// entries. It then adds an entry making the NewMaster the
|
||
|
// current master.
|
||
|
//
|
||
|
// This is done as a single TRANSACTION - either the entire
|
||
|
// step succeeds or the previous state is retained.
|
||
|
//
|
||
|
// Effects: All the indexes that participated in the master merge will
|
||
|
// be deleted from the index list and the new master will be
|
||
|
// made the only master index.
|
||
|
//
|
||
|
// Arguments: [partid] -- Partition Id where the master merge just
|
||
|
// completed.
|
||
|
// [cIndexOld] -- Count of the indexes in aIidOld.
|
||
|
// [aIidOld] -- Array of index ids to be marked zombie.
|
||
|
// [recNewMaster] -- CIndexRecord for the new master index.
|
||
|
// [widMMLog] -- WorkId of the MMLog object.
|
||
|
//
|
||
|
// History: 4-04-94 srikants Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIndexTable::SwapIndexes ( CMasterMergeSwapInfo & info )
|
||
|
{
|
||
|
CIndexRecord & recNewMaster = info._recNewIndex;
|
||
|
CIndexRecord & recNewKeyList = info._recNewKeyList;
|
||
|
|
||
|
ciDebugOut (( DEB_ITRACE, "Master Merge Completed\n"));
|
||
|
|
||
|
CWriteIndexFile indFile( GetIndexTableObj() );
|
||
|
|
||
|
//
|
||
|
// Mark old indexes as "Zombie".
|
||
|
//
|
||
|
for ( unsigned i = 0; i < info._cIndexOld; i++ )
|
||
|
{
|
||
|
CIndexId idFull = info._aIidOld[i];
|
||
|
Win4Assert( idFull.IsPersistent() );
|
||
|
Win4Assert( idFull.PartId() == info._partid );
|
||
|
|
||
|
CAddReplaceIndexRecord rec(indFile, info._aIidOld[i]);
|
||
|
|
||
|
if (!rec.Found())
|
||
|
{
|
||
|
//
|
||
|
// We have a persistent index which was not found in the
|
||
|
// index list. This must be an index corruption.
|
||
|
//
|
||
|
|
||
|
ciDebugOut(( DEB_ERROR, "Can't find index 0x%lx\n",
|
||
|
info._aIidOld[i] ));
|
||
|
Win4Assert( !"Corrupt index table" );
|
||
|
_storage.ReportCorruptComponent( L"IndexTable4" );
|
||
|
|
||
|
THROW( CException ( CI_CORRUPT_DATABASE ));
|
||
|
}
|
||
|
rec.SetType(itZombie); // And one more....
|
||
|
rec.WriteRecord();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Delete the MMLog entry.
|
||
|
//
|
||
|
DeleteObject( indFile, info._partid, itMMLog, info._widMMLog );
|
||
|
|
||
|
//
|
||
|
// Delete the itMMKeyList entry.
|
||
|
//
|
||
|
DeleteObject( indFile, partidKeyList, itMMKeyList,
|
||
|
recNewKeyList.ObjectId() );
|
||
|
|
||
|
//
|
||
|
// Delete the old itKeyList entry and add an entry for the new
|
||
|
// key list.
|
||
|
//
|
||
|
{
|
||
|
//
|
||
|
// DeleteRecord assumes that the record is found. When we create
|
||
|
// the key list for the first time, it may not be present.
|
||
|
//
|
||
|
CAddReplaceIndexRecord rec( indFile, info._iidOldKeyList );
|
||
|
if ( rec.Found() )
|
||
|
{
|
||
|
rec.SetIid( CIndexId(iidInvalid,partidInvalid) );
|
||
|
rec.WriteRecord();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AddRecord( indFile, recNewKeyList.Iid(),
|
||
|
recNewKeyList.Type(),
|
||
|
recNewKeyList.MaxWorkId(),
|
||
|
recNewKeyList.ObjectId()
|
||
|
);
|
||
|
//
|
||
|
// Delete the entry for the new master index and make it the
|
||
|
// current master index.
|
||
|
//
|
||
|
DeleteRecord( indFile, recNewMaster.Iid() );
|
||
|
AddRecord (
|
||
|
indFile,
|
||
|
recNewMaster.Iid(),
|
||
|
itMaster, // Note the change from itNewMaster to itMaster
|
||
|
recNewMaster.MaxWorkId(),
|
||
|
recNewMaster.ObjectId());
|
||
|
|
||
|
//
|
||
|
// Replace the old fresh test entry with the new fresh test entry.
|
||
|
//
|
||
|
DeleteObject( indFile, partidDefault, itFreshLog, info._widOldFreshLog );
|
||
|
AddRecord( indFile, CIndexId( 0, partidDefault ), itFreshLog, 0,
|
||
|
info._widNewFreshLog );
|
||
|
|
||
|
//
|
||
|
// Increment the master merge sequence number.
|
||
|
//
|
||
|
indFile.IncrMMergeSeqNum();
|
||
|
indFile.Commit();
|
||
|
}
|
||
|
|
||
|
PIndexTabIter* CIndexTable::QueryIterator()
|
||
|
{
|
||
|
return new CIndexTabIter ( *this );
|
||
|
}
|
||
|
|
||
|
PStorage& CIndexTable::GetStorage()
|
||
|
{
|
||
|
return(_storage);
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::RemoveIndex, public
|
||
|
//
|
||
|
// Synopsis: Removes index from table
|
||
|
//
|
||
|
// Arguments: [iid] -- index id
|
||
|
//
|
||
|
// Notes: ResMan LOCKED
|
||
|
//
|
||
|
// History: 02-May-91 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#pragma optimize( "", off )
|
||
|
void CIndexTable::RemoveIndex ( INDEXID iid )
|
||
|
{
|
||
|
CImpersonateSystem impersonate;
|
||
|
|
||
|
CWriteIndexFile indFile( GetIndexTableObj() );
|
||
|
|
||
|
DeleteRecord( indFile, iid );
|
||
|
|
||
|
indFile.Commit();
|
||
|
}
|
||
|
#pragma optimize( "", on )
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: AddObject
|
||
|
//
|
||
|
// Synopsis: Appends a record for the specified object to the
|
||
|
// index table.
|
||
|
//
|
||
|
// Arguments: [partid] -- Id of the partition to which the object
|
||
|
// belongs.
|
||
|
// [it] -- Index type of the object.
|
||
|
// [wid] -- WorkId of the object.
|
||
|
//
|
||
|
// History: 2-18-94 srikants Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CIndexTable::AddObject( PARTITIONID partid, IndexType it, WORKID wid )
|
||
|
{
|
||
|
CWriteIndexFile indFile( GetIndexTableObj() );
|
||
|
|
||
|
AddRecord ( indFile, CIndexId ( 0, partid ), it, 0, wid );
|
||
|
|
||
|
indFile.Commit();
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: AddMMergeObjects
|
||
|
//
|
||
|
// Synopsis: This method adds records for the NewMaster Index,
|
||
|
// and MasterMerge Log to the index table.
|
||
|
//
|
||
|
// Arguments: [partid] -- Partition id of the partition in which
|
||
|
// master merge is being done.
|
||
|
// [recNewMaster] -- The index record for the new master index.
|
||
|
// [widMMLog] -- WorkId of the MasterMerge Log.
|
||
|
// [deletedIndex] -- Index id for the current index
|
||
|
//
|
||
|
// History: 4-04-94 srikants Created
|
||
|
//
|
||
|
// Notes: The recNewMaster must be fully initialized with the correct
|
||
|
// indexType, WorkId and MaxWorkId.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CIndexTable::AddMMergeObjects( PARTITIONID partid,
|
||
|
CIndexRecord & recNewMaster,
|
||
|
WORKID widMMLog,
|
||
|
WORKID widMMKeyList,
|
||
|
INDEXID iidDelOld,
|
||
|
INDEXID iidDelNew )
|
||
|
{
|
||
|
|
||
|
CWriteIndexFile indFile( GetIndexTableObj() );
|
||
|
|
||
|
Win4Assert( recNewMaster.Type() == itNewMaster );
|
||
|
Win4Assert( iidDeleted1 == iidDelOld && iidDeleted2 == iidDelNew ||
|
||
|
iidDeleted2 == iidDelOld && iidDeleted1 == iidDelNew );
|
||
|
|
||
|
#if CIDBG == 1
|
||
|
CIndexId iid( recNewMaster.Iid() );
|
||
|
Win4Assert( iid.PartId() == partid );
|
||
|
#endif // CIDBG == 1
|
||
|
|
||
|
AddRecord( indFile, recNewMaster.Iid(), itNewMaster,
|
||
|
recNewMaster.MaxWorkId(), recNewMaster.ObjectId() );
|
||
|
AddRecord( indFile, CIndexId( 0, partid ), itMMLog, 0,widMMLog );
|
||
|
AddRecord( indFile, CIndexId( 0, partidKeyList ), itMMKeyList, 0, widMMKeyList );
|
||
|
|
||
|
DeleteRecord( indFile, iidDelOld );
|
||
|
AddRecord( indFile, iidDelNew, itDeleted, 0, 0 );
|
||
|
|
||
|
indFile.Commit();
|
||
|
}
|
||
|
|
||
|
|
||
|
inline BOOL IsMatched( const CIndexRecord & rec,
|
||
|
INDEXID iid, IndexType it, WORKID wid )
|
||
|
{
|
||
|
return rec.Type() == (ULONG) it && rec.Iid() == iid && rec.ObjectId() == wid ;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DeleteObject
|
||
|
//
|
||
|
// Synopsis: Deletes the record for the specified object by marking
|
||
|
// it as "iidInvalid". The record will be deleted only
|
||
|
// if there is an exact match with the partid, it and wid.
|
||
|
//
|
||
|
// Arguments: [partid] -- Partition Id.
|
||
|
// [it] -- Index type of the object.
|
||
|
// [wid] -- Work Id to match on.
|
||
|
//
|
||
|
// History: 2-18-94 srikants Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIndexTable::DeleteObject( PARTITIONID partid, IndexType it, WORKID wid )
|
||
|
{
|
||
|
CWriteIndexFile indFile( GetIndexTableObj() );
|
||
|
DeleteObject( indFile, partid, it, wid );
|
||
|
indFile.Commit();
|
||
|
}
|
||
|
|
||
|
void CIndexTable::DeleteObject( CWriteIndexFile & indFile,
|
||
|
PARTITIONID partid, IndexType it, WORKID wid )
|
||
|
{
|
||
|
CIndexRecord rec;
|
||
|
BOOL found;
|
||
|
indFile.Rewind();
|
||
|
do
|
||
|
{
|
||
|
found = indFile.ReadRecord ( &rec );
|
||
|
}
|
||
|
while ( found && !IsMatched( rec, CIndexId(0, partid), it, wid) );
|
||
|
|
||
|
if ( found ) {
|
||
|
indFile.BackUp();
|
||
|
rec._iid = (INDEXID) CIndexId(iidInvalid, partidInvalid);
|
||
|
rec._objectId = widInvalid;
|
||
|
indFile.WriteRecord( &rec );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::AddRecord, private
|
||
|
//
|
||
|
// Synopsis: Adds new record to table
|
||
|
//
|
||
|
// Arguments: [iid] -- index id
|
||
|
// [type] -- type of record
|
||
|
// [maxWorkId] -- max work id in the index
|
||
|
// [objectId] -- id of the index object
|
||
|
//
|
||
|
// Notes: ResMan LOCKED
|
||
|
//
|
||
|
// History: 02-May-91 BartoszM Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CIndexTable::AddRecord( CWriteIndexFile & indFile,
|
||
|
INDEXID iid,
|
||
|
ULONG type,
|
||
|
WORKID maxWorkId,
|
||
|
WORKID objectId )
|
||
|
{
|
||
|
ciDebugOut (( DEB_ITRACE, "Indexes: AddRecord %lx, %ld %s\n",
|
||
|
iid, maxWorkId, (type == itMaster)? "master": "not-master" ));
|
||
|
|
||
|
CAddReplaceIndexRecord rec(indFile, CIndexId(iidInvalid,partidInvalid) );
|
||
|
|
||
|
rec.SetIid(iid);
|
||
|
rec.SetType(type);
|
||
|
rec.SetWid(maxWorkId);
|
||
|
rec.SetObjectId ( objectId );
|
||
|
rec.WriteRecord();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::AddIndex, public
|
||
|
//
|
||
|
// Synopsis: Adds new index to table
|
||
|
//
|
||
|
// Arguments: [iid] -- index id
|
||
|
// [type] -- type of record
|
||
|
// [maxWorkId] -- max work id in the index
|
||
|
// [objectId] -- id of the index object
|
||
|
//
|
||
|
// Notes: ResMan LOCKED
|
||
|
//
|
||
|
// History: 14-Jul-94 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIndexTable::AddIndex( INDEXID iid,
|
||
|
IndexType type,
|
||
|
WORKID maxWorkId,
|
||
|
WORKID objectId )
|
||
|
{
|
||
|
CWriteIndexFile indFile( GetIndexTableObj() );
|
||
|
AddRecord( indFile, iid, type, maxWorkId, objectId );
|
||
|
indFile.Commit();
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::LokEmpty, public
|
||
|
//
|
||
|
// Synopsis: Deleted everything from the index table
|
||
|
//
|
||
|
// Notes: ResMan LOCKED
|
||
|
//
|
||
|
// History: 16-Aug-94 DwightKr Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIndexTable::LokEmpty()
|
||
|
{
|
||
|
|
||
|
PRcovStorageObj & rcovObj = GetIndexTableObj();
|
||
|
CRcovStrmWriteTrans xact( rcovObj );
|
||
|
|
||
|
rcovObj.GetHeader().SetCount( rcovObj.GetHeader().GetBackup(), 0 );
|
||
|
xact.Empty();
|
||
|
xact.Seek(0);
|
||
|
|
||
|
xact.Commit();
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::LokMakeBackupCopy
|
||
|
//
|
||
|
// Synopsis: Makes a backup copy of the index table.
|
||
|
//
|
||
|
// Arguments: [storage] - Storage to use for creation of the
|
||
|
// destination index table.
|
||
|
// [fFullSave] - Set to TRUE if a full save is being performed.
|
||
|
// [progressTracker] - Progress tracker.
|
||
|
//
|
||
|
// History: 3-18-97 srikants Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CIndexTable::LokMakeBackupCopy( PStorage & storage,
|
||
|
BOOL fFullSave,
|
||
|
PSaveProgressTracker & progressTracker )
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Create a new index table object using the storage provided.
|
||
|
//
|
||
|
PRcovStorageObj * pDstObj = storage.QueryIdxTableObject();
|
||
|
XPtr<PRcovStorageObj> xDstObj( pDstObj );
|
||
|
|
||
|
PRcovStorageObj & srcObj = GetIndexTableObj();
|
||
|
|
||
|
//
|
||
|
// Copy the contents of source to destination.
|
||
|
//
|
||
|
CCopyRcovObject copier( *pDstObj, srcObj );
|
||
|
NTSTATUS status = copier.DoIt();
|
||
|
|
||
|
if ( STATUS_SUCCESS != status )
|
||
|
{
|
||
|
THROW(CException(status) );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the Full/Partial Save bit appropriately.
|
||
|
//
|
||
|
CRcovStrmAppendTrans xact( *pDstObj );
|
||
|
|
||
|
CRcovStorageHdr & storageHdr = pDstObj->GetHeader();
|
||
|
|
||
|
CRcovUserHdr usrHdr;
|
||
|
CIndexTableUsrHdr * pIdxUsrHdr = (CIndexTableUsrHdr *) &usrHdr;
|
||
|
|
||
|
storageHdr.GetUserHdr( storageHdr.GetBackup(), usrHdr );
|
||
|
|
||
|
if ( fFullSave )
|
||
|
pIdxUsrHdr->SetFullSave();
|
||
|
else pIdxUsrHdr->ClearFullSave();
|
||
|
|
||
|
storageHdr.SetUserHdr( storageHdr.GetBackup(), usrHdr );
|
||
|
|
||
|
xact.Commit();
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIndexTable::GetUserHdrInfo
|
||
|
//
|
||
|
// Synopsis: Retrieves the information in the user header.
|
||
|
//
|
||
|
// Arguments: [mMergeSeqNum] - Master Merge sequence number.
|
||
|
// [fFullSave] - Set to TRUE if a full save was performed.
|
||
|
//
|
||
|
// History: 3-21-97 srikants Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CIndexTable::GetUserHdrInfo( unsigned & mMergeSeqNum, BOOL & fFullSave )
|
||
|
{
|
||
|
PRcovStorageObj & obj = GetIndexTableObj();
|
||
|
|
||
|
CRcovUserHdr usrHdr;
|
||
|
CIndexTableUsrHdr * pIdxUsrHdr = (CIndexTableUsrHdr *) &usrHdr;
|
||
|
|
||
|
CRcovStorageHdr & storageHdr = obj.GetHeader();
|
||
|
|
||
|
storageHdr.GetUserHdr( storageHdr.GetPrimary(), usrHdr );
|
||
|
ciDebugOut(( DEB_ERROR, "Current MMerge Seq Num = %d \n",
|
||
|
pIdxUsrHdr->GetMMergeSeqNum() ));
|
||
|
|
||
|
mMergeSeqNum = pIdxUsrHdr->GetMMergeSeqNum();
|
||
|
fFullSave = pIdxUsrHdr->IsFullSave();
|
||
|
|
||
|
}
|