IncProjectBuilder to use timestamps service only via Timestamps interface

This commit is contained in:
Eugene Zhuravlev
2012-04-24 13:45:47 +02:00
parent ca5c4ca90c
commit 86279cee88
8 changed files with 81 additions and 51 deletions
@@ -31,6 +31,7 @@ import org.jetbrains.jps.server.ProjectDescriptor;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.*;
@@ -149,11 +150,11 @@ final class BuildSession implements Runnable, CanceledStatus {
ProjectDescriptor pd;
final Project project = loadProject(projectPath);
final BuildFSState fsState = new BuildFSState(false);
ProjectTimestamps timestamps = null;
ProjectTimestamps projectTimestamps = null;
BuildDataManager dataManager = null;
final File dataStorageRoot = Utils.getDataStorageRoot(project);
try {
timestamps = new ProjectTimestamps(dataStorageRoot);
projectTimestamps = new ProjectTimestamps(dataStorageRoot);
dataManager = new BuildDataManager(dataStorageRoot, true);
if (dataManager.versionDiffers()) {
forceCleanCaches = true;
@@ -163,21 +164,21 @@ final class BuildSession implements Runnable, CanceledStatus {
catch (Exception e) {
// second try
LOG.info(e);
if (timestamps != null) {
timestamps.close();
if (projectTimestamps != null) {
projectTimestamps.close();
}
if (dataManager != null) {
dataManager.close();
}
forceCleanCaches = true;
FileUtil.delete(dataStorageRoot);
timestamps = new ProjectTimestamps(dataStorageRoot);
projectTimestamps = new ProjectTimestamps(dataStorageRoot);
dataManager = new BuildDataManager(dataStorageRoot, true);
// second attempt succeded
msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.INFO, "Project rebuild forced: " + e.getMessage()));
}
pd = new ProjectDescriptor(project, fsState, timestamps, dataManager, BuildLoggingManager.DEFAULT);
pd = new ProjectDescriptor(project, fsState, projectTimestamps, dataManager, BuildLoggingManager.DEFAULT);
try {
for (int attempt = 0; attempt < 2; attempt++) {
@@ -185,8 +186,19 @@ final class BuildSession implements Runnable, CanceledStatus {
// if compilation scope is the whole project and cache rebuild is forced, use PROJECT_REBUILD for faster compilation
buildType = BuildType.PROJECT_REBUILD;
}
final CompileScope compileScope = createCompilationScope(buildType, pd, modules, artifacts, paths);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), builderParams, cs);
if (buildType == BuildType.PROJECT_REBUILD || forceCleanCaches) {
try {
pd.timestamps.clean();
}
catch (IOException e) {
throw new ProjectBuildException("Error cleaning timestamps storage", e);
}
}
final Timestamps timestamps = pd.timestamps.getStorage();
final CompileScope compileScope = createCompilationScope(buildType, pd, timestamps, modules, artifacts, paths);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), timestamps, builderParams, cs);
builder.addMessageHandler(msgHandler);
try {
switch (buildType) {
@@ -352,7 +364,11 @@ final class BuildSession implements Runnable, CanceledStatus {
return !(projectFile.isFile() && projectFile.getName().endsWith(".ipr"));
}
private static CompileScope createCompilationScope(BuildType buildType, ProjectDescriptor pd, Set<String> modules, Collection<String> artifactNames, Collection<String> paths) throws Exception {
private static CompileScope createCompilationScope(BuildType buildType,
ProjectDescriptor pd,
final Timestamps timestamps, Set<String> modules,
Collection<String> artifactNames,
Collection<String> paths) throws Exception {
Set<Artifact> artifacts = new HashSet<Artifact>();
if (artifactNames.isEmpty() && buildType == BuildType.PROJECT_REBUILD) {
artifacts.addAll(pd.project.getArtifacts().values());
@@ -385,8 +401,6 @@ final class BuildSession implements Runnable, CanceledStatus {
forcedModules = Collections.emptySet();
}
final Timestamps tsStorage = pd.timestamps.getStorage();
final Map<String, Set<File>> filesToCompile;
if (!paths.isEmpty()) {
filesToCompile = new HashMap<String, Set<File>>();
@@ -401,7 +415,7 @@ final class BuildSession implements Runnable, CanceledStatus {
}
files.add(file);
if (buildType == BuildType.FORCED_COMPILATION) {
pd.fsState.markDirty(file, rd, tsStorage);
pd.fsState.markDirty(file, rd, timestamps);
}
}
}
@@ -51,9 +51,9 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler
ProjectChunks testChunks,
MessageHandler delegateMessageHandler,
Map<String, String> builderParams,
CanceledStatus cancelStatus) throws ProjectBuildException {
final Timestamps timestamps, CanceledStatus cancelStatus) throws ProjectBuildException {
myProjectDescriptor = pd;
myTimestamps = myProjectDescriptor.timestamps.getStorage();
myTimestamps = timestamps;
myBuilderParams = Collections.unmodifiableMap(builderParams);
myCancelStatus = cancelStatus;
myCompilationStartStamp = System.currentTimeMillis();
@@ -272,7 +272,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler
return myProjectDescriptor.dataManager;
}
public Timestamps getTimestampStorage() {
public Timestamps getTimestamps() {
return myTimestamps;
}
@@ -1,8 +1,6 @@
package org.jetbrains.jps.incremental;
import com.intellij.openapi.Forceable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.io.MappingFailedException;
@@ -22,6 +20,7 @@ import org.jetbrains.jps.incremental.messages.ProgressMessage;
import org.jetbrains.jps.incremental.storage.BuildDataManager;
import org.jetbrains.jps.incremental.storage.SourceToFormMapping;
import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
import org.jetbrains.jps.incremental.storage.Timestamps;
import org.jetbrains.jps.server.ProjectDescriptor;
import java.io.BufferedWriter;
@@ -63,8 +62,9 @@ public class IncProjectBuilder {
private final float myTotalModulesWork;
private final int myTotalModuleLevelBuilderCount;
private final List<Future> myAsyncTasks = new ArrayList<Future>();
private final Timestamps myTimestamps;
public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, Map<String, String> builderParams, CanceledStatus cs) {
public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, final Timestamps timestamps, Map<String, String> builderParams, CanceledStatus cs) {
myProjectDescriptor = pd;
myBuilderRegistry = builderRegistry;
myBuilderParams = builderParams;
@@ -73,6 +73,7 @@ public class IncProjectBuilder {
myTestChunks = new ProjectChunks(pd.project, ClasspathKind.TEST_COMPILE);
myTotalModulesWork = (float)pd.rootsIndex.getTotalModuleCount() * 2; /* multiply by 2 to reflect production and test sources */
myTotalModuleLevelBuilderCount = builderRegistry.getModuleLevelBuilderCount();
myTimestamps = timestamps;
}
public void addMessageHandler(MessageHandler handler) {
@@ -80,18 +81,6 @@ public class IncProjectBuilder {
}
public void build(CompileScope scope, final boolean isMake, final boolean isProjectRebuild, boolean forceCleanCaches) throws RebuildRequestedException{
final LowMemoryWatcher memWatcher = LowMemoryWatcher.register(new Forceable() {
@Override
public boolean isDirty() {
return true; // always perform flush when not enough memory
}
@Override
public void force() {
myProjectDescriptor.dataManager.flush(false);
myProjectDescriptor.timestamps.getStorage().force();
}
});
CompileContext context = null;
try {
context = createContext(scope, isMake, isProjectRebuild);
@@ -121,7 +110,6 @@ public class IncProjectBuilder {
}
}
finally {
memWatcher.stop();
flushContext(context);
// wait for the async tasks
for (Future task : myAsyncTasks) {
@@ -137,7 +125,7 @@ public class IncProjectBuilder {
private static void flushContext(CompileContext context) {
if (context != null) {
context.getProjectDescriptor().timestamps.getStorage().force();
context.getTimestamps().force();
context.getDataManager().flush(false);
}
final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context);
@@ -208,18 +196,12 @@ public class IncProjectBuilder {
private CompileContext createContext(CompileScope scope, boolean isMake, final boolean isProjectRebuild) throws ProjectBuildException {
return new CompileContext(
scope, myProjectDescriptor, isMake, isProjectRebuild, myProductionChunks, myTestChunks, myMessageDispatcher,
myBuilderParams, myCancelStatus
myBuilderParams, myTimestamps, myCancelStatus
);
}
private void cleanOutputRoots(CompileContext context) throws ProjectBuildException {
// whole project is affected
try {
myProjectDescriptor.timestamps.clean();
}
catch (IOException e) {
throw new ProjectBuildException("Error cleaning timestamps storage", e);
}
try {
context.getDataManager().clean();
}
@@ -8,6 +8,7 @@ import java.io.IOException;
* Date: 4/24/12
*/
public interface Timestamps {
void force();
void saveStamp(File file, long timestamp) throws IOException;
@@ -1,6 +1,8 @@
package org.jetbrains.jps.server;
import com.intellij.openapi.Forceable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import groovy.util.Node;
@@ -28,6 +30,7 @@ import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
import org.jetbrains.jps.incremental.storage.Timestamps;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;
@@ -171,14 +174,39 @@ class ServerState {
pd.incUsageCounter();
}
final ProjectDescriptor finalPd = pd;
final LowMemoryWatcher memWatcher = LowMemoryWatcher.register(new Forceable() {
@Override
public boolean isDirty() {
return true; // always perform flush when not enough memory
}
@Override
public void force() {
finalPd.dataManager.flush(false);
finalPd.timestamps.getStorage().force();
}
});
try {
for (int attempt = 0; attempt < 2; attempt++) {
if (forceCleanCaches && modules.isEmpty() && paths.isEmpty()) {
// if compilation scope is the whole project and cache rebuild is forced, use PROJECT_REBUILD for faster compilation
buildType = BuildType.PROJECT_REBUILD;
}
final CompileScope compileScope = createCompilationScope(buildType, pd, modules, artifacts, paths);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), builderParams, cs);
if (buildType == BuildType.PROJECT_REBUILD || forceCleanCaches) {
try {
pd.timestamps.clean();
}
catch (IOException e) {
throw new ProjectBuildException("Error cleaning timestamps storage", e);
}
}
final Timestamps timestamps = pd.timestamps.getStorage();
final CompileScope compileScope = createCompilationScope(buildType, pd, timestamps, modules, artifacts, paths);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), timestamps, builderParams, cs);
builder.addMessageHandler(msgHandler);
try {
switch (buildType) {
@@ -213,13 +241,18 @@ class ServerState {
}
}
finally {
memWatcher.stop();
pd.release();
clearZipIndexCache();
}
}
private static CompileScope createCompilationScope(BuildType buildType, ProjectDescriptor pd, Set<String> modules,
Collection<String> artifactNames, Collection<String> paths) throws Exception {
private static CompileScope createCompilationScope(BuildType buildType,
ProjectDescriptor pd,
final Timestamps timestamps,
Set<String> modules,
Collection<String> artifactNames,
Collection<String> paths) throws Exception {
Set<Artifact> artifacts = new HashSet<Artifact>();
if (artifactNames.isEmpty() && buildType == BuildType.PROJECT_REBUILD) {
artifacts.addAll(pd.project.getArtifacts().values());
@@ -252,8 +285,6 @@ class ServerState {
forcedModules = Collections.emptySet();
}
final Timestamps marker = pd.timestamps.getStorage();
final Map<String, Set<File>> filesToCompile;
if (!paths.isEmpty()) {
filesToCompile = new HashMap<String, Set<File>>();
@@ -268,7 +299,7 @@ class ServerState {
}
files.add(file);
if (buildType == BuildType.FORCED_COMPILATION) {
pd.fsState.markDirty(file, rd, marker);
pd.fsState.markDirty(file, rd, timestamps);
}
}
}
@@ -208,7 +208,7 @@ public abstract class IncrementalTestCase extends TestCase {
new BuildDataManager(dataStorageRoot, true), new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), javaBuilderLogger));
try {
new IncProjectBuilder(
projectDescriptor, BuilderRegistry.getInstance(), Collections.<String, String>emptyMap(), CanceledStatus.NULL
projectDescriptor, BuilderRegistry.getInstance(), projectDescriptor.timestamps.getStorage(), Collections.<String, String>emptyMap(), CanceledStatus.NULL
).build(
new AllProjectScope(project, Collections.<Artifact>emptySet(), true), false, true, false
);
@@ -220,7 +220,7 @@ public abstract class IncrementalTestCase extends TestCase {
}
new IncProjectBuilder(
projectDescriptor, BuilderRegistry.getInstance(), Collections.<String, String>emptyMap(), CanceledStatus.NULL
projectDescriptor, BuilderRegistry.getInstance(), projectDescriptor.timestamps.getStorage(), Collections.<String, String>emptyMap(), CanceledStatus.NULL
).build(
new AllProjectScope(project, Collections.<Artifact>emptySet(), false), true, false, false
);
@@ -31,6 +31,7 @@ import org.jetbrains.jps.incremental.java.JavaBuilderLoggerImpl;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.storage.BuildDataManager;
import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
import org.jetbrains.jps.incremental.storage.Timestamps;
import org.jetbrains.jps.server.ClasspathBootstrap;
import org.jetbrains.jps.server.ProjectDescriptor;
@@ -181,7 +182,8 @@ public abstract class ArtifactBuilderTestCase extends UsefulTestCase {
myDescriptor.incUsageCounter();
}
myArtifactBuilderLogger.clear();
IncProjectBuilder builder = new IncProjectBuilder(myDescriptor, BuilderRegistry.getInstance(), Collections.<String, String>emptyMap(), CanceledStatus.NULL);
final Timestamps timestamps = myDescriptor.timestamps.getStorage();
IncProjectBuilder builder = new IncProjectBuilder(myDescriptor, BuilderRegistry.getInstance(), timestamps, Collections.<String, String>emptyMap(), CanceledStatus.NULL);
final List<BuildMessage> errorMessages = new ArrayList<BuildMessage>();
final List<BuildMessage> infoMessages = new ArrayList<BuildMessage>();
builder.addMessageHandler(new MessageHandler() {
@@ -318,7 +318,7 @@ public class AndroidDexBuilder extends ProjectLevelBuilder {
final AndroidFileSetState newState = new AndroidFileSetState(allFiles, AndroidJpsUtil.CLASSES_AND_JARS_FILTER, true);
final AndroidFileSetState oldState = proguardStateStorage.getState(module.getName());
if (context.getTimestampStorage().getStamp(proguardCfgFile) == proguardCfgFile.lastModified() &&
if (context.getTimestamps().getStamp(proguardCfgFile) == proguardCfgFile.lastModified() &&
newState.equalsTo(oldState)) {
return true;
}
@@ -349,7 +349,7 @@ public class AndroidDexBuilder extends ProjectLevelBuilder {
proguardStateStorage.update(module.getName(), success ? newState : null);
if (success) {
context.getTimestampStorage().saveStamp(proguardCfgFile, proguardCfgFile.lastModified());
context.getTimestamps().saveStamp(proguardCfgFile, proguardCfgFile.lastModified());
}
return success;
}