|
|
/*++
Copyright (C) 2000-2001 Microsoft Corporation
--*/
#include <wbemcomn.h>
#include <reposit.h>
#include <sync.h>
#include <malloc.h>
#include "longstg.h"
#define A51_INSTRUCTION_TYPE_WRITEFILE 1
#define A51_INSTRUCTION_TYPE_SETENDOFFILE 2
CTempMemoryManager g_LongFileCacheManager;
__int64 CWriteFileInstruction::mstatic_lNextZOrder = 0;
DWORD g_dwFailureCount = 0; DWORD g_dwFailureFrequency = 0; DWORD g_dwLastFailureCheck = 0; #define FAILURE_INJECTION_CHECK_INTERVAL 10000
CLongFileInstruction::CLongFileInstruction(CLongFileStagingFile* pFile) : CStageInstruction(pFile) { }
CLongFileInstruction::CLongFileInstruction(CLongFileStagingFile* pFile, int nFileId, TFileOffset lStartOffset) : CStageInstruction(pFile), m_Location(nFileId, lStartOffset) { }
DWORD CLongFileInstruction::ComputeSpaceForLocation() { return (sizeof(BYTE) + sizeof(m_Location.m_lStartOffset)); }
long CLongFileInstruction::RecoverLocation(HANDLE hFile) { DWORD dwRead;
BYTE nFileId; if(!ReadFile(hFile, &nFileId, sizeof(BYTE), &dwRead, NULL)) return GetLastError();
m_Location.m_nFileId = nFileId;
if(!ReadFile(hFile, (BYTE*)&m_Location.m_lStartOffset, sizeof m_Location.m_lStartOffset, &dwRead, NULL)) { return GetLastError(); }
return ERROR_SUCCESS; }
BYTE* CLongFileInstruction::WriteLocation(BYTE* pBuffer) { *pBuffer = (BYTE)m_Location.m_nFileId; memcpy(pBuffer + 1, (BYTE*)&m_Location.m_lStartOffset, sizeof m_Location.m_lStartOffset); return pBuffer + 1 + sizeof m_Location.m_lStartOffset; }
void CLongFileInstruction::Dump() { ERRORTRACE((LOG_WBEMCORE, "File %d, Start %d, stage offset %d\n", (int)m_Location.m_nFileId, (int)m_Location.m_lStartOffset, (int)m_lStageOffset)); }
void CWriteFileInstruction::Dump() { ERRORTRACE((LOG_WBEMCORE, "File %d, Start %d, Len %d, stage offset %d\n", (int)m_Location.m_nFileId, (int)m_Location.m_lStartOffset, (int)m_dwLen, (int)m_lStageOffset)); } void CWriteFileInstruction::MakeTopmost() { m_lZOrder = mstatic_lNextZOrder++; } DWORD CWriteFileInstruction::ComputeNeededSpace() { if (!m_bReuse) return sizeof(BYTE) + // for the type
ComputeSpaceForLocation() + sizeof(DWORD) + // for the length of data
m_dwLen + // for the data
A51_TAIL_SIZE; // for the trailer
else return sizeof(BYTE) + // for the type
ComputeSpaceForLocation() + sizeof(DWORD) + // for the length of data
m_dwLen; // for the data
//NO TAIL if we are re-using the old write instruction as they are overwritten
//by next instruction in log
}
TFileOffset CWriteFileInstruction::ComputeOriginalOffset() { return m_lStageOffset - sizeof(BYTE) - ComputeSpaceForLocation() - sizeof(DWORD); } long CWriteFileInstruction::Write(TFileOffset lOffset, BYTE* pBuffer) { _ASSERT(m_Location.m_lStartOffset >= 0 && m_Location.m_lStartOffset < 0x70000000, L"");
//
// Construct an in-memory buffer large enough for the whole thing
//
DWORD dwNeededSpace = ComputeNeededSpace(); BYTE* pWholeBuffer = (BYTE*)TempAlloc(dwNeededSpace); if(pWholeBuffer == NULL) return ERROR_OUTOFMEMORY; CTempFreeMe vdm(pWholeBuffer, dwNeededSpace);
BYTE* pCurrent = pWholeBuffer;
//
// Write instruction type
//
*pCurrent = A51_INSTRUCTION_TYPE_WRITEFILE; pCurrent++;
//
// Write location
//
pCurrent = WriteLocation(pCurrent);
//
// Write the length of the data for the file
//
memcpy(pCurrent, (void*)&m_dwLen, sizeof(DWORD)); pCurrent += sizeof(DWORD);
//
// Write the data itself and record its offset
//
memcpy(pCurrent, pBuffer, m_dwLen); m_lStageOffset = lOffset + (pCurrent - pWholeBuffer);
//
// Write the trailer - only if this is an original instruction. In the
// case of a reused instruction we ignore the tail because it had already
// (probably) been overwritten
//
if (!m_bReuse) memset(pCurrent + m_dwLen, 0, sizeof(DWORD)); //
// Write it
//
return m_pManager->WriteInstruction(lOffset, pWholeBuffer, dwNeededSpace, m_bReuse); }
long CWriteFileInstruction::RecoverData(HANDLE hFile) { //
// Recover the file name first
//
long lRes = RecoverLocation(hFile); if(lRes != ERROR_SUCCESS) return lRes;
//
// Read the length of the data from the file
//
DWORD dwRead;
if(!ReadFile(hFile, (BYTE*)&m_dwLen, sizeof(DWORD), &dwRead, NULL)) return GetLastError();
if(dwRead != sizeof(DWORD)) return ERROR_HANDLE_EOF;
//
// We do not need to actually read the data from the file --- we keep it
// there until it is time to flush. But we do need to skip it. At the same
// time, we need to record the position in the file where this data resides
//
LARGE_INTEGER liFileLen; liFileLen.QuadPart = m_dwLen; LARGE_INTEGER liNewPosition; if(!SetFilePointerEx(hFile, liFileLen, &liNewPosition, FILE_CURRENT)) return GetLastError();
_ASSERT(liNewPosition.HighPart == 0, L"Staging file too long!");
m_lStageOffset = (long)(liNewPosition.QuadPart - m_dwLen); return ERROR_SUCCESS; }
void CWriteFileInstruction::GetEnd(CFileLocation* pLocation) { pLocation->m_nFileId = m_Location.m_nFileId; pLocation->m_lStartOffset = m_Location.m_lStartOffset + m_dwLen - 1; }
long CWriteFileInstruction::GetData(HANDLE hFile, long lExtraOffset, DWORD dwLen, BYTE* pBuffer) { //
// Lock the file
//
CInCritSec ics(m_pManager->GetLock());
_ASSERT(m_pManager->GetFirstFreeOffset() >= m_lStageOffset, L"Instruction points to empty space in stage file");
long lRes = A51ReadFromFileSync(hFile, m_lStageOffset + lExtraOffset, pBuffer, dwLen); if(lRes != ERROR_SUCCESS) { return lRes; }
return ERROR_SUCCESS; }
long CWriteFileInstruction::Execute() { long lRes;
//
// Read the data from the staging file
//
BYTE* pBuffer = (BYTE*)TempAlloc(m_dwLen); if(pBuffer == NULL) return ERROR_OUTOFMEMORY; CTempFreeMe tfm(pBuffer);
lRes = GetData(m_pManager->GetHandle(), 0, m_dwLen, pBuffer); if(lRes != ERROR_SUCCESS) return lRes;
lRes = ((CLongFileStagingFile*)m_pManager)->WriteToActualFile( m_Location.m_nFileId, m_Location.m_lStartOffset, pBuffer, m_dwLen); if(lRes != ERROR_SUCCESS) { return lRes; }
return ERROR_SUCCESS; }
DWORD CSetEndOfFileInstruction::ComputeNeededSpace() { return sizeof(BYTE) + // for instruction type
ComputeSpaceForLocation() + A51_TAIL_SIZE; // for the trailer
}
long CSetEndOfFileInstruction::Write(TFileOffset lOffset) { //
// Construct an in-memory buffer large enough for the whole thing
//
DWORD dwNeededSpace = ComputeNeededSpace(); BYTE* pWholeBuffer = (BYTE*)TempAlloc(dwNeededSpace); if(pWholeBuffer == NULL) return ERROR_OUTOFMEMORY; CTempFreeMe vdm(pWholeBuffer, dwNeededSpace);
BYTE* pCurrent = pWholeBuffer;
//
// Write the instruction type
//
*pCurrent = A51_INSTRUCTION_TYPE_SETENDOFFILE; pCurrent++; //
// Write the file name
//
pCurrent = WriteLocation(pCurrent); m_lStageOffset = lOffset + (pCurrent - pWholeBuffer);
//
// Write the trailer
//
memset(pCurrent, 0, sizeof(DWORD));
//
// Write it
//
return m_pManager->WriteInstruction(lOffset, pWholeBuffer, dwNeededSpace); }
long CSetEndOfFileInstruction::RecoverData(HANDLE hFile) { long lRes = RecoverLocation(hFile); if(lRes != ERROR_SUCCESS) return lRes;
LARGE_INTEGER liZero; liZero.QuadPart = 0; LARGE_INTEGER liPosition; if(!SetFilePointerEx(hFile, liZero, &liPosition, FILE_CURRENT)) return GetLastError();
_ASSERT(liPosition.HighPart == 0, L"Staging file too long!");
m_lStageOffset = (long)(liPosition.QuadPart); return ERROR_SUCCESS; } long CSetEndOfFileInstruction::Execute() { long lRes = ((CLongFileStagingFile*)m_pManager)->SetEndOfActualFile( m_Location.m_nFileId, m_Location.m_lStartOffset); return lRes; }
//
// CStageManager
//
// |
//
// CExecutableStageManager
//
// |
//
// CLongFileStagingFile
//
/////////////////////////////////////////////////////////////////////////////
CLongFileStagingFile::CLongFileStagingFile(long lMaxFileSize, long lAbortTransactionFileSize) : CExecutableStageManager(lMaxFileSize, lAbortTransactionFileSize), m_mapStarts(TMap::key_compare(), TMap::allocator_type(&g_LongFileCacheManager)), m_mapEnds(TMap::key_compare(), TMap::allocator_type(&g_LongFileCacheManager)) { for(int i = 0; i < A51_MAX_FILES; i++) m_aFiles[i].m_h = NULL; }
CLongFileStagingFile::~CLongFileStagingFile() { }
long CLongFileStagingFile::Create(LPCWSTR wszStagingFileName) { return CExecutableStageManager::Create(wszStagingFileName); };
long CLongFileStagingFile::Initialize() { CInCritSec ics(&m_cs); return CExecutableStageManager::Start(); };
long CLongFileStagingFile::Uninitialize(DWORD dwShutDownFlags) { // do not hold the CritSec here, since the FlusherThread needs it
CExecutableStageManager::Stop(dwShutDownFlags);
CInCritSec ics(&m_cs); CloseAllFiles();
m_mapStarts.clear(); m_mapEnds.clear(); return ERROR_SUCCESS; };
long CLongFileStagingFile::RemoveInstructionFromMap( CStageInstruction* pRawInst) { CInCritSec ics(&m_cs);
CLongFileInstruction* pInst = (CLongFileInstruction*)pRawInst; if(!pInst->IsWrite()) return ERROR_SUCCESS;
/*
ERRORTRACE((LOG_WBEMCORE, "Remove instruction\n")); pInst->Dump(); */
TIterator it = m_mapStarts.find(pInst->m_Location); while(it != m_mapStarts.end() && it->second != pInst) it++;
if(it == m_mapStarts.end()) { return ERROR_FILE_NOT_FOUND; }
it->second->Release(); m_mapStarts.erase(it);
CFileLocation Location; ((CWriteFileInstruction*)pInst)->GetEnd(&Location);
it = m_mapEnds.find(Location); while(it != m_mapEnds.end() && it->second != pInst) it++;
if(it == m_mapEnds.end()) { return ERROR_FILE_NOT_FOUND; }
it->second->Release(); m_mapEnds.erase(it);
return ERROR_SUCCESS; }
void CLongFileStagingFile::FlushDataFiles() { CInCritSec ics(&m_cs); for(int i = 0; i < A51_MAX_FILES; i++) { HANDLE h = m_aFiles[i].m_h; if(h) { FlushFileBuffers(h); } }
} long CLongFileStagingFile::WriteFile(int nFileId, DWORD dwStartOffset, BYTE* pBuffer, DWORD dwLen, DWORD* pdwWritten) { CInCritSec ics(&m_cs); long lRes;
#ifdef DBG
if(InjectFailure()) { ERRORTRACE((LOG_WBEMCORE, "FAIL: File %d, offset %d, len %d\n", (int)nFileId, (int)dwStartOffset, (int)dwLen)); return ERROR_SECTOR_NOT_FOUND; } #endif
if(pdwWritten) *pdwWritten = dwLen;
if(DoesSupportOverwrites(nFileId)) { //
// For this file, it is considered efficient to look for another
// instruction within the same transaction. It is guaranteed that
// writes within this file never intersect!
//
CFileLocation StartLocation; StartLocation.m_nFileId = nFileId; StartLocation.m_lStartOffset = (TFileOffset)dwStartOffset; CWriteFileInstruction* pLatestMatch = NULL;
TIterator itStart = m_mapStarts.lower_bound(StartLocation); while(itStart != m_mapStarts.end() && itStart->first.m_nFileId == nFileId && itStart->first.m_lStartOffset == (TFileOffset)dwStartOffset) { CWriteFileInstruction* pInst = itStart->second; if(pInst->m_dwLen == dwLen && !pInst->IsCommitted()) { //
// Exact match. Compare to the other matches
//
if(pLatestMatch == NULL || pInst->m_lZOrder > pLatestMatch->m_lZOrder) { pLatestMatch = pInst; }
} itStart++; }
if(pLatestMatch) { //
// Exact match. All we need to do is overwrite the original
// instruction. Of course, we also need to afjust the hash!!
//
pLatestMatch->SetReuseFlag(); lRes = pLatestMatch->Write(pLatestMatch->ComputeOriginalOffset(), pBuffer); if(lRes) return lRes;
/*
ERRORTRACE((LOG_WBEMCORE, "Replaced instruction:\n")); pLatestMatch->Dump(); */
//
// No need to make sure this instruction comes up in the Z-order!
// After all, it's already topmost by selection criteria!
//
return ERROR_SUCCESS; } }
//
// No match --- add a new instruction
//
CWriteFileInstruction* pInst = new CWriteFileInstruction(this, nFileId, dwStartOffset, dwLen); if(pInst == NULL) return ERROR_OUTOFMEMORY; pInst->AddRef(); CTemplateReleaseMe<CLongFileInstruction> rm1(pInst);
DWORD dwSpaceNeeded = pInst->ComputeNeededSpace();
if(!CanWriteInTransaction(dwSpaceNeeded)) return ERROR_NOT_ENOUGH_QUOTA;
{ CInCritSec ics(&m_cs);
//
// Write all the data into the staging area
//
lRes = pInst->Write(m_lFirstFreeOffset, pBuffer); if(lRes) return lRes; m_lFirstFreeOffset += dwSpaceNeeded - A51_TAIL_SIZE; lRes = AddInstruction(pInst); } return lRes; }
long CLongFileStagingFile::SetFileLength(int nFileId, DWORD dwLen) { CInCritSec ics(&m_cs); long lRes;
CSetEndOfFileInstruction* pInst = new CSetEndOfFileInstruction(this, nFileId, dwLen); if(pInst == NULL) return ERROR_OUTOFMEMORY; pInst->AddRef(); CTemplateReleaseMe<CSetEndOfFileInstruction> rm1(pInst);
DWORD dwSpaceNeeded = pInst->ComputeNeededSpace();
if(!CanWriteInTransaction(dwSpaceNeeded)) return ERROR_NOT_ENOUGH_QUOTA;
{ CInCritSec ics(&m_cs);
//
// Write all the data into the staging area
//
lRes = pInst->Write(m_lFirstFreeOffset); if(lRes) return lRes; //
// Write the new offset into the offset file
//
m_lFirstFreeOffset += dwSpaceNeeded - A51_TAIL_SIZE; lRes = AddInstruction(pInst); } return lRes; }
long CLongFileStagingFile::AddInstructionToMap(CStageInstruction* pRawInst, CStageInstruction** ppUndoInst) { CInCritSec ics(&m_cs);
if(ppUndoInst) *ppUndoInst = NULL;
CLongFileInstruction* pLongInst = (CLongFileInstruction*)pRawInst; if(!pLongInst->IsWrite()) return ERROR_SUCCESS;
CWriteFileInstruction* pInst = (CWriteFileInstruction*)pLongInst;
/*
ERRORTRACE((LOG_WBEMCORE, "Add instruction\n")); pInst->Dump(); */
pInst->AddRef(); TIterator itStart;
try { itStart = m_mapStarts.insert(TValue(pInst->m_Location, pInst)); } catch(...) { //
// Put everything back as well as we can
//
pInst->Release(); return ERROR_OUTOFMEMORY; }
pInst->AddRef();
try { CFileLocation Location; pInst->GetEnd(&Location);
m_mapEnds.insert(TValue(Location, pInst)); } catch(...) { //
// Put everything back as well as we can
//
pInst->Release(); m_mapStarts.erase(itStart);
pInst->Release(); } return ERROR_SUCCESS; }
bool CLongFileStagingFile::IsStillCurrent(CStageInstruction* pRawInst) { CInCritSec ics(&m_cs);
CLongFileInstruction* pInst = (CLongFileInstruction*)pRawInst; if(!pInst->IsWrite()) return true;
_ASSERT(m_mapStarts.find(pInst->m_Location) != m_mapStarts.end(), L"Why would we be asking about an instruction that is " "not even there?"); return true; }
long CLongFileStagingFile::ReadFile(int nFileId, DWORD dwStartOffset, BYTE* pBuffer, DWORD dwLen, DWORD* pdwRead) { if(pdwRead) *pdwRead = dwLen; long lRes;
CInCritSec ics(&m_cs);
//
// Search for the file
//
CFileLocation StartLocation; StartLocation.m_nFileId = nFileId; StartLocation.m_lStartOffset = (TFileOffset)dwStartOffset;
bool bComplete = false; CRefedPointerArray<CWriteFileInstruction> apRelevant;
TIterator itStart = m_mapStarts.lower_bound(StartLocation); while(itStart != m_mapStarts.end() && itStart->first.m_nFileId == nFileId && itStart->first.m_lStartOffset < (TFileOffset)dwStartOffset + dwLen) { CWriteFileInstruction* pInst = itStart->second;
if(pInst->m_Location.m_lStartOffset == dwStartOffset && pInst->m_dwLen >= dwLen) { bComplete = true; } apRelevant.Add(pInst); itStart++; } TIterator itEnd = m_mapEnds.lower_bound(StartLocation);
while(itEnd != m_mapEnds.end() && itEnd->first.m_nFileId == nFileId && itEnd->second->m_Location.m_lStartOffset < (TFileOffset)dwStartOffset) { CWriteFileInstruction* pInst = itEnd->second; if(itEnd->first.m_lStartOffset >= (TFileOffset)dwStartOffset + dwLen - 1) { //
// Completely covers us!
//
bComplete = true; }
apRelevant.Add(pInst); itEnd++; }
if(!bComplete) { //
// Read from the real file
//
lRes = A51ReadFromFileSync(m_aFiles[nFileId].m_h, dwStartOffset, pBuffer, dwLen); if(lRes != ERROR_SUCCESS) { return lRes; } }
//
// Now, sort all the instructions by z-order
//
int i = 0; while(i < apRelevant.GetSize() - 1) { CWriteFileInstruction* pInst1 = apRelevant[i]; CWriteFileInstruction* pInst2 = apRelevant[i+1]; if(pInst1->m_lZOrder > pInst2->m_lZOrder) { apRelevant.Swap(i, i+1); if(i > 0) i--; } else { i++; } }
//
// Apply them in this order
//
/*
if(apRelevant.GetSize() > 0) { ERRORTRACE((LOG_WBEMCORE, "Using instructions to read %d bytes " "from file %d starting at %d:\n", (int)dwStartOffset, (int)nFileId, (int)dwLen)); } */
for(i = 0; i < apRelevant.GetSize(); i++) { CWriteFileInstruction* pInstruction = apRelevant[i]; // pInstruction->Dump();
long lIntersectionStart = max(pInstruction->m_Location.m_lStartOffset, dwStartOffset);
long lIntersectionEnd = min(pInstruction->m_Location.m_lStartOffset + pInstruction->m_dwLen, dwStartOffset + dwLen); DWORD dwReadLen = (DWORD)(lIntersectionEnd - lIntersectionStart); long lInstructionReadOffset = lIntersectionStart - pInstruction->m_Location.m_lStartOffset;
long lDestinationBufferOffset = lIntersectionStart - dwStartOffset;
long lRes = pInstruction->GetData(m_hFile, lInstructionReadOffset, dwReadLen, pBuffer + lDestinationBufferOffset); if(lRes != ERROR_SUCCESS) { return lRes; } }
return ERROR_SUCCESS; }
long CLongFileStagingFile::GetFileLength(int nFileId, DWORD* pdwLength) { _ASSERT(pdwLength, L"Invalid parameter");
*pdwLength = 0; long lRes;
CInCritSec ics(&m_cs);
//
// Find the instruction that ends as far as we can see --- that would be
// the last one in the map of Ends
//
CFileLocation Location; Location.m_nFileId = nFileId+1; Location.m_lStartOffset = 0;
TIterator itEnd = m_mapEnds.lower_bound(Location); if(itEnd != m_mapEnds.begin()) { itEnd--; if(itEnd->first.m_nFileId == nFileId) { *pdwLength = itEnd->first.m_lStartOffset+1; } }
//
// Now, check out the length of the actual file
//
BY_HANDLE_FILE_INFORMATION fi; if(!GetFileInformationByHandle(m_aFiles[nFileId].m_h, &fi)) { long lRes = GetLastError(); _ASSERT(lRes != ERROR_SUCCESS, L"Success from failure"); return lRes; } _ASSERT(fi.nFileSizeHigh == 0, L"Free file too long");
if(fi.nFileSizeLow > *pdwLength) *pdwLength = fi.nFileSizeLow;
return ERROR_SUCCESS; }
long CLongFileStagingFile::ConstructInstructionFromType(int nType, CStageInstruction** ppInst) { CLongFileInstruction* pInst = NULL; switch(nType) { case A51_INSTRUCTION_TYPE_WRITEFILE: pInst = new CWriteFileInstruction(this); break; case A51_INSTRUCTION_TYPE_SETENDOFFILE: pInst = new CSetEndOfFileInstruction(this); break; default: return ERROR_RXACT_INVALID_STATE; }
if(pInst == NULL) return WBEM_E_OUT_OF_MEMORY; pInst->AddRef(); *ppInst = pInst; return ERROR_SUCCESS; }
long CLongFileStagingFile::WriteToActualFile(int nFileId, TFileOffset lFileOffset, BYTE* pBuffer, DWORD dwLen) { CInCritSec ics(&m_cs);
long lRet = A51WriteToFileSync(m_aFiles[nFileId].m_h, lFileOffset, pBuffer, dwLen); // FlushFileBuffers(m_aFiles[nFileId].m_h);
return lRet; }
long CLongFileStagingFile::SetEndOfActualFile(int nFileId, TFileOffset lFileLength) { CInCritSec ics(&m_cs);
LARGE_INTEGER liEnd; liEnd.QuadPart = lFileLength;
if(!SetFilePointerEx(m_aFiles[nFileId].m_h, liEnd, NULL, FILE_BEGIN)) return GetLastError();
if(!SetEndOfFile(m_aFiles[nFileId].m_h)) return GetLastError();
return ERROR_SUCCESS; }
long CLongFileStagingFile::CloseAllFiles() { CInCritSec ics(&m_cs);
for(int i = 0; i < A51_MAX_FILES; i++) { if(m_aFiles[i].m_h != NULL) { CloseHandle(m_aFiles[i].m_h); } m_aFiles[i].m_h = NULL; m_aFiles[i].m_bSupportsOverwrites = false; }
return ERROR_SUCCESS; } long CLongFileStagingFile::RegisterFile(int nFileId, HANDLE hFile, bool bSupportsOverwrites) { _ASSERT(nFileId < A51_MAX_FILES, L"File ID is too large");
if(m_aFiles[nFileId].m_h != NULL) CloseHandle(m_aFiles[nFileId].m_h);
m_aFiles[nFileId].m_h = hFile; m_aFiles[nFileId].m_bSupportsOverwrites = bSupportsOverwrites;
return ERROR_SUCCESS; }
bool CLongFileStagingFile::DoesSupportOverwrites(int nFileId) { return m_aFiles[nFileId].m_bSupportsOverwrites; }
long CLongFileStagingFile::WriteEmpty() { _ASSERT(m_mapStarts.size() == 0 && m_mapEnds.size() == 0, L""); FlushDataFiles(); return CExecutableStageManager::WriteEmpty(); }
bool CLongFileStagingFile::InjectFailure() { #ifdef A51_INJECT_FAILURE
if(GetTickCount() > g_dwLastFailureCheck + FAILURE_INJECTION_CHECK_INTERVAL) { HKEY hKey; long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\WBEM\\CIMOM", 0, KEY_READ | KEY_WRITE, &hKey); if(lRes) return false; CRegCloseMe cm(hKey); DWORD dwLen = sizeof(DWORD); lRes = RegQueryValueExW(hKey, L"Failure Frequency", NULL, NULL, (LPBYTE)&g_dwFailureFrequency, &dwLen); if(lRes != ERROR_SUCCESS) g_dwFailureFrequency = 0;
g_dwLastFailureCheck = GetTickCount(); }
if(g_dwFailureFrequency && ++g_dwFailureCount == g_dwFailureFrequency) { g_dwFailureCount = 0; m_bMustFail = true; return true; } else { return false; } #else
return false; #endif
}
void CLongFileStagingFile::Dump(FILE* f) { fprintf(f, "BEGINS:\n");
TIterator itStart = m_mapStarts.begin(); while(itStart != m_mapStarts.end()) { CWriteFileInstruction* pInst = itStart->second; fprintf(f, "File %d (%d-%d): instruction %p\n", (int)pInst->m_Location.m_nFileId, (int)pInst->m_Location.m_lStartOffset, (int)pInst->m_Location.m_lStartOffset + pInst->m_dwLen, pInst); itStart++; }
fprintf(f, "IN ORDER:\n");
int nSize = m_qToWrite.size(); for(int i = 0; i < nSize; i++) { CLongFileInstruction* pInstruction = (CLongFileInstruction*)m_qToWrite.front(); if(pInstruction->IsWrite()) { CWriteFileInstruction* pInst = (CWriteFileInstruction*)pInstruction; fprintf(f, "File %d (%d-%d): instruction %p\n", (int)pInst->m_Location.m_nFileId, (int)pInst->m_Location.m_lStartOffset, (int)pInst->m_Location.m_lStartOffset + pInst->m_dwLen, pInst); } else { CSetEndOfFileInstruction* pInst = (CSetEndOfFileInstruction*)pInstruction; fprintf(f, "Truncate file %d at %d: instruction %p\n", (int)pInst->m_Location.m_nFileId, (int)pInst->m_Location.m_lStartOffset, pInst); }
m_qToWrite.pop_front(); m_qToWrite.push_back(pInstruction); } }
|