263 lines
6.6 KiB
C++
263 lines
6.6 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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);
|
||
|
}
|
||
|
|