Skip to content

Commit

Permalink
hash based deps processing
Browse files Browse the repository at this point in the history
  • Loading branch information
treblereel committed Sep 7, 2022
1 parent 55ee66b commit 96e9762
Show file tree
Hide file tree
Showing 34 changed files with 372 additions and 778 deletions.
5 changes: 5 additions & 0 deletions build-caching/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<version>3.28.0-GA</version>
</dependency>

<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>3.24.4</version>
</dependency>

<!-- watch service -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.vertispan.j2cl.build;

import com.vertispan.j2cl.build.impl.CollectedTaskInputs;
import com.vertispan.j2cl.build.incremental.BuildMap;
import com.vertispan.j2cl.build.incremental.BuildMapHashReader;
import com.vertispan.j2cl.build.incremental.JavaFileHashReader;
import com.vertispan.j2cl.build.task.OutputTypes;
import com.vertispan.j2cl.build.task.TaskFactory;
import org.apache.commons.io.FileUtils;
Expand All @@ -23,8 +26,6 @@
import java.util.stream.Stream;

public class BuildService {

private Map<Project, Path> strippedSources = new HashMap<>();
private final TaskRegistry taskRegistry;
private final TaskScheduler taskScheduler;
private final DiskCache diskCache;
Expand All @@ -35,6 +36,9 @@ public class BuildService {

// hashes of each file in each project, updated under lock
private final Map<Project, Map<Path, DiskCache.CacheEntry>> currentProjectSourceHash = new HashMap<>();
private final AtomicReference<Map<Project, Map<Path, DiskCache.CacheEntry>>> createdFilesRef = new AtomicReference<>();
private final AtomicReference<Map<Project, Map<Path, DiskCache.CacheEntry>>> changedFilesRef = new AtomicReference<>();
private final AtomicReference<Map<Project, Map<Path, DiskCache.CacheEntry>>> deletedFilesRef = new AtomicReference<>();

private BlockingBuildListener prevBuild;

Expand All @@ -48,10 +52,6 @@ public BuildService(TaskRegistry taskRegistry, TaskScheduler taskScheduler, Disk
this.incremental = incremental;
}

public void addStrippedSourcesPath(Project project, Path path) {
this.strippedSources.put(project, path);
}

public Map<Project, BuildMap> getBuildMaps() {
return buildMaps;
}
Expand All @@ -69,6 +69,10 @@ public DiskCache getDiskCache() {
public void assignProject(Project project, String finalTask, PropertyTrackingConfig.ConfigValueProvider config) {
// find the tasks and their upstream tasks
collectTasksFromProject(finalTask, project, config, inputs);
// TODO this is a bit of a hack, but it's the only way to get the project's .class files
if(incremental) {
collectTasksFromProject(OutputTypes.BYTECODE, project, config, inputs);
}
}

private void collectTasksFromProject(String taskName, Project project, PropertyTrackingConfig.ConfigValueProvider config, Map<Input, CollectedTaskInputs> collectedSoFar) {
Expand All @@ -89,7 +93,7 @@ private void collectTasksFromProject(String taskName, Project project, PropertyT
throw new NullPointerException("Missing task factory: " + taskName);
}
assert taskFactory.inputs.isEmpty();
TaskFactory.Task task = taskFactory.resolve(project, propertyTrackingConfig, this);
TaskFactory.Task task = taskFactory.resolve(project, propertyTrackingConfig);
collectedInputs.setTask(task);
collectedInputs.setInputs(new ArrayList<>(taskFactory.inputs));
taskFactory.inputs.clear();
Expand Down Expand Up @@ -184,10 +188,6 @@ public synchronized void initialHashes() {
});
}

AtomicReference<Map<Project, Map<Path, DiskCache.CacheEntry>>> createdFilesRef = new AtomicReference<>();
AtomicReference<Map<Project, Map<Path, DiskCache.CacheEntry>>> changedFilesRef = new AtomicReference<>();
AtomicReference<Map<Project, Map<Path, DiskCache.CacheEntry>>> deletedFilesRef = new AtomicReference<>();

/**
* Marks that a file has been created, deleted, or modified in the given project.
*/
Expand Down Expand Up @@ -238,7 +238,6 @@ public synchronized Cancelable requestBuild(BuildListener buildListener) throws
prevBuild.blockUntilFinished();
}


if(incremental) {
Map<Project, Map<Path, DiskCache.CacheEntry>> createdFiles = createdFilesRef.getAndSet(new HashMap<>());
Map<Project, Map<Path, DiskCache.CacheEntry>> changedFiles = changedFilesRef.getAndSet(new HashMap<>());
Expand Down Expand Up @@ -325,8 +324,20 @@ private BuildMap createBuildMap(Project project, Path dir, Map<Project, Map<Path
}

if (changedFilesMap != null) {
for (DiskCache.CacheEntry value : changedFilesMap.values()) {
if (value.getSourcePath().toString().endsWith(".java")) {
String fileName = value.getSourcePath().toString()
.substring(0, value.getSourcePath().toString().lastIndexOf(".java"));
String buildMapFileName = fileName + ".build.map";
Path buildMapFile = dir.resolve("results").resolve(buildMapFileName);
String hash = new BuildMapHashReader(buildMapFile).hash();
boolean propagate = new JavaFileHashReader(value.getAbsolutePath()).hash().equals(hash);
//read hash from .java and compare to propagate deps
value.setPropagate(!propagate);
}
}
changedFilesMap.values().forEach(e -> dirToProjectFiles.get(e.getAbsoluteParent().toString())
.getUpdated().add(e.getSourcePath().toString()));
.getUpdated().put(e.getSourcePath().toString(), e.isPropagate()));
}

if (deletedFilesMap != null) {
Expand All @@ -341,7 +352,7 @@ private BuildMap createBuildMap(Project project, Path dir, Map<Project, Map<Path
// we don't know what this module will link to, so all classes need to be cloned.
for (com.vertispan.j2cl.build.task.Dependency dep : project.getDependencies()) {
BuildMap depBuildMap = buildMaps.get(dep.getProject());
Input input = new Input((Project) dep.getProject(), OutputTypes.TRANSPILED_JS);
Input input = new Input((Project) dep.getProject(), OutputTypes.BYTECODE);
Path path = diskCache.getLastSuccessfulDirectory(input);
if (depBuildMap == null && path != null) {
depBuildMap = safeCreateBuildMap((Project) dep.getProject(), path,
Expand All @@ -353,7 +364,10 @@ private BuildMap createBuildMap(Project project, Path dir, Map<Project, Map<Path
depBuildMap.cloneToTargetBuildMap(buildMap);
}
}
buildMap.build(strippedSources.get(project));

Input input = new Input(project, OutputTypes.BYTECODE);
Path path = diskCache.getLastSuccessfulDirectory(input);
buildMap.build(path);

} catch (Exception e) {
e.printStackTrace();
Expand Down Expand Up @@ -401,7 +415,7 @@ private void buildRequested(Map<Project, Map<Path, DiskCache.CacheEntry>> curren
// null check avoids re-entrance, as createBuildMap is recursive
// and the same dep can be revisited.
if (buildMaps.get(p) == null) {
Input input = new Input(p, OutputTypes.TRANSPILED_JS);
Input input = new Input(p, OutputTypes.BYTECODE);
if (diskCache.lastSuccessfulTaskDir.containsKey(input)) {
safeCreateBuildMap(p, diskCache.getLastSuccessfulDirectory(input),
createdFiles, changedFiles, deletedFiles);
Expand Down Expand Up @@ -430,10 +444,6 @@ public void copyAndDeleteFiles(Project project, String outputType, Path path) {
String binaryTypeName = firstPart.replace('/', '.');

if (visited.add(binaryTypeName)) {
Path javaPath = path.resolve(firstPart + ".java");
boolean b1 = Files.deleteIfExists(javaPath);
System.out.println("Delete: " + javaPath + ":" + b1);

if (outputType.equals(OutputTypes.STRIPPED_SOURCES)) {
Path jsNativePath = path.resolve(firstPart + ".native.js");
Files.deleteIfExists(jsNativePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.function.Predicate;

import com.vertispan.j2cl.build.incremental.BuildMap;
import com.vertispan.j2cl.build.task.CachedPath;
import io.methvin.watcher.hashing.FileHash;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ public static class CacheEntry implements Comparable<CacheEntry>, CachedPath {

private long time;

private boolean propagate;

public CacheEntry(Path sourcePath, Path absoluteParent, FileHash hash) {
if (sourcePath.isAbsolute()) {
this.sourcePath = absoluteParent.relativize(sourcePath);
Expand Down Expand Up @@ -306,6 +308,14 @@ public String toString() {
", hash=" + hash +
'}';
}

public boolean isPropagate() {
return propagate;
}

public void setPropagate(boolean propagate) {
this.propagate = propagate;
}
}

/**
Expand Down Expand Up @@ -583,4 +593,9 @@ public void markFailed(CacheResult failedResult) {
}
}


public BuildService buildService() {
return buildService;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public String getVersion() {
}

@Override
public Task resolve(Project project, Config config, BuildService buildService) {
public Task resolve(Project project, Config config) {
return (ignore) -> {};
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package com.vertispan.j2cl.build;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;

public class ProjectFiles {
private String dir;

private List<String> removed = new ArrayList<>(); // files
private Set<String> updated = new HashSet<>(); // files
private Map<String, Boolean> updated = new HashMap<>(); // files
private Set<String> added = new HashSet<>(); // files
private Set<String> all; // files

Expand All @@ -26,7 +23,7 @@ public List<String> getRemoved() {
return removed;
}

public Set<String> getUpdated() {
public Map<String, Boolean> getUpdated() {
return updated;
}

Expand All @@ -41,7 +38,7 @@ public Set<String> getAll() {
@Override public String toString() {
return "ProjectFiles{" +
"removed=" + removed +
", updated=" + updated +
", updated=" + updated.keySet() +
", added=" + added +
", all=" + all +
'}';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import com.vertispan.j2cl.build.task.TaskContext;

import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
Expand Down Expand Up @@ -211,7 +210,7 @@ private void executeTask(CollectedTaskInputs taskDetails, DiskCache.CacheResult
}
try {
long start = System.currentTimeMillis();
taskDetails.getTask().execute(new TaskContext(result.outputDir(), log));
taskDetails.getTask().execute(new TaskContext(result.outputDir(), log, diskCache.buildService()));
if (Thread.currentThread().isInterrupted()) {
// Tried and failed to be canceled, so even though we were successful, some files might
// have been deleted. Continue deleting contents
Expand Down Expand Up @@ -349,7 +348,7 @@ private boolean executeFinalTask(CollectedTaskInputs taskDetails, DiskCache.Cach
try {
//TODO Make sure that we want to write this to _only_ the current log, and not also to any file
//TODO Also be sure to write a prefix automatically
((TaskFactory.FinalOutputTask) taskDetails.getTask()).finish(new TaskContext(cacheResult.outputDir(), buildLog));
((TaskFactory.FinalOutputTask) taskDetails.getTask()).finish(new TaskContext(cacheResult.outputDir(), buildLog, diskCache.buildService()));
buildLog.info("Finished final task " + taskDetails.getDebugName() + " in " + (System.currentTimeMillis() - start) + "ms");
} catch (Throwable t) {
buildLog.error("FAILED " + taskDetails.getDebugName() + " in " + (System.currentTimeMillis() - start) + "ms",t);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public String getVersion() {
}

@Override
public Task resolve(Project project, Config config, BuildService buildService) {
public Task resolve(Project project, Config config) {
// we don't have any proper inputs or configs

// given the first (only) entry in the project's sources, unpack them
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public static CollectedTaskInputs jar(Project project) {

CollectedTaskInputs t = new CollectedTaskInputs(project);
t.setTaskFactory(new UnpackJarTaskFactory());
t.setTask(t.getTaskFactory().resolve(project, null, null));
t.setTask(t.getTaskFactory().resolve(project, null));
// create a fake input and give it a hash so that this unpack only runs if the jar changes
Input jarInput = new Input(project, "jar");
try {
Expand Down
Loading

0 comments on commit 96e9762

Please sign in to comment.