Добавлена папка source в CristalDiskMark

This commit is contained in:
2026-05-29 13:04:54 +07:00
commit bdc2295ee4
240 changed files with 94035 additions and 0 deletions
@@ -0,0 +1,885 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "XmlProfileParser.h"
#include <Objbase.h>
#include <msxml6.h>
#include <assert.h>
// the vc com headers define a partial set of smartptr typedefs, which unfortunately
// aren't 1) complete for our use case and 2) vary between revs of the headers.
// this define disables the automatic definitions, letting us do them ourselves.
#define _COM_NO_STANDARD_GUIDS_
#include <comdef.h>
_COM_SMARTPTR_TYPEDEF(IXMLDOMDocument2, __uuidof(IXMLDOMDocument2));
_COM_SMARTPTR_TYPEDEF(IXMLDOMNode, __uuidof(IXMLDOMNodeList));
_COM_SMARTPTR_TYPEDEF(IXMLDOMNodeList, __uuidof(IXMLDOMNodeList));
bool XmlProfileParser::ParseFile(const char *pszPath, Profile *pProfile)
{
assert(pszPath != nullptr);
assert(pProfile != nullptr);
bool fComInitialized = false;
HRESULT hr = CoInitialize(nullptr);
if (SUCCEEDED(hr))
{
fComInitialized = true;
IXMLDOMDocument2Ptr spXmlDoc;
hr = CoCreateInstance(__uuidof(DOMDocument60), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spXmlDoc));
if (SUCCEEDED(hr))
{
hr = spXmlDoc->put_async(VARIANT_FALSE);
if (SUCCEEDED(hr))
{
VARIANT_BOOL fvIsOk;
_variant_t vPath(pszPath);
hr = spXmlDoc->load(vPath, &fvIsOk);
if (SUCCEEDED(hr))
{
bool fVerbose;
hr = _GetVerbose(spXmlDoc, &fVerbose);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetVerbose(fVerbose);
}
if (SUCCEEDED(hr))
{
DWORD dwProgress;
hr = _GetProgress(spXmlDoc, &dwProgress);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetProgress(dwProgress);
}
}
if (SUCCEEDED(hr))
{
string sResultFormat;
hr = _GetString(spXmlDoc, "//Profile/ResultFormat", &sResultFormat);
if (SUCCEEDED(hr) && (hr != S_FALSE) && sResultFormat == "xml")
{
pProfile->SetResultsFormat(ResultsFormat::Xml);
}
}
if (SUCCEEDED(hr))
{
string sCreateFiles;
hr = _GetString(spXmlDoc, "//Profile/PrecreateFiles", &sCreateFiles);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
if (sCreateFiles == "UseMaxSize")
{
pProfile->SetPrecreateFiles(PrecreateFiles::UseMaxSize);
}
else if (sCreateFiles == "CreateOnlyFilesWithConstantSizes")
{
pProfile->SetPrecreateFiles(PrecreateFiles::OnlyFilesWithConstantSizes);
}
else if (sCreateFiles == "CreateOnlyFilesWithConstantOrZeroSizes")
{
pProfile->SetPrecreateFiles(PrecreateFiles::OnlyFilesWithConstantOrZeroSizes);
}
else
{
hr = E_INVALIDARG;
}
}
}
if (SUCCEEDED(hr))
{
hr = _ParseEtw(spXmlDoc, pProfile);
}
if (SUCCEEDED(hr))
{
hr = _ParseTimeSpans(spXmlDoc, pProfile);
}
}
}
}
}
if (fComInitialized)
{
CoUninitialize();
}
return SUCCEEDED(hr);
}
HRESULT XmlProfileParser::_ParseEtw(IXMLDOMDocument2 &XmlDoc, Profile *pProfile)
{
bool fEtwProcess;
HRESULT hr = _GetBool(XmlDoc, "//Profile/ETW/Process", &fEtwProcess);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwProcess(fEtwProcess);
}
if (SUCCEEDED(hr))
{
bool fEtwThread;
hr = _GetBool(XmlDoc, "//Profile/ETW/Thread", &fEtwThread);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwThread(fEtwThread);
}
}
if (SUCCEEDED(hr))
{
bool fEtwImageLoad;
hr = _GetBool(XmlDoc, "//Profile/ETW/ImageLoad", &fEtwImageLoad);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwImageLoad(fEtwImageLoad);
}
}
if (SUCCEEDED(hr))
{
bool fEtwDiskIO;
hr = _GetBool(XmlDoc, "//Profile/ETW/DiskIO", &fEtwDiskIO);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwDiskIO(fEtwDiskIO);
}
}
if (SUCCEEDED(hr))
{
bool fEtwMemoryPageFaults;
hr = _GetBool(XmlDoc, "//Profile/ETW/MemoryPageFaults", &fEtwMemoryPageFaults);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwMemoryPageFaults(fEtwMemoryPageFaults);
}
}
if (SUCCEEDED(hr))
{
bool fEtwMemoryHardFaults;
hr = _GetBool(XmlDoc, "//Profile/ETW/MemoryHardFaults", &fEtwMemoryHardFaults);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwMemoryHardFaults(fEtwMemoryHardFaults);
}
}
if (SUCCEEDED(hr))
{
bool fEtwNetwork;
hr = _GetBool(XmlDoc, "//Profile/ETW/Network", &fEtwNetwork);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwNetwork(fEtwNetwork);
}
}
if (SUCCEEDED(hr))
{
bool fEtwRegistry;
hr = _GetBool(XmlDoc, "//Profile/ETW/Registry", &fEtwRegistry);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwRegistry(fEtwRegistry);
}
}
if (SUCCEEDED(hr))
{
bool fEtwUsePagedMemory;
hr = _GetBool(XmlDoc, "//Profile/ETW/UsePagedMemory", &fEtwUsePagedMemory);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwUsePagedMemory(fEtwUsePagedMemory);
}
}
if (SUCCEEDED(hr))
{
bool fEtwUsePerfTimer;
hr = _GetBool(XmlDoc, "//Profile/ETW/UsePerfTimer", &fEtwUsePerfTimer);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwUsePerfTimer(fEtwUsePerfTimer);
}
}
if (SUCCEEDED(hr))
{
bool fEtwUseSystemTimer;
hr = _GetBool(XmlDoc, "//Profile/ETW/UseSystemTimer", &fEtwUseSystemTimer);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwUseSystemTimer(fEtwUseSystemTimer);
}
}
if (SUCCEEDED(hr))
{
bool fEtwUseCyclesCounter;
hr = _GetBool(XmlDoc, "//Profile/ETW/UseCyclesCounter", &fEtwUseCyclesCounter);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pProfile->SetEtwEnabled(true);
pProfile->SetEtwUseCyclesCounter(fEtwUseCyclesCounter);
}
}
return hr;
}
HRESULT XmlProfileParser::_ParseTimeSpans(IXMLDOMDocument2 &XmlDoc, Profile *pProfile)
{
IXMLDOMNodeListPtr spNodeList;
_variant_t query("//Profile/TimeSpans/TimeSpan");
HRESULT hr = XmlDoc.selectNodes(query.bstrVal, &spNodeList);
if (SUCCEEDED(hr))
{
long cNodes;
hr = spNodeList->get_length(&cNodes);
if (SUCCEEDED(hr))
{
for (int i = 0; i < cNodes; i++)
{
IXMLDOMNodePtr spNode;
hr = spNodeList->get_item(i, &spNode);
if (SUCCEEDED(hr))
{
TimeSpan timeSpan;
hr = _ParseTimeSpan(spNode, &timeSpan);
if (SUCCEEDED(hr))
{
pProfile->AddTimeSpan(timeSpan);
}
}
}
}
}
return hr;
}
HRESULT XmlProfileParser::_ParseTimeSpan(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan)
{
UINT32 ulDuration;
HRESULT hr = _GetUINT32(XmlNode, "Duration", &ulDuration);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetDuration(ulDuration);
}
if (SUCCEEDED(hr))
{
UINT32 ulWarmup;
hr = _GetUINT32(XmlNode, "Warmup", &ulWarmup);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetWarmup(ulWarmup);
}
}
if (SUCCEEDED(hr))
{
UINT32 ulCooldown;
hr = _GetUINT32(XmlNode, "Cooldown", &ulCooldown);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetCooldown(ulCooldown);
}
}
if (SUCCEEDED(hr))
{
UINT32 ulRandSeed;
hr = _GetUINT32(XmlNode, "RandSeed", &ulRandSeed);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetRandSeed(ulRandSeed);
}
}
if (SUCCEEDED(hr))
{
UINT32 ulThreadCount;
hr = _GetUINT32(XmlNode, "ThreadCount", &ulThreadCount);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetThreadCount(ulThreadCount);
}
}
if (SUCCEEDED(hr))
{
bool fGroupAffinity;
hr = _GetBool(XmlNode, "GroupAffinity", &fGroupAffinity);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetGroupAffinity(fGroupAffinity);
}
}
if (SUCCEEDED(hr))
{
bool fDisableAffinity;
hr = _GetBool(XmlNode, "DisableAffinity", &fDisableAffinity);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetDisableAffinity(fDisableAffinity);
}
}
if (SUCCEEDED(hr))
{
bool fCompletionRoutines;
hr = _GetBool(XmlNode, "CompletionRoutines", &fCompletionRoutines);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetCompletionRoutines(fCompletionRoutines);
}
}
if (SUCCEEDED(hr))
{
bool fMeasureLatency;
hr = _GetBool(XmlNode, "MeasureLatency", &fMeasureLatency);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetMeasureLatency(fMeasureLatency);
}
}
if (SUCCEEDED(hr))
{
bool fCalculateIopsStdDev;
hr = _GetBool(XmlNode, "CalculateIopsStdDev", &fCalculateIopsStdDev);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetCalculateIopsStdDev(fCalculateIopsStdDev);
}
}
if (SUCCEEDED(hr))
{
UINT32 ulIoBucketDuration;
hr = _GetUINT32(XmlNode, "IoBucketDuration", &ulIoBucketDuration);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTimeSpan->SetIoBucketDurationInMilliseconds(ulIoBucketDuration);
}
}
if (SUCCEEDED(hr))
{
hr = _ParseAffinityAssignment(XmlNode, pTimeSpan);
}
if (SUCCEEDED(hr))
{
hr = _ParseTargets(XmlNode, pTimeSpan);
}
return hr;
}
HRESULT XmlProfileParser::_ParseTargets(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan)
{
_variant_t query("Targets/Target");
IXMLDOMNodeListPtr spNodeList;
HRESULT hr = XmlNode.selectNodes(query.bstrVal, &spNodeList);
if (SUCCEEDED(hr))
{
long cNodes;
hr = spNodeList->get_length(&cNodes);
if (SUCCEEDED(hr))
{
for (int i = 0; i < cNodes; i++)
{
IXMLDOMNodePtr spNode;
hr = spNodeList->get_item(i, &spNode);
if (SUCCEEDED(hr))
{
Target target;
_ParseTarget(spNode, &target);
pTimeSpan->AddTarget(target);
}
}
}
}
return hr;
}
HRESULT XmlProfileParser::_ParseRandomDataSource(IXMLDOMNode &XmlNode, Target *pTarget)
{
IXMLDOMNodeListPtr spNodeList;
_variant_t query("RandomDataSource");
HRESULT hr = XmlNode.selectNodes(query.bstrVal, &spNodeList);
if (SUCCEEDED(hr))
{
long cNodes;
hr = spNodeList->get_length(&cNodes);
if (SUCCEEDED(hr) && (cNodes == 1))
{
IXMLDOMNodePtr spNode;
hr = spNodeList->get_item(0, &spNode);
if (SUCCEEDED(hr))
{
UINT64 cb;
hr = _GetUINT64(spNode, "SizeInBytes", &cb);
if (SUCCEEDED(hr) && (S_FALSE != hr))
{
pTarget->SetRandomDataWriteBufferSize(cb);
string sPath;
hr = _GetString(spNode, "FilePath", &sPath);
if (SUCCEEDED(hr) && (S_FALSE != hr))
{
pTarget->SetRandomDataWriteBufferSourcePath(sPath);
}
}
}
}
}
return hr;
}
HRESULT XmlProfileParser::_ParseWriteBufferContent(IXMLDOMNode &XmlNode, Target *pTarget)
{
IXMLDOMNodeListPtr spNodeList;
_variant_t query("WriteBufferContent");
HRESULT hr = XmlNode.selectNodes(query.bstrVal, &spNodeList);
if (SUCCEEDED(hr))
{
long cNodes;
hr = spNodeList->get_length(&cNodes);
if (SUCCEEDED(hr) && (cNodes == 1))
{
IXMLDOMNodePtr spNode;
hr = spNodeList->get_item(0, &spNode);
if (SUCCEEDED(hr))
{
string sPattern;
hr = _GetString(spNode, "Pattern", &sPattern);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
if (sPattern == "sequential")
{
// that's the default option - do nothing
}
else if (sPattern == "zero")
{
pTarget->SetZeroWriteBuffers(true);
}
else if (sPattern == "random")
{
hr = _ParseRandomDataSource(spNode, pTarget);
}
else
{
hr = E_INVALIDARG;
}
}
}
}
}
return hr;
}
HRESULT XmlProfileParser::_ParseTarget(IXMLDOMNode &XmlNode, Target *pTarget)
{
string sPath;
HRESULT hr = _GetString(XmlNode, "Path", &sPath);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetPath(sPath);
}
if (SUCCEEDED(hr))
{
DWORD dwBlockSize;
hr = _GetDWORD(XmlNode, "BlockSize", &dwBlockSize);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetBlockSizeInBytes(dwBlockSize);
}
}
if (SUCCEEDED(hr))
{
UINT64 ullStrideSize;
hr = _GetUINT64(XmlNode, "StrideSize", &ullStrideSize);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetBlockAlignmentInBytes(ullStrideSize);
}
}
if (SUCCEEDED(hr))
{
bool fInterlockedSequential;
hr = _GetBool(XmlNode, "InterlockedSequential", &fInterlockedSequential);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetUseInterlockedSequential(fInterlockedSequential);
}
}
if (SUCCEEDED(hr))
{
UINT64 ullBaseFileOffset;
hr = _GetUINT64(XmlNode, "BaseFileOffset", &ullBaseFileOffset);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetBaseFileOffsetInBytes(ullBaseFileOffset);
}
}
if (SUCCEEDED(hr))
{
bool fSequentialScan;
hr = _GetBool(XmlNode, "SequentialScan", &fSequentialScan);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetSequentialScanHint(fSequentialScan);
}
}
if (SUCCEEDED(hr))
{
bool fRandomAccess;
hr = _GetBool(XmlNode, "RandomAccess", &fRandomAccess);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetRandomAccessHint(fRandomAccess);
}
}
if (SUCCEEDED(hr))
{
bool fUseLargePages;
hr = _GetBool(XmlNode, "UseLargePages", &fUseLargePages);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetUseLargePages(fUseLargePages);
}
}
if (SUCCEEDED(hr))
{
DWORD dwRequestCount;
hr = _GetDWORD(XmlNode, "RequestCount", &dwRequestCount);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetRequestCount(dwRequestCount);
}
}
if (SUCCEEDED(hr))
{
UINT64 ullRandom;
hr = _GetUINT64(XmlNode, "Random", &ullRandom);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetUseRandomAccessPattern(true);
pTarget->SetBlockAlignmentInBytes(ullRandom);
}
}
if (SUCCEEDED(hr))
{
bool fDisableOSCache;
hr = _GetBool(XmlNode, "DisableOSCache", &fDisableOSCache);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetDisableOSCache(fDisableOSCache);
}
}
if (SUCCEEDED(hr))
{
bool fDisableAllCache;
hr = _GetBool(XmlNode, "DisableAllCache", &fDisableAllCache);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetDisableAllCache(fDisableAllCache);
}
}
if (SUCCEEDED(hr))
{
hr = _ParseWriteBufferContent(XmlNode, pTarget);
}
if (SUCCEEDED(hr))
{
DWORD dwBurstSize;
hr = _GetDWORD(XmlNode, "BurstSize", &dwBurstSize);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetBurstSize(dwBurstSize);
pTarget->SetUseBurstSize(true);
}
}
if (SUCCEEDED(hr))
{
DWORD dwThinkTime;
hr = _GetDWORD(XmlNode, "ThinkTime", &dwThinkTime);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetThinkTime(dwThinkTime);
pTarget->SetEnableThinkTime(true);
}
}
if (SUCCEEDED(hr))
{
DWORD dwThroughput;
hr = _GetDWORD(XmlNode, "Throughput", &dwThroughput);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetThroughput(dwThroughput);
}
}
if (SUCCEEDED(hr))
{
DWORD dwThreadsPerFile;
hr = _GetDWORD(XmlNode, "ThreadsPerFile", &dwThreadsPerFile);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetThreadsPerFile(dwThreadsPerFile);
}
}
if (SUCCEEDED(hr))
{
UINT64 ullFileSize;
hr = _GetUINT64(XmlNode, "FileSize", &ullFileSize);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetFileSize(ullFileSize);
pTarget->SetCreateFile(true);
}
}
if (SUCCEEDED(hr))
{
UINT64 ullMaxFileSize;
hr = _GetUINT64(XmlNode, "MaxFileSize", &ullMaxFileSize);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetMaxFileSize(ullMaxFileSize);
}
}
if (SUCCEEDED(hr))
{
UINT32 ulWriteRatio;
hr = _GetUINT32(XmlNode, "WriteRatio", &ulWriteRatio);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetWriteRatio(ulWriteRatio);
}
}
if (SUCCEEDED(hr))
{
bool fParallelAsyncIO;
hr = _GetBool(XmlNode, "ParallelAsyncIO", &fParallelAsyncIO);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetUseParallelAsyncIO(fParallelAsyncIO);
}
}
if (SUCCEEDED(hr))
{
UINT64 ullThreadStride;
hr = _GetUINT64(XmlNode, "ThreadStride", &ullThreadStride);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
pTarget->SetThreadStrideInBytes(ullThreadStride);
}
}
if (SUCCEEDED(hr))
{
UINT32 ulIOPriority;
hr = _GetUINT32(XmlNode, "IOPriority", &ulIOPriority);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
PRIORITY_HINT hint[] = { IoPriorityHintVeryLow, IoPriorityHintLow, IoPriorityHintNormal };
pTarget->SetIOPriorityHint(hint[ulIOPriority - 1]);
}
}
return hr;
}
HRESULT XmlProfileParser::_ParseAffinityAssignment(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan)
{
IXMLDOMNodeListPtr spNodeList;
_variant_t query("Affinity/AffinityAssignment");
HRESULT hr = XmlNode.selectNodes(query.bstrVal, &spNodeList);
if (SUCCEEDED(hr))
{
long cNodes;
hr = spNodeList->get_length(&cNodes);
if (SUCCEEDED(hr))
{
for (int i = 0; i < cNodes; i++)
{
IXMLDOMNodePtr spNode;
hr = spNodeList->get_item(i, &spNode);
if (SUCCEEDED(hr))
{
BSTR bstrText;
hr = spNode->get_text(&bstrText);
if (SUCCEEDED(hr))
{
pTimeSpan->AddAffinityAssignment(_wtoi((wchar_t *)bstrText)); // TODO: change to unsigned
SysFreeString(bstrText);
}
}
}
}
}
return hr;
}
HRESULT XmlProfileParser::_GetUINT32(IXMLDOMNode &XmlNode, const char *pszQuery, UINT32 *pulValue) const
{
IXMLDOMNodePtr spNode;
_variant_t query(pszQuery);
HRESULT hr = XmlNode.selectSingleNode(query.bstrVal, &spNode);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
BSTR bstrText;
hr = spNode->get_text(&bstrText);
if (SUCCEEDED(hr))
{
*pulValue = _wtoi((wchar_t *)bstrText); // TODO: make sure it works on large unsigned ints
SysFreeString(bstrText);
}
}
return hr;
}
HRESULT XmlProfileParser::_GetString(IXMLDOMNode &XmlNode, const char *pszQuery, string *psValue) const
{
IXMLDOMNodePtr spNode;
_variant_t query(pszQuery);
HRESULT hr = XmlNode.selectSingleNode(query.bstrVal, &spNode);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
BSTR bstrText;
hr = spNode->get_text(&bstrText);
if (SUCCEEDED(hr))
{
// TODO: use wstring?
char path[MAX_PATH] = {};
WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, (wchar_t *)bstrText, static_cast<int>(wcslen((wchar_t *)bstrText)), path, sizeof(path)-1, 0 /*lpDefaultChar*/, 0 /*lpUsedDefaultChar*/);
*psValue = string(path);
}
SysFreeString(bstrText);
}
return hr;
}
HRESULT XmlProfileParser::_GetUINT64(IXMLDOMNode &XmlNode, const char *pszQuery, UINT64 *pullValue) const
{
IXMLDOMNodePtr spNode;
_variant_t query(pszQuery);
HRESULT hr = XmlNode.selectSingleNode(query.bstrVal, &spNode);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
BSTR bstrText;
hr = spNode->get_text(&bstrText);
if (SUCCEEDED(hr))
{
*pullValue = _wtoi64((wchar_t *)bstrText); // TODO: make sure it works on large unsigned ints
}
SysFreeString(bstrText);
}
return hr;
}
HRESULT XmlProfileParser::_GetDWORD(IXMLDOMNode &XmlNode, const char *pszQuery, DWORD *pdwValue) const
{
UINT32 value = 0;
HRESULT hr = _GetUINT32(XmlNode, pszQuery, &value);
if (SUCCEEDED(hr))
{
*pdwValue = value;
}
return hr;
}
HRESULT XmlProfileParser::_GetBool(IXMLDOMNode &XmlNode, const char *pszQuery, bool *pfValue) const
{
HRESULT hr = S_OK;
IXMLDOMNodePtr spNode;
_variant_t query(pszQuery);
hr = XmlNode.selectSingleNode(query.bstrVal, &spNode);
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
BSTR bstrText;
hr = spNode->get_text(&bstrText);
if (SUCCEEDED(hr))
{
*pfValue = (_wcsicmp(L"true", (wchar_t *)bstrText) == 0);
SysFreeString(bstrText);
}
}
return hr;
}
HRESULT XmlProfileParser::_GetVerbose(IXMLDOMDocument2 &pXmlDoc, bool *pfVerbose)
{
return _GetBool(pXmlDoc, "//Profile/Verbose", pfVerbose);
}
HRESULT XmlProfileParser::_GetProgress(IXMLDOMDocument2 &pXmlDoc, DWORD *pdwProgress)
{
return _GetDWORD(pXmlDoc, "//Profile/Progress", pdwProgress);
}
@@ -0,0 +1,57 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <MsXml6.h>
#include "Common.h"
class XmlProfileParser
{
public:
bool ParseFile(const char *pszPath, Profile *pProfile);
private:
HRESULT _ParseEtw(IXMLDOMDocument2 &XmlDoc, Profile *pProfile);
HRESULT _ParseTimeSpans(IXMLDOMDocument2 &XmlDoc, Profile *pProfile);
HRESULT _ParseTimeSpan(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan);
HRESULT _ParseTargets(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan);
HRESULT _ParseRandomDataSource(IXMLDOMNode &XmlNode, Target *pTarget);
HRESULT _ParseWriteBufferContent(IXMLDOMNode &XmlNode, Target *pTarget);
HRESULT _ParseTarget(IXMLDOMNode &XmlNode, Target *pTarget);
HRESULT _ParseAffinityAssignment(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan);
HRESULT _GetString(IXMLDOMNode &XmlNode, const char *pszQuery, string *psValue) const;
HRESULT _GetUINT32(IXMLDOMNode &XmlNode, const char *pszQuery, UINT32 *pulValue) const;
HRESULT _GetUINT64(IXMLDOMNode &XmlNode, const char *pszQuery, UINT64 *pullValue) const;
HRESULT _GetDWORD(IXMLDOMNode &XmlNode, const char *pszQuery, DWORD *pdwValue) const;
HRESULT _GetBool(IXMLDOMNode &XmlNode, const char *pszQuery, bool *pfValue) const;
HRESULT _GetVerbose(IXMLDOMDocument2 &XmlDoc, bool *pfVerbose);
HRESULT _GetProgress(IXMLDOMDocument2 &XmlDoc, DWORD *pdwProgress);
};
@@ -0,0 +1,273 @@
#pragma once
#using <mscorlib.dll>
#using <System.dll>
#using <System.Data.dll>
#using <System.Xml.dll>
using namespace System::Security::Permissions;
[assembly:SecurityPermissionAttribute(SecurityAction::RequestMinimum, SkipVerification=false)];
//
// このソース コードは xsd によって自動生成されました。Version=4.0.30319.33440 です。
//
using namespace System;
ref class NewDataSet;
/// <summary>
///Represents a strongly typed in-memory cache of data.
///</summary>
[System::Serializable,
System::ComponentModel::DesignerCategoryAttribute(L"code"),
System::ComponentModel::ToolboxItem(true),
System::Xml::Serialization::XmlSchemaProviderAttribute(L"GetTypedDataSetSchema"),
System::Xml::Serialization::XmlRootAttribute(L"NewDataSet"),
System::ComponentModel::Design::HelpKeywordAttribute(L"vs.data.DataSet")]
public ref class NewDataSet : public ::System::Data::DataSet {
private: ::System::Data::SchemaSerializationMode _schemaSerializationMode;
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
NewDataSet();
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
NewDataSet(::System::Runtime::Serialization::SerializationInfo^ info, ::System::Runtime::Serialization::StreamingContext context);
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
System::ComponentModel::BrowsableAttribute(true),
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Visible)]
virtual property ::System::Data::SchemaSerializationMode SchemaSerializationMode {
::System::Data::SchemaSerializationMode get() override;
System::Void set(::System::Data::SchemaSerializationMode value) override;
}
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Hidden)]
property ::System::Data::DataTableCollection^ Tables {
::System::Data::DataTableCollection^ get() new;
}
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Hidden)]
property ::System::Data::DataRelationCollection^ Relations {
::System::Data::DataRelationCollection^ get() new;
}
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
virtual ::System::Void InitializeDerivedDataSet() override;
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
virtual ::System::Data::DataSet^ Clone() override;
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
virtual ::System::Boolean ShouldSerializeTables() override;
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
virtual ::System::Boolean ShouldSerializeRelations() override;
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
virtual ::System::Void ReadXmlSerializable(::System::Xml::XmlReader^ reader) override;
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
virtual ::System::Xml::Schema::XmlSchema^ GetSchemaSerializable() override;
internal: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
::System::Void InitVars();
internal: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
::System::Void InitVars(::System::Boolean initTable);
private: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
::System::Void InitClass();
private: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
::System::Void SchemaChanged(::System::Object^ sender, ::System::ComponentModel::CollectionChangeEventArgs^ e);
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
static ::System::Xml::Schema::XmlSchemaComplexType^ GetTypedDataSetSchema(::System::Xml::Schema::XmlSchemaSet^ xs);
};
inline NewDataSet::NewDataSet() {
this->BeginInit();
this->InitClass();
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &NewDataSet::SchemaChanged);
__super::Tables->CollectionChanged += schemaChangedHandler;
__super::Relations->CollectionChanged += schemaChangedHandler;
this->EndInit();
}
inline NewDataSet::NewDataSet(::System::Runtime::Serialization::SerializationInfo^ info, ::System::Runtime::Serialization::StreamingContext context) :
::System::Data::DataSet(info, context, false) {
if (this->IsBinarySerialized(info, context) == true) {
this->InitVars(false);
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler1 = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &NewDataSet::SchemaChanged);
this->Tables->CollectionChanged += schemaChangedHandler1;
this->Relations->CollectionChanged += schemaChangedHandler1;
return;
}
::System::String^ strSchema = (cli::safe_cast<::System::String^ >(info->GetValue(L"XmlSchema", ::System::String::typeid)));
if (this->DetermineSchemaSerializationMode(info, context) == ::System::Data::SchemaSerializationMode::IncludeSchema) {
::System::Data::DataSet^ ds = (gcnew ::System::Data::DataSet());
ds->ReadXmlSchema((gcnew ::System::Xml::XmlTextReader((gcnew ::System::IO::StringReader(strSchema)))));
this->DataSetName = ds->DataSetName;
this->Prefix = ds->Prefix;
this->Namespace = ds->Namespace;
this->Locale = ds->Locale;
this->CaseSensitive = ds->CaseSensitive;
this->EnforceConstraints = ds->EnforceConstraints;
this->Merge(ds, false, ::System::Data::MissingSchemaAction::Add);
this->InitVars();
}
else {
this->ReadXmlSchema((gcnew ::System::Xml::XmlTextReader((gcnew ::System::IO::StringReader(strSchema)))));
}
this->GetSerializationData(info, context);
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &NewDataSet::SchemaChanged);
__super::Tables->CollectionChanged += schemaChangedHandler;
this->Relations->CollectionChanged += schemaChangedHandler;
}
inline ::System::Data::SchemaSerializationMode NewDataSet::SchemaSerializationMode::get() {
return this->_schemaSerializationMode;
}
inline System::Void NewDataSet::SchemaSerializationMode::set(::System::Data::SchemaSerializationMode value) {
this->_schemaSerializationMode = __identifier(value);
}
inline ::System::Data::DataTableCollection^ NewDataSet::Tables::get() {
return __super::Tables;
}
inline ::System::Data::DataRelationCollection^ NewDataSet::Relations::get() {
return __super::Relations;
}
inline ::System::Void NewDataSet::InitializeDerivedDataSet() {
this->BeginInit();
this->InitClass();
this->EndInit();
}
inline ::System::Data::DataSet^ NewDataSet::Clone() {
NewDataSet^ cln = (cli::safe_cast<NewDataSet^ >(__super::Clone()));
cln->InitVars();
cln->SchemaSerializationMode = this->SchemaSerializationMode;
return cln;
}
inline ::System::Boolean NewDataSet::ShouldSerializeTables() {
return false;
}
inline ::System::Boolean NewDataSet::ShouldSerializeRelations() {
return false;
}
inline ::System::Void NewDataSet::ReadXmlSerializable(::System::Xml::XmlReader^ reader) {
if (this->DetermineSchemaSerializationMode(reader) == ::System::Data::SchemaSerializationMode::IncludeSchema) {
this->Reset();
::System::Data::DataSet^ ds = (gcnew ::System::Data::DataSet());
ds->ReadXml(reader);
this->DataSetName = ds->DataSetName;
this->Prefix = ds->Prefix;
this->Namespace = ds->Namespace;
this->Locale = ds->Locale;
this->CaseSensitive = ds->CaseSensitive;
this->EnforceConstraints = ds->EnforceConstraints;
this->Merge(ds, false, ::System::Data::MissingSchemaAction::Add);
this->InitVars();
}
else {
this->ReadXml(reader);
this->InitVars();
}
}
inline ::System::Xml::Schema::XmlSchema^ NewDataSet::GetSchemaSerializable() {
::System::IO::MemoryStream^ stream = (gcnew ::System::IO::MemoryStream());
this->WriteXmlSchema((gcnew ::System::Xml::XmlTextWriter(stream, nullptr)));
stream->Position = 0;
return ::System::Xml::Schema::XmlSchema::Read((gcnew ::System::Xml::XmlTextReader(stream)), nullptr);
}
inline ::System::Void NewDataSet::InitVars() {
this->InitVars(true);
}
inline ::System::Void NewDataSet::InitVars(::System::Boolean initTable) {
}
inline ::System::Void NewDataSet::InitClass() {
this->DataSetName = L"NewDataSet";
this->Prefix = L"";
this->Namespace = L"http://microsoft.com/diskspd/DiskSpdConfig.xsd";
this->Locale = (gcnew ::System::Globalization::CultureInfo(L""));
this->EnforceConstraints = true;
this->SchemaSerializationMode = ::System::Data::SchemaSerializationMode::IncludeSchema;
}
inline ::System::Void NewDataSet::SchemaChanged(::System::Object^ sender, ::System::ComponentModel::CollectionChangeEventArgs^ e) {
if (e->Action == ::System::ComponentModel::CollectionChangeAction::Remove) {
this->InitVars();
}
}
inline ::System::Xml::Schema::XmlSchemaComplexType^ NewDataSet::GetTypedDataSetSchema(::System::Xml::Schema::XmlSchemaSet^ xs) {
NewDataSet^ ds = (gcnew NewDataSet());
::System::Xml::Schema::XmlSchemaComplexType^ type = (gcnew ::System::Xml::Schema::XmlSchemaComplexType());
::System::Xml::Schema::XmlSchemaSequence^ sequence = (gcnew ::System::Xml::Schema::XmlSchemaSequence());
::System::Xml::Schema::XmlSchemaAny^ any = (gcnew ::System::Xml::Schema::XmlSchemaAny());
any->Namespace = ds->Namespace;
sequence->Items->Add(any);
type->Particle = sequence;
::System::Xml::Schema::XmlSchema^ dsSchema = ds->GetSchemaSerializable();
if (xs->Contains(dsSchema->TargetNamespace)) {
::System::IO::MemoryStream^ s1 = (gcnew ::System::IO::MemoryStream());
::System::IO::MemoryStream^ s2 = (gcnew ::System::IO::MemoryStream());
try {
::System::Xml::Schema::XmlSchema^ schema = nullptr;
dsSchema->Write(s1);
for ( ::System::Collections::IEnumerator^ schemas = xs->Schemas(dsSchema->TargetNamespace)->GetEnumerator(); schemas->MoveNext(); ) {
schema = (cli::safe_cast<::System::Xml::Schema::XmlSchema^ >(schemas->Current));
s2->SetLength(0);
schema->Write(s2);
if (s1->Length == s2->Length) {
s1->Position = 0;
s2->Position = 0;
for ( ; ((s1->Position != s1->Length)
&& (s1->ReadByte() == s2->ReadByte())); ) {
;
}
if (s1->Position == s1->Length) {
return type;
}
}
}
}
finally {
if (s1 != nullptr) {
s1->Close();
}
if (s2 != nullptr) {
s2->Close();
}
}
}
xs->Add(dsSchema);
return type;
}
@@ -0,0 +1,236 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://microsoft.com/diskspd/DiskSpdConfig.xsd"
elementFormDefault="qualified"
xmlns="http://microsoft.com/diskspd/DiskSpdConfig.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="Profile">
<xs:all>
<xs:element name="TimeSpans" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="TimeSpan" minOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="Targets" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Target" minOccurs="1">
<!-- file / disk -->
<xs:complexType>
<xs:all>
<!-- string _sPath -->
<xs:element name="Path" type="xs:string" minOccurs="1" maxOccurs="1"></xs:element>
<!-- DWORD dwBlockSize -->
<xs:element name="BlockSize" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT64 ullStrideSize -->
<xs:element name="StrideSize" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT64 ullBaseFileOffset -->
<xs:element name="BaseFileOffset" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bSequentialScan (open file with the FILE_FLAG_SEQUENTIAL_SCAN flag) -->
<xs:element name="SequentialScan" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bRandomAccess (open file with the FILE_FLAG_RANDOM_ACCESS flag) -->
<xs:element name="RandomAccess" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bUseLargePages (Use large pages for IO buffers) -->
<xs:element name="UseLargePages" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- DWORD dwRequestCount -->
<!-- -o<count> number of overlapped I/O requests per file per thread
(1=synchronous I/O, unless more than 1 thread is specified with -F) [default=2]-->
<xs:element name="RequestCount" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT64 ullRandom
-r<align>[K|M|G|b] random I/O aligned to <align> bytes (doesn't make sense with -s)
<align> can be stated in bytes/KB/MB/GB/blocks [default access=sequential, default alignment=block size] -->
<xs:element name="Random" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bDisableOSCache -->
<xs:element name="DisableOSCache" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bDisableAllCache -->
<xs:element name="DisableAllCache" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<xs:element name="WriteBufferContent" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="Pattern">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="sequential"></xs:enumeration>
<xs:enumeration value="zero"></xs:enumeration>
<xs:enumeration value="random"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:element>
<!-- used only with pattern == random -->
<xs:element name="RandomDataSource">
<xs:complexType>
<xs:all>
<xs:element name="SizeInBytes" type="xs:unsignedLong" minOccurs="1" maxOccurs="1"></xs:element>
<xs:element name="FilePath" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
<!-- DWORD dwBurstSize (number of IOs in a burst) -->
<xs:element name="BurstSize" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- DWORD dwThinkTime (time to pause before issuing the next burst of IOs) -->
<xs:element name="ThinkTime" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- DWORD dwThroughput (in bytes per millisecond); this can not be specified when using completion routines -->
<xs:element name="Throughput" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- DWORD dwThreadsPerFile -->
<xs:element name="ThreadsPerFile" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT64 ullFileSize -->
<!-- used by the -c (create file) switch-->
<xs:element name="FileSize" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT64 ullMaxFileSize -->
<xs:element name="MaxFileSize" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT32 ulWriteRatio -->
<xs:element name="WriteRatio" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bParallelAsyncIO
-p start async (overlapped) I/O operations with the same offset (makes sense only with -o2 or grater) -->
<xs:element name="ParallelAsyncIO" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT64 ullThreadStride -->
<xs:element name="ThreadStride" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
<!-- 0 - not set, 1 - very low, 2 - low, 3 - normal -->
<xs:element name="IOPriority" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- UINT32 ulDuration -->
<xs:element name="Duration" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT32 ulWarmUp -->
<xs:element name="Warmup" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT32 ulCoolDown -->
<xs:element name="Cooldown" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT32 ulRandSeed
-z set random seed [default=0 if parameter not provided, GetTickCount() if value not provided] -->
<xs:element name="RandSeed" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- DWORD dwThreadCount
-F<count> total number of threads (cannot be used with -t) this cannot be used if per-file thread count is provided -->
<xs:element name="ThreadCount" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bGroupAffinity -->
<xs:element name="GroupAffinity" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- UINT32 *puAffinity -->
<xs:element name="Affinity" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="AffinityAssignment" type="xs:unsignedInt" minOccurs="1"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- BOOL bDisableAffinity
-n disable affinity (cannot be used with -a) -->
<xs:element name="DisableAffinity" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bCompletionRoutines -->
<!-- TODO: this should be decided on a target level -->
<xs:element name="CompletionRoutines" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<xs:element name="MeasureLatency" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<xs:element name="CalculateIopsStdDev" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<xs:element name="IoBucketDuration" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
<!-- BOOL bVerbose -->
<xs:element name="Verbose" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- DWORD dwProgress -->
<xs:element name="Progress" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
<xs:element name="ResultFormat" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="text"></xs:enumeration>
<xs:enumeration value="xml"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:element>
<!-- ETWMask -->
<xs:element name="ETW">
<xs:complexType>
<xs:all>
<!-- BOOL bProcess -->
<xs:element name="Process" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bThread -->
<xs:element name="Thread" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bImageLoad -->
<xs:element name="ImageLoad" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bDiskIO -->
<xs:element name="DiskIO" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bMemoryPageFaults -->
<xs:element name="MemoryPageFaults" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bMemoryHardFaults -->
<xs:element name="MemoryHardFaults" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bNetwork -->
<xs:element name="Network" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bRegistry -->
<xs:element name="Registry" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bUsePagedMemory -->
<xs:element name="UsePagedMemory" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bUsePerfTimer -->
<xs:element name="UsePerfTimer" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bUseSystemTimer -->
<xs:element name="UseSystemTimer" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
<!-- BOOL bUseCyclesCounter -->
<xs:element name="UseCyclesCounter" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
</xs:all>
</xs:complexType>
</xs:element>
<!-- files should be created before the first time span -->
<xs:element name="PrecreateFiles" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<!-- if the same path exists in multiple time spans, the max size will be used -->
<xs:enumeration value="UseMaxSize"></xs:enumeration>
<xs:enumeration value="CreateOnlyFilesWithConstantSizes"></xs:enumeration>
<xs:enumeration value="CreateOnlyFilesWithConstantOrZeroSizes"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:schema>