Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

415 lines
11 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1998.
//
// File: changlog.hxx
//
// Contents: Persistent Change Log manager and related classes.
//
// Classes: CDocNotification, CDocChunk, CChunkList, CChangeLog
//
// History: 5-26-94 srikants ReWrite Change Log implementation.
//
//----------------------------------------------------------------------------
#pragma once
#include <glbconst.hxx>
#include <rcstxact.hxx>
#include <eventlog.hxx>
#include <doclist.hxx>
#include <usninfo.hxx>
class CResManager;
class CNotificationTransaction;
const unsigned cDocInChunk = 16;
//+---------------------------------------------------------------------------
//
// Class: CDocNotification
//
// Purpose: Notification
//
// History: 11-Aug-93 BartoszM Created.
// 08-Feb-94 DwightKr Added retries
// 24-Feb-97 SitaramR Push filtering
//
//----------------------------------------------------------------------------
#include <pshpack2.h>
class CDocNotification
{
public:
CDocNotification() { _wid = widInvalid; }
void Set ( WORKID wid,
USN usn,
VOLUMEID volumeId,
ULONG action,
ULONG retries,
ULONG secQRetries )
{
_wid = wid;
_usn = usn;
_volumeId = volumeId;
Win4Assert( action <= 0xffff );
Win4Assert( retries <= 0xffff );
Win4Assert( secQRetries <= 0xffff );
_action = (USHORT) action;
_retries = (USHORT) retries;
_secQRetries = (USHORT) secQRetries;
}
WORKID Wid() const { return _wid; }
USN Usn() const { return _usn; }
VOLUMEID VolumeId() const { return _volumeId; }
ULONG Action() const { return _action; }
ULONG Retries() const { return _retries; }
ULONG SecQRetries() const { return _secQRetries; }
BOOL IsDeletion () const { return (_action & CI_DELETE_OBJ) != 0; }
#ifdef CIEXTMODE
void CiExtDump(void *ciExtSelf);
#endif
private:
USN _usn;
WORKID _wid;
VOLUMEID _volumeId;
USHORT _action;
USHORT _retries;
USHORT _secQRetries;
};
#include <poppack.h>
//+---------------------------------------------------------------------------
//
// Class: CDocChunk
//
// Purpose: Array of document notifications
//
// History: 11-Aug-93 BartoszM Created.
//
//----------------------------------------------------------------------------
class CDocChunk
{
public:
CDocChunk () : _pNext(0)
{
Win4Assert (sizeof(_aNotify) == (sizeof(CDocNotification) * cDocInChunk));
}
CDocChunk* GetNext() const { return _pNext; }
void SetNext ( CDocChunk* pNext ) { _pNext = pNext; }
CDocNotification* GetDoc( unsigned offset )
{
Win4Assert( offset < cDocInChunk );
return( &_aNotify[offset] );
}
CDocNotification* GetArray() { return &_aNotify[0]; }
unsigned Size() { return cDocInChunk; }
void UpdateMaxUsn( CCountedDynArray<CUsnFlushInfo> & aUsnFlushInfo );
#ifdef CIEXTMODE
void CiExtDump(void *ciExtSelf);
#endif
private:
CDocChunk* _pNext;
CDocNotification _aNotify[cDocInChunk];
};
//+---------------------------------------------------------------------------
//
// Class: CChunkList
//
// Purpose: A singly linked list of CDocChunks.
//
// History: 5-26-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
class CChunkList
{
public:
CChunkList() : _pHead(0), _pTail(0), _count(0)
{
}
~CChunkList()
{
DestroyUpto();
}
CDocChunk * GetFirst() { return _pHead; }
CDocChunk * GetLast() { return _pTail; }
BOOL IsEmpty() const { return 0 == _pHead; }
ULONG Count( ) const { return _count; }
void Append( CDocChunk * pChunk );
CDocChunk * Pop();
void DestroyUpto( CDocChunk * pChunk = 0 );
CDocChunk * Acquire()
{
CDocChunk * pTemp = _pHead;
_pHead = _pTail = 0;
_count = 0;
return(pTemp);
}
void TruncateFrom( CDocChunk * pChunk );
void AcquireAndAppend( CChunkList & chunkList );
#ifdef CIEXTMODE
void CiExtDump(void *ciExtSelf);
#endif
private:
CDocChunk * _pHead; // Head of the linked list.
CDocChunk * _pTail; // Tail of the linked list.
ULONG _count; // number of chunks in the list.
};
//+---------------------------------------------------------------------------
//
// Function: Append
//
// Synopsis: Appends the specified chunk to the list.
//
// Arguments: [pChunk] -- Chunk to append.
//
// History: 5-26-94 srikants Created
//
//----------------------------------------------------------------------------
inline void CChunkList::Append( CDocChunk * pChunk )
{
Win4Assert( 0 != pChunk );
pChunk->SetNext(0);
if ( 0 != _pHead )
{
Win4Assert( 0 != _pTail );
_pTail->SetNext( pChunk );
}
else
{
Win4Assert( 0 == _pTail );
_pHead = pChunk;
}
_pTail = pChunk;
_count++;
}
//+---------------------------------------------------------------------------
//
// Function: Pop
//
// Synopsis: Removes and returns the first element in the list.
//
// History: 5-26-94 srikants Created
//
//----------------------------------------------------------------------------
inline CDocChunk * CChunkList::Pop()
{
CDocChunk * pChunk = 0;
if ( 0 != _pHead )
{
pChunk = _pHead;
_pHead = _pHead->GetNext();
if ( 0 == _pHead )
{
Win4Assert( 1 == _count );
Win4Assert( pChunk == _pTail );
_pTail = 0;
}
pChunk->SetNext(0);
Win4Assert( _count > 0 );
_count--;
}
else
{
Win4Assert( 0 == _pTail );
}
return(pChunk);
}
//+---------------------------------------------------------------------------
//
// Function: DestroyUpto
//
// Synopsis: Destroys all the elements in the list and frees them.
//
// History: 5-26-94 srikants Created
//
//----------------------------------------------------------------------------
inline void CChunkList::DestroyUpto( CDocChunk * pChunk )
{
while ( _pHead != pChunk )
{
CDocChunk * pDelete = Pop();
delete pDelete;
}
}
//+---------------------------------------------------------------------------
//
// Function: TruncateFrom
//
// Synopsis: Removes all the elements in the queue from the specified node
// to the end of the list. It has been assumed that the specified
// node is part of the list.
//
// Arguments: [pChunk] -- The first chunk to be deleted from the list.
//
// History: 5-26-94 srikants Created
//
//----------------------------------------------------------------------------
inline void CChunkList::TruncateFrom( CDocChunk * pChunk )
{
Win4Assert( 0 != pChunk );
CDocChunk * pDelete = pChunk->GetNext();
while ( 0 != pDelete )
{
CDocChunk * pNext = pDelete->GetNext();
delete pDelete;
Win4Assert( _count > 0 );
_count--;
pDelete = pNext;
}
Win4Assert( _count > 0 );
_pTail = pChunk;
pChunk->SetNext(0);
}
class CFreshTest;
class PStorage;
//+---------------------------------------------------------------------------
//
// Class: CChangeLog
//
// Purpose: Persistent change list manager. This class is capable of
// doing operations on the persistent change log, eg.
// serializing, de-serializing, and compacting.
//
// History: 5-26-94 srikants Created
// 2-24-97 SitaramR Push filtering
//
//----------------------------------------------------------------------------
const LONGLONG eSigChangeLog = 0x474f4c474e414843i64; // "CHANGLOG"
class CChangeLog
{
public:
CChangeLog( WORKID widChangeLog, PStorage & storage,
PStorage::EChangeLogType type );
~CChangeLog();
void LokEmpty();
BOOL IsEmpty() const { return 0 == _cChunksAvail; }
BOOL IsPrimary() const { return PStorage::ePrimChangeLog == _type; }
BOOL IsSecondary() const { return PStorage::eSecChangeLog == _type; }
ULONG AvailChunkCount() const { return _cChunksAvail; }
ULONG DeSerialize( CChunkList & deserializedList,
ULONG cChunksToRead );
ULONG Serialize( CChunkList & listToSerialize,
CCountedDynArray<CUsnFlushInfo> & aUsnFlushInfo );
ULONG LokDeleteWIDsInPersistentIndexes( ULONG cFilteredChunks,
CFreshTest & freshTestLatest,
CFreshTest & freshTestAtMerge,
CDocList & docList,
CNotificationTransaction & notifTrans );
void LokDisableUpdates();
void LokEnableUpdates( BOOL fFirstTimeUpdatesAreEnabled );
BOOL AreUpdatesEnabled() { return _fUpdatesEnabled; }
void SkipChunk()
{
Win4Assert( _cChunksAvail > 0 );
Win4Assert( _oChunkToRead + _cChunksAvail == _cChunksTotal );
_oChunkToRead++;
_cChunksAvail--;
}
void SetResMan( CResManager * pResManager, BOOL fPushFiltering );
BOOL FPushFiltering() { return _fPushFiltering; }
#ifdef CIEXTMODE
void CiExtDump(void *ciExtSelf);
#endif
private:
void InitSize();
void LokVerifyConsistency();
BOOL IsWidInDocList( WORKID wid, CDocList& docList );
const LONGLONG _sigChangeLog;
CResManager * _pResManager; // Resman
WORKID _widChangeLog; // WorkId of the changelog.
PStorage & _storage; // Persistent storage object.
PStorage::EChangeLogType _type; // Type of change log
BOOL _fUpdatesEnabled; // Flag indicating whether updates
// are allowed or not.
BOOL _fPushFiltering; // Using push model of filtering ?
SRcovStorageObj _PersDocQueue; // The persistent doc queue.
ULONG _oChunkToRead; // Offset of the next chunk to
// read from the log.
ULONG _cChunksAvail; // Number of chunks available in
// the change log for reading.
ULONG _cChunksTotal; // Total number of chunks.
// (For debugging).
};