|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 1998.
//
// File: FRESH.CXX
//
// Contents: Fresh list
//
// Classes: CFresh
//
// History: 16-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <enumstr.hxx>
#include "fresh.hxx"
#include "fretest.hxx"
#include "indxact.hxx"
#include "merge.hxx"
#include "wordlist.hxx"
class CEnumWorkid;
//+---------------------------------------------------------------------------
//
// Member: CFresh::CFresh, public
//
// Synopsis: Constructor.
//
// History: 16-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
CFresh::CFresh ( PStorage& storage, CTransaction& xact, CPartList & partList ) : _storage( storage ), _persFresh( storage, partList ), _master( 0 ), _partList( partList ) { ULONG count = max( _persFresh.GetPersRecCount(), 100 );
XPtr<CFreshTest> xMaster( new CFreshTest ( count ) );
SFreshTable freshTable( xMaster.GetReference() ); _persFresh.LoadFreshTest( *freshTable );
_master = xMaster.Acquire(); }
//+---------------------------------------------------------------------------
//
// Member: CFresh::~CFresh, public
//
// Synopsis: Destructor.
//
// History: 16-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
CFresh::~CFresh () { delete _master; }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokInit, public
//
// Synopsis: Empties and re-initializes the fresh test
//
// History: 15-Nov-94 DwightKr Created.
//
//----------------------------------------------------------------------------
void CFresh::LokInit() { _persFresh.LokEmpty();
unsigned count = 100; CFreshTest* newFreshTest = new CFreshTest ( count );
LokCommitMaster( newFreshTest ); }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokGetFreshTest, public
//
// Synopsis: Creates CFreshTest object
//
// History: 16-May-91 BartoszM Created.
//
// Notes: ResMan LOCKED
// FreshTest has to be released
//
//----------------------------------------------------------------------------
CFreshTest* CFresh::LokGetFreshTest() { ciDebugOut (( DEB_ITRACE, ">> get fresh test\n")); _master->Reference(); return _master; }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokReleaseFreshTest, public
//
// Synopsis: Dereferences CFreshTest object
//
// History: 16-May-91 BartoszM Created.
//
// Notes: ResMan LOCKED
//
//----------------------------------------------------------------------------
void CFresh::LokReleaseFreshTest( CFreshTest* test ) { ciDebugOut (( DEB_ITRACE, "<< release fresh test\n" )); if ( test != 0 && test->Dereference() == 0 && test != _master ) { delete test; } }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokCommitMaster, public
//
// Synopsis: Adds a new master fresh test
//
// History: 16-May-91 BartoszM Created.
//
// Notes: ResMan LOCKED
//
//----------------------------------------------------------------------------
void CFresh::LokCommitMaster ( CFreshTest* newMaster ) { ciDebugOut (( DEB_ITRACE, "Commit new master fresh test\n" )); Win4Assert ( newMaster != 0 ); Win4Assert ( _master != 0 );
CFreshTest* old = _master; _master = newMaster;
ciDebugOut(( DEB_ITRACE, "New master (0x%x) has %u deletes\n", _master, _master->DeleteCount() ));
if ( !old->InUse() ) { delete old; } }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokAddIndex, public
//
// Synopsis: Adds new mapping iid <-> documents after filtering
//
// Arguments: [xact] -- transaction
// [iid] -- index id
// [iidDeleted] -- index id for deleted objects
// [docList] -- list of wids
//
// History: 16-May-91 BartoszM Created.
//
// Notes: ResMan LOCKED
//
//----------------------------------------------------------------------------
void CFresh::LokAddIndex ( CIndexTrans& xact, INDEXID iid, INDEXID iidDeleted, CDocList& docList, CWordList const & wordList ) { ciDebugOut (( DEB_ITRACE, "Fresh: Adding documents, iid %lx\n", iid ));
CFreshTest* newMaster = new CFreshTest ( *_master ); xact.LogFresh ( newMaster );
unsigned cDocuments = docList.Count();
for ( unsigned i = 0; i < cDocuments; i++ ) { STATUS status = docList.Status(i); if ( status == SUCCESS ) { WORKID wid = docList.Wid(i); ciDebugOut (( DEB_FRESH, "Fresh wid %ld, iid %lx\n", wid, iid ));
#if CIDBG==1
Win4Assert( widInvalid != wid && wordList.IsWorkIdPresent( wid ) ); #endif // CIDBG==1
newMaster->AddReplace ( wid, iid ); } else if ( status == DELETED || status == WL_NULL ) { WORKID wid = docList.Wid(i); ciDebugOut (( DEB_FRESH, "Fresh wid %ld deleted \n", wid )); newMaster->AddReplaceDelete ( wid, iidDeleted ); } else { ciDebugOut (( DEB_FRESH, "Fresh wid %ld, not changed. Status 0x%X\n", docList.Wid(i), status )); #if CIDBG==1
Win4Assert( !wordList.IsWorkIdPresent( docList.Wid(i)) ); #endif // CIDBG==1
} }
newMaster->ModificationsComplete(); }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokDeleteDocuments, public
//
// Synopsis: Mark documents as deleted
//
// Arguments: [xact] -- transaction
// [docList] -- list of wids
// [iidDeleted] -- index id for deleted objects
//
// History: 16-May-91 BartoszM Created.
// 12-Jun-97 KyleP Track unlogged deletions
//
// Notes: ResMan LOCKED
//
//----------------------------------------------------------------------------
void CFresh::LokDeleteDocuments( CIndexTrans& xact, CDocList& docList, INDEXID iidDeleted ) { ciDebugOut (( DEB_ITRACE, "Fresh: Deleting documents\n" ));
CFreshTest* newMaster = new CFreshTest ( *_master ); xact.LogFresh ( newMaster );
unsigned cDocuments = docList.Count();
for ( unsigned i = 0; i < cDocuments; i++ ) { if ( docList.Status(i) == DELETED) { WORKID wid = docList.Wid(i); ciDebugOut (( DEB_FRESH, "Fresh wid %ld deleted \n", wid )); newMaster->AddReplaceDelete ( wid, iidDeleted );
} }
newMaster->ModificationsComplete(); }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokUpdate, public
//
// Synopsis: Replaces old entries with the more recent entries after merge
//
// Arguments: [merge] -- Merge object
// [xact] -- Merge transaction
// [newFreshLog] -- New fresh log
// [newIid] -- New index id
// [cInd] -- Count of index id's to be replaced
// [aIidOld] -- Array of index id's to be replaced
// [xFreshTestAtMerge] -- If a new fresh test that was used at
// merge time is created, store in here
//
// History: 16-May-91 BartoszM Created.
// 01-Dec-93 DwightKr Write changes to pers. fresh log
// 04-Oct-94 SrikantS Support for creating a new fresh
// log after merge.
//
// Notes: ResMan LOCKED
//
//----------------------------------------------------------------------------
WORKID CFresh::LokUpdate ( CMerge& merge, CMergeTrans& xact, CPersFresh & newFreshLog, INDEXID newIid, int cInd, INDEXID aIidOld[], XPtr<CFreshTest> & xFreshTestAtMerge ) { ciDebugOut (( DEB_ITRACE, "Fresh list: updating %d entries\n", cInd ));
CIdxSubstitution subst (FALSE, newIid, cInd, aIidOld);
CFreshTest * newMaster = new CFreshTest( *_master, subst ); xact.LogFresh( newMaster );
WORKID widNewFreshLog;
//
// The new memory fresh test is created by applying the transformtion on
// the master fresh test. We should apply the transformation for
// persistent log on the freshtest used by the merge. If a fresh test is
// created then we pass ownership to xFreshTestAtMerge, so that
// LokDeleteWidsInPersistentIndex can use the newly created fresh test.
//
// optimization to avoid creating a new fresh test
if ( _master == merge.GetFresh() ) { widNewFreshLog = LokBuildNewFreshLog( newMaster, newFreshLog, subst);
newMaster->DecrementDeleteCount( _master->DeleteCount() ); } else { xFreshTestAtMerge.Set( new CFreshTest( *(merge.GetFresh()), subst ) ); widNewFreshLog = LokBuildNewFreshLog( xFreshTestAtMerge.GetPointer(), newFreshLog, subst );
newMaster->DecrementDeleteCount( xFreshTestAtMerge->DeleteCount() ); }
newMaster->ModificationsComplete();
xact.LogNewFreshLog( newMaster, widNewFreshLog );
return widNewFreshLog; }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokRemoveIndexes, public
//
// Synopsis: Removes indexes from table after master merge
//
// Arguments: [xact] -- merge transaction
// [cInd] -- count of inexes to be removed
// [aIidOld] -- array of index ids of obsolete indexes
// [iidOldDeleted] -- old index id for deleted objects
//
// History: 16-May-91 BartoszM Created.
//
// Notes: ResMan LOCKED
//
//----------------------------------------------------------------------------
WORKID CFresh::LokRemoveIndexes( CMergeTrans& xact, CPersFresh & newFreshLog, unsigned cInd, INDEXID aIidOld[], INDEXID iidOldDeleted ) {
ciDebugOut (( DEB_ITRACE, "FreshList: Removing indexes\n" ));
CIdxSubstitution subst (TRUE, iidOldDeleted, cInd, aIidOld);
XPtr<CFreshTest> xNewMaster( new CFreshTest( *_master, subst ) );
WORKID widNewFreshLog = LokBuildNewFreshLog( xNewMaster.GetPointer(), newFreshLog, subst );
// LogNewFreshLog can't fail, so the acquire is safe to do
// before the call.
xNewMaster->ModificationsComplete();
xact.LogNewFreshLog( xNewMaster.Acquire(), widNewFreshLog );
return(widNewFreshLog); }
//+---------------------------------------------------------------------------
//
// Function: LokBuildNewFreshLog
//
// Synopsis: Builds a new persistent fresh log by combining the existing
// fresh log and the new fresh test.
//
// Arguments: [newFreTest] -- Input - the new fresh test.
// [newFreshLog] -- Input/Output - the new fresh log object.
// [subst] -- Index substitution object
//
// Returns: ObjectId of the new persistent fresh log created.
//
// History: 03-Oct-94 srikants Created
// 11-Jun-97 KyleP Track unlogged deletions
//
//----------------------------------------------------------------------------
WORKID CFresh::LokBuildNewFreshLog( CFreshTest * newFreTest, CPersFresh & newFreshLog, CIdxSubstitution& subst ) { SFreshTable freshTable( *newFreTest ); CFreshTableIter iter( *freshTable );
//
// Create a new persistent fresh log.
//
WORKID widNewFreshLog = _storage.GetNewObjectIdForFreshLog(); _storage.InitRcovObj( widNewFreshLog, FALSE );
PRcovStorageObj *pPersFreshLog = _storage.QueryFreshLog( widNewFreshLog ); SRcovStorageObj PersFreshLog( pPersFreshLog );
//
// Inside kernel, we are guaranteed that a new object has no data in
// it. In user space, we may be using an object that was not deleted
// before due to a failure.
//
PersFreshLog->InitHeader(_storage.GetStorageVersion());
newFreshLog.LokCompactLog( PersFreshLog, iter, subst);
return(widNewFreshLog); }
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokMakeFreshLogBackup
//
// Synopsis: Makes a backup of the current persistent freshlog to the
// storage provided.
//
// Arguments: [storage] - Destination storage.
// [tracker] - Progress tracker and abort indication.
//
// History: 3-18-97 srikants Created
//
//----------------------------------------------------------------------------
void CFresh::LokMakeFreshLogBackup( PStorage & storage, PSaveProgressTracker & tracker, XInterface<ICiEnumWorkids> & xEnumWorkids ) {
//
// Create a fresh log with the same name using the storage object
// provided.
//
WORKID widFreshLog = _storage.GetSpecialItObjectId( itFreshLog );
ULONG cRec = 0; //
// Scope for physical copy of the object.
//
{ //
// Open the source fresh log
//
PRcovStorageObj *pSrcFreshLog = _storage.QueryFreshLog( widFreshLog ); SRcovStorageObj xSrcFreshLog( pSrcFreshLog );
//
// Create the destination fresh log
//
PRcovStorageObj *pDstFreshLog = storage.QueryFreshLog( widFreshLog ); SRcovStorageObj xDstFreshLog( pDstFreshLog );
//
// Copy the contents of the source to the destination.
//
CCopyRcovObject copyData( *pDstFreshLog, *pSrcFreshLog ); NTSTATUS status = copyData.DoIt(); if ( STATUS_SUCCESS != status ) THROW( CException( status ) );
CRcovStorageHdr & hdr = pSrcFreshLog->GetHeader(); cRec = hdr.GetCount( hdr.GetPrimary() ); }
//
// Get the list of WORKIDs in the persistent freshlog.
//
CFreshTest * pFreshTest = new CFreshTest ( max(100,cRec) ); XPtr<CFreshTest> xFreTest( pFreshTest );
SFreshTable freshTable( *pFreshTest );
//
// The source and destination persistent freshlogs are identical.
//
_persFresh.LoadFreshTest( *freshTable );
//
// Copy the workids from freshhash entries to the workid enumerator.
//
CEnumWorkid * pEnumWorkids = new CEnumWorkid( freshTable->Count() ); xEnumWorkids.Set( pEnumWorkids );
for ( CFreshTableIter iter( *freshTable ); !iter.AtEnd(); iter.Advance() ) { pEnumWorkids->Append( iter->WorkId() ); }
Win4Assert( cRec == freshTable->Count() ); ciDebugOut(( DEB_ITRACE, "%d Workids Changed \n", freshTable->Count() ));
}
//+---------------------------------------------------------------------------
//
// Member: CFresh::LokEmpty, public
//
// Synopsis: Empties/deletes the fresh hash and the fresh log.
//
// History: 16-Aug-94 DwightKr Created
//
//----------------------------------------------------------------------------
void CFresh::LokEmpty() { delete _master; // Delete the fresh test
_master = 0; }
|