Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

564 lines
16 KiB

//+------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993.
//
// File: bm_nstg.cxx
//
// Contents: Nested Storage test
//
// Classes: CNestedStorageTest
//
// History: 09-June-94 t-vadims Created
//
//--------------------------------------------------------------------------
#include <headers.cxx>
#pragma hdrstop
#include <bm_nstg.hxx>
#define DEF_DATASIZE 4096
#define INFINITY 0xffffffff // max value of 32-bit ulong
TCHAR *CNestedStorageTest::Name ()
{
return TEXT("NestedStorageTest");
}
SCODE CNestedStorageTest::Setup (CTestInput *pInput)
{
SCODE sc;
ULONG iIndex;
TCHAR pszBuf[15];
CTestBase::Setup(pInput);
// get iteration count
m_ulIterations = pInput->GetIterations(Name());
// initialize timing arrays
INIT_RESULTS(m_ulStgCreateDocfile);
INIT_RESULTS(m_ulFinalStorageCommit);
INIT_RESULTS(m_ulFinalStorageRelease);
for(iIndex = 0; iIndex <TEST_MAX_ITERATIONS; iIndex++)
{
m_ulCreateStorageTotal[iIndex] = 0;
m_ulCreateStreamTotal[iIndex] = 0;
m_ulStreamWriteTotal[iIndex] = 0;
m_ulStreamReleaseTotal[iIndex] = 0;
m_ulDestroyElementTotal[iIndex] = 0;
m_ulStorageCommitTotal[iIndex] = 0;
m_ulStorageReleaseTotal[iIndex] = 0;
m_ulTotal[iIndex] = 0;
m_ulCreateStreamMin[iIndex] = INFINITY;
m_ulStreamWriteMin[iIndex] = INFINITY;
m_ulStreamReleaseMin[iIndex] = INFINITY;
m_ulDestroyElementMin[iIndex] = INFINITY;
m_ulCreateStreamMax[iIndex] = 0;
m_ulStreamWriteMax[iIndex] = 0;
m_ulStreamReleaseMax[iIndex] = 0;
m_ulDestroyElementMax[iIndex] = 0;
for (ULONG iLevel =0; iLevel < MAX_NESTING; iLevel++)
{
m_ulStorageCommitMin[iLevel][iIndex] = INFINITY;
m_ulStorageReleaseMin[iLevel][iIndex] = INFINITY;
m_ulCreateStorageMin[iLevel][iIndex] = INFINITY;
m_ulCreateStorageMax[iLevel][iIndex] = 0;
m_ulStorageCommitMax[iLevel][iIndex] = 0;
m_ulStorageReleaseMax[iLevel][iIndex] = 0;
}
}
sc = InitCOM();
if (FAILED(sc))
{
Log (TEXT("Setup - CoInitialize failed."), sc);
return sc;
}
// get malloc interface for this task
m_piMalloc = NULL;
sc = CoGetMalloc(MEMCTX_TASK, &m_piMalloc);
if (FAILED(sc))
{
Log (TEXT("Setup - CoGetMalloc"), sc);
return sc;
}
m_cbSize = pInput->GetConfigInt(Name(), TEXT("DataSize"), DEF_DATASIZE);
// initialize array to be written to the file.
m_pbData = (BYTE *)m_piMalloc->Alloc(m_cbSize);
if(m_pbData == NULL)
{
Log (TEXT("Setup - Cannot allocate memory"), E_OUTOFMEMORY);
return E_OUTOFMEMORY;
}
for (iIndex=0; iIndex < m_cbSize; iIndex++)
m_pbData[iIndex] = (BYTE)iIndex;
// get file name to be used and values of other parameters
pInput->GetConfigString(Name(), TEXT("FileName"), TEXT("stgtest.bm"),
m_pszFile, MAX_PATH);
#ifdef UNICODE
wcscpy(m_pwszFile, m_pszFile);
#else
mbstowcs(m_pwszFile, m_pszFile, strlen(m_pszFile)+1);
#endif
pInput->GetConfigString(Name(), TEXT("FileMode"), TEXT("DIRECT"), m_pszFileMode, 15);
if(lstrcmpi(m_pszFileMode, TEXT("DIRECT")) == 0)
m_flCreateFlags = STGM_DIRECT;
else
m_flCreateFlags = STGM_TRANSACTED;
// get the nesting factor
m_cNesting = pInput->GetConfigInt(Name(), TEXT("Nesting"), 3);
if(m_cNesting > MAX_NESTING)
m_cNesting = MAX_NESTING;
if(m_cNesting == 0)
m_cNesting = 1;
// get the branching factor
m_cBranching = pInput->GetConfigInt(Name(), TEXT("Branching"), 3);
if(m_cBranching > MAX_BRANCHING)
m_cBranching = MAX_BRANCHING;
if(m_cBranching == 0)
m_cBranching = 1;
// get the value of Delete element option
pInput->GetConfigString(Name(), TEXT("Delete"), TEXT("OFF"), pszBuf, 15);
if( lstrcmpi(pszBuf, TEXT("OFF")) == 0 ||
lstrcmpi(pszBuf, TEXT("FALSE")) == 0)
m_bDelete = FALSE;
else
m_bDelete = TRUE;
// now compute number of streams and storages, depeding on
// the nesting and branching factors. Formulas are as follows:
// Nesting = n;
// Branching = b;
// n
// Streams = b
//
// n
// b - 1
// Storages = ---------
// b - 1
//
// n-1
// b - 1
// ParentFactor = ---------
// b - 1
//
// Parent factor is used to determine the parent storage of the stream
//
m_cStreams = 1;
ULONG n = m_cNesting;
while(n-- > 0) // compute b^n
m_cStreams *= m_cBranching;
m_cStorages = (m_cStreams - 1) / (m_cBranching - 1);
m_cParentFactor = (m_cStreams / m_cBranching - 1) /
(m_cBranching - 1);
// allocate arrays for storages
m_piStorages = (LPSTORAGE *)m_piMalloc->Alloc(m_cStorages *
sizeof(LPSTORAGE));
if (m_piStorages == NULL)
{
Log(TEXT("Cannot allocate memory"), E_OUTOFMEMORY);
return E_OUTOFMEMORY;
}
return S_OK;
}
SCODE CNestedStorageTest::Cleanup ()
{
// delete the file
DeleteFile (m_pszFile);
// free all memory
if(m_piMalloc)
{
if (m_pbData)
m_piMalloc->Free(m_pbData);
if (m_piStorages)
m_piMalloc->Free(m_piStorages);
m_piMalloc->Release();
m_piMalloc = NULL;
}
UninitCOM();
return S_OK;
}
// Some macros that are used only in Run() function.
#define STG_PARENT(iIndex) ((iIndex - 1) / m_cBranching )
#define STREAM_PARENT(iIndex) (iIndex / m_cBranching + m_cParentFactor )
// STG_NAME and STREAM_NAME macros are very ugly, but they save
// doing a bunch of allocations and name generation in the beginning.
#define STG_NAME(iIndex) (swprintf(pwszBuf, L"Storage%d", iIndex), pwszBuf)
#define STREAM_NAME(iIndex) (swprintf(pwszBuf, L"Stream%d", iIndex), pwszBuf)
SCODE CNestedStorageTest::Run ()
{
CStopWatch sw;
HRESULT hr;
ULONG cb;
ULONG iCurStream;
LONG iCurStg; // has to be long, not ulong, for looping down to zero.
LPSTREAM piStream;
ULONG iIter;
OLECHAR pwszBuf[20];
ULONG ulTime;
ULONG iLevel;
ULONG iParent;
for (iIter =0; iIter < m_ulIterations; iIter++)
{
sw.Reset();
hr = StgCreateDocfile(m_pwszFile, m_flCreateFlags | STGM_WRITE
| STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &m_piStorages[0]);
m_ulStgCreateDocfile[iIter] = sw.Read();
Log(TEXT("StgCreateDocfile"), hr);
if (FAILED(hr))
return hr;
// Create a complete tree of storages
for (iCurStg = 1; iCurStg < (LONG)m_cStorages; iCurStg++)
{
// determine level of curent storage.
iLevel = 0;
iParent = STG_PARENT(iCurStg);
while(iParent > 0)
{
iParent = STG_PARENT(iParent);
iLevel++;
}
sw.Reset();
hr = m_piStorages[STG_PARENT(iCurStg)]->
CreateStorage(STG_NAME(iCurStg),
m_flCreateFlags | STGM_WRITE |
STGM_CREATE | STGM_SHARE_EXCLUSIVE,
0, 0, &m_piStorages[iCurStg]);
ulTime = sw.Read();
m_ulCreateStorageTotal[iIter] += ulTime;
if(ulTime < m_ulCreateStorageMin[iLevel][iIter])
m_ulCreateStorageMin[iLevel][iIter] = ulTime;
if(ulTime > m_ulCreateStorageMax[iLevel][iIter])
m_ulCreateStorageMax[iLevel][iIter] = ulTime;
if (FAILED(hr))
{
Log(TEXT("CreateStorage"), hr);
return hr;
}
}
Log(TEXT("CreateStorage"), S_OK);
// For each storage in final level, open several streams,
// write some data to them, and release them
for (iCurStream = 0; iCurStream < m_cStreams; iCurStream++)
{
sw.Reset();
hr = m_piStorages[STREAM_PARENT(iCurStream)]->
CreateStream(STREAM_NAME(iCurStream),
STGM_DIRECT | STGM_WRITE |
STGM_CREATE | STGM_SHARE_EXCLUSIVE,
0, 0, &piStream);
ulTime = sw.Read();
m_ulCreateStreamTotal[iIter] += ulTime;
if(ulTime < m_ulCreateStreamMin[iIter])
m_ulCreateStreamMin[iIter] = ulTime;
if(ulTime > m_ulCreateStreamMax[iIter])
m_ulCreateStreamMax[iIter] = ulTime;
if (FAILED(hr))
{
Log(TEXT("CreateStream"), hr);
return hr;
}
sw.Reset();
piStream->Write((LPVOID)m_pbData, m_cbSize, &cb);
ulTime = sw.Read();
m_ulStreamWriteTotal[iIter] += ulTime;
if(ulTime < m_ulStreamWriteMin[iIter])
m_ulStreamWriteMin[iIter] = ulTime;
if(ulTime > m_ulStreamWriteMax[iIter])
m_ulStreamWriteMax[iIter] = ulTime;
sw.Reset();
piStream->Release();
ulTime = sw.Read();
m_ulStreamReleaseTotal[iIter] += ulTime;
if(ulTime < m_ulStreamReleaseMin[iIter])
m_ulStreamReleaseMin[iIter] = ulTime;
if(ulTime > m_ulStreamReleaseMax[iIter])
m_ulStreamReleaseMax[iIter] = ulTime;
}
Log(TEXT("CreateStream"), S_OK);
Log(TEXT("StreamWrite"), S_OK);
Log(TEXT("StreamRelease"), S_OK);
if (m_bDelete)
{
// delete 1 stream from every branch.
for (iCurStream = 1; iCurStream < m_cStreams; iCurStream += m_cBranching)
{
sw.Reset();
hr = m_piStorages[STREAM_PARENT(iCurStream)]->
DestroyElement(STREAM_NAME(iCurStream));
ulTime = sw.Read();
m_ulDestroyElementTotal[iIter] += ulTime;
if (ulTime < m_ulDestroyElementMin[iIter])
m_ulDestroyElementMin[iIter] = ulTime;
if (ulTime > m_ulDestroyElementMax[iIter])
m_ulDestroyElementMax[iIter] = ulTime;
if (FAILED(hr))
{
Log(TEXT("DestroyElement"), hr);
return hr;
}
}
Log( TEXT("DestroyElement"), S_OK);
m_ulDestroyElementAverage[iIter] = m_ulDestroyElementTotal[iIter] /
(m_cStreams / m_cBranching);
}
// for each storage, do commit if in transacted mode
// and release the storage.
for (iCurStg = m_cStorages-1 ; iCurStg >= 0 ; iCurStg--)
{
// determine level of curent storage.
iLevel = 0;
iParent = STG_PARENT(iCurStg);
while(iParent > 0)
{
iParent = STG_PARENT(iParent);
iLevel++;
}
if (m_flCreateFlags == STGM_TRANSACTED)
{
sw.Reset();
m_piStorages[iCurStg]->Commit(STGC_DEFAULT);
ulTime = sw.Read();
m_ulStorageCommitTotal[iIter] += ulTime;
if (iCurStg != 0)
{
if (ulTime < m_ulStorageCommitMin[iLevel][iIter])
m_ulStorageCommitMin[iLevel][iIter] = ulTime;
if (ulTime > m_ulStorageCommitMax[iLevel][iIter])
m_ulStorageCommitMax[iLevel][iIter] = ulTime;
}
else
{
m_ulFinalStorageCommit[iIter] = ulTime;
}
}
sw.Reset();
m_piStorages[iCurStg]->Release();
ulTime = sw.Read();
m_ulStorageReleaseTotal[iIter] += ulTime;
if (iCurStg != 0)
{
if (ulTime < m_ulStorageReleaseMin[iLevel][iIter])
m_ulStorageReleaseMin[iLevel][iIter] = ulTime;
if (ulTime > m_ulStorageReleaseMax[iLevel][iIter])
m_ulStorageReleaseMax[iLevel][iIter] = ulTime;
}
else
{
m_ulFinalStorageRelease[iIter] = ulTime;
}
}
Log(TEXT("StorageCommit"), S_OK);
Log(TEXT("StorageRelease"), S_OK);
m_ulCreateStorageAverage[iIter] = m_ulCreateStorageTotal[iIter] / m_cStorages;
m_ulCreateStreamAverage[iIter] = m_ulCreateStreamTotal[iIter] / m_cStreams;
m_ulStreamWriteAverage[iIter] = m_ulStreamWriteTotal[iIter] / m_cStreams;
m_ulStreamReleaseAverage[iIter] = m_ulStreamReleaseTotal[iIter] / m_cStreams;
m_ulStorageCommitAverage[iIter] = m_ulStorageCommitTotal[iIter] / m_cStorages;
m_ulStorageReleaseAverage[iIter] = m_ulStorageReleaseTotal[iIter] / m_cStorages;
m_ulTotal[iIter] = m_ulStgCreateDocfile[iIter] +
m_ulCreateStorageTotal[iIter] +
m_ulCreateStreamTotal[iIter] +
m_ulStreamWriteTotal[iIter] +
m_ulStreamReleaseTotal[iIter] +
m_ulDestroyElementTotal[iIter] +
m_ulStorageCommitTotal[iIter] +
m_ulStorageReleaseTotal[iIter];
}
return S_OK;
}
SCODE CNestedStorageTest::Report (CTestOutput &output)
{
TCHAR pszBuf[80];
wsprintf(pszBuf, TEXT("Nested Storage Test in %s Mode writing %d bytes"),
m_pszFileMode, m_cbSize);
output.WriteSectionHeader (Name(), pszBuf, *m_pInput);
output.WriteString (TEXT("\n"));
for ( ULONG iLevel = 0; iLevel < m_cNesting - 1; iLevel++)
{
wsprintf(pszBuf, TEXT("\nLevel %d\n"), iLevel + 1);
output.WriteString (pszBuf);
output.WriteResults (TEXT("CreateStorage Min"), m_ulIterations,
m_ulCreateStorageMin[iLevel]);
output.WriteResults (TEXT("CreateStorage Max"), m_ulIterations,
m_ulCreateStorageMax[iLevel]);
if (m_flCreateFlags == STGM_TRANSACTED)
{
output.WriteResults (TEXT("StorageCommit Min"), m_ulIterations,
m_ulStorageCommitMin[iLevel] );
output.WriteResults (TEXT("StorageCommit Max"), m_ulIterations,
m_ulStorageCommitMax[iLevel] );
}
output.WriteResults (TEXT("StorageRelease Min"), m_ulIterations,
m_ulStorageReleaseMin[iLevel]);
output.WriteResults (TEXT("StorageRelease Max"), m_ulIterations,
m_ulStorageReleaseMax[iLevel]);
}
output.WriteString (TEXT("\nOverall\n"));
output.WriteResults (TEXT("StgCreateDocfile "), m_ulIterations,
m_ulStgCreateDocfile);
if (m_flCreateFlags == STGM_TRANSACTED)
output.WriteResults (TEXT("Final Storage Commit"), m_ulIterations,
m_ulFinalStorageCommit);
output.WriteResults (TEXT("Final Storage Release"), m_ulIterations,
m_ulFinalStorageRelease);
output.WriteString (TEXT("\n"));
output.WriteResults (TEXT("CreateStorage Average"), m_ulIterations,
m_ulCreateStorageAverage );
output.WriteResults (TEXT("CreateStorage Total"), m_ulIterations,
m_ulCreateStorageTotal );
output.WriteString (TEXT("\n"));
output.WriteResults (TEXT("CreateStream Min"), m_ulIterations,
m_ulCreateStreamMin);
output.WriteResults (TEXT("CreateStream Max"), m_ulIterations,
m_ulCreateStreamMax);
output.WriteResults (TEXT("CreateStream Average"), m_ulIterations,
m_ulCreateStreamAverage);
output.WriteResults (TEXT("CreateStream Total"), m_ulIterations,
m_ulCreateStreamTotal );
output.WriteString (TEXT("\n"));
output.WriteResults (TEXT("StreamWrite Min"), m_ulIterations,
m_ulStreamWriteMin );
output.WriteResults (TEXT("StreamWrite Max"), m_ulIterations,
m_ulStreamWriteMax );
output.WriteResults (TEXT("StreamWrite Average"), m_ulIterations,
m_ulStreamWriteAverage );
output.WriteResults (TEXT("StreamWrite Total"), m_ulIterations,
m_ulStreamWriteTotal );
output.WriteString (TEXT("\n"));
output.WriteResults (TEXT("StreamRelease Min"), m_ulIterations,
m_ulStreamReleaseMin );
output.WriteResults (TEXT("StreamRelease Max"), m_ulIterations,
m_ulStreamReleaseMax );
output.WriteResults (TEXT("StreamRelease Average"), m_ulIterations,
m_ulStreamReleaseAverage );
output.WriteResults (TEXT("StreamRelease Total"), m_ulIterations,
m_ulStreamReleaseTotal );
output.WriteString (TEXT("\n"));
if(m_bDelete)
{
output.WriteResults (TEXT("DestroyElement Min"), m_ulIterations,
m_ulDestroyElementMin );
output.WriteResults (TEXT("DestroyElement Max"), m_ulIterations,
m_ulDestroyElementMax );
output.WriteResults (TEXT("DestroyElement Average"), m_ulIterations,
m_ulDestroyElementAverage );
output.WriteResults (TEXT("DestroyElement Total"), m_ulIterations,
m_ulDestroyElementTotal );
output.WriteString (TEXT("\n"));
}
if (m_flCreateFlags == STGM_TRANSACTED)
{
output.WriteResults (TEXT("StorageCommit Average"), m_ulIterations,
m_ulStorageCommitAverage );
output.WriteResults (TEXT("StorageCommit Total"), m_ulIterations,
m_ulStorageCommitTotal );
output.WriteString (TEXT("\n"));
}
output.WriteResults (TEXT("StorageRelease Average"), m_ulIterations,
m_ulStorageReleaseAverage );
output.WriteResults (TEXT("StorageRelease Total"), m_ulIterations,
m_ulStorageReleaseTotal );
output.WriteString (TEXT("\n"));
output.WriteResults (TEXT("Overall Total "), m_ulIterations, m_ulTotal );
return S_OK;
}