Skip to content

Commit 2ceb589

Browse files
wiwaShaneDelmore
andcommitted
Add test utils and tests for ProtoCoordinator
Co-authored-by: Shane Delmore <shane@delmore.io>
1 parent 756023e commit 2ceb589

File tree

16 files changed

+488
-102
lines changed

16 files changed

+488
-102
lines changed

src/main/java/build/buildfarm/worker/Executor.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -452,12 +452,7 @@ private Code executeCommand(
452452
Tree execTree = workerContext.getQueuedOperation(operationContext.queueEntry).getTree();
453453

454454
WorkFilesContext filesContext =
455-
new WorkFilesContext(
456-
execDir,
457-
execTree,
458-
ImmutableList.copyOf(operationContext.command.getOutputPathsList()),
459-
ImmutableList.copyOf(operationContext.command.getOutputFilesList()),
460-
ImmutableList.copyOf(operationContext.command.getOutputDirectoriesList()));
455+
WorkFilesContext.fromContext(execDir, execTree, operationContext.command);
461456

462457
return PersistentExecutor.runOnPersistentWorker(
463458
limits.persistentWorkerCommand,
@@ -467,6 +462,7 @@ private Code executeCommand(
467462
ImmutableMap.copyOf(environment),
468463
limits,
469464
timeout,
465+
PersistentExecutor.defaultWorkRootsDir,
470466
resultBuilder);
471467
}
472468

src/main/java/build/buildfarm/worker/OperationContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import com.google.longrunning.Operation;
2323
import java.nio.file.Path;
2424

25-
final class OperationContext {
25+
public final class OperationContext {
2626
final ExecuteResponse.Builder executeResponse;
2727
final Operation operation;
2828
final Poller poller;

src/main/java/build/buildfarm/worker/persistent/FileAccessUtils.java

Lines changed: 24 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,41 @@
33
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
44
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
55

6+
import com.google.common.collect.ImmutableSet;
67
import java.io.IOException;
78
import java.nio.file.Files;
89
import java.nio.file.Path;
10+
import java.nio.file.attribute.PosixFilePermission;
11+
import java.util.Set;
912
import java.util.concurrent.ConcurrentHashMap;
1013
import java.util.function.Supplier;
1114
import java.util.logging.Logger;
1215

13-
// Utility for concurrent move/copy/link of files
16+
/**
17+
* Utility for concurrent move/copy of files Can be extended in the future to (sym)linking if we
18+
* need performance
19+
*/
1420
public final class FileAccessUtils {
1521
// singleton class with only static methods
1622
private FileAccessUtils() {}
1723

1824
private static final Logger logger = Logger.getLogger(FileAccessUtils.class.getName());
1925

26+
public static Path addPosixOwnerWrite(Path absPath) throws IOException {
27+
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(absPath);
28+
29+
ImmutableSet<PosixFilePermission> permsWithWrite =
30+
ImmutableSet.<PosixFilePermission>builder()
31+
.addAll(perms)
32+
.add(PosixFilePermission.OWNER_WRITE)
33+
.build();
34+
35+
return Files.setAttribute(absPath, "posix:permissions", permsWithWrite);
36+
}
37+
2038
private static final ConcurrentHashMap<Path, PathLock> fileLocks = new ConcurrentHashMap<>();
2139

22-
// Used here for locking "files"
40+
// Used here as a simple lock for locking "files" (paths)
2341
private static class PathLock {
2442
// Not used elsewhere
2543
private PathLock() {}
@@ -46,13 +64,10 @@ public static void copyFile(Path from, Path to) throws IOException {
4664
() -> {
4765
try {
4866
Files.copy(from, absTo, REPLACE_EXISTING, COPY_ATTRIBUTES);
49-
boolean writeable = absTo.toFile().setWritable(true);
50-
if (!writeable) {
51-
return new IOException("copyFile() could not set writeable: " + absTo);
52-
}
67+
addPosixOwnerWrite(absTo);
5368
return null;
5469
} catch (IOException e) {
55-
return e;
70+
return new IOException("copyFile() could not set writeable: " + absTo, e);
5671
}
5772
});
5873
if (ioException != null) {
@@ -81,44 +96,10 @@ public static void moveFile(Path from, Path to) throws IOException {
8196
() -> {
8297
try {
8398
Files.move(from, absTo, REPLACE_EXISTING);
84-
boolean writeable = absTo.toFile().setWritable(true);
85-
if (!writeable) {
86-
return new IOException("moveFile() could not set writeable: " + absTo);
87-
}
88-
return null;
89-
} catch (IOException e) {
90-
return e;
91-
}
92-
});
93-
if (ioException != null) {
94-
throw ioException;
95-
}
96-
}
97-
98-
/**
99-
* Creates a symlink, creating necessary directories. Deletes pre-existing files/links which have
100-
* the same path as the specified link, effectively overwriting any existing files/links.
101-
*
102-
* @param from
103-
* @param to
104-
* @throws IOException
105-
*/
106-
public static void linkFile(Path from, Path to) throws IOException {
107-
Path absTo = to.toAbsolutePath();
108-
logger.finer("linkFile: " + from + " to " + absTo);
109-
if (!Files.exists(from)) {
110-
throw new IOException("linkFile: source file doesn't exist: " + from);
111-
}
112-
IOException ioException =
113-
writeFileSafe(
114-
absTo,
115-
() -> {
116-
try {
117-
Files.deleteIfExists(absTo);
118-
Files.createSymbolicLink(absTo, from);
99+
addPosixOwnerWrite(absTo);
119100
return null;
120101
} catch (IOException e) {
121-
return e;
102+
return new IOException("copyFile() could not set writeable: " + absTo, e);
122103
}
123104
});
124105
if (ioException != null) {

src/main/java/build/buildfarm/worker/persistent/Keymaker.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
import persistent.bazel.client.PersistentWorker;
1414
import persistent.bazel.client.WorkerKey;
1515

16+
/** Much of the logic (hashing) is from Bazel itself (private library/methods, i.e. WorkerKey). */
1617
public class Keymaker {
1718
// Constructs a key with its worker tool input files being relative paths
1819
public static WorkerKey make(
1920
Path opRoot,
21+
Path workRootsDir,
2022
ImmutableList<String> workerInitCmd,
2123
ImmutableList<String> workerInitArgs,
2224
ImmutableMap<String, String> workerEnv,
@@ -29,7 +31,13 @@ public static WorkerKey make(
2931

3032
Path workRoot =
3133
calculateWorkRoot(
32-
workerInitCmd, workerInitArgs, workerEnv, executionName, sandboxed, cancellable);
34+
workRootsDir,
35+
workerInitCmd,
36+
workerInitArgs,
37+
workerEnv,
38+
executionName,
39+
sandboxed,
40+
cancellable);
3341
Path toolsRoot = workRoot.resolve(PersistentWorker.TOOL_INPUT_SUBDIR);
3442

3543
SortedMap<Path, HashCode> hashedTools = workerFilesWithHashes(workerFiles);
@@ -49,6 +57,7 @@ public static WorkerKey make(
4957

5058
// Hash of a subset of the WorkerKey
5159
private static Path calculateWorkRoot(
60+
Path workRootsDir,
5261
ImmutableList<String> workerInitCmd,
5362
ImmutableList<String> workerInitArgs,
5463
ImmutableMap<String, String> workerEnv,
@@ -57,7 +66,7 @@ private static Path calculateWorkRoot(
5766
boolean cancellable) {
5867
int workRootId = Objects.hash(workerInitCmd, workerInitArgs, workerEnv, sandboxed, cancellable);
5968
String workRootDirName = "work-root_" + executionName + "_" + workRootId;
60-
return PersistentExecutor.workRootsDir.resolve(workRootDirName);
69+
return workRootsDir.resolve(workRootDirName);
6170
}
6271

6372
private static ImmutableSortedMap<Path, HashCode> workerFilesWithHashes(

src/main/java/build/buildfarm/worker/persistent/PersistentExecutor.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,19 @@
2424
* Executes an Action like Executor/DockerExecutor, writing to ActionResult.
2525
*
2626
* <p>Currently has special code for discriminating between Javac/Scalac, and other persistent
27-
* workers.
27+
* workers, likely for debugging purposes, but need to revisit. (Can't remember fully since it was
28+
* so long ago!)
2829
*/
2930
public class PersistentExecutor {
3031
private static final Logger logger = Logger.getLogger(PersistentExecutor.class.getName());
3132

32-
// How many workers can exist at once for a given WorkerKey
33-
// There may be multiple WorkerKeys per mnemonic,
34-
// e.g. if builds are run with different tool fingerprints
35-
private static final int defaultMaxWorkersPerKey = 6;
36-
3733
private static final ProtoCoordinator coordinator =
3834
ProtoCoordinator.ofCommonsPool(getMaxWorkersPerKey());
3935

4036
// TODO load from config (i.e. {worker_root}/persistent)
41-
static final Path workRootsDir = Paths.get("/tmp/worker/persistent/");
37+
public static final Path defaultWorkRootsDir = Paths.get("/tmp/worker/persistent/");
4238

43-
static final String PERSISTENT_WORKER_FLAG = "--persistent_worker";
39+
public static final String PERSISTENT_WORKER_FLAG = "--persistent_worker";
4440

4541
// TODO Revisit hardcoded actions
4642
static final String JAVABUILDER_JAR =
@@ -49,6 +45,11 @@ public class PersistentExecutor {
4945
private static final String SCALAC_EXEC_NAME = "Scalac";
5046
private static final String JAVAC_EXEC_NAME = "JavaBuilder";
5147

48+
// How many workers can exist at once for a given WorkerKey
49+
// There may be multiple WorkerKeys per mnemonic,
50+
// e.g. if builds are run with different tool fingerprints
51+
private static final int defaultMaxWorkersPerKey = 6;
52+
5253
private static int getMaxWorkersPerKey() {
5354
try {
5455
return Integer.parseInt(System.getenv("BUILDFARM_MAX_WORKERS_PER_KEY"));
@@ -73,6 +74,7 @@ public static Code runOnPersistentWorker(
7374
ImmutableMap<String, String> envVars,
7475
ResourceLimits limits,
7576
Duration timeout,
77+
Path workRootsDir,
7678
ActionResult.Builder resultBuilder)
7779
throws IOException {
7880
//// Pull out persistent worker start command from the overall action request
@@ -87,6 +89,7 @@ public static Code runOnPersistentWorker(
8789
return Code.INVALID_ARGUMENT;
8890
}
8991

92+
// TODO revisit why this was necessary in the first place
9093
ImmutableMap<String, String> env;
9194
if (executionName.equals(JAVAC_EXEC_NAME)) {
9295
env = ImmutableMap.of();
@@ -112,7 +115,13 @@ public static Code runOnPersistentWorker(
112115

113116
WorkerKey key =
114117
Keymaker.make(
115-
context.opRoot, workerExecCmd, workerInitArgs, env, executionName, workerFiles);
118+
context.opRoot,
119+
workRootsDir,
120+
workerExecCmd,
121+
workerInitArgs,
122+
env,
123+
executionName,
124+
workerFiles);
116125

117126
coordinator.copyToolInputsIntoWorkerToolRoot(key, workerFiles);
118127

src/main/java/build/buildfarm/worker/persistent/ProtoCoordinator.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ private void copyNontoolInputs(WorkerInputs workerInputs, Path workerExecRoot)
206206

207207
// Make outputs visible to the rest of Worker machinery
208208
// see DockerExecutor::copyOutputsOutOfContainer
209-
private void moveOutputsToOperationRoot(WorkFilesContext context, Path workerExecRoot)
209+
void moveOutputsToOperationRoot(WorkFilesContext context, Path workerExecRoot)
210210
throws IOException {
211211
Path opRoot = context.opRoot;
212212

@@ -216,9 +216,11 @@ private void moveOutputsToOperationRoot(WorkFilesContext context, Path workerExe
216216
}
217217

218218
for (String relOutput : context.outputFiles) {
219-
Path relPath = Paths.get(relOutput);
220-
Path opOutputPath = opRoot.resolve(relPath);
221-
Path execOutputPath = workerExecRoot.resolve(relPath);
219+
System.out.println(relOutput);
220+
Path execOutputPath = workerExecRoot.resolve(relOutput);
221+
System.out.println(execOutputPath);
222+
Path opOutputPath = opRoot.resolve(relOutput);
223+
System.out.println(opOutputPath);
222224

223225
FileAccessUtils.moveFile(execOutputPath, opOutputPath);
224226
}

src/main/java/build/buildfarm/worker/persistent/WorkFilesContext.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package build.buildfarm.worker.persistent;
22

3+
import build.bazel.remote.execution.v2.Command;
34
import build.buildfarm.v1test.Tree;
45
import build.buildfarm.worker.util.InputsIndexer;
56
import com.google.common.collect.ImmutableList;
@@ -37,14 +38,23 @@ public WorkFilesContext(
3738
this.outputFiles = outputFiles;
3839
this.outputDirectories = outputDirectories;
3940

40-
this.inputsIndexer = new InputsIndexer(execTree);
41+
this.inputsIndexer = new InputsIndexer(execTree, this.opRoot);
42+
}
43+
44+
public static WorkFilesContext fromContext(Path opRoot, Tree inputsTree, Command opCommand) {
45+
return new WorkFilesContext(
46+
opRoot,
47+
inputsTree,
48+
ImmutableList.copyOf(opCommand.getOutputPathsList()),
49+
ImmutableList.copyOf(opCommand.getOutputFilesList()),
50+
ImmutableList.copyOf(opCommand.getOutputDirectoriesList()));
4151
}
4252

4353
// Paths are absolute paths from the opRoot; same as the Input.getPath();
4454
public ImmutableMap<Path, Input> getPathInputs() {
4555
synchronized (this) {
4656
if (pathInputs == null) {
47-
pathInputs = inputsIndexer.getAllInputs(opRoot);
57+
pathInputs = inputsIndexer.getAllInputs();
4858
}
4959
}
5060
return pathInputs;
@@ -53,7 +63,7 @@ public ImmutableMap<Path, Input> getPathInputs() {
5363
public ImmutableMap<Path, Input> getToolInputs() {
5464
synchronized (this) {
5565
if (toolInputs == null) {
56-
toolInputs = inputsIndexer.getToolInputs(opRoot);
66+
toolInputs = inputsIndexer.getToolInputs();
5767
}
5868
}
5969
return toolInputs;

src/main/java/build/buildfarm/worker/persistent/WorkerInputs.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,6 @@ public void copyInputFile(Path from, Path to) throws IOException {
5757
FileAccessUtils.copyFile(from, to);
5858
}
5959

60-
public void moveInputFile(Path from, Path to) throws IOException {
61-
checkFileIsInput("moveInputFile()", from);
62-
FileAccessUtils.moveFile(from, to);
63-
}
64-
65-
public void linkInputFile(Path from, Path to) throws IOException {
66-
checkFileIsInput("linkInputFile()", from);
67-
FileAccessUtils.linkFile(from, to);
68-
}
69-
7060
public void deleteInputFileIfExists(Path workerExecRoot, Path opPathInput) throws IOException {
7161
checkFileIsInput("deleteInputFile()", opPathInput);
7262
Path execPathInput = relativizeInput(workerExecRoot, opPathInput);
@@ -109,6 +99,8 @@ public static WorkerInputs from(WorkFilesContext workFilesContext, List<String>
10999

110100
logger.fine(inputsDebugMsg);
111101

102+
System.out.println(inputsDebugMsg);
103+
112104
return new WorkerInputs(workFilesContext.opRoot, absToolInputs, toolInputs, pathInputs);
113105
}
114106
}

0 commit comments

Comments
 (0)