Skip to content

Commit ba5b2a7

Browse files
jablincopybara-github
authored andcommitted
when writing to local disk cache, open files later in order to avoid "too many open files"
Re-use the existing "LazyFileOutputStream" in DiskAndRemoteCacheClient.java in order to avoid "Too many open files". Resolves bazelbuild#13435 Closes bazelbuild#13574. PiperOrigin-RevId: 379892227
1 parent 9c17adc commit ba5b2a7

File tree

3 files changed

+72
-56
lines changed

3 files changed

+72
-56
lines changed

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

+1-51
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import com.google.devtools.build.lib.remote.RemoteCache.ActionResultMetadata.DirectoryMetadata;
5757
import com.google.devtools.build.lib.remote.RemoteCache.ActionResultMetadata.FileMetadata;
5858
import com.google.devtools.build.lib.remote.RemoteCache.ActionResultMetadata.SymlinkMetadata;
59+
import com.google.devtools.build.lib.remote.common.LazyFileOutputStream;
5960
import com.google.devtools.build.lib.remote.common.OutputDigestMismatchException;
6061
import com.google.devtools.build.lib.remote.common.RemoteActionExecutionContext;
6162
import com.google.devtools.build.lib.remote.common.RemoteActionFileArtifactValue;
@@ -1099,57 +1100,6 @@ private static FailureDetail createFailureDetail(String message, Code detailedCo
10991100
.build();
11001101
}
11011102

1102-
/**
1103-
* Creates an {@link OutputStream} that isn't actually opened until the first data is written.
1104-
* This is useful to only have as many open file descriptors as necessary at a time to avoid
1105-
* running into system limits.
1106-
*/
1107-
private static class LazyFileOutputStream extends OutputStream {
1108-
1109-
private final Path path;
1110-
private OutputStream out;
1111-
1112-
public LazyFileOutputStream(Path path) {
1113-
this.path = path;
1114-
}
1115-
1116-
@Override
1117-
public void write(byte[] b) throws IOException {
1118-
ensureOpen();
1119-
out.write(b);
1120-
}
1121-
1122-
@Override
1123-
public void write(byte[] b, int off, int len) throws IOException {
1124-
ensureOpen();
1125-
out.write(b, off, len);
1126-
}
1127-
1128-
@Override
1129-
public void write(int b) throws IOException {
1130-
ensureOpen();
1131-
out.write(b);
1132-
}
1133-
1134-
@Override
1135-
public void flush() throws IOException {
1136-
ensureOpen();
1137-
out.flush();
1138-
}
1139-
1140-
@Override
1141-
public void close() throws IOException {
1142-
ensureOpen();
1143-
out.close();
1144-
}
1145-
1146-
private void ensureOpen() throws IOException {
1147-
if (out == null) {
1148-
out = path.getOutputStream();
1149-
}
1150-
}
1151-
}
1152-
11531103
/** In-memory representation of action result metadata. */
11541104
static class ActionResultMetadata {
11551105

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2021 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package com.google.devtools.build.lib.remote.common;
15+
16+
import com.google.devtools.build.lib.vfs.Path;
17+
import java.io.IOException;
18+
import java.io.OutputStream;
19+
20+
/**
21+
* Creates an {@link OutputStream} that isn't actually opened until the first data is written. This
22+
* is useful to only have as many open file descriptors as necessary at a time to avoid running into
23+
* system limits.
24+
*/
25+
public class LazyFileOutputStream extends OutputStream {
26+
27+
private final Path path;
28+
private OutputStream out;
29+
30+
public LazyFileOutputStream(Path path) {
31+
this.path = path;
32+
}
33+
34+
@Override
35+
public void write(byte[] b) throws IOException {
36+
ensureOpen();
37+
out.write(b);
38+
}
39+
40+
@Override
41+
public void write(byte[] b, int off, int len) throws IOException {
42+
ensureOpen();
43+
out.write(b, off, len);
44+
}
45+
46+
@Override
47+
public void write(int b) throws IOException {
48+
ensureOpen();
49+
out.write(b);
50+
}
51+
52+
@Override
53+
public void flush() throws IOException {
54+
ensureOpen();
55+
out.flush();
56+
}
57+
58+
@Override
59+
public void close() throws IOException {
60+
ensureOpen();
61+
out.close();
62+
}
63+
64+
private void ensureOpen() throws IOException {
65+
if (out == null) {
66+
out = path.getOutputStream();
67+
}
68+
}
69+
}

src/main/java/com/google/devtools/build/lib/remote/disk/DiskAndRemoteCacheClient.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.common.util.concurrent.Futures;
2121
import com.google.common.util.concurrent.ListenableFuture;
2222
import com.google.common.util.concurrent.MoreExecutors;
23+
import com.google.devtools.build.lib.remote.common.LazyFileOutputStream;
2324
import com.google.devtools.build.lib.remote.common.RemoteActionExecutionContext;
2425
import com.google.devtools.build.lib.remote.common.RemoteCacheClient;
2526
import com.google.devtools.build.lib.remote.options.RemoteOptions;
@@ -142,11 +143,7 @@ public ListenableFuture<Void> downloadBlob(
142143

143144
Path tempPath = newTempPath();
144145
final OutputStream tempOut;
145-
try {
146-
tempOut = tempPath.getOutputStream();
147-
} catch (IOException e) {
148-
return Futures.immediateFailedFuture(e);
149-
}
146+
tempOut = new LazyFileOutputStream(tempPath);
150147

151148
if (!options.incompatibleRemoteResultsIgnoreDisk || options.remoteAcceptCached) {
152149
ListenableFuture<Void> download =

0 commit comments

Comments
 (0)