📄 gmmf.cpp
字号:
dwStatus = GetLastError();
if (NULL == pbTemp)
{
//kyu001204 - this should not happen, in case this happens,
//get another base address
m_pbFile = (PBYTE)ResAddrSpace(NULL, m_dwFileSizeMax + m_dwOverrunBuf);
UnmapViewOfFile(m_pbFile);
CloseHandle(m_hFileMapRes);
//
// Map the view again for the size of dwDiskFileNew:
//
pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMap,
FILE_MAP_ALL_ACCESS,
0,
0,
dwDiskFileNew,
m_pbFile);
if(pbTemp == NULL)
{
//if failed again, log the error:
LogError(GetLastError(), MEM_MAP_VIEW, m_szRegionName);
}
}
//
// Check to see if our region has been corrupted
// by another thread.
//
if (pbTemp != m_pbFile)
{
RaiseException(EXCEPTION_GMMF_CORRUPTEDRGN,
EXCEPTION_NONCONTINUABLE,
0,
NULL);
}
//
// If the memory region is larger than the size of the file,
// clear the leftover to zeros
//
DWORD dwRegionSize = (DWORD)((((float)m_dwFileSizeNow + (float)m_dwFileGrowInc - 1) /
(float)m_dwFileGrowInc) * (float)m_dwFileGrowInc);
if (ERROR_ALREADY_EXISTS != dwStatus)
{
if (m_dwFileSizeNow < dwRegionSize)
{
memset((m_pbFile + m_dwFileSizeNow), 0,
(dwRegionSize - m_dwFileSizeNow));
}
}
InterlockedIncrement((LPLONG)&m_pCtlBlock->dwCurrentlyMapped);
}
if (dwDiskFileNew < m_dwFileSizeMax + m_dwOverrunBuf)
{
//
// Reserve space after the GMMF for growth detection.
// The space should be reserved after the MMF and the size should be the
// maximum size of the file plus the overrun buffer size minus the
// current size of the MMF.
//
m_hFileMapRes = CreateFileMapping(HFILE_PAGEFILE,
&m_SecAttr,
PAGE_READONLY|SEC_RESERVE,
0,
((m_dwFileSizeMax+m_dwOverrunBuf)-dwDiskFileNew),
NULL);
if (NULL != m_hFileMapRes)
{
pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMapRes,
FILE_MAP_READ,
0, 0, 0,
m_pbFile+dwDiskFileNew);
if (NULL == pbTemp)
{
//kyu001204 - Retry to get a new base address:
//
m_pbFile = (PBYTE)ResAddrSpace(NULL, m_dwFileSizeMax + m_dwOverrunBuf);
UnmapViewOfFile(m_pbFile);
CloseHandle(m_hFileMapRes);
pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMap,
FILE_MAP_ALL_ACCESS,
0,
0,
dwDiskFileNew,
m_pbFile);
if(pbTemp == NULL)
{
LogError(GetLastError(), MEM_MAP_VIEW, m_szRegionName);
//
// File-mapping could not be created, the disk is
// probably full.
//
RaiseException(EXCEPTION_GMMF_DISKFULL,
EXCEPTION_NONCONTINUABLE,
0,
NULL);
}
m_hFileMapRes = CreateFileMapping(HFILE_PAGEFILE,
&m_SecAttr,
PAGE_READONLY|SEC_RESERVE,
0,
((m_dwFileSizeMax+m_dwOverrunBuf)-dwDiskFileNew),
NULL);
if(m_hFileMapRes !=NULL)
{
pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMapRes,
FILE_MAP_READ,
0, 0, 0,
m_pbFile+dwDiskFileNew);
if(pbTemp == NULL)
{
TCHAR chWin32Error[MAX_PATH];
m_pLog->GetErrorText(GetLastError(), (TCHAR *)&chWin32Error[0]);
m_pLog->WriteEventLog(MEM_MAP_RESERVE,
EVENTLOG_ERROR_TYPE,
0,
NULL,
chWin32Error,
NULL);
}
}
}
}
else
{
TCHAR chWin32Error[MAX_PATH];
m_pLog->GetErrorText(GetLastError(), (TCHAR *)&chWin32Error[0]);
m_pLog->WriteEventLog(MEM_CREATE_RESERVE,
EVENTLOG_ERROR_TYPE,
0,
NULL,
chWin32Error,
NULL);
}
dwStatus = GetLastError();
//
// Check to see if our region has been corrupted
// by another thread.
//
if (pbTemp != (m_pbFile + dwDiskFileNew))
{
TCHAR dummy[80],dummy1[80];
//kyu001204 - itoa() does not work here:
sprintf(dummy,"%d",pbTemp);
sprintf(dummy1,"%d",m_pbFile+dwDiskFileNew);
m_pLog->WriteEventLog(MEM_CORRUPT,
EVENTLOG_ERROR_TYPE,
0,
NULL,
//itoa((int)pbTemp,(TCHAR *)&dummy,10),
//itoa((int)(m_pbFile+dwDiskFileNew),(TCHAR *)&dummy,10),
dummy,
dummy1,
NULL);
RaiseException(EXCEPTION_GMMF_CORRUPTEDRGN,
EXCEPTION_NONCONTINUABLE,
0,
NULL);
}
}
m_dwFileSizeNow = dwDiskFileNew;
}
//
// @mfunc <c Adjust> This function actually handles the re-allocation
// of memory when an exception occures.
//
// @parm IN DWORD | dwDiskFileNow | New size for the memory
//
// @rvalue None |
//
void CGmmf::Adjust(IN DWORD dwDiskFileNow)
{
int nThreadPriority,
nMaxLoops = 0;
__try
{
//
// Boost our thread's priority so that another thread is
// less likely to use the same address space while
// we're changing it.
//
nThreadPriority = GetThreadPriority(GetCurrentThread());
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
//
// Clear the contents of the memory
//
if (Clear())
{
//
// If someone else is mapped, set an event to signal them
// to free their memory. They will remap on the next time
// they try to access the memory. We need to set a
// flag (m_bItsMe) so the local thread won't also call clear().
//
if (m_pCtlBlock->dwCurrentlyMapped)
{
m_bItsMe = TRUE;
PulseEvent(m_hRemapEvent);
while ((m_pCtlBlock->dwCurrentlyMapped > 0 ) &&
nMaxLoops < 100)
{
Sleep(10);
nMaxLoops++;
}
}
}
//
// Restore the contents with the properly adjusted lengths
//
Construct(dwDiskFileNow);
}
__finally
{
//
// Make sure that we always restore our priority class and thread
// priority so that we do not continue to adversely affect other
// threads in the system.
//
SetThreadPriority(GetCurrentThread(), nThreadPriority);
}
}
//
// @mfunc <c GetAddress> This function returns the address at the base
// of the memory region.
//
// @rvalue VOID * | Pointer the the beginning of the gmmf
//
void *CGmmf::GetAddress()
{
return(m_pbFile);
}
//
// @mfunc <c GetCurrentSize> Returns the current size, in bytes, of the
// memory area.
//
// @rvalue DWORD | Current size of the gmmf
//
DWORD CGmmf::GetCurrentSize()
{
return(m_dwFileSizeNow);
}
//
// @mfunc <c GetMaximumSize> Returns the maximum size that this memory
// area will be allowed to expand. The value
// is defined in the registry.
//
// @rvalue DWORD | Maximum size memory will be allowed to grow
//
DWORD CGmmf::GetMaximumSize()
{
return(m_dwFileSizeMax);
}
//
// @mfunc <c GetElements> Returns the number of elements that are stored
// in the memory object.
//
// @rvalue DWORD | Number of elements
//
DWORD CGmmf::GetElements()
{
return(m_pCtlBlock->dwElements);
}
//
// @mfunc <c IncElements> Increments the number of elements that are stored
// in the memory object. This object really doesn't
// care but this information needs to be kept global
// to all instances of this object so its stored in
// the control block and accessed via member functions.
//
// @rvalue None |
//
void CGmmf::IncElements()
{
InterlockedIncrement((LPLONG)&m_pCtlBlock->dwElements);
}
//
// @mfunc <c DecElements> Decrements the number of elements that are stored
// in the memory object. This object really doesn't
// care but this information needs to be kept global
// to all instances of this object so its stored in
// the control block and accessed via member functions.
//
// @rvalue None |
//
void CGmmf::DecElements()
{
InterlockedDecrement((LPLONG)&m_pCtlBlock->dwElements);
}
//
// @mfunc <c MapControlBlock> This function maps a global mapped file to
// be used as a control block for this object.
// We don't have to concern ourselves with
// re-sizing this area so it will exist as long
// as there is at least one instantiation of
// this object.
//
// @parm IN const TCHAR * | szName | Name used to derive the name of the block
//
// @rvalue TRUE | If successful, otherwise it returns FALSE
//
BOOL CGmmf::MapControlBlock(IN const TCHAR *szName)
{
DWORD dwReturnStatus;
TCHAR szMemoryName[MAX_PATH];
sprintf(szMemoryName, "%s_CB", szName);
m_hCBlock = CreateFileMapping(HFILE_PAGEFILE,
&m_SecAttr,
PAGE_READWRITE,
0,
sizeof(CBLOCK),
szMemoryName);
dwReturnStatus = GetLastError();
if (m_hCBlock)
{
m_pCtlBlock = (CBLOCK *)MapViewOfFile(m_hCBlock, FILE_MAP_WRITE,
0, 0, 0);
if (m_pCtlBlock)
{
if (ERROR_ALREADY_EXISTS != dwReturnStatus)
{
memset(m_pCtlBlock, 0, sizeof(CBLOCK));
m_pCtlBlock->dwTotalInstances = 0;
m_pCtlBlock->dwCurrentlyMapped = 0;
}
}
else
{
LogError(GetLastError(), MEM_MAP_VIEW, szMemoryName);
CloseHandle(m_hCBlock);
return(FALSE);
}
}
else
{
LogError(GetLastError(), MEM_CREATE_MMFCB, szMemoryName);
return(FALSE);
}
return(TRUE);
}
//
// @mfunc <c StartRemapThread> Creates an event and a thread that are
// used to clear the memory if another instance
// of this object expands the memory
//
// @parm IN const TCHAR * | szName | Name used to derive the event name
//
// @rvalue TRUE | If successful, otherwise it returns FALSE
//
BOOL CGmmf::StartRemapThread(IN const TCHAR *szName)
{
DWORD dwThreadId;
TCHAR szEventName[MAX_PATH];
sprintf(szEventName, "%s_EV", szName);
m_hRemapEvent = CreateEvent(&m_SecAttr,TRUE,FALSE,szEventName);
if (NULL != m_hRemapEvent)
{
m_hShutdownEvent = CreateEvent(&m_SecAttr,FALSE,FALSE,NULL);
if (NULL != m_hShutdownEvent)
{
m_hRemapThread = CreateThread(&m_SecAttr,
0,
(LPTHREAD_START_ROUTINE)RemapHandler,
(LPVOID)this,
0,
&dwThreadId);
if (NULL == m_hRemapThread)
{
LogError(GetLastError(), MEM_CREATE_REMAPTHREAD, szName);
return(FALSE);
}
}
}
else
{
LogError(GetLastError(), MEM_CREATE_REMAPEVENT, szName);
return(FALSE);
}
return(TRUE);
}
//
// @mfunc <c RemapHandler> Thread function that is responsible for
// clearing the memory if another instance attempts
// to expand it. This is necessary because the
// other instance will attempt to create a new
// memory mapped file with the same name as the
// existing one.
//
// @parm IN LPVOID | pObj | Pointer to the "this" object
//
// @rvalue None |
//
VOID CGmmf::RemapHandler(IN LPVOID pObj)
{
#define REMAP_EVENT 0
#define SHUTDOWN_EVENT 1
#define NUMBER_OF_EVENTS 2
CGmmf *pObject = (CGmmf *)pObj;
DWORD dwStatus;
HANDLE hWaitList[NUMBER_OF_EVENTS];
hWaitList[REMAP_EVENT] = pObject->m_hRemapEvent;
hWaitList[SHUTDOWN_EVENT] = pObject->m_hShutdownEvent;
while (!pObject->m_bShutdown)
{
dwStatus = WaitForMultipleObjects(NUMBER_OF_EVENTS,
(HANDLE *)hWaitList,
FALSE,
INFINITE);
switch(dwStatus)
{
case WAIT_OBJECT_0 + REMAP_EVENT:
if (pObject->m_bItsMe)
{
pObject->m_bItsMe = FALSE;
}
else
{
if ((pObject->m_pCtlBlock->dwCurrentlyMapped > 0) &&
(!pObject->m_bShutdown))
{
pObject->Clear();
}
}
break;
case WAIT_OBJECT_0 + SHUTDOWN_EVENT:
break;
case WAIT_ABANDONED:
case WAIT_TIMEOUT:
break;
}
}
}
//
// @mfunc <c LogError> Wrapper function that simply makes it a little
// easier to call WriteEventLog(). Since most of
// the calls use the same parameters, this makes
// the rest of the code much easier to read
//
// @parm IN DWORD | dwWin32Code | Last Win32 error returned from GetLastError()
//
// @parm IN LONG | lErrorCode | Elwood error code defined in ItkErr.h
//
// @parm IN TCHAR [] | szText | Insertion string
//
// @rvalue None |
//
VOID CGmmf::LogError(IN DWORD dwWin32Code, IN LONG lErrorCode, IN const TCHAR *szText)
{
TCHAR chWin32Error[256];
m_pLog->GetErrorText(dwWin32Code, (TCHAR *)&chWin32Error[0]);
m_pLog->WriteEventLog(lErrorCode,
EVENTLOG_ERROR_TYPE,
0,
NULL,
szText,
chWin32Error,
NULL);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -