Leaked source code of windows server 2003
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
17 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993.
  5. //
  6. // File: bm_nstg.cxx
  7. //
  8. // Contents: Nested Storage test
  9. //
  10. // Classes: CNestedStorageTest
  11. //
  12. // History: 09-June-94 t-vadims Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <headers.cxx>
  16. #pragma hdrstop
  17. #include <bm_nstg.hxx>
  18. #define DEF_DATASIZE 4096
  19. #define INFINITY 0xffffffff // max value of 32-bit ulong
  20. TCHAR *CNestedStorageTest::Name ()
  21. {
  22. return TEXT("NestedStorageTest");
  23. }
  24. SCODE CNestedStorageTest::Setup (CTestInput *pInput)
  25. {
  26. SCODE sc;
  27. ULONG iIndex;
  28. TCHAR pszBuf[15];
  29. CTestBase::Setup(pInput);
  30. // get iteration count
  31. m_ulIterations = pInput->GetIterations(Name());
  32. // initialize timing arrays
  33. INIT_RESULTS(m_ulStgCreateDocfile);
  34. INIT_RESULTS(m_ulFinalStorageCommit);
  35. INIT_RESULTS(m_ulFinalStorageRelease);
  36. for(iIndex = 0; iIndex <TEST_MAX_ITERATIONS; iIndex++)
  37. {
  38. m_ulCreateStorageTotal[iIndex] = 0;
  39. m_ulCreateStreamTotal[iIndex] = 0;
  40. m_ulStreamWriteTotal[iIndex] = 0;
  41. m_ulStreamReleaseTotal[iIndex] = 0;
  42. m_ulDestroyElementTotal[iIndex] = 0;
  43. m_ulStorageCommitTotal[iIndex] = 0;
  44. m_ulStorageReleaseTotal[iIndex] = 0;
  45. m_ulTotal[iIndex] = 0;
  46. m_ulCreateStreamMin[iIndex] = INFINITY;
  47. m_ulStreamWriteMin[iIndex] = INFINITY;
  48. m_ulStreamReleaseMin[iIndex] = INFINITY;
  49. m_ulDestroyElementMin[iIndex] = INFINITY;
  50. m_ulCreateStreamMax[iIndex] = 0;
  51. m_ulStreamWriteMax[iIndex] = 0;
  52. m_ulStreamReleaseMax[iIndex] = 0;
  53. m_ulDestroyElementMax[iIndex] = 0;
  54. for (ULONG iLevel =0; iLevel < MAX_NESTING; iLevel++)
  55. {
  56. m_ulStorageCommitMin[iLevel][iIndex] = INFINITY;
  57. m_ulStorageReleaseMin[iLevel][iIndex] = INFINITY;
  58. m_ulCreateStorageMin[iLevel][iIndex] = INFINITY;
  59. m_ulCreateStorageMax[iLevel][iIndex] = 0;
  60. m_ulStorageCommitMax[iLevel][iIndex] = 0;
  61. m_ulStorageReleaseMax[iLevel][iIndex] = 0;
  62. }
  63. }
  64. sc = InitCOM();
  65. if (FAILED(sc))
  66. {
  67. Log (TEXT("Setup - CoInitialize failed."), sc);
  68. return sc;
  69. }
  70. // get malloc interface for this task
  71. m_piMalloc = NULL;
  72. sc = CoGetMalloc(MEMCTX_TASK, &m_piMalloc);
  73. if (FAILED(sc))
  74. {
  75. Log (TEXT("Setup - CoGetMalloc"), sc);
  76. return sc;
  77. }
  78. m_cbSize = pInput->GetConfigInt(Name(), TEXT("DataSize"), DEF_DATASIZE);
  79. // initialize array to be written to the file.
  80. m_pbData = (BYTE *)m_piMalloc->Alloc(m_cbSize);
  81. if(m_pbData == NULL)
  82. {
  83. Log (TEXT("Setup - Cannot allocate memory"), E_OUTOFMEMORY);
  84. return E_OUTOFMEMORY;
  85. }
  86. for (iIndex=0; iIndex < m_cbSize; iIndex++)
  87. m_pbData[iIndex] = (BYTE)iIndex;
  88. // get file name to be used and values of other parameters
  89. pInput->GetConfigString(Name(), TEXT("FileName"), TEXT("stgtest.bm"),
  90. m_pszFile, MAX_PATH);
  91. #ifdef UNICODE
  92. wcscpy(m_pwszFile, m_pszFile);
  93. #else
  94. mbstowcs(m_pwszFile, m_pszFile, strlen(m_pszFile)+1);
  95. #endif
  96. pInput->GetConfigString(Name(), TEXT("FileMode"), TEXT("DIRECT"), m_pszFileMode, 15);
  97. if(lstrcmpi(m_pszFileMode, TEXT("DIRECT")) == 0)
  98. m_flCreateFlags = STGM_DIRECT;
  99. else
  100. m_flCreateFlags = STGM_TRANSACTED;
  101. // get the nesting factor
  102. m_cNesting = pInput->GetConfigInt(Name(), TEXT("Nesting"), 3);
  103. if(m_cNesting > MAX_NESTING)
  104. m_cNesting = MAX_NESTING;
  105. if(m_cNesting == 0)
  106. m_cNesting = 1;
  107. // get the branching factor
  108. m_cBranching = pInput->GetConfigInt(Name(), TEXT("Branching"), 3);
  109. if(m_cBranching > MAX_BRANCHING)
  110. m_cBranching = MAX_BRANCHING;
  111. if(m_cBranching == 0)
  112. m_cBranching = 1;
  113. // get the value of Delete element option
  114. pInput->GetConfigString(Name(), TEXT("Delete"), TEXT("OFF"), pszBuf, 15);
  115. if( lstrcmpi(pszBuf, TEXT("OFF")) == 0 ||
  116. lstrcmpi(pszBuf, TEXT("FALSE")) == 0)
  117. m_bDelete = FALSE;
  118. else
  119. m_bDelete = TRUE;
  120. // now compute number of streams and storages, depeding on
  121. // the nesting and branching factors. Formulas are as follows:
  122. // Nesting = n;
  123. // Branching = b;
  124. // n
  125. // Streams = b
  126. //
  127. // n
  128. // b - 1
  129. // Storages = ---------
  130. // b - 1
  131. //
  132. // n-1
  133. // b - 1
  134. // ParentFactor = ---------
  135. // b - 1
  136. //
  137. // Parent factor is used to determine the parent storage of the stream
  138. //
  139. m_cStreams = 1;
  140. ULONG n = m_cNesting;
  141. while(n-- > 0) // compute b^n
  142. m_cStreams *= m_cBranching;
  143. m_cStorages = (m_cStreams - 1) / (m_cBranching - 1);
  144. m_cParentFactor = (m_cStreams / m_cBranching - 1) /
  145. (m_cBranching - 1);
  146. // allocate arrays for storages
  147. m_piStorages = (LPSTORAGE *)m_piMalloc->Alloc(m_cStorages *
  148. sizeof(LPSTORAGE));
  149. if (m_piStorages == NULL)
  150. {
  151. Log(TEXT("Cannot allocate memory"), E_OUTOFMEMORY);
  152. return E_OUTOFMEMORY;
  153. }
  154. return S_OK;
  155. }
  156. SCODE CNestedStorageTest::Cleanup ()
  157. {
  158. // delete the file
  159. DeleteFile (m_pszFile);
  160. // free all memory
  161. if(m_piMalloc)
  162. {
  163. if (m_pbData)
  164. m_piMalloc->Free(m_pbData);
  165. if (m_piStorages)
  166. m_piMalloc->Free(m_piStorages);
  167. m_piMalloc->Release();
  168. m_piMalloc = NULL;
  169. }
  170. UninitCOM();
  171. return S_OK;
  172. }
  173. // Some macros that are used only in Run() function.
  174. #define STG_PARENT(iIndex) ((iIndex - 1) / m_cBranching )
  175. #define STREAM_PARENT(iIndex) (iIndex / m_cBranching + m_cParentFactor )
  176. // STG_NAME and STREAM_NAME macros are very ugly, but they save
  177. // doing a bunch of allocations and name generation in the beginning.
  178. #define STG_NAME(iIndex) (swprintf(pwszBuf, L"Storage%d", iIndex), pwszBuf)
  179. #define STREAM_NAME(iIndex) (swprintf(pwszBuf, L"Stream%d", iIndex), pwszBuf)
  180. SCODE CNestedStorageTest::Run ()
  181. {
  182. CStopWatch sw;
  183. HRESULT hr;
  184. ULONG cb;
  185. ULONG iCurStream;
  186. LONG iCurStg; // has to be long, not ulong, for looping down to zero.
  187. LPSTREAM piStream;
  188. ULONG iIter;
  189. OLECHAR pwszBuf[20];
  190. ULONG ulTime;
  191. ULONG iLevel;
  192. ULONG iParent;
  193. for (iIter =0; iIter < m_ulIterations; iIter++)
  194. {
  195. sw.Reset();
  196. hr = StgCreateDocfile(m_pwszFile, m_flCreateFlags | STGM_WRITE
  197. | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &m_piStorages[0]);
  198. m_ulStgCreateDocfile[iIter] = sw.Read();
  199. Log(TEXT("StgCreateDocfile"), hr);
  200. if (FAILED(hr))
  201. return hr;
  202. // Create a complete tree of storages
  203. for (iCurStg = 1; iCurStg < (LONG)m_cStorages; iCurStg++)
  204. {
  205. // determine level of curent storage.
  206. iLevel = 0;
  207. iParent = STG_PARENT(iCurStg);
  208. while(iParent > 0)
  209. {
  210. iParent = STG_PARENT(iParent);
  211. iLevel++;
  212. }
  213. sw.Reset();
  214. hr = m_piStorages[STG_PARENT(iCurStg)]->
  215. CreateStorage(STG_NAME(iCurStg),
  216. m_flCreateFlags | STGM_WRITE |
  217. STGM_CREATE | STGM_SHARE_EXCLUSIVE,
  218. 0, 0, &m_piStorages[iCurStg]);
  219. ulTime = sw.Read();
  220. m_ulCreateStorageTotal[iIter] += ulTime;
  221. if(ulTime < m_ulCreateStorageMin[iLevel][iIter])
  222. m_ulCreateStorageMin[iLevel][iIter] = ulTime;
  223. if(ulTime > m_ulCreateStorageMax[iLevel][iIter])
  224. m_ulCreateStorageMax[iLevel][iIter] = ulTime;
  225. if (FAILED(hr))
  226. {
  227. Log(TEXT("CreateStorage"), hr);
  228. return hr;
  229. }
  230. }
  231. Log(TEXT("CreateStorage"), S_OK);
  232. // For each storage in final level, open several streams,
  233. // write some data to them, and release them
  234. for (iCurStream = 0; iCurStream < m_cStreams; iCurStream++)
  235. {
  236. sw.Reset();
  237. hr = m_piStorages[STREAM_PARENT(iCurStream)]->
  238. CreateStream(STREAM_NAME(iCurStream),
  239. STGM_DIRECT | STGM_WRITE |
  240. STGM_CREATE | STGM_SHARE_EXCLUSIVE,
  241. 0, 0, &piStream);
  242. ulTime = sw.Read();
  243. m_ulCreateStreamTotal[iIter] += ulTime;
  244. if(ulTime < m_ulCreateStreamMin[iIter])
  245. m_ulCreateStreamMin[iIter] = ulTime;
  246. if(ulTime > m_ulCreateStreamMax[iIter])
  247. m_ulCreateStreamMax[iIter] = ulTime;
  248. if (FAILED(hr))
  249. {
  250. Log(TEXT("CreateStream"), hr);
  251. return hr;
  252. }
  253. sw.Reset();
  254. piStream->Write((LPVOID)m_pbData, m_cbSize, &cb);
  255. ulTime = sw.Read();
  256. m_ulStreamWriteTotal[iIter] += ulTime;
  257. if(ulTime < m_ulStreamWriteMin[iIter])
  258. m_ulStreamWriteMin[iIter] = ulTime;
  259. if(ulTime > m_ulStreamWriteMax[iIter])
  260. m_ulStreamWriteMax[iIter] = ulTime;
  261. sw.Reset();
  262. piStream->Release();
  263. ulTime = sw.Read();
  264. m_ulStreamReleaseTotal[iIter] += ulTime;
  265. if(ulTime < m_ulStreamReleaseMin[iIter])
  266. m_ulStreamReleaseMin[iIter] = ulTime;
  267. if(ulTime > m_ulStreamReleaseMax[iIter])
  268. m_ulStreamReleaseMax[iIter] = ulTime;
  269. }
  270. Log(TEXT("CreateStream"), S_OK);
  271. Log(TEXT("StreamWrite"), S_OK);
  272. Log(TEXT("StreamRelease"), S_OK);
  273. if (m_bDelete)
  274. {
  275. // delete 1 stream from every branch.
  276. for (iCurStream = 1; iCurStream < m_cStreams; iCurStream += m_cBranching)
  277. {
  278. sw.Reset();
  279. hr = m_piStorages[STREAM_PARENT(iCurStream)]->
  280. DestroyElement(STREAM_NAME(iCurStream));
  281. ulTime = sw.Read();
  282. m_ulDestroyElementTotal[iIter] += ulTime;
  283. if (ulTime < m_ulDestroyElementMin[iIter])
  284. m_ulDestroyElementMin[iIter] = ulTime;
  285. if (ulTime > m_ulDestroyElementMax[iIter])
  286. m_ulDestroyElementMax[iIter] = ulTime;
  287. if (FAILED(hr))
  288. {
  289. Log(TEXT("DestroyElement"), hr);
  290. return hr;
  291. }
  292. }
  293. Log( TEXT("DestroyElement"), S_OK);
  294. m_ulDestroyElementAverage[iIter] = m_ulDestroyElementTotal[iIter] /
  295. (m_cStreams / m_cBranching);
  296. }
  297. // for each storage, do commit if in transacted mode
  298. // and release the storage.
  299. for (iCurStg = m_cStorages-1 ; iCurStg >= 0 ; iCurStg--)
  300. {
  301. // determine level of curent storage.
  302. iLevel = 0;
  303. iParent = STG_PARENT(iCurStg);
  304. while(iParent > 0)
  305. {
  306. iParent = STG_PARENT(iParent);
  307. iLevel++;
  308. }
  309. if (m_flCreateFlags == STGM_TRANSACTED)
  310. {
  311. sw.Reset();
  312. m_piStorages[iCurStg]->Commit(STGC_DEFAULT);
  313. ulTime = sw.Read();
  314. m_ulStorageCommitTotal[iIter] += ulTime;
  315. if (iCurStg != 0)
  316. {
  317. if (ulTime < m_ulStorageCommitMin[iLevel][iIter])
  318. m_ulStorageCommitMin[iLevel][iIter] = ulTime;
  319. if (ulTime > m_ulStorageCommitMax[iLevel][iIter])
  320. m_ulStorageCommitMax[iLevel][iIter] = ulTime;
  321. }
  322. else
  323. {
  324. m_ulFinalStorageCommit[iIter] = ulTime;
  325. }
  326. }
  327. sw.Reset();
  328. m_piStorages[iCurStg]->Release();
  329. ulTime = sw.Read();
  330. m_ulStorageReleaseTotal[iIter] += ulTime;
  331. if (iCurStg != 0)
  332. {
  333. if (ulTime < m_ulStorageReleaseMin[iLevel][iIter])
  334. m_ulStorageReleaseMin[iLevel][iIter] = ulTime;
  335. if (ulTime > m_ulStorageReleaseMax[iLevel][iIter])
  336. m_ulStorageReleaseMax[iLevel][iIter] = ulTime;
  337. }
  338. else
  339. {
  340. m_ulFinalStorageRelease[iIter] = ulTime;
  341. }
  342. }
  343. Log(TEXT("StorageCommit"), S_OK);
  344. Log(TEXT("StorageRelease"), S_OK);
  345. m_ulCreateStorageAverage[iIter] = m_ulCreateStorageTotal[iIter] / m_cStorages;
  346. m_ulCreateStreamAverage[iIter] = m_ulCreateStreamTotal[iIter] / m_cStreams;
  347. m_ulStreamWriteAverage[iIter] = m_ulStreamWriteTotal[iIter] / m_cStreams;
  348. m_ulStreamReleaseAverage[iIter] = m_ulStreamReleaseTotal[iIter] / m_cStreams;
  349. m_ulStorageCommitAverage[iIter] = m_ulStorageCommitTotal[iIter] / m_cStorages;
  350. m_ulStorageReleaseAverage[iIter] = m_ulStorageReleaseTotal[iIter] / m_cStorages;
  351. m_ulTotal[iIter] = m_ulStgCreateDocfile[iIter] +
  352. m_ulCreateStorageTotal[iIter] +
  353. m_ulCreateStreamTotal[iIter] +
  354. m_ulStreamWriteTotal[iIter] +
  355. m_ulStreamReleaseTotal[iIter] +
  356. m_ulDestroyElementTotal[iIter] +
  357. m_ulStorageCommitTotal[iIter] +
  358. m_ulStorageReleaseTotal[iIter];
  359. }
  360. return S_OK;
  361. }
  362. SCODE CNestedStorageTest::Report (CTestOutput &output)
  363. {
  364. TCHAR pszBuf[80];
  365. wsprintf(pszBuf, TEXT("Nested Storage Test in %s Mode writing %d bytes"),
  366. m_pszFileMode, m_cbSize);
  367. output.WriteSectionHeader (Name(), pszBuf, *m_pInput);
  368. output.WriteString (TEXT("\n"));
  369. for ( ULONG iLevel = 0; iLevel < m_cNesting - 1; iLevel++)
  370. {
  371. wsprintf(pszBuf, TEXT("\nLevel %d\n"), iLevel + 1);
  372. output.WriteString (pszBuf);
  373. output.WriteResults (TEXT("CreateStorage Min"), m_ulIterations,
  374. m_ulCreateStorageMin[iLevel]);
  375. output.WriteResults (TEXT("CreateStorage Max"), m_ulIterations,
  376. m_ulCreateStorageMax[iLevel]);
  377. if (m_flCreateFlags == STGM_TRANSACTED)
  378. {
  379. output.WriteResults (TEXT("StorageCommit Min"), m_ulIterations,
  380. m_ulStorageCommitMin[iLevel] );
  381. output.WriteResults (TEXT("StorageCommit Max"), m_ulIterations,
  382. m_ulStorageCommitMax[iLevel] );
  383. }
  384. output.WriteResults (TEXT("StorageRelease Min"), m_ulIterations,
  385. m_ulStorageReleaseMin[iLevel]);
  386. output.WriteResults (TEXT("StorageRelease Max"), m_ulIterations,
  387. m_ulStorageReleaseMax[iLevel]);
  388. }
  389. output.WriteString (TEXT("\nOverall\n"));
  390. output.WriteResults (TEXT("StgCreateDocfile "), m_ulIterations,
  391. m_ulStgCreateDocfile);
  392. if (m_flCreateFlags == STGM_TRANSACTED)
  393. output.WriteResults (TEXT("Final Storage Commit"), m_ulIterations,
  394. m_ulFinalStorageCommit);
  395. output.WriteResults (TEXT("Final Storage Release"), m_ulIterations,
  396. m_ulFinalStorageRelease);
  397. output.WriteString (TEXT("\n"));
  398. output.WriteResults (TEXT("CreateStorage Average"), m_ulIterations,
  399. m_ulCreateStorageAverage );
  400. output.WriteResults (TEXT("CreateStorage Total"), m_ulIterations,
  401. m_ulCreateStorageTotal );
  402. output.WriteString (TEXT("\n"));
  403. output.WriteResults (TEXT("CreateStream Min"), m_ulIterations,
  404. m_ulCreateStreamMin);
  405. output.WriteResults (TEXT("CreateStream Max"), m_ulIterations,
  406. m_ulCreateStreamMax);
  407. output.WriteResults (TEXT("CreateStream Average"), m_ulIterations,
  408. m_ulCreateStreamAverage);
  409. output.WriteResults (TEXT("CreateStream Total"), m_ulIterations,
  410. m_ulCreateStreamTotal );
  411. output.WriteString (TEXT("\n"));
  412. output.WriteResults (TEXT("StreamWrite Min"), m_ulIterations,
  413. m_ulStreamWriteMin );
  414. output.WriteResults (TEXT("StreamWrite Max"), m_ulIterations,
  415. m_ulStreamWriteMax );
  416. output.WriteResults (TEXT("StreamWrite Average"), m_ulIterations,
  417. m_ulStreamWriteAverage );
  418. output.WriteResults (TEXT("StreamWrite Total"), m_ulIterations,
  419. m_ulStreamWriteTotal );
  420. output.WriteString (TEXT("\n"));
  421. output.WriteResults (TEXT("StreamRelease Min"), m_ulIterations,
  422. m_ulStreamReleaseMin );
  423. output.WriteResults (TEXT("StreamRelease Max"), m_ulIterations,
  424. m_ulStreamReleaseMax );
  425. output.WriteResults (TEXT("StreamRelease Average"), m_ulIterations,
  426. m_ulStreamReleaseAverage );
  427. output.WriteResults (TEXT("StreamRelease Total"), m_ulIterations,
  428. m_ulStreamReleaseTotal );
  429. output.WriteString (TEXT("\n"));
  430. if(m_bDelete)
  431. {
  432. output.WriteResults (TEXT("DestroyElement Min"), m_ulIterations,
  433. m_ulDestroyElementMin );
  434. output.WriteResults (TEXT("DestroyElement Max"), m_ulIterations,
  435. m_ulDestroyElementMax );
  436. output.WriteResults (TEXT("DestroyElement Average"), m_ulIterations,
  437. m_ulDestroyElementAverage );
  438. output.WriteResults (TEXT("DestroyElement Total"), m_ulIterations,
  439. m_ulDestroyElementTotal );
  440. output.WriteString (TEXT("\n"));
  441. }
  442. if (m_flCreateFlags == STGM_TRANSACTED)
  443. {
  444. output.WriteResults (TEXT("StorageCommit Average"), m_ulIterations,
  445. m_ulStorageCommitAverage );
  446. output.WriteResults (TEXT("StorageCommit Total"), m_ulIterations,
  447. m_ulStorageCommitTotal );
  448. output.WriteString (TEXT("\n"));
  449. }
  450. output.WriteResults (TEXT("StorageRelease Average"), m_ulIterations,
  451. m_ulStorageReleaseAverage );
  452. output.WriteResults (TEXT("StorageRelease Total"), m_ulIterations,
  453. m_ulStorageReleaseTotal );
  454. output.WriteString (TEXT("\n"));
  455. output.WriteResults (TEXT("Overall Total "), m_ulIterations, m_ulTotal );
  456. return S_OK;
  457. }