265 lines
7.9 KiB
C++
265 lines
7.9 KiB
C++
|
|
// Copyright (c) 1996-1999 Microsoft Corporation
|
|
|
|
//+============================================================================
|
|
//
|
|
// oplog.cxx
|
|
//
|
|
// Implementation for COperationsLog, which maintains a simple, circular
|
|
// log of events.
|
|
//
|
|
//+============================================================================
|
|
|
|
|
|
#include "pch.cxx"
|
|
#pragma hdrstop
|
|
|
|
#ifndef NO_OPLOG
|
|
|
|
#include "trklib.hxx"
|
|
|
|
#define OPERATION_LOG_SIZE ( (( (1024*1024) - sizeof(SHeader) )/sizeof(SRecord))*sizeof(SRecord) + sizeof(SHeader) )
|
|
#define OPERATION_LOG_RECORD_COUNT ( (OPERATION_LOG_SIZE - sizeof(SHeader)) / sizeof(SRecord) )
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// COperationLog::InitializeLogFile
|
|
//
|
|
// Initialize the operations log file. This is called lazily so that we don't
|
|
// impact service start (and don't get called unless the oplog is turned on).
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
COperationLog::InitializeLogFile( )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
ULONG cbFile = 0;
|
|
|
|
_iRecord = 0;
|
|
|
|
Lock();
|
|
|
|
__try
|
|
{
|
|
BY_HANDLE_FILE_INFORMATION FileInfo;
|
|
|
|
_fLogFileInitialized = TRUE;
|
|
|
|
TrkLog(( TRKDBG_VOLUME, TEXT("Initializing operation log file (%s)"), _ptszOperationLog ));
|
|
|
|
// Loop twice, if we find a problem the first time, we'll delete and
|
|
// try again.
|
|
|
|
for( int i = 0; i < 2; i++ )
|
|
{
|
|
if( INVALID_HANDLE_VALUE != _hFile )
|
|
CloseHandle( _hFile );
|
|
|
|
// Open/create the file on the first pass, create it on the second pass.
|
|
|
|
_hFile = CreateFile( _ptszOperationLog, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL,
|
|
0 == i ? OPEN_ALWAYS : CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE );
|
|
if( INVALID_HANDLE_VALUE == _hFile )
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Couldn't create/open status log file (%lu)"),
|
|
GetLastError() ));
|
|
TrkRaiseLastError();
|
|
}
|
|
|
|
// On the first pass, check the file to see if it looks valid.
|
|
// If not, continue the loop so that a new file can be created.
|
|
|
|
if( 1 == i )
|
|
cbFile = 0;
|
|
else
|
|
{
|
|
// All we check is the size. There's no support for trying
|
|
// to migrate a file if we change the file size.
|
|
|
|
if( !GetFileInformationByHandle( _hFile, &FileInfo ))
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Couldn't get status file info") ));
|
|
TrkRaiseLastError();
|
|
}
|
|
if( 0 != FileInfo.nFileSizeHigh )
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Operation file to big") ));
|
|
continue;
|
|
}
|
|
else if( 0 != FileInfo.nFileSizeLow
|
|
&&
|
|
OPERATION_LOG_SIZE != FileInfo.nFileSizeLow )
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT( "Operation log file wrong size") ));
|
|
continue;
|
|
}
|
|
cbFile = FileInfo.nFileSizeLow;
|
|
}
|
|
}
|
|
|
|
// Create a mapping of the file.
|
|
|
|
_hFileMapping = CreateFileMapping( _hFile, NULL, PAGE_READWRITE, 0, OPERATION_LOG_SIZE, NULL );
|
|
if( INVALID_HANDLE_VALUE == _hFileMapping )
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Couldn't create status log file mapping (%lu)"), GetLastError() ));
|
|
TrkRaiseLastError();
|
|
}
|
|
|
|
// And map a view of the file.
|
|
|
|
_pHeader = (SHeader*) MapViewOfFile( _hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, OPERATION_LOG_SIZE );
|
|
if( NULL == _pHeader )
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Couldn't map view of status log file (%lu)"),
|
|
GetLastError() ));
|
|
TrkRaiseLastError();
|
|
}
|
|
|
|
// If we opened an existing file, validate the shutdown and version.
|
|
// If anything looks wrong, or if this file is new, zero it out.
|
|
|
|
if( 0 == cbFile
|
|
||
|
|
0 == (_pHeader->grfFlags & PROPER_SHUTDOWN)
|
|
||
|
|
OPERATION_LOG_VERSION != _pHeader->dwVersion )
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Re-initializing operation log file") ));
|
|
_iRecord = 0;
|
|
memset( _pHeader, 0, OPERATION_LOG_SIZE );
|
|
_pHeader->dwVersion = OPERATION_LOG_VERSION;
|
|
}
|
|
else
|
|
_iRecord = _pHeader->iRecord;
|
|
|
|
// Show that the file isn't properly shut down.
|
|
|
|
_pHeader->grfFlags &= ~PROPER_SHUTDOWN;
|
|
_prgRecords = (SRecord*) ( (BYTE*)_pHeader + sizeof(SHeader) );
|
|
Flush();
|
|
|
|
TrkLog(( TRKDBG_VOLUME, TEXT("Status log starts at index %d"), _iRecord ));
|
|
hr = S_OK;
|
|
|
|
}
|
|
__except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
hr = GetExceptionCode();
|
|
}
|
|
|
|
|
|
Unlock();
|
|
return( hr );
|
|
}
|
|
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// COperationsLog::Flush
|
|
//
|
|
// Flush the operations log to disk.
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
void
|
|
COperationLog::Flush()
|
|
{
|
|
__try
|
|
{
|
|
if( !_fLogFileInitialized )
|
|
__leave;
|
|
|
|
_pHeader->iRecord = _iRecord;
|
|
|
|
if( NULL != _pHeader && !FlushViewOfFile( _pHeader, OPERATION_LOG_SIZE ))
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Couldn't flush operation log file view") ));
|
|
}
|
|
if( INVALID_HANDLE_VALUE != _hFile && !FlushFileBuffers( _hFile ))
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Couldn't flush operation log file") ));
|
|
}
|
|
}
|
|
__except( BreakOnDebuggableException() )
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Ignoring exception in COpLog::Flush (0x%08x)"),
|
|
GetExceptionCode() ));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// COperationLog::InternalAdd
|
|
//
|
|
// Add an entry to the operation log.
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
void
|
|
COperationLog::InternalAdd( DWORD dwOperation, HRESULT hr, const CMachineId &mcidSource,
|
|
DWORD dwExtra0, DWORD dwExtra1, DWORD dwExtra2, DWORD dwExtra3,
|
|
DWORD dwExtra4, DWORD dwExtra5, DWORD dwExtra6, DWORD dwExtra7 )
|
|
{
|
|
ULONG iFile = 0;
|
|
ULONG cbWritten = 0;
|
|
|
|
Lock();
|
|
__try
|
|
{
|
|
// Lazy initialization of the log file.
|
|
|
|
if( !_fLogFileInitialized )
|
|
{
|
|
if( FAILED( InitializeLogFile() ))
|
|
__leave;
|
|
}
|
|
|
|
// Ensure we have valid mappings.
|
|
|
|
if( NULL == _pHeader || NULL == _prgRecords )
|
|
__leave;
|
|
|
|
// Add the data to the next record.
|
|
|
|
_prgRecords[_iRecord].dwOperation = dwOperation;
|
|
_prgRecords[_iRecord].ftOperation = CFILETIME();
|
|
_prgRecords[_iRecord].mcidSource = mcidSource;
|
|
_prgRecords[_iRecord].hr = hr;
|
|
|
|
_prgRecords[_iRecord].rgdwExtra[0] = dwExtra0;
|
|
_prgRecords[_iRecord].rgdwExtra[1] = dwExtra1;
|
|
_prgRecords[_iRecord].rgdwExtra[2] = dwExtra2;
|
|
_prgRecords[_iRecord].rgdwExtra[3] = dwExtra3;
|
|
_prgRecords[_iRecord].rgdwExtra[4] = dwExtra4;
|
|
_prgRecords[_iRecord].rgdwExtra[5] = dwExtra5;
|
|
_prgRecords[_iRecord].rgdwExtra[6] = dwExtra6;
|
|
_prgRecords[_iRecord].rgdwExtra[7] = dwExtra7;
|
|
|
|
// Advance the seek pointer.
|
|
|
|
_iRecord++;
|
|
if( OPERATION_LOG_RECORD_COUNT == _iRecord )
|
|
{
|
|
_iRecord = 0;
|
|
TrkLog(( TRKDBG_VOLUME, TEXT("Wrapping operation log") ));
|
|
}
|
|
}
|
|
__except( BreakOnDebuggableException() )
|
|
{
|
|
TrkLog(( TRKDBG_WARNING, TEXT("Ignoring exception in COpLog::InternalAdd (0x%08x)"),
|
|
GetExceptionCode() ));
|
|
}
|
|
|
|
|
|
Unlock();
|
|
}
|
|
|
|
|
|
#endif // #ifndef NO_OPLOG
|