From ef6493532ef6ce94ba390249e3bd6bf32a3b3323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sun, 21 Apr 2024 08:42:17 +0200 Subject: [PATCH] Improve caching of artifacts using new Transport#downloadArtifact Currently Tycho maintain different caches, e.g. some items are cached in the local maven repository, some are cached in the transport caches and there is even a P2 remote cache maintained. Apart from that, P2/PDE/Ooomph also maintain so called bundle pools. With the new Transport#downloadArtifact method we now have an opportunity to merge all these caches in a reliable way just using the artifact that is already there saving both downloads times and disk space. --- .../transport/TychoRepositoryTransport.java | 73 ++++++++++++++++--- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransport.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransport.java index 81c68efcc3..6ba77b4fe0 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransport.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransport.java @@ -43,6 +43,9 @@ import org.eclipse.equinox.internal.provisional.p2.repository.IStateful; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.core.spi.IAgentServiceFactory; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.eclipse.equinox.p2.metadata.Version; +import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor; @Component(role = org.eclipse.equinox.internal.p2.repository.Transport.class, hint = "tycho") public class TychoRepositoryTransport extends org.eclipse.equinox.internal.p2.repository.Transport @@ -94,35 +97,81 @@ public IStatus download(URI toDownload, OutputStream target, long startPos, IPro @Override public IStatus download(URI toDownload, OutputStream target, IProgressMonitor monitor) { + return downloadArtifact(toDownload, target, null, monitor); + } + + private IStatus reportStatus(IStatus status, OutputStream target) { + if (target instanceof IStateful stateful) { + stateful.setStatus(status); + } + return status; + } + + @Override + public IStatus downloadArtifact(URI source, OutputStream target, IArtifactDescriptor descriptor, + IProgressMonitor monitor) { + if (descriptor != null) { + // TODO query the p2 pools! + Path cacheLocation = getCacheLocation(descriptor); + if (Files.isRegularFile(cacheLocation)) { + // TODO need to check local properties! + try { + Files.copy(cacheLocation, target); + } catch (IOException e) { + return reportStatus(Status.error("download from " + source + " failed", e), target); + } + return reportStatus(Status.OK_STATUS, target); + } else { + // TODO need to download to cache! + } + } String id = "p2"; // TODO we might compute the id from the IRepositoryIdManager based on the URI? - if (cacheConfig.isInteractive()) { - logger.info("Downloading from " + id + ": " + toDownload); + boolean printMessage = cacheConfig.isInteractive() && !cacheConfig.isOffline(); + if (printMessage) { + logger.info("Downloading from " + id + ": " + source); } try { DownloadStatusOutputStream statusOutputStream = new DownloadStatusOutputStream(target, - "Download of " + toDownload); - stream(toDownload, monitor).transferTo(statusOutputStream); + "Download of " + source); + stream(source, monitor).transferTo(statusOutputStream); DownloadStatus downloadStatus = statusOutputStream.getStatus(); - if (cacheConfig.isInteractive()) { - logger.info("Downloaded from " + id + ": " + toDownload + " (" + if (printMessage) { + logger.info("Downloaded from " + id + ": " + source + " (" + FileUtils.byteCountToDisplaySize(downloadStatus.getFileSize()) + " at " + FileUtils.byteCountToDisplaySize(downloadStatus.getTransferRate()) + "/s)"); } return reportStatus(downloadStatus, target); } catch (AuthenticationFailedException e) { - return Status.error("authentication failed for " + toDownload, e); + return Status.error("authentication failed for " + source, e); } catch (IOException e) { - return reportStatus(Status.error("download from " + toDownload + " failed", e), target); + return reportStatus(Status.error("download from " + source + " failed", e), target); } catch (CoreException e) { return reportStatus(e.getStatus(), target); } } - private IStatus reportStatus(IStatus status, OutputStream target) { - if (target instanceof IStateful stateful) { - stateful.setStatus(status); + private Path getCacheLocation(IArtifactDescriptor descriptor) { + Path location = cacheConfig.getCacheLocation().toPath(); + IArtifactKey artifactKey = descriptor.getArtifactKey(); + // TODO check the maven properties and construct a path to the local repo! + return location.resolve(getClassifier(artifactKey)).resolve(artifactKey.getId()) + .resolve(getVersion(artifactKey)); + } + + private String getVersion(IArtifactKey artifactKey) { + Version version = artifactKey.getVersion(); + if (version == null) { + return "0.0.0"; } - return status; + return version.toString(); + } + + private String getClassifier(IArtifactKey artifactKey) { + String classifier = artifactKey.getClassifier(); + if (classifier == null || classifier.isBlank()) { + return "artifacts"; + } + return classifier; } @Override