Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java')
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java151
1 files changed, 151 insertions, 0 deletions
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
new file mode 100644
index 000000000..55cc3811f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Rapicorp Inc. 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:
+ * Rapicorp, Inc. - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.internal.p2.director;
+
+import java.math.BigInteger;
+import java.util.*;
+import java.util.Map.Entry;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.core.helpers.CollectionUtils;
+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.WeightedObject;
+
+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;
+ private IQueryable<IInstallableUnit> lastState;
+ private List<AbstractVariable> abstractVariables;
+
+ // 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) {
+ this.lastState = lastState;
+ this.abstractVariables = abstractVariables;
+ this.picker = picker;
+ this.selectionContext = selectionContext;
+ this.slice = slice;
+ }
+
+ //Create an optimization function favoring the highest version of each IU
+ public List<WeightedObject<? extends Object>> createOptimizationFunction(IInstallableUnit metaIu, Collection<IInstallableUnit> newRoots) {
+ numberOfInstalledIUs = sizeOf(lastState);
+ List<WeightedObject<? extends Object>> weightedObjects = new ArrayList<WeightedObject<? extends Object>>();
+
+ Set<IInstallableUnit> transitiveClosure;
+ if (newRoots.isEmpty()) {
+ transitiveClosure = CollectionUtils.emptySet();
+ } else {
+ IQueryable<IInstallableUnit> queryable = new Slicer(picker, selectionContext, false).slice(newRoots.toArray(new IInstallableUnit[newRoots.size()]), new NullProgressMonitor());
+ if (queryable == null) {
+ transitiveClosure = CollectionUtils.emptySet();
+ } else {
+ transitiveClosure = queryable.query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).toSet();
+ }
+ }
+
+ Set<Entry<String, Map<Version, IInstallableUnit>>> s = slice.entrySet();
+ final BigInteger POWER = BigInteger.valueOf(numberOfInstalledIUs > 0 ? numberOfInstalledIUs + 1 : 2);
+
+ BigInteger maxWeight = POWER;
+ for (Entry<String, Map<Version, IInstallableUnit>> entry : s) {
+ List<IInstallableUnit> conflictingEntries = new ArrayList<IInstallableUnit>(entry.getValue().values());
+ if (conflictingEntries.size() == 1) {
+ IInstallableUnit iu = conflictingEntries.get(0);
+ if (iu != metaIu) {
+ weightedObjects.add(WeightedObject.newWO(iu, POWER));
+ }
+ continue;
+ }
+ // IUs are sorted from highest version to lowest.
+ Collections.sort(conflictingEntries, Collections.reverseOrder());
+ BigInteger weight = POWER;
+ // have we already found a version that is already installed?
+ boolean foundInstalled = false;
+ // have we already found a version that is in the new roots?
+ boolean foundRoot = false;
+ for (IInstallableUnit iu : conflictingEntries) {
+ if (!foundRoot && isInstalled(iu) && !transitiveClosure.contains(iu)) {
+ foundInstalled = true;
+ weightedObjects.add(WeightedObject.newWO(iu, BigInteger.ONE));
+ } else if (!foundInstalled && !foundRoot && isRoot(iu, newRoots)) {
+ foundRoot = true;
+ weightedObjects.add(WeightedObject.newWO(iu, BigInteger.ONE));
+ } else {
+ weightedObjects.add(WeightedObject.newWO(iu, weight));
+ }
+ weight = weight.multiply(POWER);
+ }
+ if (weight.compareTo(maxWeight) > 0)
+ maxWeight = weight;
+ }
+
+ // no need to add one here, since maxWeight is strictly greater than the
+ // 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));
+ }
+
+ maxWeight = maxWeight.multiply(POWER).add(BigInteger.ONE);
+
+ BigInteger optionalWeight = maxWeight.negate();
+ long countOptional = 1;
+ List<IInstallableUnit> requestedPatches = new ArrayList<IInstallableUnit>();
+ Collection<IRequirement> reqs = metaIu.getRequirements();
+ for (IRequirement req : reqs) {
+ if (req.getMin() > 0 || !req.isGreedy())
+ continue;
+ IQueryResult<IInstallableUnit> matches = picker.query(QueryUtil.createMatchQuery(req.getMatches()), null);
+ for (Iterator<IInstallableUnit> iterator = matches.iterator(); iterator.hasNext();) {
+ IInstallableUnit match = iterator.next();
+ if (match instanceof IInstallableUnitPatch) {
+ requestedPatches.add(match);
+ countOptional = countOptional + 1;
+ } else {
+ weightedObjects.add(WeightedObject.newWO(match, optionalWeight));
+ }
+ }
+ }
+
+ 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));
+ }
+ return weightedObjects;
+ }
+
+ protected boolean isInstalled(IInstallableUnit iu) {
+ return !lastState.query(QueryUtil.createIUQuery(iu), null).isEmpty();
+ }
+
+ private boolean isRoot(IInstallableUnit iu, Collection<IInstallableUnit> newRoots) {
+ return newRoots.contains(iu);
+ }
+
+ /**
+ * Efficiently compute the size of a queryable
+ */
+ private int sizeOf(IQueryable<IInstallableUnit> installedIUs) {
+ IQueryResult<IInstallableUnit> qr = installedIUs.query(QueryUtil.createIUAnyQuery(), null);
+ if (qr instanceof Collector<?>)
+ return ((Collector<?>) qr).size();
+ return qr.toUnmodifiableSet().size();
+ }
+
+}

Back to the top