Skip to content

Commit 97dea59

Browse files
coeuvrecopybara-github
authored andcommitted
Implement getDirectoryEntries and readdir for RemoteActionFileSystem.
So spawns can read content of directires within action exuection. Part of bazelbuild#16556. PiperOrigin-RevId: 486918859 Change-Id: Ida86e4c927093d26f7f96d2f0c2aa0d1d74cc8a4
1 parent a7fc88a commit 97dea59

File tree

2 files changed

+189
-11
lines changed

2 files changed

+189
-11
lines changed

src/main/java/com/google/devtools/build/lib/remote/RemoteActionFileSystem.java

+70-11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import static com.google.common.collect.Streams.stream;
2323

2424
import com.google.common.annotations.VisibleForTesting;
25+
import com.google.common.collect.ImmutableList;
2526
import com.google.common.collect.ImmutableMap;
2627
import com.google.devtools.build.lib.actions.ActionInputMap;
2728
import com.google.devtools.build.lib.actions.Artifact;
@@ -50,6 +51,8 @@
5051
import java.io.OutputStream;
5152
import java.nio.channels.ReadableByteChannel;
5253
import java.util.Collection;
54+
import java.util.HashMap;
55+
import java.util.HashSet;
5356
import java.util.Map;
5457
import javax.annotation.Nullable;
5558

@@ -604,6 +607,73 @@ public boolean createDirectory(PathFragment path) throws IOException {
604607
return created;
605608
}
606609

610+
@Override
611+
protected ImmutableList<String> getDirectoryEntries(PathFragment path) throws IOException {
612+
HashSet<String> entries = new HashSet<>();
613+
614+
boolean ignoredNotFoundInRemote = false;
615+
if (isOutput(path)) {
616+
try {
617+
delegateFs.getPath(path).getDirectoryEntries().stream()
618+
.map(Path::getBaseName)
619+
.forEach(entries::add);
620+
ignoredNotFoundInRemote = true;
621+
} catch (FileNotFoundException ignored) {
622+
// Intentionally ignored
623+
}
624+
}
625+
626+
try {
627+
remoteOutputTree.getPath(path).getDirectoryEntries().stream()
628+
.map(Path::getBaseName)
629+
.forEach(entries::add);
630+
} catch (FileNotFoundException e) {
631+
if (!ignoredNotFoundInRemote) {
632+
throw e;
633+
}
634+
}
635+
636+
// sort entries to get a deterministic order.
637+
return ImmutableList.sortedCopyOf(entries);
638+
}
639+
640+
@Override
641+
protected Collection<Dirent> readdir(PathFragment path, boolean followSymlinks)
642+
throws IOException {
643+
HashMap<String, Dirent> entries = new HashMap<>();
644+
645+
boolean ignoredNotFoundInRemote = false;
646+
if (isOutput(path)) {
647+
try {
648+
for (var entry :
649+
delegateFs
650+
.getPath(path)
651+
.readdir(followSymlinks ? Symlinks.FOLLOW : Symlinks.NOFOLLOW)) {
652+
entries.put(entry.getName(), entry);
653+
}
654+
ignoredNotFoundInRemote = true;
655+
} catch (FileNotFoundException ignored) {
656+
// Intentionally ignored
657+
}
658+
}
659+
660+
try {
661+
for (var entry :
662+
remoteOutputTree
663+
.getPath(path)
664+
.readdir(followSymlinks ? Symlinks.FOLLOW : Symlinks.NOFOLLOW)) {
665+
entries.put(entry.getName(), entry);
666+
}
667+
} catch (FileNotFoundException e) {
668+
if (!ignoredNotFoundInRemote) {
669+
throw e;
670+
}
671+
}
672+
673+
// sort entries to get a deterministic order.
674+
return ImmutableList.sortedCopyOf(entries.values());
675+
}
676+
607677
/*
608678
* -------------------- TODO(buchgr): Not yet implemented --------------------
609679
*
@@ -613,23 +683,12 @@ public boolean createDirectory(PathFragment path) throws IOException {
613683
* sure to fully implement this file system.
614684
*/
615685

