blob: d5175a5250b0d55384199d91fdcf60e1745301e3 [file]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/persistent_cache/persistent_cache.h"
#include <memory>
#include <optional>
#include <utility>
#include "base/check.h"
#include "base/metrics/histogram_functions.h"
#include "base/numerics/safe_conversions.h"
#include "base/synchronization/lock.h"
#include "base/timer/elapsed_timer.h"
#include "base/types/expected.h"
#include "base/types/expected_macros.h"
#include "components/persistent_cache/backend.h"
#include "components/persistent_cache/backend_type.h"
#include "components/persistent_cache/metrics_util.h"
#include "components/persistent_cache/pending_backend.h"
#include "components/persistent_cache/sqlite/sqlite_backend_impl.h"
#include "components/persistent_cache/transaction_error.h"
namespace persistent_cache {
// static
base::expected<std::unique_ptr<PersistentCache>, TransactionError>
PersistentCache::Bind(Client client, PendingBackend pending_backend) {
// If there is ever occasion to have more than one type, branch on the type
// here.
ASSIGN_OR_RETURN(auto backend,
SqliteBackendImpl::Bind(std::move(pending_backend), client));
return std::make_unique<PersistentCache>(client, std::move(backend));
}
PersistentCache::PersistentCache(Client client,
std::unique_ptr<Backend> backend)
: client_(client), backend_(std::move(backend)) {
CHECK(backend_);
}
PersistentCache::~PersistentCache() = default;
base::expected<std::optional<EntryMetadata>, TransactionError>
PersistentCache::Find(base::span<const uint8_t> key,
BufferProvider buffer_provider) {
std::optional<base::ElapsedTimer> timer = MaybeGetTimerForHistogram();
auto entry_metadata = backend_->Find(key, buffer_provider);
if (timer.has_value()) {
base::UmaHistogramMicrosecondsTimes(
GetHistogramName(client_, "Find", !backend_->IsReadOnly()),
timer->Elapsed());
}
return entry_metadata;
}
base::expected<void, TransactionError> PersistentCache::Insert(
base::span<const uint8_t> key,
base::span<const uint8_t> content,
EntryMetadata metadata) {
std::optional<base::ElapsedTimer> timer = MaybeGetTimerForHistogram();
auto result = backend_->Insert(key, content, metadata);
if (timer.has_value()) {
base::UmaHistogramMicrosecondsTimes(GetHistogramName(client_, "Insert"),
timer->Elapsed());
if (result.has_value()) {
base::UmaHistogramCounts10M(GetHistogramName(client_, "InsertSize"),
base::saturated_cast<int>(content.size()));
}
}
return result;
}
LockState PersistentCache::Abandon() {
return backend_->Abandon();
}
Backend* PersistentCache::GetBackendForTesting() {
return backend_.get();
}
std::optional<base::ElapsedTimer> PersistentCache::MaybeGetTimerForHistogram() {
std::optional<base::ElapsedTimer> timer;
static constexpr double kTimingLoggingProbability = 0.01;
if (base::ShouldRecordSubsampledMetric(kTimingLoggingProbability)) {
timer.emplace();
}
return timer;
}
} // namespace persistent_cache