//+--------------------------------------------------------------------------- // // 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 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); }