blob: 30e71924e3c66450ebad7437d65a49911d5d616b [file] [log] [blame]
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.worker;
import com.google.devtools.build.lib.actions.UserExecException;
import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxInputs;
import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxOutputs;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest;
import com.google.devtools.build.lib.worker.WorkerProtocol.WorkResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import java.util.logging.Logger;
/** A proxy that talks to the multiplexer */
final class WorkerProxy extends Worker {
private static final Logger logger = Logger.getLogger(WorkerProxy.class.getName());
private WorkerMultiplexer workerMultiplexer;
private String recordingStreamMessage;
WorkerProxy(
WorkerKey workerKey,
int workerId,
Path workDir,
Path logFile,
WorkerMultiplexer workerMultiplexer) {
super(workerKey, workerId, workDir, logFile);
this.workerMultiplexer = workerMultiplexer;
}
@Override
void createProcess() throws IOException {
workerMultiplexer.createProcess(workerKey, workDir, logFile);
}
@Override
boolean isAlive() {
return workerMultiplexer.isProcessAlive();
}
@Override
public void prepareExecution(
SandboxInputs inputFiles, SandboxOutputs outputs, Set<PathFragment> workerFiles)
throws IOException {
createProcess();
}
@Override
synchronized void destroy() throws IOException {
super.destroy();
try {
WorkerMultiplexerManager.removeInstance(workerKey.hashCode());
} catch (InterruptedException e) {
logger.warning(
"InterruptedException was caught while destroying multiplexer. "
+ "It could because the multiplexer was interrupted.");
} catch (UserExecException e) {
logger.warning(e.toString());
}
}
/** Send the WorkRequest to multiplexer. */
@Override
void putRequest(WorkRequest request) throws IOException {
try {
workerMultiplexer.resetResponseChecker(workerId);
workerMultiplexer.putRequest(request);
} catch (InterruptedException e) {
/**
* We can't throw InterruptedException to WorkerSpawnRunner because of the principle of
* override. InterruptedException will happen when Bazel is waiting for semaphore but user
* terminates the process, so we do nothing here.
*/
logger.warning(
"InterruptedException was caught while sending worker request. "
+ "It could because the multiplexer was interrupted.");
}
}
/** Wait for WorkResponse from multiplexer. */
@Override
WorkResponse getResponse() throws IOException {
try {
InputStream inputStream = workerMultiplexer.getResponse(workerId);
if (inputStream == null) {
return null;
}
return WorkResponse.parseDelimitedFrom(inputStream);
} catch (IOException e) {
recordingStreamMessage = e.toString();
throw new IOException(
"IOException was caught while waiting for worker response. "
+ "It could because the worker returned unparseable response.");
} catch (InterruptedException e) {
/**
* We can't throw InterruptedException to WorkerSpawnRunner because of the principle of
* override. InterruptedException will happen when Bazel is waiting for semaphore but user
* terminates the process, so we do nothing here.
*/
logger.warning(
"InterruptedException was caught while waiting for work response. "
+ "It could because the multiplexer was interrupted.");
}
// response can be null when the worker has already closed stdout at this point and thus
// the InputStream is at EOF.
return null;
}
@Override
String getRecordingStreamMessage() {
return recordingStreamMessage;
}
}