[platform] performs project roots check in background; ensures watcher has finished setting roots (IDEA-155767)

This commit is contained in:
Roman Shevchenko
2016-05-19 13:48:50 +02:00
parent c718f493fa
commit 1e6deb6f4e
2 changed files with 32 additions and 61 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,11 +45,13 @@ import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
import com.intellij.util.PathUtil;
import com.intellij.util.SmartList;
import com.intellij.util.TimeoutUtil;
import com.intellij.util.io.storage.HeavyProcessLatch;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.ide.PooledThreadExecutor;
import java.io.FileNotFoundException;
import java.util.Collection;
@@ -111,6 +113,7 @@ public class StartupManagerImpl extends StartupManagerEx {
return myPostStartupActivitiesPassed;
}
@SuppressWarnings("SynchronizeOnThis")
public void runStartupActivities() {
ApplicationManager.getApplication().runReadAction(() -> {
AccessToken token = HeavyProcessLatch.INSTANCE.processStarted("Running Startup Activities");
@@ -118,14 +121,14 @@ public class StartupManagerImpl extends StartupManagerEx {
runActivities(myPreStartupActivities);
// to avoid atomicity issues if runWhenProjectIsInitialized() is run at the same time
synchronized (StartupManagerImpl.this) {
synchronized (this) {
myPreStartupActivitiesPassed = true;
myStartupActivitiesRunning = true;
}
runActivities(myStartupActivities);
synchronized (StartupManagerImpl.this) {
synchronized (this) {
myStartupActivitiesRunning = false;
myStartupActivitiesPassed = true;
}
@@ -260,32 +263,38 @@ public class StartupManagerImpl extends StartupManagerEx {
}
private void checkProjectRoots() {
VirtualFile[] roots = ProjectRootManager.getInstance(myProject).getContentRoots();
if (roots.length == 0) return;
LocalFileSystem fs = LocalFileSystem.getInstance();
if (!(fs instanceof LocalFileSystemImpl)) return;
FileWatcher watcher = ((LocalFileSystemImpl)fs).getFileWatcher();
if (!watcher.isOperational()) return;
Collection<String> manualWatchRoots = watcher.getManualWatchRoots();
if (manualWatchRoots.isEmpty()) return;
VirtualFile[] roots = ProjectRootManager.getInstance(myProject).getContentRoots();
if (roots.length == 0) return;
List<String> nonWatched = new SmartList<String>();
for (VirtualFile root : roots) {
if (!(root.getFileSystem() instanceof LocalFileSystem)) continue;
String rootPath = root.getPath();
for (String manualWatchRoot : manualWatchRoots) {
if (FileUtil.isAncestor(manualWatchRoot, rootPath, false)) {
nonWatched.add(rootPath);
PooledThreadExecutor.INSTANCE.submit(() -> {
LOG.debug("FW/roots waiting started");
while (watcher.isSettingRoots()) TimeoutUtil.sleep(10);
LOG.debug("FW/roots waiting finished");
Collection<String> manualWatchRoots = watcher.getManualWatchRoots();
if (!manualWatchRoots.isEmpty()) {
List<String> nonWatched = new SmartList<String>();
for (VirtualFile root : roots) {
if (!(root.getFileSystem() instanceof LocalFileSystem)) continue;
String rootPath = root.getPath();
for (String manualWatchRoot : manualWatchRoots) {
if (FileUtil.isAncestor(manualWatchRoot, rootPath, false)) {
nonWatched.add(rootPath);
}
}
}
if (!nonWatched.isEmpty()) {
String message = ApplicationBundle.message("watcher.non.watchable.project");
watcher.notifyOnFailure(message, null);
LOG.info("unwatched roots: " + nonWatched);
LOG.info("manual watches: " + manualWatchRoots);
}
}
}
if (!nonWatched.isEmpty()) {
String message = ApplicationBundle.message("watcher.non.watchable.project");
watcher.notifyOnFailure(message, null);
LOG.info("unwatched roots: " + nonWatched);
LOG.info("manual watches: " + manualWatchRoots);
}
});
}
public void startCacheUpdate() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package com.intellij.openapi.project.impl;
import com.intellij.CommonBundle;
import com.intellij.conversion.ConversionResult;
import com.intellij.conversion.ConversionService;
import com.intellij.ide.AppLifecycleListener;
@@ -33,7 +32,6 @@ import com.intellij.openapi.components.impl.stores.StorageUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.*;
import com.intellij.openapi.progress.util.ProgressWindow;
import com.intellij.openapi.project.*;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.startup.StartupManager;
@@ -41,11 +39,8 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.ZipHandler;
import com.intellij.openapi.vfs.impl.local.FileWatcher;
import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl;
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
import com.intellij.ui.GuiUtils;
import com.intellij.util.ArrayUtil;
@@ -323,20 +318,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable {
return false;
}
DumbService.allowStartingDumbModeInside(DumbModePermission.MAY_START_BACKGROUND, () ->
DumbService.getInstance(project).queueTask(new DumbModeTask() {
@Override
public void performInDumbMode(@NotNull ProgressIndicator indicator) {
waitForFileWatcher(indicator);
}
@Override
public String toString() {
return "wait for file watcher";
}
})
);
Runnable process = () -> {
TransactionGuard.getInstance().submitTransactionAndWait(() -> fireProjectOpened(project));
@@ -402,25 +383,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable {
return !(indicator instanceof NonCancelableSection);
}
private static void waitForFileWatcher(@NotNull ProgressIndicator indicator) {
LocalFileSystem fs = LocalFileSystem.getInstance();
if (!(fs instanceof LocalFileSystemImpl)) return;
final FileWatcher watcher = ((LocalFileSystemImpl)fs).getFileWatcher();
if (!watcher.isOperational() || !watcher.isSettingRoots()) return;
LOG.info("FW/roots waiting started");
indicator.setIndeterminate(true);
indicator.setText(ProjectBundle.message("project.load.waiting.watcher"));
if (indicator instanceof ProgressWindow) {
((ProgressWindow)indicator).setCancelButtonText(CommonBundle.message("button.skip"));
}
while (watcher.isSettingRoots() && !indicator.isCanceled()) {
TimeoutUtil.sleep(10);
}
LOG.info("FW/roots waiting finished");
}
@Override
public Project loadAndOpenProject(@NotNull final String filePath) throws IOException {
Project project = myProgressManager.run(new Task.WithResult<Project, IOException>(null, ProjectBundle.message("project.load.progress"), true) {