// Copyright (c) 2013 The Chromium 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 "gn/import_manager.h"

#include <memory>

#include "gn/err.h"
#include "gn/parse_tree.h"
#include "gn/scheduler.h"
#include "gn/scope_per_file_provider.h"
#include "gn/trace.h"
#include "util/ticks.h"

namespace {

// Returns a newly-allocated scope on success, null on failure.
std::unique_ptr<Scope> UncachedImport(const Settings* settings,
                                      const SourceFile& file,
                                      const ParseNode* node_for_err,
                                      Err* err) {
  ScopedTrace load_trace(TraceItem::TRACE_IMPORT_LOAD, file.value());
  load_trace.SetToolchain(settings->toolchain_label());

  const ParseNode* node = g_scheduler->input_file_manager()->SyncLoadFile(
      node_for_err->GetRange(), settings->build_settings(), file, err);
  if (!node)
    return nullptr;

  std::unique_ptr<Scope> scope =
      std::make_unique<Scope>(settings->base_config());
  scope->set_source_dir(file.GetDir());

  // Don't allow ScopePerFileProvider to provide target-related variables.
  // These will be relative to the imported file, which is probably not what
  // people mean when they use these.
  ScopePerFileProvider per_file_provider(scope.get(), false);

  scope->SetProcessingImport();
  node->Execute(scope.get(), err);
  if (err->has_error()) {
    // If there was an error, append the caller location so the error message
    // displays a why the file was imported (esp. useful for failed asserts).
    err->AppendSubErr(Err(node_for_err, "whence it was imported."));
    return nullptr;
  }
  scope->ClearProcessingImport();

  return scope;
}

}  // namespace

struct ImportManager::ImportInfo {
  ImportInfo() = default;
  ~ImportInfo() = default;

  // This lock protects the unique_ptr. Once the scope is computed,
  // it is const and can be accessed read-only outside of the lock.
  std::mutex load_lock;

  std::unique_ptr<const Scope> scope;

  // The result of loading the import. If the load failed, the scope will be
  // null but this will be set to error. In this case the thread should not
  // attempt to load the file, even if the scope is null.
  Err load_result;
};

ImportManager::ImportManager() = default;

ImportManager::~ImportManager() = default;

bool ImportManager::DoImport(const SourceFile& file,
                             const ParseNode* node_for_err,
                             Scope* scope,
                             Err* err) {
  // Key for the current import on the current thread in imports_in_progress_.
  std::stringstream ss;
  ss << std::this_thread::get_id() << file.value();
  std::string key = ss.str();

  // See if we have a cached import, but be careful to actually do the scope
  // copying outside of the lock.
  ImportInfo* import_info = nullptr;
  {
    std::lock_guard<std::mutex> lock(imports_lock_);
    std::unique_ptr<ImportInfo>& info_ptr = imports_[file];
    if (!info_ptr)
      info_ptr = std::make_unique<ImportInfo>();

    // Promote the ImportInfo to outside of the imports lock.
    import_info = info_ptr.get();

    if (imports_in_progress_.find(key) != imports_in_progress_.end()) {
      *err = Err(Location(), file.value() + " is part of an import loop.");
      return false;
    }
    imports_in_progress_.insert(key);
  }

  // Now use the per-import-file lock to block this thread if another thread
  // is already processing the import.
  const Scope* import_scope = nullptr;
  {
    Ticks import_block_begin = TicksNow();
    std::lock_guard<std::mutex> lock(import_info->load_lock);

    if (!import_info->scope) {
      // Only load if the import hasn't already failed.
      if (!import_info->load_result.has_error()) {
        import_info->scope = UncachedImport(
            scope->settings(), file, node_for_err, &import_info->load_result);
      }
      if (import_info->load_result.has_error()) {
        *err = import_info->load_result;
        return false;
      }
    } else {
      // Add trace if this thread was blocked for a long period of time and did
      // not load the import itself.
      Ticks import_block_end = TicksNow();
      constexpr auto kImportBlockTraceThresholdMS = 20;
      if (TracingEnabled() &&
          TicksDelta(import_block_end, import_block_begin).InMilliseconds() >
              kImportBlockTraceThresholdMS) {
        auto import_block_trace = std::make_unique<TraceItem>(
            TraceItem::TRACE_IMPORT_BLOCK, file.value(),
            std::this_thread::get_id());
        import_block_trace->set_begin(import_block_begin);
        import_block_trace->set_end(import_block_end);
        import_block_trace->set_toolchain(
            scope->settings()->toolchain_label().GetUserVisibleName(false));
        AddTrace(std::move(import_block_trace));
      }
    }

    // Promote the now-read-only scope to outside the load lock.
    import_scope = import_info->scope.get();
  }

  Scope::MergeOptions options;
  options.skip_private_vars = true;
  options.mark_dest_used = true;  // Don't require all imported values be used.

  {
    std::lock_guard<std::mutex> lock(imports_lock_);
    imports_in_progress_.erase(key);
  }

  return import_scope->NonRecursiveMergeTo(scope, options, node_for_err,
                                           "import", err);
}

std::vector<SourceFile> ImportManager::GetImportedFiles() const {
  std::vector<SourceFile> imported_files;
  imported_files.resize(imports_.size());
  std::transform(imports_.begin(), imports_.end(), imported_files.begin(),
                 [](const ImportMap::value_type& val) { return val.first; });
  return imported_files;
}
