windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/xfiles/pagemanager.cpp
2020-09-26 16:20:57 +08:00

507 lines
13 KiB
C++

#include <windows.h>
#ifdef __XFILES_TEST_PAGE_MANAGER
#include <stdio.h>
#include <unk.h>
#include <arrtempl.h>
#include <FlexArry.h>
#include "pagemgr.h"
#include <wbemutil.h>
//#define PF_VERBOSE_LOGGING
//*****************************************************************************
//*****************************************************************************
CPageFile::CPageFile(const char *pszFile)
: m_bInTransaction (false), m_pszFile(pszFile)
{
}
//*****************************************************************************
//*****************************************************************************
CPageFile::~CPageFile()
{
}
//*****************************************************************************
//*****************************************************************************
ULONG CPageFile::AddRef( )
{
return 0;
}
//*****************************************************************************
//*****************************************************************************
ULONG CPageFile::Release( )
{
return 0;
}
DWORD CPageFile::RetrievePage(DWORD dwId, Page **ppPage)
{
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Retrieving page 0x%08X\n", m_pszFile, dwId));
#endif
DWORD dwRes = ERROR_FILE_NOT_FOUND;
PAGETABLE::iterator iter = m_aTransactionPageTable.find(dwId);
if (iter != m_aTransactionPageTable.end())
{
*ppPage = iter->second;
dwRes = ERROR_SUCCESS;
}
else
{
iter = m_aMasterPageTable.find(dwId);
if (iter != m_aMasterPageTable.end())
{
*ppPage = iter->second;
dwRes = ERROR_SUCCESS;
}
}
return dwRes;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageFile::StorePage(Page *pPage)
{
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Storing page 0x%08X, %s\n", m_pszFile, pPage->dwPageId, (pPage->bActive?"": "DELETED")));
#endif
if (!m_bInTransaction)
{
OutputDebugString(L"Storing page outside a transaction!\n");
DebugBreak();
}
DWORD dwRes = ERROR_FILE_NOT_FOUND;
PAGETABLE::iterator iter = m_aTransactionPageTable.find(pPage->dwPageId);
if (iter != m_aTransactionPageTable.end())
{
Page *pExistingPage = iter->second;
if (!pExistingPage->bActive)
{
//We should not be storing a page over the top of a deleted page!!!
DebugBreak();
dwRes = ERROR_INVALID_OPERATION;
}
else
{
CopyMemory(pExistingPage, pPage, sizeof(Page));
dwRes = ERROR_SUCCESS;
}
}
else
{
dwRes = ERROR_SUCCESS;
Page *pNewPage = new Page;
if (pNewPage == NULL)
{
dwRes = ERROR_OUTOFMEMORY;
}
else
{
CopyMemory(pNewPage, pPage, sizeof(Page));
m_aTransactionPageTable[pNewPage->dwPageId] = pNewPage;
}
}
return dwRes;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageFile::GetPage(
DWORD dwId,
DWORD dwFlags,
LPVOID pPage
)
{
Page *pExistingPage;
DWORD dwRes = RetrievePage(dwId, &pExistingPage);
if ((dwRes == ERROR_SUCCESS) && (pExistingPage->bActive))
{
CopyMemory(pPage, pExistingPage->aPage, WMIREP_PAGE_SIZE);
}
else if (dwRes == ERROR_SUCCESS)
{
//Should not be retrieving a deleted page!!!!!
DebugBreak();
dwRes = ERROR_INVALID_OPERATION;
}
return dwRes;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageFile::PutPage(
DWORD dwId,
DWORD dwFlags,
LPVOID pbPage
)
{
Page *pExistingPage;
DWORD dwRes = RetrievePage(dwId, &pExistingPage);
if (dwRes == ERROR_SUCCESS)
{
if (!pExistingPage->bActive)
{
//Should not be retrieving a deleted page!!!!!
DebugBreak();
dwRes = ERROR_INVALID_OPERATION;
}
else
{
Page *pNewPage = new Page;
if (pNewPage == NULL)
{
dwRes = ERROR_OUTOFMEMORY;
}
else
{
pNewPage->bActive = true;
pNewPage->dwPageId = dwId;
CopyMemory(pNewPage->aPage, pbPage, WMIREP_PAGE_SIZE);
dwRes = StorePage(pNewPage);
delete pNewPage;
}
}
}
return dwRes;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageFile::NewPage(
DWORD dwFlags,
DWORD dwCount,
DWORD *pdwFirstId
)
{
DWORD dwFreeId = 0;
if (dwCount > 1)
{
//This is a multi-page item, so we get the last used ID and the position
//is the end of the list
DWORD dwTranFree = 0;
DWORD dwMasterFree = 0;
if (m_aTransactionPageTable.size())
{
PAGETABLE::iterator it = m_aTransactionPageTable.end();
it--;
dwTranFree = it->first + 1;
}
if (m_aMasterPageTable.size())
{
PAGETABLE::iterator it = m_aMasterPageTable.end();
it--;
dwMasterFree = it->first + 1;
}
if (dwTranFree > dwMasterFree)
{
dwFreeId = dwTranFree;
}
else
{
dwFreeId = dwMasterFree;
}
}
else if (dwFlags == 1)
{
//Allocation of admin page
dwFreeId = 0;
}
else
{
//Grab the first one from the free list
PAGEFREELIST::iterator it = m_aFreeList.begin();
if (it != m_aFreeList.end())
{
dwFreeId = it->first;
m_aFreeList.erase(it);
}
else
{
//We have nothing in the free list, so grab the next ID from
//the transaction and master pages and use the largest one.
DWORD dwTranFree = 0;
DWORD dwMasterFree = 0;
if (m_aTransactionPageTable.size())
{
PAGETABLE::iterator it = m_aTransactionPageTable.end();
it--;
dwTranFree = it->first + 1;
}
if (m_aMasterPageTable.size())
{
PAGETABLE::iterator it = m_aMasterPageTable.end();
it--;
dwMasterFree = it->first + 1;
}
if (dwTranFree > dwMasterFree)
{
dwFreeId = dwTranFree;
}
else
{
dwFreeId = dwMasterFree;
}
}
}
//Record the ID for the caller
*pdwFirstId = dwFreeId;
//Loop through the number of pages required
while (dwCount--)
{
Page *pPage = new Page;
if (pPage == NULL)
return ERROR_OUTOFMEMORY;
pPage->dwPageId = dwFreeId++;
pPage->bActive = true;
StorePage(pPage);
delete pPage;
}
return ERROR_SUCCESS;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageFile::FreePage(
DWORD dwFlags,
DWORD dwId
)
{
if (dwId == 0)
DebugBreak();
DWORD dwRes = ERROR_FILE_NOT_FOUND;
Page *pPage;
dwRes = RetrievePage(dwId, &pPage);
if ((dwRes == ERROR_FILE_NOT_FOUND) || (!pPage->bActive))
{
//Should not be freeing a not-found or already deleted page
DebugBreak();
dwRes = ERROR_INVALID_OPERATION;
}
else
{
Page *pNewPage = new Page;
pNewPage->bActive = false;
pNewPage->dwPageId = dwId;
StorePage(pNewPage);
delete pNewPage;
}
return dwRes;
}
DWORD CPageFile::BeginTran()
{
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Begin Transaction\n", m_pszFile));
#endif
if (m_bInTransaction)
{
OutputDebugString(L"WinMgmt: Nested transasctions are NOT supported!\n");
DebugBreak();
}
m_bInTransaction = true;
return ERROR_SUCCESS;
}
DWORD CPageFile::CommitTran()
{
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Commit Transaction\n", m_pszFile));
#endif
if (!m_bInTransaction)
{
OutputDebugString(L"WinMgmt: Commiting a transaction when we are NOT in a transaction!\n");
DebugBreak();
}
PAGETABLE::iterator it;
while (m_aTransactionPageTable.size())
{
it = m_aTransactionPageTable.begin();
PAGETABLE::iterator masterIt = m_aMasterPageTable.find(it->first);
if (masterIt != m_aMasterPageTable.end())
{
//replace it
if (it->second->bActive)
{
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Replacing existing page in master page list <0x%08X>\n", m_pszFile, it->first));
#endif
CopyMemory(masterIt->second, it->second, sizeof(Page));
}
else
{
//Deleted page and add id to free list!
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Deleting page in master page list <0x%08X>\n", m_pszFile, it->first));
#endif
m_aFreeList[it->first] = it->first;
delete masterIt->second;
m_aMasterPageTable.erase(masterIt);
}
delete it->second;
}
else
{
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Creating new page in master page list <0x%08X>\n", m_pszFile, it->first));
#endif
m_aMasterPageTable[it->first] = it->second;
}
m_aTransactionPageTable.erase(it);
}
m_bInTransaction = false;
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Commit Transaction completed\n", m_pszFile));
#endif
return ERROR_SUCCESS;
}
DWORD CPageFile::AbortTran()
{
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Abort Transaction\n", m_pszFile));
#endif
PAGETABLE::iterator it;
while (m_aTransactionPageTable.size())
{
it = m_aTransactionPageTable.begin();
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Rolling back page <0x%08X>\n", m_pszFile, it->first));
#endif
delete it->second;
m_aTransactionPageTable.erase(it);
}
m_bInTransaction = false;
#ifdef PF_VERBOSE_LOGGING
ERRORTRACE((LOG_REPDRV, "%s: Abort Transaction\n", m_pszFile));
#endif
return ERROR_SUCCESS;
}
//*****************************************************************************
//*****************************************************************************
CPageSource::CPageSource()
: m_pHeap(0)
{
}
//*****************************************************************************
//*****************************************************************************
CPageSource::~CPageSource()
{
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::Init(
DWORD dwCachePages,
DWORD dwCheckpointTime, // milliseconds
DWORD dwPageSize
)
{
m_pHeap = new CPageFile("ObjHeap");
m_pIndex = new CPageFile("Index");
return ERROR_SUCCESS;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::Shutdown(DWORD dwShutdownType )
{
delete m_pHeap;
delete m_pIndex;
return ERROR_SUCCESS;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::GetBTreePageFile(OUT CPageFile **pPF)
{
*pPF = m_pIndex;
return ERROR_SUCCESS;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::GetObjectHeapPageFile(OUT CPageFile **pPF)
{
*pPF = m_pHeap;
return ERROR_SUCCESS;
}
// Transactions
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::BeginTrans()
{
m_pIndex->BeginTran();
return m_pHeap->BeginTran();
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::CommitTrans()
{
m_pIndex->CommitTran();
return m_pHeap->CommitTran();
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::RollbackTrans()
{
m_pIndex->AbortTran();
return m_pHeap->AbortTran();
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::Flush()
{
return ERROR_SUCCESS;;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::LastCommitVersion(DWORD *pdwCommitted)
{
return ERROR_SUCCESS;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::CurrentVersion(DWORD *pdwCurrent)
{
return ERROR_SUCCESS;
}
// Checkpoint
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::Checkpoint()
{
return ERROR_SUCCESS;
}
//*****************************************************************************
//*****************************************************************************
DWORD CPageSource::Dump(FILE *f)
{
return ERROR_SUCCESS;
}
#endif /* __XFILES_TEST_PAGE_MANAGER */