From a927f26f8308300acb803be667733da7795c3fe1 Mon Sep 17 00:00:00 2001 From: Mengxin Zhu Date: Mon, 27 Feb 2012 16:47:36 +0800 Subject: Bug 358842 pausing/resuming a p2 operation. Introduce new test cases that will download artifacts from Internet, so add vm arguments to make downloading more stable. Signed-off-by: Mengxin Zhu --- .../equinox/internal/p2/engine/Messages.java | 2 ++ .../eclipse/equinox/internal/p2/engine/Phase.java | 15 ++++++++ .../equinox/internal/p2/engine/PhaseSet.java | 28 ++++++++++++++- .../equinox/internal/p2/engine/messages.properties | 1 + .../equinox/internal/p2/engine/phases/Collect.java | 42 ++++++++++++++++++++-- 5 files changed, 84 insertions(+), 4 deletions(-) (limited to 'bundles/org.eclipse.equinox.p2.engine/src') diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Messages.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Messages.java index 9c9710c4a..0b8d79429 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Messages.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Messages.java @@ -70,6 +70,8 @@ public class Messages extends NLS { public static String Phase_Install_Task; public static String Phase_Sizing_Error; public static String Phase_Sizing_Warning; + + public static String phase_thread_interrupted_error; public static String Phase_Unconfigure_Error; public static String Phase_Uninstall_Error; diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Phase.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Phase.java index f57a4829a..bcf912978 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Phase.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Phase.java @@ -44,6 +44,7 @@ public abstract class Phase { private Map> touchpointToTouchpointPhaseParameters = new HashMap>(); private Map> touchpointToTouchpointOperandParameters = new HashMap>(); ActionManager actionManager; // injected from phaseset + protected boolean isPaused = false; protected Phase(String phaseId, int weight, boolean forced) { if (phaseId == null || phaseId.length() == 0) @@ -121,6 +122,16 @@ public abstract class Phase { subMonitor.setWorkRemaining(operands.length - i); if (subMonitor.isCanceled()) throw new OperationCanceledException(); + while (isPaused) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + mergeStatus(status, new Status(IStatus.ERROR, EngineActivator.ID, NLS.bind(Messages.phase_thread_interrupted_error, phaseId), e)); + return; + } + if (subMonitor.isCanceled()) + throw new OperationCanceledException(); + } Operand operand = operands[i]; if (!isApplicable(operand)) continue; @@ -336,4 +347,8 @@ public abstract class Phase { protected String getProblemMessage() { return NLS.bind(Messages.phase_error, getClass().getName()); } + + protected void setPaused(boolean isPaused) { + this.isPaused = isPaused; + } } diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/PhaseSet.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/PhaseSet.java index d4d1c6cf3..6e03edabf 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/PhaseSet.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/PhaseSet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 IBM Corporation and others. + * Copyright (c) 2007, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,6 +19,8 @@ import org.eclipse.osgi.util.NLS; public class PhaseSet implements IPhaseSet { private final Phase[] phases; + private boolean isRunning = false; + private boolean isPaused = false; public PhaseSet(Phase[] phases) { if (phases == null) @@ -33,6 +35,7 @@ public class PhaseSet implements IPhaseSet { int totalWork = getTotalWork(weights); SubMonitor pm = SubMonitor.convert(monitor, totalWork); try { + isRunning = true; for (int i = 0; i < phases.length; i++) { if (pm.isCanceled()) { status.add(Status.CANCEL_STATUS); @@ -68,10 +71,33 @@ public class PhaseSet implements IPhaseSet { } } finally { pm.done(); + isRunning = false; } return status; } + public synchronized boolean pause() { + if (isRunning && !isPaused) { + isPaused = true; + for (Phase phase : phases) { + phase.setPaused(isPaused); + } + return true; + } + return false; + } + + public synchronized boolean resume() { + if (isRunning && isPaused) { + isPaused = false; + for (Phase phase : phases) { + phase.setPaused(isPaused); + } + return true; + } + return false; + } + public final IStatus validate(ActionManager actionManager, IProfile profile, Operand[] operands, ProvisioningContext context, IProgressMonitor monitor) { Set missingActions = new HashSet(); for (int i = 0; i < phases.length; i++) { diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/messages.properties b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/messages.properties index 597ef540d..f5af6f295 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/messages.properties +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/messages.properties @@ -105,5 +105,6 @@ Phase_Install_Error=An error occurred while installing the items Phase_Install_Task=Installing {0} Phase_Sizing_Error=Error computing the size. Some of the items to be installed could not be found. Phase_Sizing_Warning=The size may not be accurate. Some of the items did not report a size. +phase_thread_interrupted_error=Phase({0}) is interrupted. Phase_Unconfigure_Error=An error occurred while unconfiguring the items to uninstall Phase_Uninstall_Error=An error occurred while uninstalling diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/Collect.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/Collect.java index df2435eda..640bf0807 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/Collect.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/Collect.java @@ -12,9 +12,9 @@ package org.eclipse.equinox.internal.p2.engine.phases; import java.util.*; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.*; import org.eclipse.equinox.internal.p2.engine.*; +import org.eclipse.equinox.internal.p2.repository.DownloadPauseResumeEvent; import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.engine.*; @@ -22,6 +22,7 @@ import org.eclipse.equinox.p2.engine.spi.ProvisioningAction; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.metadata.ITouchpointType; import org.eclipse.equinox.p2.repository.artifact.IArtifactRequest; +import org.eclipse.osgi.util.NLS; /** * The goal of the collect phase is to ask the touchpoints if the artifacts associated with an IU need to be downloaded. @@ -29,6 +30,7 @@ import org.eclipse.equinox.p2.repository.artifact.IArtifactRequest; public class Collect extends InstallableUnitPhase { public static final String PARM_ARTIFACT_REQUESTS = "artifactRequests"; //$NON-NLS-1$ public static final String NO_ARTIFACT_REPOSITORIES_AVAILABLE = "noArtifactRepositoriesAvailable"; //$NON-NLS-1$ + private IProvisioningAgent agent = null; public Collect(int weight) { super(PhaseSetFactory.PHASE_COLLECT, weight); @@ -67,8 +69,23 @@ public class Collect extends InstallableUnitPhase { protected IStatus completePhase(IProgressMonitor monitor, IProfile profile, Map parameters) { @SuppressWarnings("unchecked") List artifactRequests = (List) parameters.get(PARM_ARTIFACT_REQUESTS); + // it happens when rollbacking + if (artifactRequests.size() == 0) + return Status.OK_STATUS; ProvisioningContext context = (ProvisioningContext) parameters.get(PARM_CONTEXT); - IProvisioningAgent agent = (IProvisioningAgent) parameters.get(PARM_AGENT); + synchronized (this) { + agent = (IProvisioningAgent) parameters.get(PARM_AGENT); + } + + if (isPaused) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + return new Status(IStatus.ERROR, EngineActivator.ID, NLS.bind(Messages.phase_thread_interrupted_error, phaseId), e); + } + if (monitor.isCanceled()) + return Status.CANCEL_STATUS; + } List totalArtifactRequests = new ArrayList(artifactRequests.size()); DownloadManager dm = new DownloadManager(context, agent); @@ -87,6 +104,9 @@ public class Collect extends InstallableUnitPhase { } finally { if (downloadStatus.isOK() && bus != null) bus.publishEvent(new CollectEvent(CollectEvent.TYPE_OVERALL_END, null, context, totalArtifactRequests.toArray(new IArtifactRequest[totalArtifactRequests.size()]))); + synchronized (this) { + agent = null; + } } } @@ -95,6 +115,22 @@ public class Collect extends InstallableUnitPhase { return null; } + @Override + protected void setPaused(boolean isPaused) { + super.setPaused(isPaused); + firePauseEventToDownloadJobs(); + } + + private void firePauseEventToDownloadJobs() { + synchronized (this) { + if (agent != null) { + IProvisioningEventBus bus = (IProvisioningEventBus) agent.getService(IProvisioningEventBus.SERVICE_NAME); + if (bus != null) + bus.publishEvent(new DownloadPauseResumeEvent(isPaused ? DownloadPauseResumeEvent.TYPE_PAUSE : DownloadPauseResumeEvent.TYPE_RESUME)); + } + } + } + protected IStatus initializeOperand(IProfile profile, InstallableUnitOperand operand, Map parameters, IProgressMonitor monitor) { IStatus status = super.initializeOperand(profile, operand, parameters, monitor); // defer setting the IU until after the super method to avoid triggering touchpoint initialization -- cgit v1.2.3