616-
@Override
617-
protected Collection<String> getDirectoryEntries(PathFragment path) throws IOException {
618-
return super.getDirectoryEntries(path);
619-
}
620-
621686
@Override
622687
protected void createFSDependentHardLink(PathFragment linkPath, PathFragment originalPath)
623688
throws IOException {
624689
super.createFSDependentHardLink(linkPath, originalPath);
625690
}
626691

627-
@Override
628-
protected Collection<Dirent> readdir(PathFragment path, boolean followSymlinks)
629-
throws IOException {
630-
return super.readdir(path, followSymlinks);
631-
}
632-
633692
@Override
634693
protected void createHardLink(PathFragment linkPath, PathFragment originalPath)
635694
throws IOException {

src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTestBase.java

+119
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,18 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.remote;
1515

16+
import static com.google.common.collect.ImmutableList.toImmutableList;
1617
import static com.google.common.truth.Truth.assertThat;
1718
import static org.junit.Assert.assertThrows;
1819

1920
import com.google.common.collect.ImmutableList;
2021
import com.google.devtools.build.lib.actions.ActionInputMap;
2122
import com.google.devtools.build.lib.actions.Artifact;
23+
import com.google.devtools.build.lib.vfs.Dirent;
2224
import com.google.devtools.build.lib.vfs.FileSystem;
25+
import com.google.devtools.build.lib.vfs.Path;
2326
import com.google.devtools.build.lib.vfs.PathFragment;
27+
import com.google.devtools.build.lib.vfs.Symlinks;
2428
import java.io.FileNotFoundException;
2529
import java.io.IOException;
2630
import org.junit.Test;
@@ -209,4 +213,119 @@ public void createDirectory_createLocallyAndRemotely() throws Exception {
209213
assertThat(getRemoteFileSystem(actionFs).getPath(path).isDirectory()).isTrue();
210214
assertThat(getLocalFileSystem(actionFs).getPath(path).isDirectory()).isTrue();
211215
}
216+
217+
interface DirectoryEntriesProvider {
218+
ImmutableList<String> getDirectoryEntries(Path path) throws IOException;
219+
}
220+
221+
private void readdirNonEmptyLocalDirectoryReadFromLocal(
222+
DirectoryEntriesProvider directoryEntriesProvider) throws IOException {
223+
FileSystem actionFs = createActionFileSystem();
224+
PathFragment dir = getOutputPath("parent/dir");
225+
actionFs.getPath(dir).createDirectoryAndParents();
226+
writeLocalFile(actionFs, dir.getChild("file1"), "content1");
227+
writeLocalFile(actionFs, dir.getChild("file2"), "content2");
228+
229+
ImmutableList<String> entries =
230+
directoryEntriesProvider.getDirectoryEntries(actionFs.getPath(dir));
231+
232+
assertThat(entries).containsExactly("file1", "file2");
233+
}
234+
235+
private void readdirNonEmptyInMemoryDirectoryReadFromMemory(
236+
DirectoryEntriesProvider directoryEntriesProvider) throws IOException {
237+
FileSystem actionFs = createActionFileSystem();
238+
PathFragment dir = getOutputPath("parent/dir");
239+
actionFs.getPath(dir).createDirectoryAndParents();
240+
injectRemoteFile(actionFs, dir.getChild("file1"), "content1");
241+
injectRemoteFile(actionFs, dir.getChild("file2"), "content2");
242+
243+
ImmutableList<String> entries =
244+
directoryEntriesProvider.getDirectoryEntries(actionFs.getPath(dir));
245+
246+
assertThat(entries).containsExactly("file1", "file2");
247+
}
248+
249+
private void readdirNonEmptyLocalAndInMemoryDirectoryCombineThem(
250+
DirectoryEntriesProvider directoryEntriesProvider) throws IOException {
251+
FileSystem actionFs = createActionFileSystem();
252+
PathFragment dir = getOutputPath("parent/dir");
253+
actionFs.getPath(dir).createDirectoryAndParents();
254+
writeLocalFile(actionFs, dir.getChild("file1"), "content1");
255+
writeLocalFile(actionFs, dir.getChild("file2"), "content2");
256+
injectRemoteFile(actionFs, dir.getChild("file2"), "content2inmemory");
257+
injectRemoteFile(actionFs, dir.getChild("file3"), "content3");
258+
259+
ImmutableList<String> entries =
260+
directoryEntriesProvider.getDirectoryEntries(actionFs.getPath(dir));
261+
262+
assertThat(entries).containsExactly("file1", "file2", "file3");
263+
}
264+
265+
private void readdirNothingThereThrowsFileNotFound(
266+
DirectoryEntriesProvider directoryEntriesProvider) throws IOException {
267+
FileSystem actionFs = createActionFileSystem();
268+
PathFragment dir = getOutputPath("parent/dir");
269+
270+
assertThrows(
271+
FileNotFoundException.class,
272+
() -> directoryEntriesProvider.getDirectoryEntries(actionFs.getPath(dir)));
273+
}
274+
275+
@Test
276+
public void readdir_nonEmptyLocalDirectory_readFromLocal() throws IOException {
277+
readdirNonEmptyLocalDirectoryReadFromLocal(
278+
path ->
279+
path.readdir(Symlinks.FOLLOW).stream().map(Dirent::getName).collect(toImmutableList()));
280+
}
281+
282+
@Test
283+
public void readdir_nonEmptyInMemoryDirectory_readFromMemory() throws IOException {
284+
readdirNonEmptyInMemoryDirectoryReadFromMemory(
285+
path ->
286+
path.readdir(Symlinks.FOLLOW).stream().map(Dirent::getName).collect(toImmutableList()));
287+
}
288+
289+
@Test
290+
public void readdir_nonEmptyLocalAndInMemoryDirectory_combineThem() throws IOException {
291+
readdirNonEmptyLocalAndInMemoryDirectoryCombineThem(
292+
path ->
293+
path.readdir(Symlinks.FOLLOW).stream().map(Dirent::getName).collect(toImmutableList()));
294+
}
295+
296+
@Test
297+
public void readdir_nothingThere_throwsFileNotFound() throws IOException {
298+
readdirNothingThereThrowsFileNotFound(
299+
path ->
300+
path.readdir(Symlinks.FOLLOW).stream().map(Dirent::getName).collect(toImmutableList()));
301+
}
302+
303+
@Test
304+
public void getDirectoryEntries_nonEmptyLocalDirectory_readFromLocal() throws IOException {
305+
readdirNonEmptyLocalDirectoryReadFromLocal(
306+
path ->
307+
path.getDirectoryEntries().stream().map(Path::getBaseName).collect(toImmutableList()));
308+
}
309+
310+
@Test
311+
public void getDirectoryEntries_nonEmptyInMemoryDirectory_readFromMemory() throws IOException {
312+
readdirNonEmptyInMemoryDirectoryReadFromMemory(
313+
path ->
314+
path.getDirectoryEntries().stream().map(Path::getBaseName).collect(toImmutableList()));
315+
}
316+
317+
@Test
318+
public void getDirectoryEntries_nonEmptyLocalAndInMemoryDirectory_combineThem()
319+
throws IOException {
320+
readdirNonEmptyLocalAndInMemoryDirectoryCombineThem(
321+
path ->
322+
path.getDirectoryEntries().stream().map(Path::getBaseName).collect(toImmutableList()));
323+
}
324+
325+
@Test
326+
public void getDirectoryEntries_nothingThere_throwsFileNotFound() throws IOException {
327+
readdirNothingThereThrowsFileNotFound(
328+
path ->
329+
path.getDirectoryEntries().stream().map(Path::getBaseName).collect(toImmutableList()));
330+
}
212331
}

0 commit comments

Comments
 (0)