添加缓存

This commit is contained in:
shell committed 2026-07-13 23:53:11 +08:00
1 parent 4d7dde104d
commit fb63205a70
4 files changed
+132 -7

No files matched your search

+1
View File
@@ -54,6 +54,7 @@ add_executable(seadisk src/main.cpp
src/seafile/fs/winfsp_adapter.cpp
include/seafile/fs/winfsp_adapter.hpp
src/util/string_util.cpp
include/seafile/cache/cache.hpp
)
target_compile_definitions(seadisk PRIVATE
+112
View File
@@ -0,0 +1,112 @@
//
// Created by Shell on 2026/7/13.
//
#ifndef SEADISK_CACHE_HPP
#define SEADISK_CACHE_HPP
#include <chrono>
#include <shared_mutex>
#include <unordered_map>
namespace seafile::cache {
template<typename K, typename V>
class Cache final{
public:
using Clock = std::chrono::steady_clock;
using Duration = Clock::duration;
/// 设置缓存
/// @param key 键
/// @param value 值
/// @param ttl 超时时间
void put(const K &key, V value, const Duration ttl) {
std::unique_lock lock(mutex_);
cache_[key] = Entry{
std::move(value),
Clock::now() + ttl
};
}
/// 获取缓存值
/// @param key 键
/// @return 缓存值
std::optional<V> get(const K &key) {
// 第一阶段:读锁
{
std::shared_lock lock(mutex_);
auto it = cache_.find(key);
if (it == cache_.end())
return std::nullopt;
if (Clock::now() < it->second.expire_time)
return it->second.value;
}
// 第二阶段:删除过期数据
{
std::unique_lock lock(mutex_);
auto it = cache_.find(key);
if (it != cache_.end() &&
Clock::now() >= it->second.expire_time)
{
cache_.erase(it);
}
}
return std::nullopt;
}
/// 移除缓存
/// @param key 键
void remove(const K &key) {
std::unique_lock lock(mutex_);
cache_.erase(key);
}
///清空缓存
void clear() {
std::unique_lock lock(mutex_);
cache_.clear();
}
///清理过时的缓存
void cleanup() {
auto now = Clock::now();
std::unique_lock lock(mutex_);
for (auto it = cache_.begin(); it != cache_.end();)
{
if (it->second.expireTime <= now)
{
it = cache_.erase(it);
}
else
{
++it;
}
}
}
///缓存大小
size_t size() const {
std::unique_lock lock(mutex_);
return cache_.size();
}
private:
struct Entry final {
V value;
Clock::time_point expire_time;
};
mutable std::shared_mutex mutex_;
std::unordered_map<K, Entry> cache_;
};
}
#endif //SEADISK_CACHE_HPP
@@ -9,6 +9,7 @@
#include "../api/seafile_api.hpp"
#include "../api/token_type.hpp"
#include "seafile/cache/cache.hpp"
namespace seafile::fs
{
@@ -19,6 +20,8 @@ namespace seafile::fs
TokenType token_type = TokenType::TOKEN;
SeaFileApi api;
std::wstring volume_label;
cache::Cache<std::string,std::vector<RepoEntry>> repo_dir_cache{};
public:
explicit SeafileFileSystem(const std::string& server,
+16 -7
View File
@@ -3,6 +3,7 @@
#include "seafile/fs/file_context.hpp"
#include "util/string_util.hpp"
#include <spdlog/spdlog.h>
#include <format>
namespace seafile::fs {
namespace {
@@ -26,7 +27,8 @@ namespace seafile::fs {
return (static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
}
void SetFileInfo(FSP_FSCTL_FILE_INFO *FileInfo, const uint32_t attributes, const uint64_t size,const int64_t mtime) {
void SetFileInfo(FSP_FSCTL_FILE_INFO *FileInfo, const uint32_t attributes, const uint64_t size,
const int64_t mtime) {
FileInfo->FileAttributes = attributes;
FileInfo->AllocationSize = size;
FileInfo->FileSize = size;
@@ -156,7 +158,7 @@ namespace seafile::fs {
const auto copy_len = (std::min)(data.size(), static_cast<size_t>(Length));
memcpy(Buffer, data.data(), copy_len);
*PBytesTransferred = static_cast<ULONG>(copy_len);
spdlog::info(std::format("read file {} bytes offset {} length {} success", fc->path,Offset, Length));
spdlog::info(std::format("read file {} bytes offset {} length {} success", fc->path, Offset, Length));
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
@@ -166,11 +168,19 @@ namespace seafile::fs {
PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred) {
const auto fc = static_cast<SeaFileContext *>(FileContext);
*PBytesTransferred = 0;
const auto path = std::ranges::replace(fc->path, '\\', '/');
const auto entries_result = api.repoDir(fc->repo_id, fc->path, token, token_type);
const auto cache_key = std::format("{}_{}", fc->repo_id, fc->path);
auto repo_entries = repo_dir_cache.get(cache_key);
if (!repo_entries.has_value()) {
if (auto entries_result = api.repoDir(fc->repo_id, fc->path, token, token_type); entries_result.has_value()) {
repo_entries = entries_result.value();
repo_dir_cache.put(cache_key, repo_entries.value(),std::chrono::seconds(60));
}else {
spdlog::error(std::format("can't read directory {},due to {}", fc->path,entries_result.error().what()));
}
}
if (entries_result.has_value()) {
const auto &entries = entries_result.value();
if (repo_entries.has_value()) {
const auto &entries = repo_entries.value();
size_t start = 0;
if (Marker) {
const auto marker = shell::util::StringUtil::utf16le_to_utf8(Marker);
@@ -208,7 +218,6 @@ namespace seafile::fs {
return STATUS_SUCCESS;
}
std::cout << entries_result.error().what() << std::endl;
return STATUS_UNSUCCESSFUL;
}