blob: 7ce46c88a86baed3ca884f9ad52cf0ba242a78ef [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "missive/scheduler/enqueue_job.h"
#include <fcntl.h>
#include <memory>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <utility>
#include <base/strings/strcat.h>
#include <base/strings/string_number_conversions.h>
#include "missive/proto/interface.pb.h"
#include "missive/scheduler/scheduler.h"
#include "missive/storage/storage_module_interface.h"
#include "missive/util/status.h"
namespace reporting {
namespace {
class ManagedFileDescriptor {
public:
static StatusOr<std::unique_ptr<ManagedFileDescriptor>> Create(
const std::string& path) {
const int fd = open(path.c_str(), O_RDONLY);
if (fd < 0) {
return Status(error::INTERNAL, "Unable to open record file for reading.");
}
return base::WrapUnique(new ManagedFileDescriptor(fd));
}
~ManagedFileDescriptor() {
if (IsFileOpen()) {
if (close(fd_) == -1) {
LOG(ERROR) << "Unable to close file";
}
}
}
bool IsFileOpen() const { return fd_ >= 0; }
int fd() const { return fd_; }
private:
explicit ManagedFileDescriptor(int fd) : fd_(fd) {}
const int fd_;
};
} // namespace
EnqueueJob::EnqueueResponseDelegate::EnqueueResponseDelegate(
std::unique_ptr<
brillo::dbus_utils::DBusMethodResponse<EnqueueRecordResponse>> response)
: response_(std::move(response)) {
DCHECK(response_);
}
Status EnqueueJob::EnqueueResponseDelegate::Complete() {
return SendResponse(Status::StatusOK());
}
Status EnqueueJob::EnqueueResponseDelegate::Cancel(Status status) {
return SendResponse(status);
}
Status EnqueueJob::EnqueueResponseDelegate::SendResponse(Status status) {
if (response_->IsResponseSent()) {
return Status(error::INTERNAL, "Response has already been sent");
}
EnqueueRecordResponse response_body;
status.SaveTo(response_body.mutable_status());
response_->Return(response_body);
return Status::StatusOK();
}
EnqueueJob::EnqueueJob(scoped_refptr<StorageModuleInterface> storage_module,
EnqueueRecordRequest request,
std::unique_ptr<EnqueueResponseDelegate> delegate)
: Job(std::move(delegate)),
storage_module_(storage_module),
request_(std::move(request)) {}
void EnqueueJob::StartImpl() {
auto fd_result = ManagedFileDescriptor::Create(
base::StrCat({"/proc/", base::NumberToString(request_.pid()), "/fd/",
base::NumberToString(request_.record_fd())}));
if (!fd_result.ok()) {
Finish(fd_result.status());
return;
}
Record record;
if (!record.ParseFromFileDescriptor(fd_result.ValueOrDie()->fd())) {
Finish(Status(error::INVALID_ARGUMENT,
"Unable to parse record from provided file descriptor."));
return;
}
storage_module_->AddRecord(
request_.priority(), std::move(record),
base::BindOnce(&EnqueueJob::Finish, base::Unretained(this)));
}
} // namespace reporting