From dab6dd00b781d2468e1a397fe40dcf1d1909ecc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Thu, 16 May 2024 06:29:08 +0200 Subject: [PATCH 1/2] Cache loaded repos in ProvisioningContext Currently if fetching updates the provision context is queried multiple times leading to the repositories loaded multiple times, even though this is usually faster as repo are cached this still produces unnecessary workload, especially if there is one failed repository it will be tried to be loaded over and over again. This now caches the repositories loaded on first access to speed that up. --- .../p2/engine/ProvisioningContext.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/p2/engine/ProvisioningContext.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/p2/engine/ProvisioningContext.java index 5560d8f1a..84daa9430 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/p2/engine/ProvisioningContext.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/p2/engine/ProvisioningContext.java @@ -208,18 +208,22 @@ private void getLoadedRepository(URI location, IArtifactRepositoryManager repoMa } private Set getLoadedMetadataRepositories(IProgressMonitor monitor) { - IMetadataRepositoryManager repoManager = agent.getService(IMetadataRepositoryManager.class); - URI[] repositories = metadataRepositories == null ? repoManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL) : metadataRepositories; - - Map repos = new HashMap<>(); - SubMonitor sub = SubMonitor.convert(monitor, repositories.length); - - // Clear out the list of remembered artifact repositories - referencedArtifactRepositories = new HashMap<>(); - for (URI repositorie : repositories) { - loadMetadataRepository(repoManager, repositorie, repos, shouldFollowReferences(), sub.split(1)); + if (loadedRepos == null) { + IMetadataRepositoryManager repoManager = agent.getService(IMetadataRepositoryManager.class); + URI[] repositories = metadataRepositories == null + ? repoManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL) + : metadataRepositories; + + loadedRepos = new HashMap<>(); + SubMonitor sub = SubMonitor.convert(monitor, repositories.length); + + // Clear out the list of remembered artifact repositories + referencedArtifactRepositories = new HashMap<>(); + for (URI repositorie : repositories) { + loadMetadataRepository(repoManager, repositorie, loadedRepos, shouldFollowReferences(), sub.split(1)); + } } - return new HashSet<>(repos.values()); + return new HashSet<>(loadedRepos.values()); } private void loadMetadataRepository(IMetadataRepositoryManager manager, URI location, @@ -406,6 +410,7 @@ private > void loadRepository(IRepositoryManager private static final Comparator ARTIFACT_KEY_COMPARATOR = Comparator // .comparing(IArtifactKey::getId) // .thenComparing(IArtifactKey::getVersion); + private Map loadedRepos; /** * Returns a map from simple artifact repository location to a subset of the From 5bc1d2d799a59b4323589b764d8f0954934e77ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Thu, 16 May 2024 07:55:13 +0200 Subject: [PATCH 2/2] Fix ProvisioningContextTest.testFollowHelpsResolve is violating API Currently ProvisioningContextTest.testFollowHelpsResolve() assumes it can modify the context repositories after using the context but this is not valid according to API. --- .../equinox/p2/engine/ProvisioningContext.java | 4 ++-- .../p2/tests/engine/ProvisioningContextTest.java | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/p2/engine/ProvisioningContext.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/p2/engine/ProvisioningContext.java index 84daa9430..e0a051395 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/p2/engine/ProvisioningContext.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/p2/engine/ProvisioningContext.java @@ -219,8 +219,8 @@ private Set getLoadedMetadataRepositories(IProgressMonitor // Clear out the list of remembered artifact repositories referencedArtifactRepositories = new HashMap<>(); - for (URI repositorie : repositories) { - loadMetadataRepository(repoManager, repositorie, loadedRepos, shouldFollowReferences(), sub.split(1)); + for (URI repository : repositories) { + loadMetadataRepository(repoManager, repository, loadedRepos, shouldFollowReferences(), sub.split(1)); } } return new HashSet<>(loadedRepos.values()); diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/ProvisioningContextTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/ProvisioningContextTest.java index 4fe0b5879..adb8b19c4 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/ProvisioningContextTest.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/ProvisioningContextTest.java @@ -22,7 +22,10 @@ import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil; import org.eclipse.equinox.p2.planner.IProfileChangeRequest; -import org.eclipse.equinox.p2.query.*; +import org.eclipse.equinox.p2.query.ExpressionMatchQuery; +import org.eclipse.equinox.p2.query.IQuery; +import org.eclipse.equinox.p2.query.IQueryable; +import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.equinox.p2.repository.IRepository; import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; @@ -199,6 +202,12 @@ public void testFollowHelpsResolve() { context.setArtifactRepositories(new URI[0]); IProvisioningPlan plan = getPlanner(getAgent()).getProvisioningPlan(request, context, getMonitor()); assertFalse("resolve should fail with missing requirements", plan.getStatus().isOK()); + // we need to create a new context as the planner is calling + // ProvisioningContext.getMetadata(IProgressMonitor) and after that call + // repositories are fixed as per API... + context = new ProvisioningContext(getAgent()); + context.setMetadataRepositories(new URI[] { repoA.getLocation() }); + context.setArtifactRepositories(new URI[0]); context.setProperty(ProvisioningContext.FOLLOW_REPOSITORY_REFERENCES, "true"); plan = getPlanner(getAgent()).getProvisioningPlan(request, context, getMonitor()); assertTrue("resolve should pass", plan.getStatus().isOK());