Files
scylladb/db/cache_tracker.hh
Michał Chojnowski d785364375 cache: make all cache unlinks explicit
Our LSA cache is implemented as an auto_unlink Boost intrusive list, meaning
that elements of the list unlink themselves from the list automatically on
destruction. Some parts of the code rely on that, and don't unlink them
manually.

However, this precludes accurate bookkeeping about the cache. Elements only have
access to themselves and their neighbours, not to any bookkeeping context.
Therefore, a destructor cannot update the relevant metadata.

In this patch, we fix this by adding explicit unlink calls to places where it
would be done by a destructor. In a following patch, we will add an assert to
the destructor to check that every element is unlinked before destruction.
2022-10-17 12:07:27 +02:00

154 lines
4.7 KiB
C++

/*
* Copyright (C) 2015 ScyllaDB
*/
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include "utils/lru.hh"
#include "utils/logalloc.hh"
#include "partition_version.hh"
#include "mutation_cleaner.hh"
#include <seastar/core/metrics_registration.hh>
#include <stdint.h>
class cache_entry;
namespace cache {
class autoupdating_underlying_reader;
class cache_streamed_mutation;
class cache_flat_mutation_reader;
class read_context;
class lsa_manager;
}
// Tracks accesses and performs eviction of cache entries.
class cache_tracker final {
public:
friend class row_cache;
friend class cache::read_context;
friend class cache::autoupdating_underlying_reader;
friend class cache::cache_flat_mutation_reader;
struct stats {
uint64_t partition_hits;
uint64_t partition_misses;
uint64_t row_hits;
uint64_t dummy_row_hits;
uint64_t row_misses;
uint64_t partition_insertions;
uint64_t row_insertions;
uint64_t static_row_insertions;
uint64_t concurrent_misses_same_key;
uint64_t partition_merges;
uint64_t rows_processed_from_memtable;
uint64_t rows_dropped_from_memtable;
uint64_t rows_merged_from_memtable;
uint64_t partition_evictions;
uint64_t partition_removals;
uint64_t row_evictions;
uint64_t row_removals;
uint64_t partitions;
uint64_t rows;
uint64_t mispopulations;
uint64_t underlying_recreations;
uint64_t underlying_partition_skips;
uint64_t underlying_row_skips;
uint64_t reads;
uint64_t reads_with_misses;
uint64_t reads_done;
uint64_t pinned_dirty_memory_overload;
uint64_t range_tombstone_reads;
uint64_t row_tombstone_reads;
uint64_t active_reads() const {
return reads - reads_done;
}
};
private:
stats _stats{};
seastar::metrics::metric_groups _metrics;
logalloc::region _region;
lru _lru;
mutation_cleaner _garbage;
mutation_cleaner _memtable_cleaner;
mutation_application_stats& _app_stats;
private:
void setup_metrics();
public:
using register_metrics = bool_class<class register_metrics_tag>;
cache_tracker(mutation_application_stats&, register_metrics);
cache_tracker(register_metrics = register_metrics::no);
~cache_tracker();
void clear();
void touch(rows_entry&);
void insert(cache_entry&);
void insert(partition_entry&) noexcept;
void insert(partition_version&) noexcept;
void insert(rows_entry&) noexcept;
void remove(rows_entry&) noexcept;
void clear_continuity(cache_entry& ce) noexcept;
void on_partition_erase() noexcept;
void on_partition_merge() noexcept;
void on_partition_hit() noexcept;
void on_partition_miss() noexcept;
void on_partition_eviction() noexcept;
void on_row_eviction() noexcept;
void on_row_hit() noexcept;
void on_dummy_row_hit() noexcept;
void on_row_miss() noexcept;
void on_miss_already_populated() noexcept;
void on_mispopulate() noexcept;
void on_row_processed_from_memtable() noexcept { ++_stats.rows_processed_from_memtable; }
void on_row_dropped_from_memtable() noexcept { ++_stats.rows_dropped_from_memtable; }
void on_row_merged_from_memtable() noexcept { ++_stats.rows_merged_from_memtable; }
void on_range_tombstone_read() noexcept { ++_stats.range_tombstone_reads; }
void on_row_tombstone_read() noexcept { ++_stats.row_tombstone_reads; }
void pinned_dirty_memory_overload(uint64_t bytes) noexcept;
allocation_strategy& allocator() noexcept;
logalloc::region& region() noexcept;
const logalloc::region& region() const noexcept;
mutation_cleaner& cleaner() noexcept { return _garbage; }
mutation_cleaner& memtable_cleaner() noexcept { return _memtable_cleaner; }
uint64_t partitions() const noexcept { return _stats.partitions; }
const stats& get_stats() const noexcept { return _stats; }
void set_compaction_scheduling_group(seastar::scheduling_group);
lru& get_lru() { return _lru; }
};
inline
void cache_tracker::remove(rows_entry& entry) noexcept {
--_stats.rows;
++_stats.row_removals;
if (entry.is_linked()) {
_lru.remove(entry);
}
}
inline
void cache_tracker::insert(rows_entry& entry) noexcept {
++_stats.row_insertions;
++_stats.rows;
_lru.add(entry);
}
inline
void cache_tracker::insert(partition_version& pv) noexcept {
for (rows_entry& row : pv.partition().clustered_rows()) {
insert(row);
}
}
inline
void cache_tracker::insert(partition_entry& pe) noexcept {
for (partition_version& pv : pe.versions_from_oldest()) {
insert(pv);
}
}