diff --git a/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheConfigurator.java b/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheConfigurator.java index 9471a4f453b6..5a2ab42e43d5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheConfigurator.java +++ b/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheConfigurator.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.compiler.cache; import com.intellij.compiler.CompilerConfigurationSettings; @@ -42,6 +42,7 @@ public class CompilerCacheConfigurator { builder.setDeletionSpeed(CompilerCacheLoadingSettings.getApproximateDeletionSpeed()); builder.setForceDownload(CompilerCacheLoadingSettings.getForceUpdateValue()); builder.setDisableDownload(CompilerCacheLoadingSettings.getDisableUpdateValue()); + builder.setCleanupAsynchronously(CompilerCacheLoadingSettings.getCleanupAsynchronouslyValue()); builder.setMaxDownloadDuration(CompilerCacheLoadingSettings.getMaxDownloadDuration()); return builder.build(); } diff --git a/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheLoadingSettings.java b/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheLoadingSettings.java index 019fd18dfaf1..80f3bea59398 100644 --- a/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheLoadingSettings.java +++ b/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheLoadingSettings.java @@ -9,6 +9,7 @@ public class CompilerCacheLoadingSettings { private static final String FORCE_UPDATE = "JpsOutputLoaderManager.forceUpdate"; private static final String DISABLE_UPDATE = "JpsOutputLoaderManager.disableUpdate"; + private static final String CLEANUP_ASYNCHRONOUSLY = "JpsOutputLoaderManager.cleanupAsynchronously"; private static final String MAX_DOWNLOAD_DURATION = "JpsOutputLoaderManager.maxDownloadDuration"; private static final String APPROXIMATE_DELETION_SPEED = "JpsOutputLoaderManager.deletionBytesPerSec"; private static final String APPROXIMATE_DECOMPRESSION_SPEED = "JpsOutputLoaderManager.decompressionBytesPerSec"; @@ -35,6 +36,17 @@ public class CompilerCacheLoadingSettings { return disableUpdate; } + public static void saveCleanupAsynchronouslyValue(boolean cleanupAsynchronously) { + PropertiesComponent.getInstance().setValue(CLEANUP_ASYNCHRONOUSLY, cleanupAsynchronously); + LOG.info("Saving cleanup asynchronously value: " + cleanupAsynchronously); + } + + public static boolean getCleanupAsynchronouslyValue() { + boolean cleanupAsynchronously = PropertiesComponent.getInstance().getBoolean(CLEANUP_ASYNCHRONOUSLY, false); + LOG.info("Getting cleanup asynchronously value: " + cleanupAsynchronously); + return cleanupAsynchronously; + } + public static void saveMaxDownloadDuration(int maxDownloadDuration) { PropertiesComponent.getInstance().setValue(MAX_DOWNLOAD_DURATION, String.valueOf(maxDownloadDuration)); LOG.info("Saving max download duration: " + maxDownloadDuration); diff --git a/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheConfigurable.java index 2074495a7584..f1f91752767f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheConfigurable.java @@ -23,11 +23,14 @@ public class CompilerCacheConfigurable implements SearchableConfigurable, Config private JBCheckBox myCbDisableCacheDownload; private JTextField myMaxDownloadDurationField; private JBLabel myMaxDownloadDurationDescription; + private JBCheckBox myCbCleanupAsynchronously; + private JBLabel myCleanupAsynchronouslyDescription; public CompilerCacheConfigurable(final Project project) { myProject = project; myForceUpdateDescription.setText("Turn off the heuristic that determines when it's faster to download cache or build locally and force downloads the nearest cache at each build"); //NON-NLS myMaxDownloadDurationDescription.setText("Set maximum applicable time of caches download. If the approximate time of work will be higher local build will be executed."); //NON-NLS + myCleanupAsynchronouslyDescription.setText("Removes old cache directories asynchronously. This option might produce garbage under 'system/plugins' and spawn long-living rsync processes."); //NON-NLS } @Override @@ -50,6 +53,7 @@ public class CompilerCacheConfigurable implements SearchableConfigurable, Config public boolean isModified() { boolean isModified = ComparingUtils.isModified(myCbForceUpdateCaches, CompilerCacheLoadingSettings.getForceUpdateValue()); isModified |= ComparingUtils.isModified(myCbDisableCacheDownload, CompilerCacheLoadingSettings.getDisableUpdateValue()); + isModified |= ComparingUtils.isModified(myCbCleanupAsynchronously, CompilerCacheLoadingSettings.getCleanupAsynchronouslyValue()); isModified |= ComparingUtils.isModified(myMaxDownloadDurationField, String.valueOf(CompilerCacheLoadingSettings.getMaxDownloadDuration())); return isModified; } @@ -59,6 +63,7 @@ public class CompilerCacheConfigurable implements SearchableConfigurable, Config try { CompilerCacheLoadingSettings.saveForceUpdateValue(myCbForceUpdateCaches.isSelected()); CompilerCacheLoadingSettings.saveDisableUpdateValue(myCbDisableCacheDownload.isSelected()); + CompilerCacheLoadingSettings.saveCleanupAsynchronouslyValue(myCbCleanupAsynchronously.isSelected()); CompilerCacheLoadingSettings.saveMaxDownloadDuration(Integer.parseInt(myMaxDownloadDurationField.getText())); } finally { @@ -72,6 +77,7 @@ public class CompilerCacheConfigurable implements SearchableConfigurable, Config public void reset() { myCbForceUpdateCaches.setSelected(CompilerCacheLoadingSettings.getForceUpdateValue()); myCbDisableCacheDownload.setSelected(CompilerCacheLoadingSettings.getDisableUpdateValue()); + myCbCleanupAsynchronously.setSelected(CompilerCacheLoadingSettings.getCleanupAsynchronouslyValue()); myMaxDownloadDurationField.setText(String.valueOf(CompilerCacheLoadingSettings.getMaxDownloadDuration())); } } diff --git a/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheOptionsPanel.form b/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheOptionsPanel.form index ab13e4a8e9b9..fa6afc18dc24 100644 --- a/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheOptionsPanel.form +++ b/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheOptionsPanel.form @@ -1,6 +1,6 @@
diff --git a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties index 9360dafc0fbf..877fc8cf63b5 100644 --- a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties +++ b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties @@ -334,6 +334,7 @@ notification.group.compiler=Build finished compiler.cache.description=Compiler Cache compiler.cache.option.force.update=Force update caches compiler.cache.option.disable.update=Disable cache download +compiler.cache.option.cleanup.asynchronously=Cleanup aynchronously compiler.cache.option.max.download.time=Maximum duration of caches download: compiler.cache.option.max.download.time.units= mins notification.title.jps.caches.downloader=Jps caches downloader diff --git a/jps/jps-builders/gen/org/jetbrains/jps/api/CmdlineRemoteProto.java b/jps/jps-builders/gen/org/jetbrains/jps/api/CmdlineRemoteProto.java index 9a00b61af5d4..1c5c6a197bb2 100644 --- a/jps/jps-builders/gen/org/jetbrains/jps/api/CmdlineRemoteProto.java +++ b/jps/jps-builders/gen/org/jetbrains/jps/api/CmdlineRemoteProto.java @@ -1,3 +1,5 @@ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + // Generated by the protocol buffer compiler. DO NOT EDIT! // source: cmdline_remote_proto.proto @@ -5577,6 +5579,17 @@ public final class CmdlineRemoteProto { * @return The maxDownloadDuration. */ int getMaxDownloadDuration(); + + /** + *required bool cleanup_asynchronously = 10;
+ * @return Whether the cleanupAsynchronously field is set.
+ */
+ boolean hasCleanupAsynchronously();
+ /**
+ * required bool cleanup_asynchronously = 10;
+ * @return The cleanupAsynchronously.
+ */
+ boolean getCleanupAsynchronously();
}
/**
* Protobuf type {@code org.jetbrains.jpsservice.Message.ControllerMessage.CacheDownloadSettings}
@@ -5996,6 +6009,40 @@ public final class CmdlineRemoteProto {
maxDownloadDuration_ = 0;
}
+ public static final int CLEANUP_ASYNCHRONOUSLY_FIELD_NUMBER = 10;
+ private boolean cleanupAsynchronously_;
+ /**
+ * required bool cleanup_asynchronously = 10;
+ * @return Whether the cleanupAsynchronously field is set.
+ */
+ @java.lang.Override
+ public boolean hasCleanupAsynchronously() {
+ return ((bitField0_ & 0x00000100) != 0);
+ }
+ /**
+ * required bool cleanup_asynchronously = 10;
+ * @return The cleanupAsynchronously.
+ */
+ @java.lang.Override
+ public boolean getCleanupAsynchronously() {
+ return cleanupAsynchronously_;
+ }
+ /**
+ * required bool cleanup_asynchronously = 10;
+ * @param value The cleanupAsynchronously to set.
+ */
+ private void setCleanupAsynchronously(boolean value) {
+ bitField0_ |= 0x00000100;
+ cleanupAsynchronously_ = value;
+ }
+ /**
+ * required bool cleanup_asynchronously = 10;
+ */
+ private void clearCleanupAsynchronously() {
+ bitField0_ = (bitField0_ & ~0x00000100);
+ cleanupAsynchronously_ = false;
+ }
+
public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.CacheDownloadSettings parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
@@ -6519,6 +6566,42 @@ public final class CmdlineRemoteProto {
return this;
}
+ /**
+ * required bool cleanup_asynchronously = 10;
+ * @return Whether the cleanupAsynchronously field is set.
+ */
+ @java.lang.Override
+ public boolean hasCleanupAsynchronously() {
+ return instance.hasCleanupAsynchronously();
+ }
+ /**
+ * required bool cleanup_asynchronously = 10;
+ * @return The cleanupAsynchronously.
+ */
+ @java.lang.Override
+ public boolean getCleanupAsynchronously() {
+ return instance.getCleanupAsynchronously();
+ }
+ /**
+ * required bool cleanup_asynchronously = 10;
+ * @param value The cleanupAsynchronously to set.
+ * @return This builder for chaining.
+ */
+ public Builder setCleanupAsynchronously(boolean value) {
+ copyOnWrite();
+ instance.setCleanupAsynchronously(value);
+ return this;
+ }
+ /**
+ * required bool cleanup_asynchronously = 10;
+ * @return This builder for chaining.
+ */
+ public Builder clearCleanupAsynchronously() {
+ copyOnWrite();
+ instance.clearCleanupAsynchronously();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.ControllerMessage.CacheDownloadSettings)
}
private byte memoizedIsInitialized = 2;
@@ -6547,11 +6630,12 @@ public final class CmdlineRemoteProto {
"forceDownload_",
"disableDownload_",
"maxDownloadDuration_",
+ "cleanupAsynchronously_",
};
java.lang.String info =
- "\u0001\t\u0000\u0001\u0001\t\t\u0001\u0000\b\u00012\u0002\u1508\u0000\u0003\u1504" +
+ "\u0001\n\u0000\u0001\u0001\n\n\u0001\u0000\t\u00012\u0002\u1508\u0000\u0003\u1504" +
"\u0001\u0004\u1508\u0002\u0005\u1502\u0003\u0006\u1502\u0004\u0007\u1507\u0005\b" +
- "\u1507\u0006\t\u1504\u0007";
+ "\u1507\u0006\t\u1504\u0007\n\u1507\b";
return newMessageInfo(DEFAULT_INSTANCE, info, objects);
}
// fall through
diff --git a/jps/jps-builders/proto/cmdline_remote_proto.proto b/jps/jps-builders/proto/cmdline_remote_proto.proto
index f7ff0f11b27d..eab1bdf179f6 100644
--- a/jps/jps-builders/proto/cmdline_remote_proto.proto
+++ b/jps/jps-builders/proto/cmdline_remote_proto.proto
@@ -86,6 +86,7 @@ message Message {
required bool force_download = 7;
required bool disable_download = 8;
required int32 max_download_duration = 9;
+ required bool cleanup_asynchronously = 10;
}
required Type type = 1;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cache/JpsCachesLoaderUtil.java b/jps/jps-builders/src/org/jetbrains/jps/cache/JpsCachesLoaderUtil.java
index 9ff6f516bd20..42abf3a6f53e 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/cache/JpsCachesLoaderUtil.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/cache/JpsCachesLoaderUtil.java
@@ -1,9 +1,23 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.jps.cache;
+import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.concurrency.AppExecutorUtil;
+import org.jetbrains.annotations.NotNull;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
import java.util.concurrent.ExecutorService;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static com.intellij.execution.process.ProcessIOExecutorService.INSTANCE;
@@ -20,4 +34,76 @@ public final class JpsCachesLoaderUtil {
LOG.info("Executor service will be configured with " + threadsCount + " threads");
return threadsCount;
}
+
+ public static void delete(@NotNull File dir, boolean asynchronously) {
+ if (!asynchronously) {
+ FileUtil.delete(dir);
+ return;
+ }
+
+ LOG.info("Deleting asynchronously... " + dir.getPath());
+ try {
+ File temp = getEmptyTempDir();
+ Path moved = Files.move(dir.toPath(), temp.toPath());
+ EXECUTOR_SERVICE.execute(() -> delete(moved));
+ }
+ catch (IOException e) {
+ LOG.warn("Unable to move directory: " + e.getMessage());
+ FileUtil.delete(dir);
+ }
+ }
+
+ public static void runCleanUpAsynchronously() {
+ LOG.info("Running clean-up asynchronously...");
+ Path pluginTemp = Path.of(PathManager.getPluginTempPath());
+ try (Stream