This patch implements a simple variation of LFRU eviction policy:
* We define 2 dynamic cache sections which total size should not exceed the maximum cache size.
* New cache entry is always added to the "unprivileged" section.
* After a cache entry is read more than SectionHitThreshold times it moves to the second cache section.
* Both sections' entries obey expiration and reload rules in the same way as before this patch.
* When cache entries need to be evicted due to a size restriction "unprivileged" section's
least recently used entries are evicted first.
Note:
With a 2 sections cache it's not enough for a new entry to have the latest timestamp
in order not be evicted right after insertion: e.g. if all all other entries
are from the privileged section.
And obviously we want to allow new cache entries to be added to a cache.
Therefore we can no longer first add a new entry and then shrink the cache.
Switching the order of these two operations resolves the culprit.
Fixes #8674
Signed-off-by: Vlad Zolotarov <vladz@scylladb.com>
90 lines
2.2 KiB
C++
90 lines
2.2 KiB
C++
/*
|
|
* Copyright (C) 2017-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* This file is part of Scylla.
|
|
*
|
|
* Scylla is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Scylla is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <chrono>
|
|
#include <string_view>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <optional>
|
|
#include <utility>
|
|
|
|
#include <seastar/core/future.hh>
|
|
#include <seastar/core/shared_ptr.hh>
|
|
#include <seastar/core/sstring.hh>
|
|
|
|
#include "auth/authenticated_user.hh"
|
|
#include "auth/permission.hh"
|
|
#include "auth/resource.hh"
|
|
#include "auth/role_or_anonymous.hh"
|
|
#include "log.hh"
|
|
#include "utils/hash.hh"
|
|
#include "utils/loading_cache.hh"
|
|
|
|
namespace std {
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const pair<auth::role_or_anonymous, auth::resource>& p) {
|
|
os << "{role: " << p.first << ", resource: " << p.second << "}";
|
|
return os;
|
|
}
|
|
|
|
}
|
|
|
|
namespace db {
|
|
class config;
|
|
}
|
|
|
|
namespace auth {
|
|
|
|
class service;
|
|
|
|
struct permissions_cache_config final {
|
|
std::size_t max_entries;
|
|
std::chrono::milliseconds validity_period;
|
|
std::chrono::milliseconds update_period;
|
|
};
|
|
|
|
class permissions_cache final {
|
|
using cache_type = utils::loading_cache<
|
|
std::pair<role_or_anonymous, resource>,
|
|
permission_set,
|
|
1,
|
|
utils::loading_cache_reload_enabled::yes,
|
|
utils::simple_entry_size<permission_set>,
|
|
utils::tuple_hash>;
|
|
|
|
using key_type = typename cache_type::key_type;
|
|
|
|
cache_type _cache;
|
|
|
|
public:
|
|
explicit permissions_cache(const permissions_cache_config&, service&, logging::logger&);
|
|
|
|
future <> stop() {
|
|
return _cache.stop();
|
|
}
|
|
|
|
future<permission_set> get(const role_or_anonymous&, const resource&);
|
|
};
|
|
|
|
}
|