From 56105916271ff9a7c0bfa237b45b9b3fab9c570b Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 9 Jun 2021 11:30:46 -0500 Subject: Fix building and perf for bundles with 1000s of package and BA payloads Fixes other half of #5300 --- src/burn/engine/apply.cpp | 2 +- src/burn/engine/burnextension.cpp | 11 +- src/burn/engine/burnextension.h | 1 - src/burn/engine/container.cpp | 3 +- src/burn/engine/container.h | 3 + src/burn/engine/manifest.h | 2 - src/burn/engine/payload.cpp | 80 +++++++------ src/burn/engine/payload.h | 3 +- src/burn/engine/userexperience.h | 2 +- src/libs/dutil/WixToolset.DUtil/dictutil.cpp | 128 ++++++++++----------- src/test/burn/TestData/Manual/BundleB/Bundle.wxs | 56 +++++++++ .../burn/TestData/Manual/BundleB/BundleB.wixproj | 32 ++++++ src/test/burn/TestData/Manual/BundleB/BundleB.wxs | 15 +++ src/test/burn/TestData/Manual/BundleB/ba.xslt | 21 ++++ src/test/burn/TestData/Manual/BundleB/package.xslt | 21 ++++ src/test/burn/TestExe/Task.cs | 22 ++++ .../WixToolset.Core.Burn/Bind/BindBundleCommand.cs | 7 +- .../Bundles/CreateBurnManifestCommand.cs | 5 +- src/wix/WixToolset.Core/Compile/CompilerPayload.cs | 4 +- src/wix/WixToolset.Core/Compiler_Bundle.cs | 70 ++++------- .../WixToolset.Core/Link/WixGroupingOrdering.cs | 3 +- .../BundleManifestFixture.cs | 10 +- 22 files changed, 315 insertions(+), 186 deletions(-) create mode 100644 src/test/burn/TestData/Manual/BundleB/Bundle.wxs create mode 100644 src/test/burn/TestData/Manual/BundleB/BundleB.wixproj create mode 100644 src/test/burn/TestData/Manual/BundleB/BundleB.wxs create mode 100644 src/test/burn/TestData/Manual/BundleB/ba.xslt create mode 100644 src/test/burn/TestData/Manual/BundleB/package.xslt (limited to 'src') diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp index a99a3987..c126d63c 100644 --- a/src/burn/engine/apply.cpp +++ b/src/burn/engine/apply.cpp @@ -1175,7 +1175,7 @@ static HRESULT ExtractContainer( { BOOL fExtracted = FALSE; - hr = PayloadFindEmbeddedBySourcePath(pContext->pPayloads, sczStreamName, &pExtract); + hr = PayloadFindEmbeddedBySourcePath(pContainer->sdhPayloads, sczStreamName, &pExtract); if (E_NOTFOUND != hr) { ExitOnFailure(hr, "Failed to find embedded payload by source path: %ls container: %ls", sczStreamName, pContainer->sczId); diff --git a/src/burn/engine/burnextension.cpp b/src/burn/engine/burnextension.cpp index 475df1c5..ee4b1542 100644 --- a/src/burn/engine/burnextension.cpp +++ b/src/burn/engine/burnextension.cpp @@ -26,6 +26,7 @@ EXTERN_C HRESULT BurnExtensionParseFromXml( IXMLDOMNodeList* pixnNodes = NULL; IXMLDOMNode* pixnNode = NULL; DWORD cNodes = 0; + LPWSTR scz = NULL; // Select BundleExtension nodes. hr = XmlSelectNodes(pixnBundle, L"BundleExtension", &pixnNodes); @@ -59,11 +60,11 @@ EXTERN_C HRESULT BurnExtensionParseFromXml( ExitOnFailure(hr, "Failed to get @Id."); // @EntryPayloadId - hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadId", &pExtension->sczEntryPayloadId); - ExitOnFailure(hr, "Failed to get @EntryPayloadId."); + hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadSourcePath", &scz); + ExitOnFailure(hr, "Failed to get @EntryPayloadSourcePath."); - hr = PayloadFindById(pBaPayloads, pExtension->sczEntryPayloadId, &pExtension->pEntryPayload); - ExitOnFailure(hr, "Failed to find BundleExtension EntryPayload '%ls'.", pExtension->sczEntryPayloadId); + hr = PayloadFindEmbeddedBySourcePath(pBaPayloads->sdhPayloads, scz, &pExtension->pEntryPayload); + ExitOnFailure(hr, "Failed to find BundleExtension EntryPayload '%ls'.", pExtension->sczId); // prepare next iteration ReleaseNullObject(pixnNode); @@ -72,6 +73,7 @@ EXTERN_C HRESULT BurnExtensionParseFromXml( hr = S_OK; LExit: + ReleaseStr(scz); ReleaseObject(pixnNode); ReleaseObject(pixnNodes); @@ -92,7 +94,6 @@ EXTERN_C void BurnExtensionUninitialize( { BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; - ReleaseStr(pExtension->sczEntryPayloadId); ReleaseStr(pExtension->sczId); } MemFree(pBurnExtensions->rgExtensions); diff --git a/src/burn/engine/burnextension.h b/src/burn/engine/burnextension.h index 370ddd2d..3529ef38 100644 --- a/src/burn/engine/burnextension.h +++ b/src/burn/engine/burnextension.h @@ -13,7 +13,6 @@ typedef struct _BURN_EXTENSION_ENGINE_CONTEXT BURN_EXTENSION_ENGINE_CONTEXT; typedef struct _BURN_EXTENSION { - LPWSTR sczEntryPayloadId; LPWSTR sczId; BURN_PAYLOAD* pEntryPayload; diff --git a/src/burn/engine/container.cpp b/src/burn/engine/container.cpp index c6f2ada8..aa123927 100644 --- a/src/burn/engine/container.cpp +++ b/src/burn/engine/container.cpp @@ -35,7 +35,7 @@ extern "C" HRESULT ContainersParseFromXml( pContainers->cContainers = cNodes; - // parse search elements + // parse container elements for (DWORD i = 0; i < cNodes; ++i) { BURN_CONTAINER* pContainer = &pContainers->rgContainers[i]; @@ -181,6 +181,7 @@ extern "C" void ContainersUninitialize( ReleaseStr(pContainer->downloadSource.sczUser); ReleaseStr(pContainer->downloadSource.sczPassword); ReleaseStr(pContainer->sczUnverifiedPath); + ReleaseDict(pContainer->sdhPayloads); } MemFree(pContainers->rgContainers); } diff --git a/src/burn/engine/container.h b/src/burn/engine/container.h index d454a248..f35f1da5 100644 --- a/src/burn/engine/container.h +++ b/src/burn/engine/container.h @@ -72,6 +72,9 @@ typedef struct _BURN_CONTAINER LPWSTR sczFilePath; // relative path to container. DOWNLOAD_SOURCE downloadSource; + DWORD cParsedPayloads; + STRINGDICT_HANDLE sdhPayloads; // value is BURN_PAYLOAD* + BYTE* pbHash; DWORD cbHash; BURN_CONTAINER_VERIFICATION verification; diff --git a/src/burn/engine/manifest.h b/src/burn/engine/manifest.h index 8c527279..40748c52 100644 --- a/src/burn/engine/manifest.h +++ b/src/burn/engine/manifest.h @@ -2,8 +2,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -interface IBurnPayload; // forward declare. - #if defined(__cplusplus) extern "C" { #endif diff --git a/src/burn/engine/payload.cpp b/src/burn/engine/payload.cpp index 84c32eec..e0362a76 100644 --- a/src/burn/engine/payload.cpp +++ b/src/burn/engine/payload.cpp @@ -5,13 +5,6 @@ // internal function declarations -static HRESULT FindEmbeddedBySourcePath( - __in BURN_PAYLOADS* pPayloads, - __in_opt BURN_CONTAINER* pContainer, - __in_z LPCWSTR wzStreamName, - __out BURN_PAYLOAD** ppPayload - ); - // function definitions @@ -29,6 +22,7 @@ extern "C" HRESULT PayloadsParseFromXml( LPWSTR scz = NULL; BOOL fChainPayload = pContainers && pLayoutPayloads; // These are required when parsing chain payloads. BOOL fValidFileSize = FALSE; + size_t cByteOffset = fChainPayload ? offsetof(BURN_PAYLOAD, sczKey) : offsetof(BURN_PAYLOAD, sczSourcePath); // select payload nodes hr = XmlSelectNodes(pixnBundle, L"Payload", &pixnNodes); @@ -49,7 +43,11 @@ extern "C" HRESULT PayloadsParseFromXml( pPayloads->cPayloads = cNodes; - // parse search elements + // create dictionary for payloads + hr = DictCreateWithEmbeddedKey(&pPayloads->sdhPayloads, pPayloads->cPayloads, reinterpret_cast(&pPayloads->rgPayloads), cByteOffset, DICT_FLAG_NONE); + ExitOnFailure(hr, "Failed to create dictionary for payloads."); + + // parse payload elements for (DWORD i = 0; i < cNodes; ++i) { BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i]; @@ -104,6 +102,8 @@ extern "C" HRESULT PayloadsParseFromXml( // find container hr = ContainerFindById(pContainers, scz, &pPayload->pContainer); ExitOnFailure(hr, "Failed to to find container: %ls", scz); + + pPayload->pContainer->cParsedPayloads += 1; } // @LayoutOnly @@ -190,12 +190,37 @@ extern "C" HRESULT PayloadsParseFromXml( } } + hr = DictAddValue(pPayloads->sdhPayloads, pPayload); + ExitOnFailure(hr, "Failed to add payload to payloads dictionary."); + // prepare next iteration ReleaseNullObject(pixnNode); } hr = S_OK; + if (pContainers && pContainers->cContainers) + { + for (DWORD i = 0; i < pPayloads->cPayloads; ++i) + { + BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i]; + BURN_CONTAINER* pContainer = pPayload->pContainer; + + if (!pContainer) + { + continue; + } + else if (!pContainer->sdhPayloads) + { + hr = DictCreateWithEmbeddedKey(&pContainer->sdhPayloads, pContainer->cParsedPayloads, NULL, offsetof(BURN_PAYLOAD, sczSourcePath), DICT_FLAG_NONE); + ExitOnFailure(hr, "Failed to create dictionary for container payloads."); + } + + hr = DictAddValue(pContainer->sdhPayloads, pPayload); + ExitOnFailure(hr, "Failed to add payload to container dictionary."); + } + } + LExit: ReleaseObject(pixnNodes); ReleaseObject(pixnNode); @@ -237,6 +262,8 @@ extern "C" void PayloadsUninitialize( MemFree(pPayloads->rgPayloads); } + ReleaseDict(pPayloads->sdhPayloads); + // clear struct memset(pPayloads, 0, sizeof(BURN_PAYLOADS)); } @@ -265,7 +292,7 @@ extern "C" HRESULT PayloadExtractUXContainer( ExitOnFailure(hr, "Failed to get next stream."); // find payload by stream name - hr = PayloadFindEmbeddedBySourcePath(pPayloads, sczStreamName, &pPayload); + hr = PayloadFindEmbeddedBySourcePath(pPayloads->sdhPayloads, sczStreamName, &pPayload); ExitOnFailure(hr, "Failed to find embedded payload: %ls", sczStreamName); // make file path @@ -313,51 +340,22 @@ extern "C" HRESULT PayloadFindById( ) { HRESULT hr = S_OK; - BURN_PAYLOAD* pPayload = NULL; - for (DWORD i = 0; i < pPayloads->cPayloads; ++i) - { - pPayload = &pPayloads->rgPayloads[i]; - - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczKey, -1, wzId, -1)) - { - *ppPayload = pPayload; - ExitFunction1(hr = S_OK); - } - } + hr = DictGetValue(pPayloads->sdhPayloads, wzId, reinterpret_cast(ppPayload)); - hr = E_NOTFOUND; - -LExit: return hr; } extern "C" HRESULT PayloadFindEmbeddedBySourcePath( - __in BURN_PAYLOADS* pPayloads, + __in STRINGDICT_HANDLE sdhPayloads, __in_z LPCWSTR wzStreamName, __out BURN_PAYLOAD** ppPayload ) { HRESULT hr = S_OK; - BURN_PAYLOAD* pPayload = NULL; - for (DWORD i = 0; i < pPayloads->cPayloads; ++i) - { - pPayload = &pPayloads->rgPayloads[i]; - - if (BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging) - { - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczSourcePath, -1, wzStreamName, -1)) - { - *ppPayload = pPayload; - ExitFunction1(hr = S_OK); - } - } - } + hr = DictGetValue(sdhPayloads, wzStreamName, reinterpret_cast(ppPayload)); - hr = E_NOTFOUND; - -LExit: return hr; } diff --git a/src/burn/engine/payload.h b/src/burn/engine/payload.h index c12fbe66..14738506 100644 --- a/src/burn/engine/payload.h +++ b/src/burn/engine/payload.h @@ -66,6 +66,7 @@ typedef struct _BURN_PAYLOADS { BURN_PAYLOAD* rgPayloads; DWORD cPayloads; + STRINGDICT_HANDLE sdhPayloads; // value is BURN_PAYLOAD* } BURN_PAYLOADS; typedef struct _BURN_PAYLOAD_GROUP_ITEM @@ -109,7 +110,7 @@ HRESULT PayloadFindById( __out BURN_PAYLOAD** ppPayload ); HRESULT PayloadFindEmbeddedBySourcePath( - __in BURN_PAYLOADS* pPayloads, + __in STRINGDICT_HANDLE sdhPayloads, __in_z LPCWSTR wzStreamName, __out BURN_PAYLOAD** ppPayload ); diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index 6a5ae697..584bef14 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h @@ -15,7 +15,7 @@ const DWORD MB_RETRYTRYAGAIN = 0xF; // structs -typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT; +typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT; // forward declare typedef struct _BURN_USER_EXPERIENCE { diff --git a/src/libs/dutil/WixToolset.DUtil/dictutil.cpp b/src/libs/dutil/WixToolset.DUtil/dictutil.cpp index 0d0743eb..09b150df 100644 --- a/src/libs/dutil/WixToolset.DUtil/dictutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/dictutil.cpp @@ -72,6 +72,14 @@ struct STRINGDICT_STRUCT const int STRINGDICT_HANDLE_BYTES = sizeof(STRINGDICT_STRUCT); +static HRESULT CreateDict( + __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle, + __in DICT_TYPE dtType, + __in DWORD dwNumExpectedItems, + __in_opt void** ppvArray, + __in size_t cByteOffset, + __in DICT_FLAG dfFlags + ); static HRESULT StringHash( __in const STRINGDICT_STRUCT *psd, __in DWORD dwNumBuckets, @@ -135,41 +143,7 @@ extern "C" HRESULT DAPI DictCreateWithEmbeddedKey( __in DICT_FLAG dfFlags ) { - HRESULT hr = S_OK; - - DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict"); - - // Allocate the handle - *psdHandle = static_cast(MemAlloc(sizeof(STRINGDICT_STRUCT), FALSE)); - DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object"); - - STRINGDICT_STRUCT *psd = static_cast(*psdHandle); - - // Fill out the new handle's values - psd->dtType = DICT_EMBEDDED_KEY; - psd->dfFlags = dfFlags; - psd->cByteOffset = cByteOffset; - psd->dwBucketSizeIndex = 0; - psd->dwNumItems = 0; - psd->ppvItemList = NULL; - psd->ppvValueArray = ppvArray; - - // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime - // array based on expected number of items and items to buckets ratio - // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end - // this loop past the end of the array! - while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES)-1) && - MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO) - { - ++psd->dwBucketSizeIndex; - } - - // Finally, allocate our initial buckets - psd->ppvBuckets = static_cast(MemAlloc(sizeof(void *) * MAX_BUCKET_SIZES[psd->dwBucketSizeIndex], TRUE)); - DictExitOnNull(psd->ppvBuckets, hr, E_OUTOFMEMORY, "Failed to allocate buckets for dictionary"); - -LExit: - return hr; + return CreateDict(psdHandle, DICT_EMBEDDED_KEY, dwNumExpectedItems, ppvArray, cByteOffset, dfFlags); } // The dict will store a set of keys, with no values associated with them. Use DictAddKey() and DictKeyExists() with this dictionary type. @@ -179,41 +153,7 @@ extern "C" HRESULT DAPI DictCreateStringList( __in DICT_FLAG dfFlags ) { - HRESULT hr = S_OK; - - DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict"); - - // Allocate the handle - *psdHandle = static_cast(MemAlloc(sizeof(STRINGDICT_STRUCT), FALSE)); - DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object"); - - STRINGDICT_STRUCT *psd = static_cast(*psdHandle); - - // Fill out the new handle's values - psd->dtType = DICT_STRING_LIST; - psd->dfFlags = dfFlags; - psd->cByteOffset = 0; - psd->dwBucketSizeIndex = 0; - psd->dwNumItems = 0; - psd->ppvItemList = NULL; - psd->ppvValueArray = NULL; - - // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime - // array based on expected number of items and items to buckets ratio - // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end - // this loop past the end of the array! - while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES)-1) && - MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO) - { - ++psd->dwBucketSizeIndex; - } - - // Finally, allocate our initial buckets - psd->ppvBuckets = static_cast(MemAlloc(sizeof(void *) * MAX_BUCKET_SIZES[psd->dwBucketSizeIndex], TRUE)); - DictExitOnNull(psd->ppvBuckets, hr, E_OUTOFMEMORY, "Failed to allocate buckets for dictionary"); - -LExit: - return hr; + return CreateDict(psdHandle, DICT_STRING_LIST, dwNumExpectedItems, NULL, 0, dfFlags); } extern "C" HRESULT DAPI DictCreateStringListFromArray( @@ -467,6 +407,54 @@ extern "C" void DAPI DictDestroy( ReleaseMem(psd); } +static HRESULT CreateDict( + __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle, + __in DICT_TYPE dtType, + __in DWORD dwNumExpectedItems, + __in_opt void** ppvArray, + __in size_t cByteOffset, + __in DICT_FLAG dfFlags + ) +{ + HRESULT hr = S_OK; + + DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict."); + + // Allocate the handle + *psdHandle = static_cast(MemAlloc(sizeof(STRINGDICT_STRUCT), TRUE)); + DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object."); + + STRINGDICT_STRUCT* psd = static_cast(*psdHandle); + + // Fill out the new handle's values + psd->dtType = dtType; + psd->dfFlags = dfFlags; + psd->cByteOffset = cByteOffset; + psd->ppvValueArray = ppvArray; + + // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime + // array based on expected number of items and items to buckets ratio + // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end + // this loop past the end of the array! + while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES) - 1) && + MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO) + { + ++psd->dwBucketSizeIndex; + } + + hr = MemAllocArray(reinterpret_cast(&psd->ppvBuckets), sizeof(void*), MAX_BUCKET_SIZES[psd->dwBucketSizeIndex]); + DictExitOnFailure(hr, "Failed to allocate buckets for dictionary."); + + if (dwNumExpectedItems) + { + hr = MemAllocArray(reinterpret_cast(&psd->ppvItemList), sizeof(void*), dwNumExpectedItems); + DictExitOnFailure(hr, "Failed to pre-allocate item list for dictionary."); + } + +LExit: + return hr; +} + static HRESULT StringHash( __in const STRINGDICT_STRUCT *psd, __in DWORD dwNumBuckets, diff --git a/src/test/burn/TestData/Manual/BundleB/Bundle.wxs b/src/test/burn/TestData/Manual/BundleB/Bundle.wxs new file mode 100644 index 00000000..615d4b1d --- /dev/null +++ b/src/test/burn/TestData/Manual/BundleB/Bundle.wxs @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/burn/TestData/Manual/BundleB/BundleB.wixproj b/src/test/burn/TestData/Manual/BundleB/BundleB.wixproj new file mode 100644 index 00000000..35c92246 --- /dev/null +++ b/src/test/burn/TestData/Manual/BundleB/BundleB.wixproj @@ -0,0 +1,32 @@ + + + + Bundle + hyperlinkLicense + {5DE2F206-3C37-4265-81F7-095284E16B08} + -generate payloadgroup + + + + BAPayloads + BAPayloads + ba.xslt + + + PackagePayloads + PackagePayloads + package.xslt + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/burn/TestData/Manual/BundleB/BundleB.wxs b/src/test/burn/TestData/Manual/BundleB/BundleB.wxs new file mode 100644 index 00000000..3b189b15 --- /dev/null +++ b/src/test/burn/TestData/Manual/BundleB/BundleB.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/test/burn/TestData/Manual/BundleB/ba.xslt b/src/test/burn/TestData/Manual/BundleB/ba.xslt new file mode 100644 index 00000000..54bc7fe6 --- /dev/null +++ b/src/test/burn/TestData/Manual/BundleB/ba.xslt @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + ba_ + BAPayloads + + + diff --git a/src/test/burn/TestData/Manual/BundleB/package.xslt b/src/test/burn/TestData/Manual/BundleB/package.xslt new file mode 100644 index 00000000..304ff78b --- /dev/null +++ b/src/test/burn/TestData/Manual/BundleB/package.xslt @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + package_ + PackagePayloads + + + diff --git a/src/test/burn/TestExe/Task.cs b/src/test/burn/TestExe/Task.cs index 7d39bfd9..59f774fb 100644 --- a/src/test/burn/TestExe/Task.cs +++ b/src/test/burn/TestExe/Task.cs @@ -59,6 +59,24 @@ namespace TestExe } } + public class GenerateFilesTask : Task + { + public GenerateFilesTask(string Data) : base(Data) { } + + public override void RunTask() + { + string[] tokens = this.data.Split(new char[] { '|' }, 2); + string folderPath = System.Environment.ExpandEnvironmentVariables(tokens[0]); + long size = long.Parse(tokens[1]); + Directory.CreateDirectory(folderPath); + var bytes = new byte[0]; + for (long i = 1; i <= size; i++) + { + File.WriteAllBytes(Path.Combine(folderPath, $"{i}.txt"), bytes); + } + } + } + public class LargeFileTask : Task { public LargeFileTask(string Data) : base(Data) { } @@ -163,6 +181,10 @@ namespace TestExe t = new SleepRandomTask(args[i + 1]); tasks.Add(t); break; + case "/gf": + t = new GenerateFilesTask(args[i + 1]); + tasks.Add(t); + break; case "/lf": t = new LargeFileTask(args[i + 1]); tasks.Add(t); diff --git a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs index 4a4f06f3..97007022 100644 --- a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs @@ -239,15 +239,18 @@ namespace WixToolset.Core.Burn { foreach (var facade in facades.Values) { - facade.PackageSymbol.Size = 0; + // Use temporary variable to avoid excessive number of PreviousValues. + long packageSize = 0; var packagePayloads = packagesPayloads[facade.PackageId]; foreach (var payload in packagePayloads.Values) { - facade.PackageSymbol.Size += payload.FileSize.Value; + packageSize += payload.FileSize.Value; } + facade.PackageSymbol.Size = packageSize; + if (!facade.PackageSymbol.InstallSize.HasValue) { facade.PackageSymbol.InstallSize = facade.PackageSymbol.Size; diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs index 429b3565..5a7241ab 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs @@ -604,12 +604,15 @@ namespace WixToolset.Core.Burn.Bundles // Write the BundleExtension elements. var bundleExtensions = this.Section.Symbols.OfType(); + var uxPayloadsById = this.UXContainerPayloads.ToDictionary(p => p.Id.Id); foreach (var bundleExtension in bundleExtensions) { + var entryPayload = uxPayloadsById[bundleExtension.PayloadRef]; + writer.WriteStartElement("BundleExtension"); writer.WriteAttributeString("Id", bundleExtension.Id.Id); - writer.WriteAttributeString("EntryPayloadId", bundleExtension.PayloadRef); + writer.WriteAttributeString("EntryPayloadSourcePath", entryPayload.EmbeddedId); writer.WriteEndElement(); } diff --git a/src/wix/WixToolset.Core/Compile/CompilerPayload.cs b/src/wix/WixToolset.Core/Compile/CompilerPayload.cs index 3f423034..ea63ee8c 100644 --- a/src/wix/WixToolset.Core/Compile/CompilerPayload.cs +++ b/src/wix/WixToolset.Core/Compile/CompilerPayload.cs @@ -143,7 +143,7 @@ namespace WixToolset.Core } } - public WixBundlePayloadSymbol CreatePayloadSymbol(ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType = ComplexReferenceChildType.Unknown, string previousId = null) + public WixBundlePayloadSymbol CreatePayloadSymbol(ComplexReferenceParentType parentType, string parentId) { WixBundlePayloadSymbol symbol = null; @@ -179,7 +179,7 @@ namespace WixToolset.Core Version = this.Version, }); - this.Core.CreateGroupAndOrderingRows(this.SourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, symbol.Id.Id, previousType, previousId); + this.Core.CreateGroupAndOrderingRows(this.SourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, symbol.Id.Id, ComplexReferenceChildType.Unknown, null); } return symbol; diff --git a/src/wix/WixToolset.Core/Compiler_Bundle.cs b/src/wix/WixToolset.Core/Compiler_Bundle.cs index 3e238b82..a72d434d 100644 --- a/src/wix/WixToolset.Core/Compiler_Bundle.cs +++ b/src/wix/WixToolset.Core/Compiler_Bundle.cs @@ -351,7 +351,7 @@ namespace WixToolset.Core this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads); break; case "PayloadGroupRef": - this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads, ComplexReferenceChildType.Unknown, null); + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads); break; case "RelatedBundle": this.ParseRelatedBundleElement(child); @@ -649,8 +649,6 @@ namespace WixToolset.Core { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); Identifier id = null; - Identifier previousId = null; - var previousType = ComplexReferenceChildType.Unknown; foreach (var attrib in node.Attributes()) { @@ -675,16 +673,13 @@ namespace WixToolset.Core switch (child.Name.LocalName) { case "BootstrapperApplicationDll": - previousId = this.ParseBootstrapperApplicationDllElement(child, id, previousType, previousId); - previousType = ComplexReferenceChildType.Payload; + this.ParseBootstrapperApplicationDllElement(child, id); break; case "Payload": - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId); - previousType = ComplexReferenceChildType.Payload; + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); break; case "PayloadGroupRef": - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId); - previousType = ComplexReferenceChildType.PayloadGroup; + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); break; default: this.Core.UnexpectedElement(node, child); @@ -708,9 +703,7 @@ namespace WixToolset.Core /// /// Element to parse /// - /// - /// - private Identifier ParseBootstrapperApplicationDllElement(XElement node, Identifier defaultId, ComplexReferenceChildType previousType, Identifier previousId) + private Identifier ParseBootstrapperApplicationDllElement(XElement node, Identifier defaultId) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node) @@ -805,7 +798,7 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id, previousType, previousId?.Id); + compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id); this.Core.AddSymbol(new WixBundleContainerSymbol(sourceLineNumbers, Compiler.BurnUXContainerId) { Name = "bundle-ux.cab", @@ -829,8 +822,6 @@ namespace WixToolset.Core { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string id = null; - Identifier previousId = null; - var previousType = ComplexReferenceChildType.Unknown; foreach (var attrib in node.Attributes()) { @@ -859,12 +850,10 @@ namespace WixToolset.Core switch (child.Name.LocalName) { case "Payload": - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId); - previousType = ComplexReferenceChildType.Payload; + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); break; case "PayloadGroupRef": - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId); - previousType = ComplexReferenceChildType.PayloadGroup; + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); break; default: this.Core.UnexpectedElement(node, child); @@ -1195,8 +1184,6 @@ namespace WixToolset.Core { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node); - Identifier previousId = null; - var previousType = ComplexReferenceChildType.Unknown; // This list lets us evaluate extension attributes *after* all core attributes // have been parsed and dealt with, regardless of authoring order. @@ -1241,9 +1228,7 @@ namespace WixToolset.Core this.Core.ParseExtensionAttribute(node, extensionAttribute, context); } - compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id, previousType, previousId?.Id); - previousId = compilerPayload.Id; - previousType = ComplexReferenceChildType.Payload; + compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id); foreach (var child in node.Elements()) { @@ -1252,12 +1237,10 @@ namespace WixToolset.Core switch (child.Name.LocalName) { case "Payload": - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId); - previousType = ComplexReferenceChildType.Payload; + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); break; case "PayloadGroupRef": - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId); - previousType = ComplexReferenceChildType.PayloadGroup; + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); break; default: this.Core.UnexpectedElement(node, child); @@ -1388,12 +1371,9 @@ namespace WixToolset.Core /// Element to parse /// ComplexReferenceParentType of parent element. (BA or PayloadGroup) /// Identifier of parent element. - /// - /// - private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId) + private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId) { Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); - Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType); var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node); @@ -1470,7 +1450,7 @@ namespace WixToolset.Core } } - compilerPayload.CreatePayloadSymbol(parentType, parentId?.Id, previousType, previousId?.Id); + compilerPayload.CreatePayloadSymbol(parentType, parentId?.Id); return compilerPayload.Id; } @@ -1514,8 +1494,6 @@ namespace WixToolset.Core id = Identifier.Invalid; } - var previousType = ComplexReferenceChildType.Unknown; - Identifier previousId = null; foreach (var child in node.Elements()) { if (CompilerCore.WixNamespace == child.Name.Namespace) @@ -1536,12 +1514,10 @@ namespace WixToolset.Core packageType = WixBundlePackageType.Msu; break; case "Payload": - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId); - previousType = ComplexReferenceChildType.Payload; + this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id); break; case "PayloadGroupRef": - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId); - previousType = ComplexReferenceChildType.PayloadGroup; + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id); break; default: this.Core.UnexpectedElement(node, child); @@ -1551,12 +1527,9 @@ namespace WixToolset.Core if (packageType.HasValue) { var compilerPayload = this.ParsePackagePayloadElement(null, child, packageType.Value, null); - var payloadSymbol = compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.PayloadGroup, id?.Id, previousType, previousId?.Id); + var payloadSymbol = compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.PayloadGroup, id?.Id); if (payloadSymbol != null) { - previousId = payloadSymbol.Id; - previousType = ComplexReferenceChildType.Payload; - this.CreatePackagePayloadSymbol(payloadSymbol.SourceLineNumbers, packageType.Value, payloadSymbol.Id, ComplexReferenceParentType.PayloadGroup, id); } } @@ -1582,12 +1555,9 @@ namespace WixToolset.Core /// Element to parse. /// ComplexReferenceParentType of parent element (BA or PayloadGroup). /// Identifier of parent element. - /// - /// - private Identifier ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId) + private Identifier ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId) { Debug.Assert(ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); - Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType); var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); Identifier id = null; @@ -1620,7 +1590,7 @@ namespace WixToolset.Core this.Core.ParseForExtensionElements(node); - this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id?.Id, previousType, previousId?.Id); + this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id?.Id, ComplexReferenceChildType.Unknown, null); return id; } @@ -2259,10 +2229,10 @@ namespace WixToolset.Core } break; case "Payload": - this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null); + this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id); break; case "PayloadGroupRef": - this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null); + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id); break; case "Provides": this.ParseProvidesElement(child, packageType, id.Id, out _); diff --git a/src/wix/WixToolset.Core/Link/WixGroupingOrdering.cs b/src/wix/WixToolset.Core/Link/WixGroupingOrdering.cs index f9de82a9..152f897b 100644 --- a/src/wix/WixToolset.Core/Link/WixGroupingOrdering.cs +++ b/src/wix/WixToolset.Core/Link/WixGroupingOrdering.cs @@ -645,13 +645,14 @@ namespace WixToolset.Core.Link this.AddAfter(nestedAfterItems, messageHandler); } - // We *don't* propagate ordering information from Packages or + // We *don't* propagate ordering information from Packages, PayloadGroups, or // Containers to their children, because ordering doesn't matter // for them, and a Payload in two Packages (or Containers) can // cause a circular reference to occur. private bool ShouldItemPropagateChildOrdering() { if (String.Equals(nameof(ComplexReferenceParentType.Package), this.Type, StringComparison.Ordinal) || + String.Equals(nameof(ComplexReferenceParentType.PayloadGroup), this.Type, StringComparison.Ordinal) || String.Equals(nameof(ComplexReferenceParentType.Container), this.Type, StringComparison.Ordinal)) { return false; diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs index 19d0a2fc..534086b6 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs @@ -211,15 +211,11 @@ namespace WixToolsetTest.CoreIntegration var bundleExtensions = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:BundleExtension"); Assert.Equal(1, bundleExtensions.Count); - Assert.Equal("", bundleExtensions[0].GetTestXml()); + Assert.Equal("", bundleExtensions[0].GetTestXml()); var bundleExtensionPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:UX/burn:Payload[@Id='ExampleBext']"); Assert.Equal(1, bundleExtensionPayloads.Count); - var ignored = new Dictionary> - { - { "Payload", new List { "FileSize", "Hash", "SourcePath" } }, - }; - Assert.Equal("", bundleExtensionPayloads[0].GetTestXml(ignored)); + Assert.Equal("", bundleExtensionPayloads[0].GetTestXml()); } } @@ -259,7 +255,7 @@ namespace WixToolsetTest.CoreIntegration var bundleExtensions = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:BundleExtension"); Assert.Equal(1, bundleExtensions.Count); - Assert.Equal("", bundleExtensions[0].GetTestXml()); + Assert.Equal("", bundleExtensions[0].GetTestXml()); var extensionSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:ExtensionSearch"); Assert.Equal(2, extensionSearches.Count); -- cgit v1.2.3-55-g6feb