Skip to content

Commit f2341a8

Browse files
committed
Improve substitution package handling and filter uses locally
Currently substitution packages handling can lead to a situation where the number of performed permutation increase considerably and the finding of a solution takes very long. In some cases it even times out and results in a failed resolve state. This now is improved by the following changes: When a permutation is removed from the stack, every requirement is checked if it is a substitution package and then resolve it to either external or internal case first: - if more candidates exits for this requirement a permutation is added to account for this alternative solution - now all other providers except the current one are dropped to make this a single provider as the choice can not be reverted and therefore other permutations in this path will be invalid - then it must be checked if the package resolves to an external provider in which case we need to drop the exported package capabilities of this bundle for the given package - after that all requirements are checked if they have only a single provider (what can happen independently or as part of the resolving to either external or internal) the use constraints are checked if they are in conflict with a currently selected provider and dropping such invalid choices - finally after that we check the package space consistency (that is a far more expensive check) what probably will result in more permutations created and checked until we found the best result to use
1 parent 1132e94 commit f2341a8

File tree

5 files changed

+371
-91
lines changed

5 files changed

+371
-91
lines changed

bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ public void testSubstitutableExports03() throws BundleException, IOException {
10941094

10951095
List<ModuleWire> providedWiresF = wiringF.getProvidedModuleWires(PackageNamespace.PACKAGE_NAMESPACE);
10961096
assertEquals("Wrong number of provided wires: " + providedWiresF, 0, providedWiresF.size());
1097-
assertSucessfulWith(report, 2, 1, 1, 1);
1097+
assertSucessfulWith(report, 2, 1, 1, 1); // TODO check why we now need MORE
10981098
}
10991099

11001100
@Test
@@ -3941,7 +3941,7 @@ public void testSubstitutionWithMoreThan2Providers() throws BundleException, IOE
39413941
modules.add(installDummyModule(manifest, manifest, container));
39423942
}
39433943
report = container.resolve(modules, true);
3944-
assertSucessfulWith(report, 15, 62, 47, 5);
3944+
assertSucessfulWith(report, 4, 75, 11, 1);
39453945
}
39463946

39473947
protected void assertSucessfulWith(ResolutionReport report, int maxProcessed, int maxSubstitution,
@@ -4370,14 +4370,14 @@ private static void assertWires(List<ModuleWire> required, List<ModuleWire>... p
43704370
@Test
43714371
public void testLocalUseConstraintViolations() throws Exception {
43724372
ResolutionReport result = resolveTestSet("set1");
4373-
assertSucessfulWith(result, 6, 20, 23, 6);
4373+
assertSucessfulWith(result, 3, 245, 7, 0);
43744374
}
43754375

43764376
@Test
43774377

43784378
public void testLocalUseConstraintViolations2() throws Exception {
43794379
ResolutionReport result = resolveTestSet("set2");
4380-
assertSucessfulWith(result, 3, 3, 1, 3);
4380+
assertSucessfulWith(result, 1, 2, 1, 0);
43814381
}
43824382

43834383
@Test
@@ -4394,17 +4394,18 @@ public void testSubstitutionPackageResolution() throws Exception {
43944394

43954395
@Test
43964396
public void testLargeSet() throws Exception {
4397-
ResolutionReport result = resolveModuleDatabaseDump("big", TimeUnit.MINUTES.toSeconds(5));
4398-
assertSucessfulWith(result, 1821, 29, 26359, 6736);
4397+
ResolutionReport result = resolveModuleDatabaseDump("big", 30, TimeUnit.SECONDS);
4398+
assertSucessfulWith(result, 1, 28, 1, 0);
43994399
}
44004400

44014401
@Test
44024402
public void testSdkSet() throws Exception {
4403-
ResolutionReport result = resolveModuleDatabaseDump("sdk202509", TimeUnit.MINUTES.toSeconds(1));
4404-
assertSucessfulWith(result, 9, 18, 1, 42);
4403+
ResolutionReport result = resolveModuleDatabaseDump("sdk202509", 10, TimeUnit.SECONDS);
4404+
assertSucessfulWith(result, 1, 17, 1, 0);
44054405
}
44064406

4407-
private ResolutionReport resolveModuleDatabaseDump(String testSetName, long batchTimeoutSeconds) throws Exception {
4407+
private ResolutionReport resolveModuleDatabaseDump(String testSetName, long batchTimeout, TimeUnit timeoutUnit)
4408+
throws Exception {
44084409
URL entry = getBundle().getEntry("/test_files/containerTests/" + testSetName + ".state");
44094410
assertNotNull("can't find test set: " + testSetName, entry);
44104411
int maxThreads = Math.max(Runtime.getRuntime().availableProcessors() - 1, 1);
@@ -4421,7 +4422,7 @@ private ResolutionReport resolveModuleDatabaseDump(String testSetName, long batc
44214422
ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(1);
44224423
Map<String, String> configuration = new HashMap<>();
44234424
configuration.put(EquinoxConfiguration.PROP_RESOLVER_BATCH_TIMEOUT,
4424-
Long.toString(TimeUnit.SECONDS.toMillis(batchTimeoutSeconds)));
4425+
Long.toString(timeoutUnit.toMillis(batchTimeout)));
44254426
DummyContainerAdaptor adaptor = new DummyContainerAdaptor(new DummyCollisionHook(false), configuration,
44264427
new DummyResolverHookFactory(), new DummyDebugOptions(Collections.emptyMap()));
44274428
adaptor.setResolverExecutor(executor);
@@ -4439,7 +4440,7 @@ private ResolutionReport resolveModuleDatabaseDump(String testSetName, long batc
44394440
}
44404441
}
44414442
AtomicBoolean timeout = new AtomicBoolean();
4442-
ScheduledFuture<?> watch = watchDog.schedule(() -> timeout.set(true), batchTimeoutSeconds, TimeUnit.SECONDS);
4443+
ScheduledFuture<?> watch = watchDog.schedule(() -> timeout.set(true), batchTimeout, timeoutUnit);
44434444
ResolutionReport report = container.resolve(container.getModules(), true);
44444445
watch.cancel(true);
44454446
assertFalse("Resolve operation timed out!", timeout.get());

bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Backlog.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.util.Collections;
2222
import java.util.LinkedHashMap;
23+
import java.util.List;
2324
import java.util.Map;
2425
import java.util.Map.Entry;
2526
import org.apache.felix.resolver.Candidates.FaultyResourcesReport;
@@ -57,7 +58,8 @@ public Backlog(ResolveSession session) {
5758
public Candidates getNext() {
5859
Candidates candidates;
5960
while ((candidates = session.getNextPermutation()) != null) {
60-
ResolutionError substituteError = candidates.checkSubstitutes();
61+
List<Candidates> alternatives = candidates.process(session.getLogger());
62+
alternatives.forEach(alt -> session.addPermutation(PermutationType.SUBSTITUTE, alt));
6163
FaultyResourcesReport report = candidates.getFaultyResources(Collections.emptyMap());
6264
if (!report.isMissing() || session.isCancelled()) {
6365
return candidates;

0 commit comments

Comments
 (0)