|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 1998.
//
// File: FRETEST.HXX
//
// Contents: Fresh test object
//
// Classes: CFreshTest
//
// History: 01-Oct-91 BartoszM Created.
//
//----------------------------------------------------------------------------
#pragma once
#include <fretable.hxx>
class CWidArray; class CDocList;
//+---------------------------------------------------------------------------
//
// Class: CFreshTest
//
// Purpose: Tests the freshness of the index id <-> work id association
//
// History: 16-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
class CFreshTest { public: CFreshTest ( unsigned size );
CFreshTest ( CFreshTest& source, CWidArray& widTable );
CFreshTest ( CFreshTest& source, CIdxSubstitution& subst);
CFreshTest( CFreshTest& source );
unsigned Count() { return _freshTable.Count(); }
unsigned DeleteCount() { return _cDeletes; }
void DecrementDeleteCount( unsigned cDeletes ) { _cDeletes -= cDeletes; }
void Add ( WORKID wid, INDEXID iid ) { _freshTable.Add ( wid, iid ); }
void AddReplace ( WORKID wid, INDEXID iid ) { _freshTable.AddReplace ( wid, iid ); }
void AddReplaceDelete ( WORKID wid, INDEXID iidDeleted ) { //
// NOTE: _cDeletes can be artificially high, if we get double-deletions
// but this doesn't really hurt, just possibly leads to an extra
// delete merge occasionally. So why waste the time filtering
// out the double-deletes?
//
INDEXID iidOld = _freshTable.AddReplace ( wid, iidDeleted );
if ( iidOld != iidDeleted1 && iidOld != iidDeleted2 ) _cDeletes++; }
void ModificationsComplete() { _freshTable.ModificationsComplete(); }
enum IndexSource { Invalid, Unknown, Master, Shadow };
IndexSource IsCorrectIndex( INDEXID iid, WORKID wid );
BOOL InUse() { return _refCount != 0; }
void Reference() { _refCount++; }
ULONG Dereference() { return --_refCount; }
CFreshTable * GetFreshTable() { Reference(); return &_freshTable; }
void ReleaseFreshTable(CFreshTable *p) { if (p != 0) Dereference(); }
INDEXID Find ( WORKID wid );
#ifdef CIEXTMODE
void CiExtDump(void *ciExtSelf); #endif
private:
ULONG RefCount() { return _refCount; } // for debugging only
void PatchEntry ( CFreshItem* pEntry, INDEXID iid );
ULONG _refCount;
CFreshTable _freshTable;
unsigned _cDeletes; };
//+-------------------------------------------------------------------------
//
// Class: CFreshTestLock
//
// Synopsis: A lock smart pointer on a CFreshTest object.
// Note that the destructor only de-references the fresh test
// It does NOT destroy the fresh test.
//
// History: 94-Mar-31 DwightKr Created
//
//--------------------------------------------------------------------------
class CFreshTestLock { public: inline CFreshTestLock( CFreshTest * ); inline CFreshTestLock(); inline ~CFreshTestLock(); inline CFreshTest * operator->() { return _pFreshTest; } inline CFreshTest & operator*() { return *_pFreshTest; }
private: CFreshTest * _pFreshTest; };
//+-------------------------------------------------------------------------
//
// Class: SFreshTable
//
// Synopsis: A smart pointer to a CFreshTable object
//
// History: 94-Jan-19 DwightKr Created
//
//--------------------------------------------------------------------------
class SFreshTable { public: inline SFreshTable( CFreshTest & ); inline ~SFreshTable(); inline CFreshTable * operator->() { return _pFreshTable; } inline CFreshTable & operator*() { return *_pFreshTable; }
private: CFreshTable * _pFreshTable; CFreshTest & _freshTest; };
//+---------------------------------------------------------------------------
//
// Member: CFreshTest::PatchEntry, private
//
// Synopsis: During recovery, if the wordlist
// has not been recreated yet, patch the entry
//
// Arguments: [fresh] -- fresh table
//
// History: 08-Oct-91 BartoszM Created.
//
// Notes: The assumption is that the operation is atomic.
// If there is a race to patch, the last query
// wins, but it doesn't really matter.
//
//----------------------------------------------------------------------------
inline void CFreshTest::PatchEntry ( CFreshItem* pEntry, INDEXID iid ) { ciDebugOut (( DEB_ITRACE, "FreshTest: patching entry %ld\n", iid )); pEntry->SetIndexId ( iid ); }
//+---------------------------------------------------------------------------
//----------------------------------------------------------------------------
inline INDEXID CFreshTest::Find ( WORKID wid ) { INDEXID iid = iidInvalid; // Assume it's in the master index
Reference(); CFreshItem *freshEntry = _freshTable.Find( wid );
if (0 != freshEntry) { iid = freshEntry->IndexId(); }
Dereference();
return iid; }
//+---------------------------------------------------------------------------
//
// Member: CFreshTestLock::CFreshTestLock, public
//
// Synopsis: Constructor.
//
// Arguments: [frestTest] -- freshTest to encapsulate
//
// History: 94-Mar-31 DwightKr Created.
//
//----------------------------------------------------------------------------
CFreshTestLock::CFreshTestLock( CFreshTest * pFreshTest) : _pFreshTest(pFreshTest) { }
CFreshTestLock::CFreshTestLock() : _pFreshTest( 0 ) { }
CFreshTestLock::~CFreshTestLock() { if ( _pFreshTest ) _pFreshTest->Dereference(); }
//+---------------------------------------------------------------------------
//
// Member: SFreshTable::SFreshTable, public
//
// Synopsis: Constructor.
//
// Arguments: [frestTest] -- freshTest which owns the freshTable
//
// History: 94-Jan-19 DwightKr Created.
//
//----------------------------------------------------------------------------
SFreshTable::SFreshTable( CFreshTest & freshTest) : _freshTest(freshTest), _pFreshTable(0)
{ _pFreshTable = _freshTest.GetFreshTable(); }
SFreshTable::~SFreshTable() { _freshTest.ReleaseFreshTable(_pFreshTable); }
|