mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
FilesDelta split to separate instances for production and tests
This commit is contained in:
@@ -33,7 +33,7 @@ public class BuildFSState extends FSState {
|
||||
private static final Key<FilesDelta> LAST_ROUND_DELTA_KEY = Key.create("_last_round_delta_");
|
||||
|
||||
// when true, will always determine dirty files by scanning FS and comparing timestamps
|
||||
// alternatively, when false, after first scan will rely on extarnal notifications about changes
|
||||
// alternatively, when false, after first scan will rely on external notifications about changes
|
||||
private final boolean myAlwaysScanFS;
|
||||
|
||||
public BuildFSState(boolean alwaysScanFS) {
|
||||
@@ -49,7 +49,7 @@ public class BuildFSState extends FSState {
|
||||
public Map<File, Set<File>> getSourcesToRecompile(@NotNull CompileContext context, final String moduleName, boolean forTests) {
|
||||
final FilesDelta lastRoundDelta = getRoundDelta(LAST_ROUND_DELTA_KEY, context);
|
||||
if (lastRoundDelta != null) {
|
||||
return lastRoundDelta.getSourcesToRecompile(forTests);
|
||||
return lastRoundDelta.getSourcesToRecompile();
|
||||
}
|
||||
return super.getSourcesToRecompile(context, moduleName, forTests);
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class BuildFSState extends FSState {
|
||||
final FilesDelta roundDelta = getRoundDelta(CURRENT_ROUND_DELTA_KEY, context);
|
||||
if (roundDelta != null) {
|
||||
if (getContextModules(context).contains(rd.module)) {
|
||||
roundDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
roundDelta.markRecompile(rd.root, file);
|
||||
}
|
||||
}
|
||||
return super.markDirty(context, file, rd, tsStorage);
|
||||
@@ -72,7 +72,7 @@ public class BuildFSState extends FSState {
|
||||
final FilesDelta roundDelta = getRoundDelta(CURRENT_ROUND_DELTA_KEY, context);
|
||||
if (roundDelta != null) {
|
||||
if (getContextModules(context).contains(rd.module)) {
|
||||
roundDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
roundDelta.markRecompile(rd.root, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,8 +138,8 @@ public class BuildFSState extends FSState {
|
||||
*/
|
||||
public boolean markAllUpToDate(CompileScope scope, final RootDescriptor rd, final Timestamps stamps, final long compilationStartStamp) throws IOException {
|
||||
boolean marked = false;
|
||||
final FilesDelta delta = getDelta(rd.module);
|
||||
final Set<File> files = delta.clearRecompile(rd.root, rd.isTestRoot);
|
||||
final FilesDelta delta = getDelta(rd.module, rd.isTestRoot);
|
||||
final Set<File> files = delta.clearRecompile(rd.root);
|
||||
if (files != null) {
|
||||
final CompilerExcludes excludes = scope.getProject().getCompilerConfiguration().getExcludes();
|
||||
for (File file : files) {
|
||||
@@ -149,7 +149,7 @@ public class BuildFSState extends FSState {
|
||||
if (!rd.isGeneratedSources && stamp > compilationStartStamp) {
|
||||
// if the file was modified after the compilation had started,
|
||||
// do not save the stamp considering file dirty
|
||||
delta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
delta.markRecompile(rd.root, file);
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Timestamp after compilation started; marking dirty again: " + file.getPath());
|
||||
}
|
||||
@@ -163,7 +163,7 @@ public class BuildFSState extends FSState {
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Not affected by compile scope; marking dirty again: " + file.getPath());
|
||||
}
|
||||
delta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
delta.markRecompile(rd.root, file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1,143 +1,155 @@
|
||||
package org.jetbrains.jps.incremental.fs;
|
||||
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.storage.Timestamps;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 4/20/12
|
||||
*/
|
||||
public class FSState {
|
||||
private final Map<String, FilesDelta> myDeltas = Collections.synchronizedMap(new HashMap<String, FilesDelta>());
|
||||
protected final Set<String> myInitialTestsScanPerformed = Collections.synchronizedSet(new HashSet<String>());
|
||||
protected final Set<String> myInitialProductionScanPerformed = Collections.synchronizedSet(new HashSet<String>());
|
||||
|
||||
public void save(DataOutput out) throws IOException {
|
||||
out.writeInt(myInitialTestsScanPerformed.size());
|
||||
for (String moduleName : myInitialTestsScanPerformed) {
|
||||
IOUtil.writeString(moduleName, out);
|
||||
getDelta(moduleName).save(out, true);
|
||||
}
|
||||
|
||||
out.writeInt(myInitialProductionScanPerformed.size());
|
||||
for (String moduleName : myInitialProductionScanPerformed) {
|
||||
IOUtil.writeString(moduleName, out);
|
||||
getDelta(moduleName).save(out, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void load(DataInput in) throws IOException {
|
||||
int testsDeltaCount = in.readInt();
|
||||
while (testsDeltaCount-- > 0) {
|
||||
final String moduleName = IOUtil.readString(in);
|
||||
getDelta(moduleName).load(in, true);
|
||||
myInitialTestsScanPerformed.add(moduleName);
|
||||
}
|
||||
|
||||
int productionDeltaCount = in.readInt();
|
||||
while (productionDeltaCount-- > 0) {
|
||||
final String moduleName = IOUtil.readString(in);
|
||||
getDelta(moduleName).load(in, false);
|
||||
myInitialProductionScanPerformed.add(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
myDeltas.clear();
|
||||
}
|
||||
|
||||
public void init(String moduleName, final Collection<String> deleteProduction, final Collection<String> deletedTests, final Map<File, Set<File>> recompileProduction, final Map<File, Set<File>> recompileTests) {
|
||||
getDelta(moduleName).init(deleteProduction, deletedTests, recompileProduction, recompileTests);
|
||||
myInitialTestsScanPerformed.add(moduleName);
|
||||
myInitialProductionScanPerformed.add(moduleName);
|
||||
}
|
||||
|
||||
public final void clearRecompile(final RootDescriptor rd) {
|
||||
getDelta(rd.module).clearRecompile(rd.root, rd.isTestRoot);
|
||||
}
|
||||
|
||||
public boolean markDirty(@Nullable CompileContext context, final File file, final RootDescriptor rd, final @Nullable Timestamps tsStorage) throws IOException {
|
||||
final FilesDelta mainDelta = getDelta(rd.module);
|
||||
final boolean marked = mainDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
if (marked && tsStorage != null) {
|
||||
tsStorage.removeStamp(file);
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
public boolean markDirtyIfNotDeleted(@Nullable CompileContext context,
|
||||
final File file,
|
||||
final RootDescriptor rd,
|
||||
final @Nullable Timestamps tsStorage) throws IOException {
|
||||
final boolean marked = getDelta(rd.module).markRecompileIfNotDeleted(rd.root, rd.isTestRoot, file);
|
||||
if (marked && tsStorage != null) {
|
||||
tsStorage.removeStamp(file);
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
public void registerDeleted(final String moduleName, final File file, final boolean forTests, @Nullable Timestamps tsStorage) throws IOException {
|
||||
getDelta(moduleName).addDeleted(file, forTests);
|
||||
if (tsStorage != null) {
|
||||
tsStorage.removeStamp(file);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<File, Set<File>> getSourcesToRecompile(@NotNull CompileContext context, final String moduleName, boolean forTests) {
|
||||
return getDelta(moduleName).getSourcesToRecompile(forTests);
|
||||
}
|
||||
|
||||
public void clearDeletedPaths(final String moduleName, final boolean forTests) {
|
||||
final FilesDelta delta = myDeltas.get(moduleName);
|
||||
if (delta != null) {
|
||||
delta.clearDeletedPaths(forTests);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<String> getAndClearDeletedPaths(final String moduleName, final boolean forTests) {
|
||||
final FilesDelta delta = myDeltas.get(moduleName);
|
||||
if (delta != null) {
|
||||
return delta.getAndClearDeletedPaths(forTests);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected final FilesDelta getDelta(final String moduleName) {
|
||||
synchronized (myDeltas) {
|
||||
FilesDelta delta = myDeltas.get(moduleName);
|
||||
if (delta == null) {
|
||||
delta = new FilesDelta();
|
||||
myDeltas.put(moduleName, delta);
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasWorkToDo() {
|
||||
for (Map.Entry<String, FilesDelta> entry : myDeltas.entrySet()) {
|
||||
final String moduleName = entry.getKey();
|
||||
if (!myInitialProductionScanPerformed.contains(moduleName) || !myInitialTestsScanPerformed.contains(moduleName)) {
|
||||
return true;
|
||||
}
|
||||
final FilesDelta delta = entry.getValue();
|
||||
if (delta.hasPathsToDelete() || delta.hasSourcesToRecompile()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean markInitialScanPerformed(final String moduleName, boolean forTests) {
|
||||
return (forTests ? myInitialTestsScanPerformed : myInitialProductionScanPerformed).add(moduleName);
|
||||
}
|
||||
}
|
||||
package org.jetbrains.jps.incremental.fs;
|
||||
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.storage.Timestamps;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 4/20/12
|
||||
*/
|
||||
public class FSState {
|
||||
private final Map<String, FilesDelta> myProductionDeltas = Collections.synchronizedMap(new HashMap<String, FilesDelta>());
|
||||
private final Map<String, FilesDelta> myTestDeltas = Collections.synchronizedMap(new HashMap<String, FilesDelta>());
|
||||
protected final Set<String> myInitialTestsScanPerformed = Collections.synchronizedSet(new HashSet<String>());
|
||||
protected final Set<String> myInitialProductionScanPerformed = Collections.synchronizedSet(new HashSet<String>());
|
||||
|
||||
public void save(DataOutput out) throws IOException {
|
||||
out.writeInt(myInitialTestsScanPerformed.size());
|
||||
for (String moduleName : myInitialTestsScanPerformed) {
|
||||
IOUtil.writeString(moduleName, out);
|
||||
getDelta(moduleName, true).save(out);
|
||||
}
|
||||
|
||||
out.writeInt(myInitialProductionScanPerformed.size());
|
||||
for (String moduleName : myInitialProductionScanPerformed) {
|
||||
IOUtil.writeString(moduleName, out);
|
||||
getDelta(moduleName, false).save(out);
|
||||
}
|
||||
}
|
||||
|
||||
public void load(DataInput in) throws IOException {
|
||||
int testsDeltaCount = in.readInt();
|
||||
while (testsDeltaCount-- > 0) {
|
||||
final String moduleName = IOUtil.readString(in);
|
||||
getDelta(moduleName, true).load(in);
|
||||
myInitialTestsScanPerformed.add(moduleName);
|
||||
}
|
||||
|
||||
int productionDeltaCount = in.readInt();
|
||||
while (productionDeltaCount-- > 0) {
|
||||
final String moduleName = IOUtil.readString(in);
|
||||
getDelta(moduleName, false).load(in);
|
||||
myInitialProductionScanPerformed.add(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
myProductionDeltas.clear();
|
||||
myTestDeltas.clear();
|
||||
}
|
||||
|
||||
public void init(String moduleName, final Collection<String> deleteProduction, final Collection<String> deletedTests, final Map<File, Set<File>> recompileProduction, final Map<File, Set<File>> recompileTests) {
|
||||
getDelta(moduleName, true).init(deletedTests, recompileTests);
|
||||
getDelta(moduleName, false).init(deleteProduction, recompileProduction);
|
||||
myInitialTestsScanPerformed.add(moduleName);
|
||||
myInitialProductionScanPerformed.add(moduleName);
|
||||
}
|
||||
|
||||
public final void clearRecompile(final RootDescriptor rd) {
|
||||
getDelta(rd.module, rd.isTestRoot).clearRecompile(rd.root);
|
||||
}
|
||||
|
||||
public boolean markDirty(@Nullable CompileContext context, final File file, final RootDescriptor rd, final @Nullable Timestamps tsStorage) throws IOException {
|
||||
final FilesDelta mainDelta = getDelta(rd.module, rd.isTestRoot);
|
||||
final boolean marked = mainDelta.markRecompile(rd.root, file);
|
||||
if (marked && tsStorage != null) {
|
||||
tsStorage.removeStamp(file);
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
public boolean markDirtyIfNotDeleted(@Nullable CompileContext context,
|
||||
final File file,
|
||||
final RootDescriptor rd,
|
||||
final @Nullable Timestamps tsStorage) throws IOException {
|
||||
final boolean marked = getDelta(rd.module, rd.isTestRoot).markRecompileIfNotDeleted(rd.root, rd.isTestRoot, file);
|
||||
if (marked && tsStorage != null) {
|
||||
tsStorage.removeStamp(file);
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
public void registerDeleted(final String moduleName, final File file, final boolean forTests, @Nullable Timestamps tsStorage) throws IOException {
|
||||
getDelta(moduleName, forTests).addDeleted(file);
|
||||
if (tsStorage != null) {
|
||||
tsStorage.removeStamp(file);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<File, Set<File>> getSourcesToRecompile(@NotNull CompileContext context, final String moduleName, boolean forTests) {
|
||||
return getDelta(moduleName, forTests).getSourcesToRecompile();
|
||||
}
|
||||
|
||||
public void clearDeletedPaths(final String moduleName, final boolean forTests) {
|
||||
final FilesDelta delta = getDeltas(forTests).get(moduleName);
|
||||
if (delta != null) {
|
||||
delta.clearDeletedPaths();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, FilesDelta> getDeltas(boolean forTests) {
|
||||
return forTests ? myTestDeltas : myProductionDeltas;
|
||||
}
|
||||
|
||||
public Collection<String> getAndClearDeletedPaths(final String moduleName, final boolean forTests) {
|
||||
final FilesDelta delta = getDeltas(forTests).get(moduleName);
|
||||
if (delta != null) {
|
||||
return delta.getAndClearDeletedPaths();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected final FilesDelta getDelta(final String moduleName, boolean forTests) {
|
||||
Map<String, FilesDelta> deltas = getDeltas(forTests);
|
||||
synchronized (deltas) {
|
||||
FilesDelta delta = deltas.get(moduleName);
|
||||
if (delta == null) {
|
||||
delta = new FilesDelta();
|
||||
deltas.put(moduleName, delta);
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasWorkToDo() {
|
||||
return hasWorkToDo(false) || hasWorkToDo(true);
|
||||
}
|
||||
|
||||
private boolean hasWorkToDo(final boolean forTests) {
|
||||
for (Map.Entry<String, FilesDelta> entry : getDeltas(forTests).entrySet()) {
|
||||
final String moduleName = entry.getKey();
|
||||
if (!myInitialProductionScanPerformed.contains(moduleName) || !myInitialTestsScanPerformed.contains(moduleName)) {
|
||||
return true;
|
||||
}
|
||||
final FilesDelta delta = entry.getValue();
|
||||
if (delta.hasPathsToDelete() || delta.hasSourcesToRecompile()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean markInitialScanPerformed(final String moduleName, boolean forTests) {
|
||||
return (forTests ? myInitialTestsScanPerformed : myInitialProductionScanPerformed).add(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,216 +1,188 @@
|
||||
package org.jetbrains.jps.incremental.fs;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.incremental.Utils;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/** @noinspection SynchronizationOnLocalVariableOrMethodParameter*/
|
||||
final class FilesDelta {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.fs.FilesDelta");
|
||||
|
||||
private final Set<String> myDeletedProduction = Collections.synchronizedSet(new HashSet<String>());
|
||||
private final Set<String> myDeletedTests = Collections.synchronizedSet(new HashSet<String>());
|
||||
private final Map<File, Set<File>> mySourcesToRecompile = Collections.synchronizedMap(new HashMap<File, Set<File>>()); // srcRoot -> set of sources
|
||||
private final Map<File, Set<File>> myTestsToRecompile = Collections.synchronizedMap(new HashMap<File, Set<File>>()); // srcRoot -> set of sources
|
||||
|
||||
public void save(DataOutput out, final boolean tests) throws IOException {
|
||||
final Set<String> deleted = tests? myDeletedTests : myDeletedProduction;
|
||||
out.writeInt(deleted.size());
|
||||
for (String path : deleted) {
|
||||
IOUtil.writeString(path, out);
|
||||
}
|
||||
final Map<File, Set<File>> recompile = tests? myTestsToRecompile : mySourcesToRecompile;
|
||||
out.writeInt(recompile.size());
|
||||
for (Map.Entry<File, Set<File>> entry : recompile.entrySet()) {
|
||||
final File root = entry.getKey();
|
||||
IOUtil.writeString(FileUtil.toSystemIndependentName(root.getPath()), out);
|
||||
final Set<File> files = entry.getValue();
|
||||
out.writeInt(files.size());
|
||||
for (File file : files) {
|
||||
IOUtil.writeString(FileUtil.toSystemIndependentName(file.getPath()), out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void load(DataInput in, final boolean tests) throws IOException {
|
||||
final Set<String> deleted = tests? myDeletedTests : myDeletedProduction;
|
||||
deleted.clear();
|
||||
int deletedCount = in.readInt();
|
||||
while (deletedCount-- > 0) {
|
||||
deleted.add(IOUtil.readString(in));
|
||||
}
|
||||
final Map<File, Set<File>> recompile = tests? myTestsToRecompile : mySourcesToRecompile;
|
||||
recompile.clear();
|
||||
int recompileCount = in.readInt();
|
||||
while (recompileCount-- > 0) {
|
||||
final File root = new File(IOUtil.readString(in));
|
||||
Set<File> files = recompile.get(root);
|
||||
if (files == null) {
|
||||
files = createSetOfFiles();
|
||||
recompile.put(root, files);
|
||||
}
|
||||
int filesCount = in.readInt();
|
||||
while (filesCount-- > 0) {
|
||||
final File file = new File(IOUtil.readString(in));
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Loaded " + file.getPath());
|
||||
}
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Set<File> createSetOfFiles() {
|
||||
return new THashSet<File>(new TObjectHashingStrategy<File>() {
|
||||
@Override
|
||||
public int computeHashCode(File file) {
|
||||
return FileUtil.fileHashCode(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(File f1, File f2) {
|
||||
return FileUtil.filesEqual(f1, f2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void init(Collection<String> deletedProduction, Collection<String> deletedTests, Map<File, Set<File>> recompileProduction, Map<File, Set<File>> recompileTests) {
|
||||
myDeletedProduction.clear();
|
||||
myDeletedProduction.addAll(deletedProduction);
|
||||
myDeletedTests.clear();
|
||||
myDeletedTests.addAll(deletedTests);
|
||||
mySourcesToRecompile.clear();
|
||||
mySourcesToRecompile.putAll(recompileProduction);
|
||||
myTestsToRecompile.clear();
|
||||
myTestsToRecompile.putAll(recompileTests);
|
||||
}
|
||||
|
||||
|
||||
public boolean markRecompile(File root, boolean isTestRoot, File file) {
|
||||
final boolean added = _addToRecompiled(root, isTestRoot, file);
|
||||
if (added) {
|
||||
final Set<String> deleted = isTestRoot? myDeletedTests : myDeletedProduction;
|
||||
synchronized (deleted) {
|
||||
if (!deleted.isEmpty()) { // optimization
|
||||
deleted.remove(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean markRecompileIfNotDeleted(File root, boolean isTestRoot, File file) {
|
||||
final Set<String> deleted = isTestRoot? myDeletedTests : myDeletedProduction;
|
||||
final boolean isMarkedDeleted;
|
||||
synchronized (deleted) {
|
||||
isMarkedDeleted = !deleted.isEmpty() && deleted.contains(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
if (!isMarkedDeleted) {
|
||||
return _addToRecompiled(root, isTestRoot, file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean _addToRecompiled(File root, boolean isTestRoot, File file) {
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Marking dirty: " + file.getPath());
|
||||
}
|
||||
|
||||
final Map<File, Set<File>> toRecompile = isTestRoot ? myTestsToRecompile : mySourcesToRecompile;
|
||||
Set<File> files;
|
||||
synchronized (toRecompile) {
|
||||
files = toRecompile.get(root);
|
||||
if (files == null) {
|
||||
files = createSetOfFiles();
|
||||
toRecompile.put(root, files);
|
||||
}
|
||||
return files.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDeleted(File file, boolean isTest) {
|
||||
// ensure the file is no more marked to recompilation
|
||||
final Map<File, Set<File>> toRecompile = isTest ? myTestsToRecompile : mySourcesToRecompile;
|
||||
synchronized (toRecompile) {
|
||||
for (Set<File> files : toRecompile.values()) {
|
||||
files.remove(file);
|
||||
}
|
||||
}
|
||||
final Set<String> deleted = isTest? myDeletedTests : myDeletedProduction;
|
||||
final String path = FileUtil.toCanonicalPath(file.getPath());
|
||||
deleted.add(path);
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Marking deleted: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearDeletedPaths(boolean isTest) {
|
||||
final Set<String> deleted = isTest? myDeletedTests : myDeletedProduction;
|
||||
deleted.clear();
|
||||
}
|
||||
|
||||
public Set<String> getAndClearDeletedPaths(boolean isTest) {
|
||||
final Set<String> deleted = isTest? myDeletedTests : myDeletedProduction;
|
||||
synchronized (deleted) {
|
||||
try {
|
||||
return new HashSet<String>(deleted);
|
||||
}
|
||||
finally {
|
||||
deleted.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<File, Set<File>> getSourcesToRecompile(boolean forTests) {
|
||||
return forTests? myTestsToRecompile : mySourcesToRecompile;
|
||||
}
|
||||
|
||||
public boolean hasSourcesToRecompile() {
|
||||
synchronized (myTestsToRecompile) {
|
||||
if(!myTestsToRecompile.isEmpty()) {
|
||||
for (Set<File> files : myTestsToRecompile.values()) {
|
||||
if (!files.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (mySourcesToRecompile) {
|
||||
if(!mySourcesToRecompile.isEmpty()) {
|
||||
for (Set<File> files : mySourcesToRecompile.values()) {
|
||||
if (!files.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasPathsToDelete() {
|
||||
return !myDeletedTests.isEmpty() || !myDeletedProduction.isEmpty();
|
||||
}
|
||||
|
||||
public Set<String> getDeletedPaths(boolean isTest) {
|
||||
final Set<String> deleted = isTest ? myDeletedTests : myDeletedProduction;
|
||||
synchronized (deleted) {
|
||||
return deleted.isEmpty()? Collections.<String>emptySet() : new HashSet<String>(deleted);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<File> clearRecompile(File root, boolean isTestRoot) {
|
||||
return isTestRoot? myTestsToRecompile.remove(root) : mySourcesToRecompile.remove(root);
|
||||
}
|
||||
}
|
||||
package org.jetbrains.jps.incremental.fs;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.incremental.Utils;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/** @noinspection SynchronizationOnLocalVariableOrMethodParameter*/
|
||||
final class FilesDelta {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.fs.FilesDelta");
|
||||
|
||||
private final Set<String> myDeletedPaths = Collections.synchronizedSet(new HashSet<String>());
|
||||
private final Map<File, Set<File>> myFilesToRecompile = Collections.synchronizedMap(new HashMap<File, Set<File>>()); // srcRoot -> set of sources
|
||||
|
||||
public void save(DataOutput out) throws IOException {
|
||||
out.writeInt(myDeletedPaths.size());
|
||||
for (String path : myDeletedPaths) {
|
||||
IOUtil.writeString(path, out);
|
||||
}
|
||||
out.writeInt(myFilesToRecompile.size());
|
||||
for (Map.Entry<File, Set<File>> entry : myFilesToRecompile.entrySet()) {
|
||||
final File root = entry.getKey();
|
||||
IOUtil.writeString(FileUtil.toSystemIndependentName(root.getPath()), out);
|
||||
final Set<File> files = entry.getValue();
|
||||
out.writeInt(files.size());
|
||||
for (File file : files) {
|
||||
IOUtil.writeString(FileUtil.toSystemIndependentName(file.getPath()), out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void load(DataInput in) throws IOException {
|
||||
myDeletedPaths.clear();
|
||||
int deletedCount = in.readInt();
|
||||
while (deletedCount-- > 0) {
|
||||
myDeletedPaths.add(IOUtil.readString(in));
|
||||
}
|
||||
myFilesToRecompile.clear();
|
||||
int recompileCount = in.readInt();
|
||||
while (recompileCount-- > 0) {
|
||||
final File root = new File(IOUtil.readString(in));
|
||||
Set<File> files = myFilesToRecompile.get(root);
|
||||
if (files == null) {
|
||||
files = createSetOfFiles();
|
||||
myFilesToRecompile.put(root, files);
|
||||
}
|
||||
int filesCount = in.readInt();
|
||||
while (filesCount-- > 0) {
|
||||
final File file = new File(IOUtil.readString(in));
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Loaded " + file.getPath());
|
||||
}
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Set<File> createSetOfFiles() {
|
||||
return new THashSet<File>(new TObjectHashingStrategy<File>() {
|
||||
@Override
|
||||
public int computeHashCode(File file) {
|
||||
return FileUtil.fileHashCode(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(File f1, File f2) {
|
||||
return FileUtil.filesEqual(f1, f2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void init(Collection<String> deleted, Map<File, Set<File>> recompile) {
|
||||
myDeletedPaths.clear();
|
||||
myDeletedPaths.addAll(deleted);
|
||||
myFilesToRecompile.clear();
|
||||
myFilesToRecompile.putAll(recompile);
|
||||
}
|
||||
|
||||
public boolean markRecompile(File root, File file) {
|
||||
final boolean added = _addToRecompiled(root, file);
|
||||
if (added) {
|
||||
synchronized (myDeletedPaths) {
|
||||
if (!myDeletedPaths.isEmpty()) { // optimization
|
||||
myDeletedPaths.remove(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean markRecompileIfNotDeleted(File root, boolean isTestRoot, File file) {
|
||||
final boolean isMarkedDeleted;
|
||||
synchronized (myDeletedPaths) {
|
||||
isMarkedDeleted = !myDeletedPaths.isEmpty() && myDeletedPaths.contains(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
if (!isMarkedDeleted) {
|
||||
return _addToRecompiled(root, file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean _addToRecompiled(File root, File file) {
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Marking dirty: " + file.getPath());
|
||||
}
|
||||
|
||||
Set<File> files;
|
||||
synchronized (myFilesToRecompile) {
|
||||
files = myFilesToRecompile.get(root);
|
||||
if (files == null) {
|
||||
files = createSetOfFiles();
|
||||
myFilesToRecompile.put(root, files);
|
||||
}
|
||||
return files.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDeleted(File file) {
|
||||
// ensure the file is no more marked to recompilation
|
||||
synchronized (myFilesToRecompile) {
|
||||
for (Set<File> files : myFilesToRecompile.values()) {
|
||||
files.remove(file);
|
||||
}
|
||||
}
|
||||
final String path = FileUtil.toCanonicalPath(file.getPath());
|
||||
myDeletedPaths.add(path);
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Marking deleted: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearDeletedPaths() {
|
||||
myDeletedPaths.clear();
|
||||
}
|
||||
|
||||
public Set<String> getAndClearDeletedPaths() {
|
||||
synchronized (myDeletedPaths) {
|
||||
try {
|
||||
return new HashSet<String>(myDeletedPaths);
|
||||
}
|
||||
finally {
|
||||
myDeletedPaths.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<File, Set<File>> getSourcesToRecompile() {
|
||||
return myFilesToRecompile;
|
||||
}
|
||||
|
||||
public boolean hasSourcesToRecompile() {
|
||||
synchronized (myFilesToRecompile) {
|
||||
if(!myFilesToRecompile.isEmpty()) {
|
||||
for (Set<File> files : myFilesToRecompile.values()) {
|
||||
if (!files.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasPathsToDelete() {
|
||||
return !myDeletedPaths.isEmpty();
|
||||
}
|
||||
|
||||
public Set<String> getDeletedPaths() {
|
||||
synchronized (myDeletedPaths) {
|
||||
return myDeletedPaths.isEmpty()? Collections.<String>emptySet() : new HashSet<String>(myDeletedPaths);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<File> clearRecompile(File root) {
|
||||
return myFilesToRecompile.remove(root);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user