diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2021-05-04 19:25:07 -0500 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2021-05-11 19:11:19 -0500 |
| commit | 27c6decae94536cae338731b6cb765aa92776486 (patch) | |
| tree | cabfb05464fdc64e30597da28a54113fc3a62da1 /src/burn/engine/apply.cpp | |
| parent | a2f2036c8598efcb434eebeeacd7ede84ab60dfe (diff) | |
| download | wix-27c6decae94536cae338731b6cb765aa92776486.tar.gz wix-27c6decae94536cae338731b6cb765aa92776486.tar.bz2 wix-27c6decae94536cae338731b6cb765aa92776486.zip | |
Put back the rollback cache package functionality and fix its bugs.
#3719, #4711, #5750
Diffstat (limited to 'src/burn/engine/apply.cpp')
| -rw-r--r-- | src/burn/engine/apply.cpp | 99 |
1 files changed, 58 insertions, 41 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp index 4d527409..aad9e6eb 100644 --- a/src/burn/engine/apply.cpp +++ b/src/burn/engine/apply.cpp | |||
| @@ -335,6 +335,7 @@ extern "C" void ApplyReset( | |||
| 335 | { | 335 | { |
| 336 | BURN_PACKAGE* pPackage = pPackages->rgPackages + i; | 336 | BURN_PACKAGE* pPackage = pPackages->rgPackages + i; |
| 337 | pPackage->hrCacheResult = S_OK; | 337 | pPackage->hrCacheResult = S_OK; |
| 338 | pPackage->fReachedExecution = FALSE; | ||
| 338 | pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; | 339 | pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; |
| 339 | } | 340 | } |
| 340 | } | 341 | } |
| @@ -433,7 +434,7 @@ LExit: | |||
| 433 | 434 | ||
| 434 | extern "C" HRESULT ApplyUnregister( | 435 | extern "C" HRESULT ApplyUnregister( |
| 435 | __in BURN_ENGINE_STATE* pEngineState, | 436 | __in BURN_ENGINE_STATE* pEngineState, |
| 436 | __in BOOL fFailedOrRollback, | 437 | __in BOOL fFailed, |
| 437 | __in BOOL fSuspend, | 438 | __in BOOL fSuspend, |
| 438 | __in BOOTSTRAPPER_APPLY_RESTART restart | 439 | __in BOOTSTRAPPER_APPLY_RESTART restart |
| 439 | ) | 440 | ) |
| @@ -466,7 +467,7 @@ extern "C" HRESULT ApplyUnregister( | |||
| 466 | 467 | ||
| 467 | // If apply failed in any way and we're going to be keeping the bundle registered then | 468 | // If apply failed in any way and we're going to be keeping the bundle registered then |
| 468 | // execute any rollback dependency registration actions. | 469 | // execute any rollback dependency registration actions. |
| 469 | if (fFailedOrRollback && fKeepRegistration) | 470 | if (fFailed && fKeepRegistration) |
| 470 | { | 471 | { |
| 471 | // Execute any rollback registration actions. | 472 | // Execute any rollback registration actions. |
| 472 | HRESULT hrRegistrationRollback = ExecuteDependentRegistrationActions(pEngineState->companionConnection.hPipe, &pEngineState->registration, pEngineState->plan.rgRollbackRegistrationActions, pEngineState->plan.cRollbackRegistrationActions); | 473 | HRESULT hrRegistrationRollback = ExecuteDependentRegistrationActions(pEngineState->companionConnection.hPipe, &pEngineState->registration, pEngineState->plan.rgRollbackRegistrationActions, pEngineState->plan.cRollbackRegistrationActions); |
| @@ -587,11 +588,7 @@ extern "C" HRESULT ApplyCache( | |||
| 587 | } | 588 | } |
| 588 | 589 | ||
| 589 | LExit: | 590 | LExit: |
| 590 | if (FAILED(hr)) | 591 | pContext->dwCacheCheckpoint = dwCheckpoint; |
| 591 | { | ||
| 592 | DoRollbackCache(pUX, pPlan, hPipe, dwCheckpoint); | ||
| 593 | pContext->fRollback = TRUE; | ||
| 594 | } | ||
| 595 | 592 | ||
| 596 | // Clean up any remanents in the cache. | 593 | // Clean up any remanents in the cache. |
| 597 | if (INVALID_HANDLE_VALUE != hPipe) | 594 | if (INVALID_HANDLE_VALUE != hPipe) |
| @@ -612,6 +609,16 @@ LExit: | |||
| 612 | return hr; | 609 | return hr; |
| 613 | } | 610 | } |
| 614 | 611 | ||
| 612 | extern "C" void ApplyCacheRollback( | ||
| 613 | __in BURN_USER_EXPERIENCE* pUX, | ||
| 614 | __in BURN_PLAN* pPlan, | ||
| 615 | __in HANDLE hPipe, | ||
| 616 | __in BURN_APPLY_CONTEXT* pContext | ||
| 617 | ) | ||
| 618 | { | ||
| 619 | DoRollbackCache(pUX, pPlan, hPipe, pContext->dwCacheCheckpoint); | ||
| 620 | } | ||
| 621 | |||
| 615 | extern "C" HRESULT ApplyExecute( | 622 | extern "C" HRESULT ApplyExecute( |
| 616 | __in BURN_ENGINE_STATE* pEngineState, | 623 | __in BURN_ENGINE_STATE* pEngineState, |
| 617 | __in BURN_APPLY_CONTEXT* pApplyContext, | 624 | __in BURN_APPLY_CONTEXT* pApplyContext, |
| @@ -687,7 +694,6 @@ extern "C" HRESULT ApplyExecute( | |||
| 687 | IgnoreRollbackError(hrRollback, "Failed commit transaction from disable rollback"); | 694 | IgnoreRollbackError(hrRollback, "Failed commit transaction from disable rollback"); |
| 688 | } | 695 | } |
| 689 | 696 | ||
| 690 | pApplyContext->fRollback = TRUE; | ||
| 691 | break; | 697 | break; |
| 692 | } | 698 | } |
| 693 | 699 | ||
| @@ -708,7 +714,6 @@ extern "C" HRESULT ApplyExecute( | |||
| 708 | // If the rollback boundary is vital, end execution here. | 714 | // If the rollback boundary is vital, end execution here. |
| 709 | if (pRollbackBoundary && pRollbackBoundary->fVital) | 715 | if (pRollbackBoundary && pRollbackBoundary->fVital) |
| 710 | { | 716 | { |
| 711 | pApplyContext->fRollback = TRUE; | ||
| 712 | break; | 717 | break; |
| 713 | } | 718 | } |
| 714 | 719 | ||
| @@ -2110,41 +2115,44 @@ static void DoRollbackCache( | |||
| 2110 | ) | 2115 | ) |
| 2111 | { | 2116 | { |
| 2112 | HRESULT hr = S_OK; | 2117 | HRESULT hr = S_OK; |
| 2113 | DWORD iCheckpoint = 0; | 2118 | BURN_PACKAGE* pPackage = NULL; |
| 2119 | DWORD dwLastCheckpoint = 0; | ||
| 2114 | 2120 | ||
| 2115 | // Scan to last checkpoint. | 2121 | // Rollback cache actions. |
| 2116 | for (DWORD i = 0; i < pPlan->cRollbackCacheActions; ++i) | 2122 | for (DWORD i = pPlan->cRollbackCacheActions; i > 0; --i) |
| 2117 | { | 2123 | { |
| 2118 | BURN_CACHE_ACTION* pRollbackCacheAction = &pPlan->rgRollbackCacheActions[i]; | 2124 | BURN_CACHE_ACTION* pRollbackCacheAction = &pPlan->rgRollbackCacheActions[i - 1]; |
| 2119 | 2125 | ||
| 2120 | if (BURN_CACHE_ACTION_TYPE_CHECKPOINT == pRollbackCacheAction->type && pRollbackCacheAction->checkpoint.dwId == dwCheckpoint) | 2126 | switch (pRollbackCacheAction->type) |
| 2121 | { | 2127 | { |
| 2122 | iCheckpoint = i; | 2128 | case BURN_CACHE_ACTION_TYPE_CHECKPOINT: |
| 2129 | dwLastCheckpoint = pRollbackCacheAction->checkpoint.dwId; | ||
| 2123 | break; | 2130 | break; |
| 2124 | } | ||
| 2125 | } | ||
| 2126 | 2131 | ||
| 2127 | // Rollback cache actions. | 2132 | case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE: |
| 2128 | if (iCheckpoint) | 2133 | pPackage = pRollbackCacheAction->rollbackPackage.pPackage; |
| 2129 | { | ||
| 2130 | // i has to be a signed integer so it doesn't get decremented to 0xFFFFFFFF. | ||
| 2131 | for (int i = iCheckpoint - 1; i >= 0; --i) | ||
| 2132 | { | ||
| 2133 | BURN_CACHE_ACTION* pRollbackCacheAction = &pPlan->rgRollbackCacheActions[i]; | ||
| 2134 | 2134 | ||
| 2135 | switch (pRollbackCacheAction->type) | 2135 | // If the package was executed then it's up to ApplyExecute to rollback its cache. |
| 2136 | if (!pPackage->fReachedExecution) | ||
| 2136 | { | 2137 | { |
| 2137 | case BURN_CACHE_ACTION_TYPE_CHECKPOINT: | 2138 | if (!pPackage->fCached) // only rollback when it wasn't already cached. |
| 2138 | break; | 2139 | { |
| 2139 | 2140 | if (dwLastCheckpoint <= dwCheckpoint) // only rollback when it was attempted to be cached. | |
| 2140 | case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE: | 2141 | { |
| 2141 | hr = CleanPackage(hPipe, pRollbackCacheAction->rollbackPackage.pPackage); | 2142 | hr = CleanPackage(hPipe, pPackage); |
| 2142 | break; | 2143 | } |
| 2143 | 2144 | } | |
| 2144 | default: | 2145 | else if (pPackage->fCanAffectRegistration) |
| 2145 | AssertSz(FALSE, "Invalid rollback cache action."); | 2146 | { |
| 2146 | break; | 2147 | // Don't let this already cached package cause the registration to be kept if the bundle failed and wasn't already registered. |
| 2148 | pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; | ||
| 2149 | } | ||
| 2147 | } | 2150 | } |
| 2151 | break; | ||
| 2152 | |||
| 2153 | default: | ||
| 2154 | AssertSz(FALSE, "Invalid rollback cache action."); | ||
| 2155 | break; | ||
| 2148 | } | 2156 | } |
| 2149 | } | 2157 | } |
| 2150 | } | 2158 | } |
| @@ -2180,9 +2188,11 @@ static HRESULT DoExecuteAction( | |||
| 2180 | *ppCheckpoint = &pExecuteAction->checkpoint; | 2188 | *ppCheckpoint = &pExecuteAction->checkpoint; |
| 2181 | break; | 2189 | break; |
| 2182 | 2190 | ||
| 2183 | case BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT: | 2191 | case BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE: |
| 2192 | pExecuteAction->waitCachePackage.pPackage->fReachedExecution = TRUE; | ||
| 2193 | |||
| 2184 | // wait for cache sync-point | 2194 | // wait for cache sync-point |
| 2185 | rghWait[0] = pExecuteAction->syncpoint.hEvent; | 2195 | rghWait[0] = pExecuteAction->waitCachePackage.pPackage->hCacheEvent; |
| 2186 | rghWait[1] = pContext->pApplyContext->hCacheThread; | 2196 | rghWait[1] = pContext->pApplyContext->hCacheThread; |
| 2187 | switch (::WaitForMultipleObjects(rghWait[1] ? 2 : 1, rghWait, FALSE, INFINITE)) | 2197 | switch (::WaitForMultipleObjects(rghWait[1] ? 2 : 1, rghWait, FALSE, INFINITE)) |
| 2188 | { | 2198 | { |
| @@ -2354,10 +2364,17 @@ static HRESULT DoRollbackActions( | |||
| 2354 | ExitFunction1(hr = S_OK); | 2364 | ExitFunction1(hr = S_OK); |
| 2355 | 2365 | ||
| 2356 | case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE: | 2366 | case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE: |
| 2357 | // TODO: This used to be skipped if the package was already cached. | 2367 | if (!pRollbackAction->uncachePackage.pPackage->fCached) // only rollback when it wasn't already cached. |
| 2358 | // Need to figure out new logic for when (if?) to skip it. | 2368 | { |
| 2359 | hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage); | 2369 | hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage); |
| 2360 | IgnoreRollbackError(hr, "Failed to uncache package for rollback."); | 2370 | IgnoreRollbackError(hr, "Failed to uncache package for rollback."); |
| 2371 | } | ||
| 2372 | else if (pRollbackAction->uncachePackage.pPackage->fCanAffectRegistration) | ||
| 2373 | { | ||
| 2374 | // Don't let this already cached package cause the registration to be kept if the bundle failed and wasn't already registered. | ||
| 2375 | pRollbackAction->uncachePackage.pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; | ||
| 2376 | } | ||
| 2377 | |||
| 2361 | break; | 2378 | break; |
| 2362 | 2379 | ||
| 2363 | default: | 2380 | default: |
