blob: 720b3d460f12d21ec511fc14cdbf13c88a8c6752 [file] [log] [blame]
// Copyright 2018 The Goma 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 "compiler_info_state.h"
#include "absl/memory/memory.h"
#include "absl/time/clock.h"
#include "autolock_timer.h"
#include "compiler_info_builder.h"
#include "cxx/cxx_compiler_info.h"
#include "glog/logging.h"
#include "glog/stl_logging.h"
#include "java/java_compiler_info.h"
using std::string;
namespace devtools_goma {
// static
std::unique_ptr<CompilerInfo> CompilerInfoState::MakeCompilerInfo(
std::unique_ptr<CompilerInfoData> data) {
switch (data->language_extension_case()) {
case CompilerInfoData::kCxx:
return absl::make_unique<CxxCompilerInfo>(std::move(data));
case CompilerInfoData::kJavac:
return absl::make_unique<JavacCompilerInfo>(std::move(data));
case CompilerInfoData::kJava:
return absl::make_unique<JavaCompilerInfo>(std::move(data));
case CompilerInfoData::LANGUAGE_EXTENSION_NOT_SET:
CHECK(false) << "CompilerInfoData does not have any language extension";
return nullptr;
}
CHECK(false) << "unexpected language extension case: "
<< static_cast<int>(data->language_extension_case());
return nullptr;
}
CompilerInfoState::CompilerInfoState(std::unique_ptr<CompilerInfoData> data)
: compiler_info_(MakeCompilerInfo(std::move(data))),
refcnt_(0),
disabled_(false),
used_(0) {
LOG(INFO) << "New CompilerInfoState " << this;
if (!compiler_info_->found() && !compiler_info_->HasError()) {
CompilerInfoBuilder::AddErrorMessage("compiler not found",
compiler_info_->mutable_data());
}
}
CompilerInfoState::~CompilerInfoState() {}
void CompilerInfoState::Ref() {
AUTOLOCK(lock, &mu_);
refcnt_++;
}
void CompilerInfoState::Deref() {
int refcnt;
{
AUTOLOCK(lock, &mu_);
refcnt_--;
refcnt = refcnt_;
}
if (refcnt == 0) {
LOG(INFO) << "Delete CompilerInfoState " << this;
delete this;
}
}
int CompilerInfoState::refcnt() const {
AUTOLOCK(lock, &mu_);
return refcnt_;
}
bool CompilerInfoState::disabled() const {
AUTOLOCK(lock, &mu_);
return disabled_;
}
string CompilerInfoState::GetDisabledReason() const {
AUTOLOCK(lock, &mu_);
return disabled_reason_;
}
void CompilerInfoState::SetDisabled(bool disabled,
const string& disabled_reason) {
AUTOLOCK(lock, &mu_);
LOG(INFO) << "CompilerInfoState " << this << " disabled=" << disabled
<< " reason=" << disabled_reason;
disabled_ = true;
disabled_reason_ = disabled_reason;
}
void CompilerInfoState::Use(const string& local_compiler_path,
const CompilerFlags& flags) {
{
AUTOLOCK(lock, &mu_);
if (used_++ > 0)
return;
}
// CompilerInfo::DebugString() could be too large for glog.
// glog message size is 30000 by default.
// https://github.com/google/glog/blob/bf766fac4f828c81556499d7c16d53cc871d8bd2/src/logging.cc#L335
// So, split info log at max 20000.
//
// TODO: It might be good to introduce a new compact printer for
// CompilerInfo. I tried implementing it with
// google::protobuf::TextFormat::Printer, but it is hardcoding ':'
// (key: value), so I gave it up to make a neat Printer with
// TextFormat::Printer.
string info = compiler_info_->DebugString();
absl::string_view piece(info);
LOG(INFO) << "compiler_info_state=" << this << " path=" << local_compiler_path
<< ": flags=" << flags.compiler_info_flags() << ": info="
<< piece.substr(0,
std::min(static_cast<size_t>(20000), piece.size()));
size_t begin_pos = 20000;
while (begin_pos < piece.size()) {
size_t len = std::min(static_cast<size_t>(20000), piece.size() - begin_pos);
LOG(INFO) << "info continued:"
<< " compiler_info_state=" << this
<< " info(continued)=" << piece.substr(begin_pos, len);
begin_pos += len;
}
}
int CompilerInfoState::used() const {
AUTOLOCK(lock, &mu_);
return used_;
}
void CompilerInfoState::UpdateLastUsedAt() {
compiler_info_->set_last_used_at(absl::Now());
}
ScopedCompilerInfoState::ScopedCompilerInfoState(CompilerInfoState* state)
: state_(state) {
if (state_ != nullptr)
state_->Ref();
}
ScopedCompilerInfoState::~ScopedCompilerInfoState() {
if (state_ != nullptr)
state_->Deref();
}
void ScopedCompilerInfoState::reset(CompilerInfoState* state) {
if (state != nullptr)
state->Ref();
if (state_ != nullptr)
state_->Deref();
state_ = state;
}
void ScopedCompilerInfoState::swap(ScopedCompilerInfoState* other) {
CompilerInfoState* other_state = other->state_;
other->state_ = state_;
state_ = other_state;
}
bool ScopedCompilerInfoState::disabled() const {
if (state_ == nullptr)
return true;
return state_->disabled();
}
string ScopedCompilerInfoState::GetDisabledReason() const {
if (state_ == nullptr)
return string();
return state_->GetDisabledReason();
}
} // namespace devtools_goma