// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/service/gpu_persistent_cache.h"

#include <string_view>

#include "base/containers/span.h"
#include "base/dcheck_is_on.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected_macros.h"
#include "components/persistent_cache/entry.h"
#include "components/persistent_cache/persistent_cache.h"

namespace gpu {

namespace {

constexpr size_t kMaxLoadStoreForTrackingCacheAvailable = 100;

class ScopedHistogramTimer {
 public:
  explicit ScopedHistogramTimer(const std::string& name) : name_(name) {}
  ~ScopedHistogramTimer() {
    if (enabled_) {
      base::UmaHistogramCustomMicrosecondsTimes(name_, timer_.Elapsed(),
                                                base::Microseconds(1),
                                                base::Seconds(30), 100);
    }
  }

  void SetEnabled(bool enabled) { enabled_ = enabled; }

 private:
  const std::string name_;
  base::ElapsedTimer timer_;
  bool enabled_ = true;
};

}  // namespace

GpuPersistentCache::GpuPersistentCache(std::string_view cache_prefix)
    : cache_prefix_(cache_prefix) {}

GpuPersistentCache::~GpuPersistentCache() = default;

void GpuPersistentCache::InitializeCache(
    persistent_cache::BackendParams backend_params) {
  CHECK(!initialized_.IsSet());
  persistent_cache_ =
      persistent_cache::PersistentCache::Open(std::move(backend_params));
  if (persistent_cache_) {
    initialized_.Set();
  }
}

size_t GpuPersistentCache::LoadData(const void* key,
                                    size_t key_size,
                                    void* value,
                                    size_t value_size) {
  std::string_view key_str(static_cast<const char*>(key), key_size);
  std::unique_ptr<persistent_cache::Entry> entry = LoadEntry(key_str);
  if (!entry) {
    return 0;
  }

  if (value_size > 0) {
    return entry->CopyContentTo(
        UNSAFE_TODO(base::span(static_cast<uint8_t*>(value), value_size)));
  }

  return entry->GetContentSize();
}

std::unique_ptr<persistent_cache::Entry> GpuPersistentCache::LoadEntry(
    std::string_view key) {
  ScopedHistogramTimer timer(GetHistogramName("Load"));
  const bool initialized = initialized_.IsSet();
  TRACE_EVENT1("gpu", "GpuPersistentCache::LoadEntry", "persistent_cache_",
               initialized);

  // Track cache available for the 1st kMaxLoadStoreForTrackingCacheAvailable
  // loads.
  if (load_count_.fetch_add(1, std::memory_order_relaxed) <
      kMaxLoadStoreForTrackingCacheAvailable) {
    base::UmaHistogramBoolean(GetHistogramName("Load.CacheAvailable"),
                              initialized);
  }

  if (!initialized) {
    timer.SetEnabled(false);
    return nullptr;
  }

  ASSIGN_OR_RETURN(auto entry, persistent_cache_->Find(key),
                   [](persistent_cache::TransactionError error)
                       -> std::unique_ptr<persistent_cache::Entry> {
                     // TODO(crbug.com/377475540): Handle or at least address
                     // permanent errors.
                     return nullptr;
                   });

  return entry;
}

void GpuPersistentCache::StoreData(const void* key,
                                   size_t key_size,
                                   const void* value,
                                   size_t value_size) {
  ScopedHistogramTimer timer(GetHistogramName("Store"));
  const bool initialized = initialized_.IsSet();
  TRACE_EVENT1("gpu", "GpuPersistentCache::StoreData", "persistent_cache_",
               initialized);

  // Track cache available for the 1st kMaxLoadStoreForTrackingCacheAvailable
  // stores.
  if (store_count_.fetch_add(1, std::memory_order_relaxed) <
      kMaxLoadStoreForTrackingCacheAvailable) {
    base::UmaHistogramBoolean(GetHistogramName("Store.CacheAvailable"),
                              initialized);
  }

  if (!initialized) {
    timer.SetEnabled(false);
    return;
  }

  std::string_view key_str(static_cast<const char*>(key), key_size);
  RETURN_IF_ERROR(
      persistent_cache_->Insert(
          key_str, UNSAFE_TODO(base::span(static_cast<const uint8_t*>(value),
                                          value_size))),
      [](persistent_cache::TransactionError error) {
        // TODO(crbug.com/377475540): Handle or at least address
        // permanent errors.
        return;
      });
}

std::string GpuPersistentCache::GetHistogramName(
    std::string_view metric) const {
  return "GPU.PersistentCache." + cache_prefix_ + "." + std::string(metric);
}

}  // namespace gpu
