plugins/slice/ObjectSizeCache.cc (77 lines of code) (raw):
/** @file cache.cc
Metadata cache to store object sizes.
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ObjectSizeCache.h"
#include <cassert>
ObjectSizeCache::ObjectSizeCache(cache_size_type cache_size)
: _cache_capacity(cache_size), _urls(cache_size), _object_sizes(cache_size, 0), _visits(cache_size, false)
{
}
std::optional<uint64_t>
ObjectSizeCache::get(const std::string_view url)
{
std::lock_guard lock{_mutex};
if (auto it = _index.find(url); it != _index.end()) {
// Cache hit
cache_size_type i = it->second;
_visits[i] = true;
assert(url == _urls[i]);
return _object_sizes[i];
} else {
// Cache miss
return std::nullopt;
}
}
void
ObjectSizeCache::set(const std::string_view url, uint64_t object_size)
{
std::lock_guard lock{_mutex};
cache_size_type i;
if (auto it = _index.find(url); it != _index.end()) {
// Already exists in cache. Overwrite.
i = it->second;
} else {
// Doesn't exist in cache. Evict something else.
find_eviction_slot();
i = _hand;
_urls[i] = url;
_index[_urls[i]] = _hand;
_hand++;
if (_hand >= _cache_capacity) {
_hand = 0;
}
}
_object_sizes[i] = object_size;
}
void
ObjectSizeCache::remove(const std::string_view url)
{
std::lock_guard lock{_mutex};
if (auto it = _index.find(url); it != _index.end()) {
cache_size_type i = it->second;
_visits[i] = false;
_urls[i].erase();
_index.erase(it);
}
}
/**
* @brief Make _hand point to the next entry that should be replaced, and clear that entry if it exists.
*
*/
void
ObjectSizeCache::find_eviction_slot()
{
while (_visits[_hand]) {
_visits[_hand] = false;
_hand++;
if (_hand >= _cache_capacity) {
_hand = 0;
}
}
std::string_view evicted_url = _urls[_hand];
if (!evicted_url.empty()) {
auto it = _index.find(evicted_url);
assert(it != _index.end());
_index.erase(it);
_urls[_hand].erase();
}
}
ObjectSizeCache::cache_size_type
ObjectSizeCache::cache_capacity()
{
return _cache_capacity;
}
ObjectSizeCache::cache_size_type
ObjectSizeCache::cache_count()
{
return _index.size();
}