diff options
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: |