diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-04-16 09:40:18 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-04-19 23:12:55 -0500 |
commit | 941c47e5a3f57ce9626b447a95740b1444e69343 (patch) | |
tree | 6225b78f5fc7c8f88a2abf187a6a76d45b36ec26 /src/engine/core.cpp | |
parent | d32f770ca05748df9e356444c7e617d5eeedb60c (diff) | |
download | wix-941c47e5a3f57ce9626b447a95740b1444e69343.tar.gz wix-941c47e5a3f57ce9626b447a95740b1444e69343.tar.bz2 wix-941c47e5a3f57ce9626b447a95740b1444e69343.zip |
Detect a package as cached if any of its payloads exist.
Detect is supposed to be fast, so it can't fully verify every payload for every package. The engine was wasting its time by trying to verify file sizes without the hash. Even worse, it was making decisions during planning based on that insufficient verification.
Contributes to #3640
Diffstat (limited to 'src/engine/core.cpp')
-rw-r--r-- | src/engine/core.cpp | 44 |
1 files changed, 15 insertions, 29 deletions
diff --git a/src/engine/core.cpp b/src/engine/core.cpp index 50ed6ea0..7341e4b8 100644 --- a/src/engine/core.cpp +++ b/src/engine/core.cpp | |||
@@ -388,7 +388,7 @@ extern "C" HRESULT CoreDetect( | |||
388 | pEngineState->registration.fEligibleForCleanup = FALSE; | 388 | pEngineState->registration.fEligibleForCleanup = FALSE; |
389 | } | 389 | } |
390 | 390 | ||
391 | LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingCacheStateToString(pPackage->cache), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState)); | 391 | LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingBoolToString(pPackage->fCached), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState)); |
392 | 392 | ||
393 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type) | 393 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type) |
394 | { | 394 | { |
@@ -439,7 +439,6 @@ extern "C" HRESULT CorePlan( | |||
439 | HRESULT hr = S_OK; | 439 | HRESULT hr = S_OK; |
440 | BOOL fPlanBegan = FALSE; | 440 | BOOL fPlanBegan = FALSE; |
441 | LPWSTR sczLayoutDirectory = NULL; | 441 | LPWSTR sczLayoutDirectory = NULL; |
442 | HANDLE hSyncpointEvent = NULL; | ||
443 | BURN_PACKAGE* pUpgradeBundlePackage = NULL; | 442 | BURN_PACKAGE* pUpgradeBundlePackage = NULL; |
444 | BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL; | 443 | BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL; |
445 | BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies. | 444 | BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies. |
@@ -489,7 +488,7 @@ extern "C" HRESULT CorePlan( | |||
489 | ExitOnFailure(hr, "Failed to plan the layout of the bundle."); | 488 | ExitOnFailure(hr, "Failed to plan the layout of the bundle."); |
490 | 489 | ||
491 | // Plan the packages' layout. | 490 | // Plan the packages' layout. |
492 | hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory, &hSyncpointEvent); | 491 | hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory); |
493 | ExitOnFailure(hr, "Failed to plan packages."); | 492 | ExitOnFailure(hr, "Failed to plan packages."); |
494 | } | 493 | } |
495 | else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action) | 494 | else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action) |
@@ -498,7 +497,7 @@ extern "C" HRESULT CorePlan( | |||
498 | 497 | ||
499 | pUpgradeBundlePackage = &pEngineState->update.package; | 498 | pUpgradeBundlePackage = &pEngineState->update.package; |
500 | 499 | ||
501 | hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, &hSyncpointEvent); | 500 | hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType); |
502 | ExitOnFailure(hr, "Failed to plan update."); | 501 | ExitOnFailure(hr, "Failed to plan update."); |
503 | } | 502 | } |
504 | else | 503 | else |
@@ -512,7 +511,7 @@ extern "C" HRESULT CorePlan( | |||
512 | 511 | ||
513 | pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle; | 512 | pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle; |
514 | 513 | ||
515 | hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, &hSyncpointEvent); | 514 | hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType); |
516 | ExitOnFailure(hr, "Failed to plan passthrough."); | 515 | ExitOnFailure(hr, "Failed to plan passthrough."); |
517 | } | 516 | } |
518 | else // doing an action that modifies the machine state. | 517 | else // doing an action that modifies the machine state. |
@@ -533,11 +532,11 @@ extern "C" HRESULT CorePlan( | |||
533 | hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); | 532 | hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); |
534 | ExitOnFailure(hr, "Failed to plan related bundles."); | 533 | ExitOnFailure(hr, "Failed to plan related bundles."); |
535 | 534 | ||
536 | hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL, &hSyncpointEvent); | 535 | hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL); |
537 | ExitOnFailure(hr, "Failed to plan packages."); | 536 | ExitOnFailure(hr, "Failed to plan packages."); |
538 | 537 | ||
539 | // Schedule the update of related bundles last. | 538 | // Schedule the update of related bundles last. |
540 | hr = PlanRelatedBundlesComplete(&pEngineState->registration, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, &hSyncpointEvent, dwExecuteActionEarlyIndex); | 539 | hr = PlanRelatedBundlesComplete(&pEngineState->registration, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, dwExecuteActionEarlyIndex); |
541 | ExitOnFailure(hr, "Failed to schedule related bundles."); | 540 | ExitOnFailure(hr, "Failed to schedule related bundles."); |
542 | } | 541 | } |
543 | } | 542 | } |
@@ -1669,9 +1668,8 @@ static HRESULT DetectPackagePayloadsCached( | |||
1669 | { | 1668 | { |
1670 | HRESULT hr = S_OK; | 1669 | HRESULT hr = S_OK; |
1671 | LPWSTR sczCachePath = NULL; | 1670 | LPWSTR sczCachePath = NULL; |
1672 | BURN_CACHE_STATE cache = BURN_CACHE_STATE_NONE; // assume the package will not be cached. | 1671 | BOOL fCached = FALSE; // assume the package is not cached. |
1673 | LPWSTR sczPayloadCachePath = NULL; | 1672 | LPWSTR sczPayloadCachePath = NULL; |
1674 | LONGLONG llSize = 0; | ||
1675 | 1673 | ||
1676 | if (pPackage->sczCacheId && *pPackage->sczCacheId) | 1674 | if (pPackage->sczCacheId && *pPackage->sczCacheId) |
1677 | { | 1675 | { |
@@ -1681,9 +1679,7 @@ static HRESULT DetectPackagePayloadsCached( | |||
1681 | // If the cached directory exists, we have something. | 1679 | // If the cached directory exists, we have something. |
1682 | if (DirExists(sczCachePath, NULL)) | 1680 | if (DirExists(sczCachePath, NULL)) |
1683 | { | 1681 | { |
1684 | cache = BURN_CACHE_STATE_COMPLETE; // assume all payloads are cached. | 1682 | // Check all payloads to see if they exist. |
1685 | |||
1686 | // Check all payloads to see if any are missing or not the right size. | ||
1687 | for (DWORD i = 0; i < pPackage->cPayloads; ++i) | 1683 | for (DWORD i = 0; i < pPackage->cPayloads; ++i) |
1688 | { | 1684 | { |
1689 | BURN_PACKAGE_PAYLOAD* pPackagePayload = pPackage->rgPayloads + i; | 1685 | BURN_PACKAGE_PAYLOAD* pPackagePayload = pPackage->rgPayloads + i; |
@@ -1691,35 +1687,25 @@ static HRESULT DetectPackagePayloadsCached( | |||
1691 | hr = PathConcat(sczCachePath, pPackagePayload->pPayload->sczFilePath, &sczPayloadCachePath); | 1687 | hr = PathConcat(sczCachePath, pPackagePayload->pPayload->sczFilePath, &sczPayloadCachePath); |
1692 | ExitOnFailure(hr, "Failed to concat payload cache path."); | 1688 | ExitOnFailure(hr, "Failed to concat payload cache path."); |
1693 | 1689 | ||
1694 | hr = FileSize(sczPayloadCachePath, &llSize); | 1690 | if (FileExistsEx(sczPayloadCachePath, NULL)) |
1695 | if (SUCCEEDED(hr) && static_cast<DWORD64>(llSize) != pPackagePayload->pPayload->qwFileSize) | ||
1696 | { | ||
1697 | hr = HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT); // size did not match expectations, so cache must have the wrong file. | ||
1698 | } | ||
1699 | |||
1700 | if (SUCCEEDED(hr)) | ||
1701 | { | 1691 | { |
1702 | // TODO: should we do a full on hash verification on the file to ensure | 1692 | // TODO: We shouldn't track whether the payload was cached since all we did was check whether the file exists. |
1703 | // the exact right file is cached? | ||
1704 | |||
1705 | pPackagePayload->fCached = TRUE; | 1693 | pPackagePayload->fCached = TRUE; |
1694 | fCached = TRUE; | ||
1706 | } | 1695 | } |
1707 | else | 1696 | else |
1708 | { | 1697 | { |
1709 | LogId(REPORT_STANDARD, MSG_DETECT_PACKAGE_NOT_FULLY_CACHED, pPackage->sczId, pPackagePayload->pPayload->sczKey, hr); | 1698 | LogId(REPORT_STANDARD, MSG_DETECT_PACKAGE_NOT_FULLY_CACHED, pPackage->sczId, pPackagePayload->pPayload->sczKey); |
1710 | |||
1711 | cache = BURN_CACHE_STATE_PARTIAL; // found a payload that was not cached so we are partial. | ||
1712 | hr = S_OK; | ||
1713 | } | 1699 | } |
1714 | } | 1700 | } |
1715 | } | 1701 | } |
1716 | } | 1702 | } |
1717 | 1703 | ||
1718 | pPackage->cache = cache; | 1704 | pPackage->fCached = fCached; |
1719 | 1705 | ||
1720 | if (pPackage->fCanAffectRegistration) | 1706 | if (pPackage->fCanAffectRegistration) |
1721 | { | 1707 | { |
1722 | pPackage->cacheRegistrationState = BURN_CACHE_STATE_NONE < pPackage->cache ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; | 1708 | pPackage->cacheRegistrationState = pPackage->fCached ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; |
1723 | } | 1709 | } |
1724 | 1710 | ||
1725 | LExit: | 1711 | LExit: |
@@ -1808,7 +1794,7 @@ static void LogPackages( | |||
1808 | const DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? pPackages->cPackages - 1 - i : i; | 1794 | const DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? pPackages->cPackages - 1 - i : i; |
1809 | const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage]; | 1795 | const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage]; |
1810 | 1796 | ||
1811 | LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fAcquire), LoggingBoolToString(pPackage->fUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState)); | 1797 | LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fPlannedCache), LoggingBoolToString(pPackage->fPlannedUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState)); |
1812 | 1798 | ||
1813 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type) | 1799 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type) |
1814 | { | 1800 | { |