Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal Rapicault (JBoss)2013-02-28 21:03:16 -0500
committerPascal Rapicault2013-03-23 23:11:45 -0400
commit251702b2afa7efdf3652750e667007a2878ce6bf (patch)
tree0c9e3df780c267ee12fe2daa8c5629a4f1f4cad3 /bundles/org.eclipse.equinox.p2.director
parentbb5713948807de4101b7043632b6f46397786629 (diff)
downloadrt.equinox.p2-251702b2afa7efdf3652750e667007a2878ce6bf.tar.gz
rt.equinox.p2-251702b2afa7efdf3652750e667007a2878ce6bf.tar.xz
rt.equinox.p2-251702b2afa7efdf3652750e667007a2878ce6bf.zip
Add remediation page
When an operation can't succeed, the error page is replaced by a dialog letting the user pick a better solution. This is enabled in all major workflows. At the projector level, it features a new encoding for optionality and a new way of defining optimization functions.
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.director')
-rw-r--r--bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF6
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java31
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java123
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java17
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/UserDefinedOptimizationFunction.java198
5 files changed, 284 insertions, 91 deletions
diff --git a/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
index f9ad8f358..f9d9aae1a 100644
--- a/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
@@ -23,10 +23,10 @@ Export-Package: org.eclipse.equinox.internal.p2.director;
org.eclipse.equinox.p2.installer",
org.eclipse.equinox.p2.planner;version="2.0.0"
Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.3.0,4.0.0)",
- org.sat4j.core;bundle-version="[2.2.0,2.4.0)",
- org.sat4j.pb;bundle-version="[2.2.0,2.4.0)",
org.eclipse.core.jobs;bundle-version="[3.3.0,4.0.0)",
- org.eclipse.equinox.p2.metadata;bundle-version="[2.0.0,3.0.0)"
+ org.eclipse.equinox.p2.metadata;bundle-version="[2.0.0,3.0.0)",
+ org.sat4j.pb;bundle-version="[2.3.3,3.0.0)",
+ org.sat4j.core;bundle-version="[2.3.3,3.0.0)"
Bundle-RequiredExecutionEnvironment: J2SE-1.5,
J2SE-1.4,
CDC-1.1/Foundation-1.1
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java
index 55cc3811f..c29fe8811 100644
--- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java
@@ -23,17 +23,14 @@ public class OptimizationFunction {
private IQueryable<IInstallableUnit> picker;
private IInstallableUnit selectionContext;
- private Map<String, Map<Version, IInstallableUnit>> slice; //The IUs that have been considered to be part of the problem
- private int numberOfInstalledIUs;
+ protected Map<String, Map<Version, IInstallableUnit>> slice; //The IUs that have been considered to be part of the problem
+ private int numberOfInstalledIUs; //TODO this should be renamed to consideredIUs or sliceSize
private IQueryable<IInstallableUnit> lastState;
- private List<AbstractVariable> abstractVariables;
+ private List<AbstractVariable> optionalRequirementVariable;
- // private IInstallableUnit[] alreadyExistingRoots;
- // private IQueryable<IInstallableUnit> beingInstalled;
-
- public OptimizationFunction(IQueryable<IInstallableUnit> lastState, List<AbstractVariable> abstractVariables, IQueryable<IInstallableUnit> picker, IInstallableUnit selectionContext, Map<String, Map<Version, IInstallableUnit>> slice) {
+ public OptimizationFunction(IQueryable<IInstallableUnit> lastState, List<AbstractVariable> abstractVariables, List<AbstractVariable> optionalRequirementVariable, IQueryable<IInstallableUnit> picker, IInstallableUnit selectionContext, Map<String, Map<Version, IInstallableUnit>> slice) {
this.lastState = lastState;
- this.abstractVariables = abstractVariables;
+ this.optionalRequirementVariable = optionalRequirementVariable;
this.picker = picker;
this.selectionContext = selectionContext;
this.slice = slice;
@@ -44,7 +41,7 @@ public class OptimizationFunction {
numberOfInstalledIUs = sizeOf(lastState);
List<WeightedObject<? extends Object>> weightedObjects = new ArrayList<WeightedObject<? extends Object>>();
- Set<IInstallableUnit> transitiveClosure;
+ Set<IInstallableUnit> transitiveClosure; //The transitive closure of the IUs we are adding (this also means updating)
if (newRoots.isEmpty()) {
transitiveClosure = CollectionUtils.emptySet();
} else {
@@ -63,13 +60,15 @@ public class OptimizationFunction {
for (Entry<String, Map<Version, IInstallableUnit>> entry : s) {
List<IInstallableUnit> conflictingEntries = new ArrayList<IInstallableUnit>(entry.getValue().values());
if (conflictingEntries.size() == 1) {
+ //Only one IU exists with the namespace.
IInstallableUnit iu = conflictingEntries.get(0);
if (iu != metaIu) {
weightedObjects.add(WeightedObject.newWO(iu, POWER));
}
continue;
}
- // IUs are sorted from highest version to lowest.
+
+ // Set the weight such that things that are already installed are not updated
Collections.sort(conflictingEntries, Collections.reverseOrder());
BigInteger weight = POWER;
// have we already found a version that is already installed?
@@ -96,14 +95,15 @@ public class OptimizationFunction {
// maximal weight used so far.
maxWeight = maxWeight.multiply(POWER).multiply(BigInteger.valueOf(s.size()));
- // Add the abstract variables
- BigInteger abstractWeight = maxWeight.negate();
- for (AbstractVariable var : abstractVariables) {
- weightedObjects.add(WeightedObject.newWO(var, abstractWeight));
+ // Add the optional variables
+ BigInteger optionalVarWeight = maxWeight.negate();
+ for (AbstractVariable var : optionalRequirementVariable) {
+ weightedObjects.add(WeightedObject.newWO(var, optionalVarWeight));
}
maxWeight = maxWeight.multiply(POWER).add(BigInteger.ONE);
+ //Now we deal the optional IUs,
BigInteger optionalWeight = maxWeight.negate();
long countOptional = 1;
List<IInstallableUnit> requestedPatches = new ArrayList<IInstallableUnit>();
@@ -117,12 +117,11 @@ public class OptimizationFunction {
if (match instanceof IInstallableUnitPatch) {
requestedPatches.add(match);
countOptional = countOptional + 1;
- } else {
- weightedObjects.add(WeightedObject.newWO(match, optionalWeight));
}
}
}
+ // and we make sure that patches are always favored
BigInteger patchWeight = maxWeight.multiply(POWER).multiply(BigInteger.valueOf(countOptional)).negate();
for (Iterator<IInstallableUnit> iterator = requestedPatches.iterator(); iterator.hasNext();) {
weightedObjects.add(WeightedObject.newWO(iterator.next(), patchWeight));
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java
index 59e8eb271..ba401bbd0 100644
--- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java
@@ -11,6 +11,7 @@
* Jed Anderson - switch from opb files to API calls to DependencyHelper in bug 200380
* Sonatype, Inc. - ongoing development
* Rapicorp, Inc. - split the optimization function
+ * Red Hat, Inc. - support for remediation page
******************************************************************************/
package org.eclipse.equinox.internal.p2.director;
@@ -27,9 +28,10 @@ import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.osgi.util.NLS;
+import org.sat4j.minisat.restarts.LubyRestarts;
import org.sat4j.pb.*;
-import org.sat4j.pb.tools.DependencyHelper;
-import org.sat4j.pb.tools.WeightedObject;
+import org.sat4j.pb.core.PBSolverResolution;
+import org.sat4j.pb.tools.*;
import org.sat4j.specs.*;
/**
@@ -53,7 +55,7 @@ public class Projector {
private IQueryable<IInstallableUnit> picker;
private QueryableArray patches;
- private Map<IInstallableUnit, AbstractVariable> noopVariables; //key IU, value AbstractVariable
+ private List<AbstractVariable> allOptionalAbstractRequirements;
private List<AbstractVariable> abstractVariables;
private Map<String, Map<Version, IInstallableUnit>> slice; //The IUs that have been considered to be part of the problem
@@ -78,6 +80,9 @@ public class Projector {
private Map<IInstallableUnit, AbstractVariable> nonGreedyVariables = new HashMap<IInstallableUnit, AbstractVariable>();
private Map<AbstractVariable, List<Object>> nonGreedyProvider = new HashMap<AbstractVariable, List<Object>>(); //Keeps track of all the "object" that provide an IU that is non greedly requested
+ private boolean emptyBecauseFiltered;
+ private boolean userDefinedFunction;
+
static class AbstractVariable {
// private String name;
@@ -154,24 +159,19 @@ public class Projector {
public Projector(IQueryable<IInstallableUnit> q, Map<String, String> context, Set<IInstallableUnit> nonGreedyIUs, boolean considerMetaRequirements) {
picker = q;
- noopVariables = new HashMap<IInstallableUnit, AbstractVariable>();
slice = new HashMap<String, Map<Version, IInstallableUnit>>();
selectionContext = InstallableUnit.contextIU(context);
abstractVariables = new ArrayList<AbstractVariable>();
+ allOptionalAbstractRequirements = new ArrayList<AbstractVariable>();
result = new MultiStatus(DirectorActivator.PI_DIRECTOR, IStatus.OK, Messages.Planner_Problems_resolving_plan, null);
assumptions = new ArrayList<Object>();
this.nonGreedyIUs = nonGreedyIUs;
this.considerMetaRequirements = considerMetaRequirements;
}
- // protected boolean isInstalled(IInstallableUnit iu) {
- // return !lastState.query(QueryUtil.createIUQuery(iu), null).isEmpty();
- // }
-
@SuppressWarnings("unchecked")
public void encode(IInstallableUnit entryPointIU, IInstallableUnit[] alreadyExistingRoots, IQueryable<IInstallableUnit> installedIUs, Collection<IInstallableUnit> newRoots, IProgressMonitor monitor) {
alreadyInstalledIUs = Arrays.asList(alreadyExistingRoots);
- // numberOfInstalledIUs = sizeOf(installedIUs);
lastState = installedIUs;
this.entryPoint = entryPointIU;
try {
@@ -184,7 +184,14 @@ public class Projector {
if (DEBUG_ENCODING) {
solver = new UserFriendlyPBStringSolver<Object>();
} else {
- solver = SolverFactory.newEclipseP2();
+ if (userDefinedFunction) {
+ PBSolverResolution mysolver = SolverFactory.newCompetPBResLongWLMixedConstraintsObjectiveExpSimp();
+ mysolver.setSimplifier(mysolver.SIMPLE_SIMPLIFICATION);
+ mysolver.setRestartStrategy(new LubyRestarts(512));
+ solver = mysolver;
+ } else {
+ solver = SolverFactory.newEclipseP2();
+ }
}
int timeout = DEFAULT_SOLVER_TIMEOUT;
String timeoutString = null;
@@ -204,10 +211,13 @@ public class Projector {
solver.setTimeoutOnConflicts(timeout);
IQueryResult<IInstallableUnit> queryResult = picker.query(QueryUtil.createIUAnyQuery(), null);
if (DEBUG_ENCODING) {
- dependencyHelper = new DependencyHelper<Object, Explanation>(solver, false);
+ dependencyHelper = new LexicoHelper<Object, Explanation>(solver, false);
((UserFriendlyPBStringSolver<Object>) solver).setMapping(dependencyHelper.getMappingToDomain());
} else {
- dependencyHelper = new DependencyHelper<Object, Explanation>(solver);
+ if (userDefinedFunction)
+ dependencyHelper = new LexicoHelper<Object, Explanation>(solver);
+ else
+ dependencyHelper = new DependencyHelper<Object, Explanation>(solver);
}
List<IInstallableUnit> iusToOrder = new ArrayList<IInstallableUnit>(queryResult.toSet());
Collections.sort(iusToOrder);
@@ -255,13 +265,28 @@ public class Projector {
}
+ private void createOptimizationFunction(IInstallableUnit entryPointIU, Collection<IInstallableUnit> newRoots) {
+ if (!userDefinedFunction) {
+ createStandardOptimizationFunction(entryPointIU, newRoots);
+ } else {
+ createUserDefinedOptimizationFunction(entryPointIU, newRoots);
+ }
+ }
+
//Create an optimization function favoring the highest version of each IU
- private void createOptimizationFunction(IInstallableUnit metaIu, Collection<IInstallableUnit> newRoots) {
- List<WeightedObject<? extends Object>> weights = new OptimizationFunction(lastState, abstractVariables, picker, selectionContext, slice).createOptimizationFunction(metaIu, newRoots);
+ private void createStandardOptimizationFunction(IInstallableUnit entryPointIU, Collection<IInstallableUnit> newRoots) {
+ List<WeightedObject<? extends Object>> weights = new OptimizationFunction(lastState, abstractVariables, allOptionalAbstractRequirements, picker, selectionContext, slice).createOptimizationFunction(entryPointIU, newRoots);
+ createObjectiveFunction(weights);
+ }
+
+ private void createUserDefinedOptimizationFunction(IInstallableUnit entryPointIU, Collection<IInstallableUnit> newRoots) {
+ List<WeightedObject<? extends Object>> weights = new UserDefinedOptimizationFunction(lastState, abstractVariables, allOptionalAbstractRequirements, picker, selectionContext, slice, dependencyHelper, alreadyInstalledIUs).createOptimizationFunction(entryPointIU, newRoots);
createObjectiveFunction(weights);
}
private void createObjectiveFunction(List<WeightedObject<? extends Object>> weightedObjects) {
+ if (weightedObjects == null)
+ return;
if (DEBUG) {
StringBuffer b = new StringBuffer();
for (WeightedObject<? extends Object> object : weightedObjects) {
@@ -399,6 +424,7 @@ public class Projector {
addNonGreedyProvider(getNonGreedyVariable(current), abs);
}
}
+ optionalAbstractRequirements.add(abs);
} else {
abs = getAbstractVariable(req, false);
List<Object> newConstraint = new ArrayList<Object>();
@@ -408,7 +434,6 @@ public class Projector {
}
createImplication(new Object[] {abs, iu}, newConstraint, Explanation.OPTIONAL_REQUIREMENT);
}
- optionalAbstractRequirements.add(abs);
}
}
}
@@ -425,11 +450,9 @@ public class Projector {
private void expandRequirements(Collection<IRequirement> reqs, IInstallableUnit iu, boolean isRootIu) throws ContradictionException {
if (reqs.isEmpty())
return;
- List<AbstractVariable> optionalAbstractRequirements = new ArrayList<AbstractVariable>();
for (IRequirement req : reqs) {
- expandRequirement(req, iu, optionalAbstractRequirements, isRootIu);
+ expandRequirement(req, iu, allOptionalAbstractRequirements, isRootIu);
}
- createOptionalityExpression(iu, optionalAbstractRequirements);
}
public void processIU(IInstallableUnit iu, boolean isRootIU) throws ContradictionException {
@@ -452,7 +475,7 @@ public class Projector {
expandRequirements(getRequiredCapabilities(iu), iu, isRootIU);
} else {
//Patches are applicable to the IU
- expandRequirementsWithPatches(iu, applicablePatches, isRootIU);
+ expandRequirementsWithPatches(iu, applicablePatches, allOptionalAbstractRequirements, isRootIU);
}
}
@@ -480,7 +503,7 @@ public class Projector {
Object left;
}
- private void expandRequirementsWithPatches(IInstallableUnit iu, IQueryResult<IInstallableUnit> applicablePatches, boolean isRootIu) throws ContradictionException {
+ private void expandRequirementsWithPatches(IInstallableUnit iu, IQueryResult<IInstallableUnit> applicablePatches, List<AbstractVariable> optionalAbstractRequirements, boolean isRootIu) throws ContradictionException {
//Unmodified dependencies
Collection<IRequirement> iuRequirements = getRequiredCapabilities(iu);
Map<IRequirement, List<IInstallableUnitPatch>> unchangedRequirements = new HashMap<IRequirement, List<IInstallableUnitPatch>>(iuRequirements.size());
@@ -496,7 +519,6 @@ public class Projector {
// noop(IU)-> ~ABS
// IU -> (noop(IU) or ABS)
// Therefore we only need one optional requirement statement per IU
- List<AbstractVariable> optionalAbstractRequirements = new ArrayList<AbstractVariable>();
for (int i = 0; i < reqs.length; i++) {
//The requirement is unchanged
if (reqs[i][0] == reqs[i][1]) {
@@ -568,6 +590,7 @@ public class Projector {
addNonGreedyProvider(getNonGreedyVariable(current), abs);
}
}
+ optionalAbstractRequirements.add(abs);
} else {
abs = getAbstractVariable(req, false);
List<Object> newConstraint = new ArrayList<Object>(matches.size());
@@ -577,7 +600,6 @@ public class Projector {
}
createImplication(new Object[] {patch, abs, iu}, newConstraint, Explanation.OPTIONAL_REQUIREMENT);
}
- optionalAbstractRequirements.add(abs);
}
}
}
@@ -683,7 +705,6 @@ public class Projector {
}
}
}
- createOptionalityExpression(iu, optionalAbstractRequirements);
}
// Fix: now create the pending non-patch requirements based on the full set of patches
@@ -691,7 +712,6 @@ public class Projector {
createImplication(pending.left, pending.matches, pending.explanation);
}
- List<AbstractVariable> optionalAbstractRequirements = new ArrayList<AbstractVariable>();
for (Entry<IRequirement, List<IInstallableUnitPatch>> entry : unchangedRequirements.entrySet()) {
List<IInstallableUnitPatch> patchesApplied = entry.getValue();
Iterator<IInstallableUnit> allPatches = applicablePatches.iterator();
@@ -779,7 +799,6 @@ public class Projector {
}
}
}
- createOptionalityExpression(iu, optionalAbstractRequirements);
}
private void expandLifeCycle(IInstallableUnit iu, boolean isRootIu) throws ContradictionException {
@@ -797,8 +816,6 @@ public class Projector {
createNegation(iu, req);
}
- private boolean emptyBecauseFiltered;
-
/**
* @param req
* @return a list of mandatory requirements if any, an empty list if req.isOptional().
@@ -828,7 +845,7 @@ public class Projector {
for (int i = 0; i < changes.size(); i++) {
IRequirementChange change = changes.get(i);
for (int j = 0; j < originalRequirements.length; j++) {
- if (originalRequirements[j] != null && change.matches((IRequiredCapability) originalRequirements[j])) {
+ if (originalRequirements[j] != null && safeMatch(originalRequirements, change, j)) {
found = true;
if (change.newValue() != null)
rrr.add(new IRequirement[] {originalRequirements[j], change.newValue()});
@@ -850,24 +867,12 @@ public class Projector {
return rrr.toArray(new IRequirement[rrr.size()][]);
}
- /**
- * Optional requirements are encoded via:
- * ABS -> (match1(req) or match2(req) or ... or matchN(req))
- * noop(IU)-> ~ABS
- * IU -> (noop(IU) or ABS)
- * @param iu
- * @param optionalRequirements
- * @throws ContradictionException
- */
- private void createOptionalityExpression(IInstallableUnit iu, List<AbstractVariable> optionalRequirements) throws ContradictionException {
- if (optionalRequirements.isEmpty())
- return;
- AbstractVariable noop = getNoOperationVariable(iu);
- for (AbstractVariable abs : optionalRequirements) {
- createIncompatibleValues(abs, noop);
+ private boolean safeMatch(IRequirement[] originalRequirements, IRequirementChange change, int j) {
+ try {
+ return change.matches((IRequiredCapability) originalRequirements[j]);
+ } catch (ClassCastException e) {
+ return false;
}
- optionalRequirements.add(noop);
- createImplication(iu, optionalRequirements, Explanation.OPTIONAL_REQUIREMENT);
}
//This will create as many implication as there is element in the right argument
@@ -948,18 +953,6 @@ public class Projector {
dependencyHelper.atMost(1, (Object[]) ius).named(new Explanation.Singleton(ius));
}
- private void createIncompatibleValues(AbstractVariable v1, AbstractVariable v2) throws ContradictionException {
- AbstractVariable[] vars = {v1, v2};
- if (DEBUG) {
- StringBuffer b = new StringBuffer();
- for (int i = 0; i < vars.length; i++) {
- b.append(vars[i].toString());
- }
- Tracing.debug("At most 1 of " + b); //$NON-NLS-1$
- }
- dependencyHelper.atMost(1, (Object[]) vars).named(Explanation.OPTIONAL_REQUIREMENT);
- }
-
private AbstractVariable getAbstractVariable(IRequirement req) {
return getAbstractVariable(req, true);
}
@@ -972,15 +965,6 @@ public class Projector {
return abstractVariable;
}
- private AbstractVariable getNoOperationVariable(IInstallableUnit iu) {
- AbstractVariable v = noopVariables.get(iu);
- if (v == null) {
- v = DEBUG_ENCODING ? new AbstractVariable("Noop_" + iu.toString()) : new AbstractVariable(); //$NON-NLS-1$
- noopVariables.put(iu, v);
- }
- return v;
- }
-
private AbstractVariable getNonGreedyVariable(IInstallableUnit iu) {
AbstractVariable v = nonGreedyVariables.get(iu);
if (v == null) {
@@ -1007,7 +991,7 @@ public class Projector {
backToIU();
long stop = System.currentTimeMillis();
if (DEBUG)
- Tracing.debug("Solver solution found: " + (stop - start)); //$NON-NLS-1$
+ Tracing.debug("Solver solution found in: " + (stop - start) + " ms."); //$NON-NLS-1$
} else {
long stop = System.currentTimeMillis();
if (DEBUG) {
@@ -1029,6 +1013,7 @@ public class Projector {
private void backToIU() {
solution = new ArrayList<IInstallableUnit>();
+ //TODO WORK AROUND BECAUE OF A BUG IN SAT4J
IVec<Object> sat4jSolution = dependencyHelper.getSolution();
for (Iterator<Object> iter = sat4jSolution.iterator(); iter.hasNext();) {
Object var = iter.next();
@@ -1111,4 +1096,8 @@ public class Projector {
}
existingMatches.retainAll(matches);
}
+
+ public void setUserDefined(boolean containsKey) {
+ userDefinedFunction = containsKey;
+ }
} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java
index f733b2719..7c5729336 100644
--- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others. All rights reserved. This
+ * Copyright (c) 2007, 2013 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 http://www.eclipse.org/legal/epl-v10.html
@@ -8,6 +8,7 @@
* IBM Corporation - initial API and implementation
* Genuitec - bug fixes
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
******************************************************************************/
package org.eclipse.equinox.internal.p2.director;
@@ -152,16 +153,20 @@ public class SimplePlanner implements IPlanner {
MultiStatus root = new MultiStatus(DirectorActivator.PI_DIRECTOR, 1, Messages.Director_Unsatisfied_Dependencies, null);
//try to find a more specific root message if possible
String specificMessage = null;
+ int errorCode = 0;
for (Explanation next : explanations) {
root.add(next.toStatus());
- if (specificMessage == null && next instanceof Explanation.MissingIU)
+ if (specificMessage == null && next instanceof Explanation.MissingIU) {
specificMessage = Messages.Explanation_rootMissing;
- else if (specificMessage == null && next instanceof Explanation.Singleton)
+ errorCode = 10053;
+ } else if (specificMessage == null && next instanceof Explanation.Singleton) {
specificMessage = Messages.Explanation_rootSingleton;
+ errorCode = 10054;
+ }
}
//use a more specific root message if available
if (specificMessage != null) {
- MultiStatus newRoot = new MultiStatus(DirectorActivator.PI_DIRECTOR, 1, specificMessage, null);
+ MultiStatus newRoot = new MultiStatus(DirectorActivator.PI_DIRECTOR, errorCode, specificMessage, null);
newRoot.merge(root);
root = newRoot;
}
@@ -333,6 +338,7 @@ public class SimplePlanner implements IPlanner {
final IQueryable<IInstallableUnit>[] queryables = new IQueryable[] {slice, new QueryableArray(profileChangeRequest.getAdditions().toArray(new IInstallableUnit[profileChangeRequest.getAdditions().size()]))};
slice = new CompoundQueryable<IInstallableUnit>(queryables);
Projector projector = new Projector(slice, newSelectionContext, slicer.getNonGreedyIUs(), satisfyMetaRequirements(profileChangeRequest.getProfileProperties()));
+ projector.setUserDefined(profileChangeRequest.getPropertiesToAdd().containsKey("_internal_user_defined_"));
projector.encode((IInstallableUnit) updatedPlan[0], (IInstallableUnit[]) updatedPlan[1], profile, profileChangeRequest.getAdditions(), sub.newChild(ExpandWork / 4));
IStatus s = projector.invokeSolver(sub.newChild(ExpandWork / 4));
if (s.getSeverity() == IStatus.CANCEL) {
@@ -747,7 +753,8 @@ public class SimplePlanner implements IPlanner {
//Now add any other requirement that we need to see satisfied
if (profileChangeRequest.getExtraRequirements() != null)
gatheredRequirements.addAll(profileChangeRequest.getExtraRequirements());
- return new Object[] {createIURepresentingTheProfile(gatheredRequirements), alreadyInstalled.toArray(IInstallableUnit.class)};
+ IInstallableUnit[] existingRoots = profileChangeRequest.getProfile().query(new IUProfilePropertyQuery(INCLUSION_RULES, IUProfilePropertyQuery.ANY), null).toArray(IInstallableUnit.class);
+ return new Object[] {createIURepresentingTheProfile(gatheredRequirements), existingRoots};
}
private IRequirement createRequirement(IInstallableUnit iu, String rule) {
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/UserDefinedOptimizationFunction.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/UserDefinedOptimizationFunction.java
new file mode 100644
index 000000000..6a8d69cc4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/UserDefinedOptimizationFunction.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2013 Daniel Le Berre 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 http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daniel Le Berre - initial API and implementation
+ * Red Hat, Inc. - support for remediation page
+ ******************************************************************************/
+package org.eclipse.equinox.internal.p2.director;
+
+import java.math.BigInteger;
+import java.util.*;
+import org.eclipse.equinox.internal.p2.director.Projector.AbstractVariable;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.query.*;
+import org.sat4j.pb.tools.*;
+import org.sat4j.specs.ContradictionException;
+
+public class UserDefinedOptimizationFunction extends OptimizationFunction {
+ private Collection<IInstallableUnit> alreadyExistingRoots;
+ private LexicoHelper<Object, Explanation> dependencyHelper;
+ private IQueryable<IInstallableUnit> picker;
+ private List changeVariables = new ArrayList();
+ private List removalVariables = new ArrayList();
+ private List newVariables = new ArrayList();
+
+ public UserDefinedOptimizationFunction(IQueryable<IInstallableUnit> lastState, List<AbstractVariable> abstractVariables, List<AbstractVariable> optionalVariables, IQueryable<IInstallableUnit> picker, IInstallableUnit selectionContext, Map<String, Map<Version, IInstallableUnit>> slice, DependencyHelper<Object, Explanation> dependencyHelper, Collection<IInstallableUnit> alreadyInstalledIUs) {
+ super(lastState, abstractVariables, optionalVariables, picker, selectionContext, slice);
+ this.picker = picker;
+ this.slice = slice;
+ this.dependencyHelper = (LexicoHelper<Object, Explanation>) dependencyHelper;
+ this.alreadyExistingRoots = alreadyInstalledIUs;
+ }
+
+ public List<WeightedObject<? extends Object>> createOptimizationFunction(IInstallableUnit metaIu, Collection<IInstallableUnit> newRoots) {
+ List weightedObjects = new ArrayList();
+ List objects = new ArrayList();
+ BigInteger weight = BigInteger.valueOf(slice.size() + 1);
+ String[] criteria = new String[] {"+new", "-removed", "-changed"};
+ BigInteger currentWeight = weight.pow(criteria.length - 1);
+ int formermaxvarid = dependencyHelper.getSolver().nextFreeVarId(false);
+ int newmaxvarid;
+ boolean maximizes;
+ Object thing;
+ for (int i = 0; i < criteria.length; i++) {
+ if (criteria[i].endsWith("new")) {
+ weightedObjects.clear();
+ newRoots(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ currentWeight = currentWeight.divide(weight);
+ } else if (criteria[i].endsWith("removed")) {
+ weightedObjects.clear();
+ removedRoots(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ currentWeight = currentWeight.divide(weight);
+ // } else if (criteria[i].endsWith("notuptodate")) {
+ // weightedObjects.clear();
+ // notuptodate(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ // currentWeight = currentWeight.divide(weight);
+ // } else if (criteria[i].endsWith("unsat_recommends")) {
+ // weightedObjects.clear();
+ // optional(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ // currentWeight = currentWeight.divide(weight);
+ // } else if (criteria[i].endsWith("versionchanged")) {
+ // weightedObjects.clear();
+ // versionChanged(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ } else if (criteria[i].endsWith("changed")) {
+ weightedObjects.clear();
+ changedRoots(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ currentWeight = currentWeight.divide(weight);
+ // } else if (criteria[i].contains("sum")) {
+ // weightedObjects.clear();
+ // sum(weightedObjects, criteria[i].charAt(0) == '-', metaIu, Options.extractSumProperty(criteria[i]));
+ // dependencyHelper.addWeightedCriterion(weightedObjects);
+ // System.out.println("# criteria " + criteria[i].substring(1) + " size is " + weightedObjects.size());
+ // continue;
+ // } else {
+ // System.out.println("Skipping unknown criteria:" + criteria[i]);
+ }
+ objects.clear();
+ maximizes = criteria[i].startsWith("+");
+ for (Iterator it = weightedObjects.iterator(); it.hasNext();) {
+ thing = ((WeightedObject) it.next()).thing;
+ if (maximizes) {
+ thing = dependencyHelper.not(thing);
+ }
+ objects.add(thing);
+ }
+ dependencyHelper.addCriterion(objects);
+ newmaxvarid = dependencyHelper.getSolver().nextFreeVarId(false);
+ // System.out.println("# criteria " + criteria[i].substring(1) + " size is " + objects.size() + " using new vars " + formermaxvarid + " to " + newmaxvarid);
+ formermaxvarid = newmaxvarid;
+ }
+ weightedObjects.clear();
+ return null;
+ }
+
+ protected void changedRoots(List<WeightedObject<?>> weightedObjects, BigInteger weight, IInstallableUnit entryPointIU) {
+ Collection<IRequirement> requirements = entryPointIU.getRequirements();
+ for (IRequirement req : requirements) {
+ IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery(req.getMatches());
+ IQueryResult<IInstallableUnit> matches = picker.query(query, null);
+ Object[] changed = new Object[matches.toUnmodifiableSet().size()];
+ int i = 0;
+ for (IInstallableUnit match : matches) {
+ changed[i++] = isInstalledAsRoot(match) ? dependencyHelper.not(match) : match;
+ }
+ try {
+ Projector.AbstractVariable abs = new Projector.AbstractVariable("CHANGED"); //TODO
+ changeVariables.add(abs);
+ // abs <=> iuv1 or not iuv2 or ... or not iuvn
+ dependencyHelper.or(FakeExplanation.getInstance(), abs, changed);
+ weightedObjects.add(WeightedObject.newWO(abs, weight));
+ } catch (ContradictionException e) {
+ // TODO Auto-generated catch block TODO
+ e.printStackTrace();
+ }
+ }
+ }
+
+ protected void newRoots(List<WeightedObject<?>> weightedObjects, BigInteger weight, IInstallableUnit entryPointIU) {
+ Collection<IRequirement> requirements = entryPointIU.getRequirements();
+ for (IRequirement req : requirements) {
+ IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery(req.getMatches());
+ IQueryResult<IInstallableUnit> matches = picker.query(query, null);
+ boolean oneInstalled = false;
+ for (IInstallableUnit match : matches) {
+ oneInstalled = oneInstalled || isInstalledAsRoot(match);
+ }
+ if (!oneInstalled) {
+ try {
+ Projector.AbstractVariable abs = new Projector.AbstractVariable("NEW"); //TODO
+ newVariables.add(abs);
+ // a <=> iuv1 or ... or iuvn
+ dependencyHelper.or(FakeExplanation.getInstance(), abs, matches.toArray(IInstallableUnit.class));
+ weightedObjects.add(WeightedObject.newWO(abs, weight));
+ } catch (ContradictionException e) {
+ // should not happen
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ protected void removedRoots(List<WeightedObject<?>> weightedObjects, BigInteger weight, IInstallableUnit entryPointIU) {
+ Collection<IRequirement> requirements = entryPointIU.getRequirements();
+ for (IRequirement req : requirements) {
+ IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery(req.getMatches());
+ IQueryResult<IInstallableUnit> matches = picker.query(query, null);
+ boolean installed = false;
+ Object[] literals = new Object[matches.toUnmodifiableSet().size()];
+ int i = 0;
+ for (IInstallableUnit match : matches) {
+ installed = installed || isInstalledAsRoot(match);
+ literals[i++] = dependencyHelper.not(match);
+ }
+ if (installed) {
+ try {
+ Projector.AbstractVariable abs = new Projector.AbstractVariable("REMOVED"); //TODO
+ removalVariables.add(abs);
+ // abs <=> not iuv1 and ... and not iuvn
+ dependencyHelper.and(FakeExplanation.getInstance(), abs, literals);
+ weightedObjects.add(WeightedObject.newWO(abs, weight));
+ } catch (ContradictionException e) {
+ // should not happen TODO
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private static class FakeExplanation extends Explanation {
+ private static Explanation singleton = new FakeExplanation();
+
+ public static Explanation getInstance() {
+ return singleton;
+ }
+
+ protected int orderValue() {
+ return Explanation.OTHER_REASON;
+ }
+
+ @Override
+ public int shortAnswer() {
+ return 0;
+ }
+
+ }
+
+ private boolean isInstalledAsRoot(IInstallableUnit isInstalled) {
+ for (IInstallableUnit installed : alreadyExistingRoots) {
+ if (isInstalled.equals(installed))
+ return true;
+ }
+ return false;
+ }
+
+}

Back to the top