//+--------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation, 1991 - 1998 // // File: dellog.cxx // // Contents: Deletion log for usns // // History: 28-Jul-97 SitaramR Created // //---------------------------------------------------------------------------- #include #pragma hdrstop #include #include "cicat.hxx" #include "dellog.hxx" const LONGLONG eSigDelLog = 0x64656c746e6c6f67i64; // Signature //+--------------------------------------------------------------------------- // // Member: CFakeVolIdMap::CFakeVolIdMap // // Synopsis: Constructor // // History: 28-Jul-97 SitaramR Created // //---------------------------------------------------------------------------- CFakeVolIdMap::CFakeVolIdMap() { for ( ULONG i=0; i= VolumeIdBase && volumeId-VolumeIdBase < COUNT_ALPHABETS ) { return volumeId-VolumeIdBase; } // // Lookup in _aVolIdSpecial // for ( ULONG i=0; i.. // for each volume id, and each entry has . // //---------------------------------------------------------------------------- void CDeletionLog::FastInit( CiStorage * pStorage, ULONG version ) { XPtr sStrm( pStorage->QueryDeletionLog() ); _xPersStream.Set( new CDynStream( sStrm.GetPointer() ) ); sStrm.Acquire(); _xPersStream->CheckVersion( *pStorage, version ); ULONG cVolumes = _xPersStream->Count(); _xPersStream->InitializeForRead(); for ( ULONG i=0; iRead( &llSig, sizeof(llSig) ); if ( cbRead != sizeof(llSig) ) FatalCorruption( cbRead, sizeof(llSig) ); if ( eSigDelLog != llSig ) { ciDebugOut(( DEB_ERROR, "CDeletionLog: Signature mismatch 0x%x:0x%x\n", lltoHighPart(llSig), lltoLowPart(llSig) )); FatalCorruption( 0, 0 ); } VOLUMEID volumeId; cbRead = _xPersStream->Read( &volumeId, sizeof(VOLUMEID) ); if ( cbRead != sizeof(VOLUMEID) ) FatalCorruption( cbRead, sizeof(VOLUMEID) ); ULONG cEntries; cbRead = _xPersStream->Read( &cEntries, sizeof(ULONG) ); if ( cbRead != sizeof(ULONG) ) FatalCorruption( cbRead, sizeof(ULONG) ); for ( ULONG j=0; jRead( &fileId, sizeof(FILEID) ); if ( cbRead != sizeof(FILEID) ) FatalCorruption( cbRead, sizeof(FILEID) ); WORKID wid; cbRead = _xPersStream->Read( &wid, sizeof(WORKID) ); if ( cbRead != sizeof(WORKID) ) FatalCorruption( cbRead, sizeof(WORKID) ); USN usn; cbRead = _xPersStream->Read( &usn, sizeof(USN) ); if ( cbRead != sizeof(USN) ) FatalCorruption( cbRead, sizeof(USN) ); MarkForDeletion( volumeId, fileId, wid, usn ); } } } //+--------------------------------------------------------------------------- // // Member: CDeletionLog::ReInit // // Synopsis: Empties the deletion log // // History: 28-Jul-97 SitaramR Created // //---------------------------------------------------------------------------- void CDeletionLog::ReInit( ULONG version ) { CLock lock(_mutex); _xPersStream->SetVersion( version ); for ( ULONG i=0; iInitializeForWrite( GetSize() ); LONGLONG llSig = eSigDelLog; ULONG cVolumes = 0; for ( ULONG i=0; i 0 ) { cVolumes++; _xPersStream->Write( &llSig, sizeof(llSig) ); VOLUMEID volumeId = _fakeVolIdMap.FakeVolIdToVolId( i ); _xPersStream->Write( &volumeId, sizeof(VOLUMEID) ); ULONG cEntries = _aDelLogEntryList[i].Count(); _xPersStream->Write( &cEntries, sizeof(ULONG) ); #if CIDBG==1 ULONG cEntriesInList = 0; USN usnPrev = 0; #endif for ( CDelLogEntryListIter entryListIter( _aDelLogEntryList[i] ); !_aDelLogEntryList[i].AtEnd(entryListIter); _aDelLogEntryList[i].Advance( entryListIter) ) { FILEID fileId = entryListIter->FileId(); _xPersStream->Write( &fileId, sizeof(FILEID) ); WORKID wid = entryListIter->WorkId(); _xPersStream->Write( &wid, sizeof(WORKID) ); USN usn = entryListIter->Usn(); _xPersStream->Write( &usn, sizeof(USN) ); #if CIDBG==1 // // Check usn's are monotonically increasing // cEntriesInList++; Win4Assert( entryListIter->Usn() >= usnPrev ); usnPrev = entryListIter->Usn(); #endif } #if CIDBG==1 Win4Assert( cEntriesInList == _aDelLogEntryList[i].Count() ); #endif } } _xPersStream->SetCount( cVolumes ); _xPersStream->Flush(); } //+--------------------------------------------------------------------------- // // Member: CDeletionLog::MarkForDeletion // // Synopsis: Adds a deletion entry // // History: 28-Jul-97 SitaramR Created // //---------------------------------------------------------------------------- void CDeletionLog::MarkForDeletion( VOLUMEID volumeId, FILEID fileId, WORKID wid, USN usn ) { CLock lock(_mutex); XPtr xEntry( new CDelLogEntry( fileId, wid, usn ) ); ULONG fakeVolId = _fakeVolIdMap.VolIdToFakeVolId( volumeId ); Win4Assert( fakeVolId < RTL_MAX_DRIVE_LETTERS ); if ( _aDelLogEntryList[fakeVolId].Count() == 0 ) { // // Empty list case // _aDelLogEntryList[fakeVolId].Queue( xEntry.Acquire() ); } else { CDelLogEntry *pEntryLast = _aDelLogEntryList[fakeVolId].GetLast(); if ( xEntry->Usn() > pEntryLast->Usn() ) { // // If the usn is less than the last entry's usn, then it means that it // is a usn that is being replayed, and there is no need to add it // to the deletion log again. // _aDelLogEntryList[fakeVolId].Queue( xEntry.Acquire() ); } } } //+--------------------------------------------------------------------------- // // Member: CDeletionLog::ProcessChangesFlush // // Synopsis: Process the list of changes that has been flushed by // framework/changelog and do the actual deletes from // the file id map. // // Arguments: [usnFlushInfoList] -- List of changes flushed // // History: 28-Jul-97 SitaramR Created // //---------------------------------------------------------------------------- void CDeletionLog::ProcessChangesFlush( CUsnFlushInfoList & usnFlushInfoList ) { CLock lock( _mutex ); for ( ULONG i=0; iVolumeId() ); Win4Assert( fakeVolId < RTL_MAX_DRIVE_LETTERS ); CDelLogEntryList& entryList = _aDelLogEntryList[fakeVolId]; #if CIDBG==1 USN usnPrev = 0; #endif CDelLogEntryListIter entryListIter( entryList ); while ( !entryList.AtEnd( entryListIter ) ) { CDelLogEntry *pEntry = entryListIter.GetEntry(); entryList.Advance( entryListIter ); #if CIDBG==1 // // Check that usn's are monotonically increasing // Win4Assert( pEntry->Usn() >= usnPrev ); usnPrev = pEntry->Usn(); #endif if ( pEntry->Usn() <= pFlushInfo->UsnHighest() ) { entryList.RemoveFromList( pEntry ); _fileIdMap.Delete( pEntry->FileId(), pEntry->WorkId() ); delete pEntry; } else { // // Since the list is in increasing usn order, we are done // with this volume id. // break; } } } } //+--------------------------------------------------------------------------- // // Member: CDeletionLog::GetSize // // Synopsis: Returns the size of the serialized stream in bytes // // History: 28-Jul-97 SitaramR Created // //---------------------------------------------------------------------------- ULONG CDeletionLog::GetSize() { // // Start with a slop factor // ULONG ulSize = 1024; for ( ULONG i=0; i