FilesDelta split to separate instances for production and tests

This commit is contained in:
nik
2012-07-25 20:21:57 +04:00
parent 316adb62b1
commit 91d4b867e1
3 changed files with 351 additions and 367 deletions
@@ -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);
}
}