forked from facebook/rocksdb
-
Notifications
You must be signed in to change notification settings - Fork 138
Expand file tree
/
Copy pathcloud_file_cache.cc
More file actions
157 lines (137 loc) · 4.59 KB
/
Copy pathcloud_file_cache.cc
File metadata and controls
157 lines (137 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Copyright (c) 2021 Rockset.
#ifndef ROCKSDB_LITE
#include <cinttypes>
#include "cloud/cloud_env_impl.h"
namespace ROCKSDB_NAMESPACE {
namespace {
// The Value inside every cached entry
struct Value {
std::string path;
CloudEnvImpl* cenv;
Value(const std::string& _path, CloudEnvImpl* _cenv)
: path(_path), cenv(_cenv) {}
};
// static method to use as a callback from the cache.
static void DeleteEntry(const Slice& key, void* v) {
Value* value = reinterpret_cast<Value*>(v);
std::string filename(key.data(), key.size());
value->cenv->FileCacheDeleter(filename);
delete value;
}
// These are used to retrieve all the values from the cache.
// Only used for unit tests.
static Value* DecodeValue(void* v) {
return static_cast<Value*>(reinterpret_cast<Value*>(v));
}
static std::vector<std::pair<Value*, uint64_t>> callback_state;
static void callback(void* entry, size_t charge) {
callback_state.push_back({DecodeValue(entry), charge});
}
static void clear_callback_state() { callback_state.clear(); }
} // namespace
//
// Touch the file so that is the the most-recent LRU item in cache.
//
void CloudEnvImpl::FileCacheAccess(const std::string& fname) {
if (!cloud_env_options.hasSstFileCache()) {
return;
}
Slice key(fname);
Cache::Handle* handle = cloud_env_options.sst_file_cache->Lookup(key);
if (handle) {
cloud_env_options.sst_file_cache->Release(handle);
}
log(InfoLogLevel::DEBUG_LEVEL, fname, "access");
}
//
// Record the file into the cache.
//
void CloudEnvImpl::FileCacheInsert(const std::string& fname,
uint64_t filesize) {
if (!cloud_env_options.hasSstFileCache()) {
return;
}
// insert into cache, key is the file path.
Slice key(fname);
cloud_env_options.sst_file_cache->Insert(key, new Value(fname, this),
filesize, DeleteEntry);
log(InfoLogLevel::INFO_LEVEL, fname, "insert");
}
//
// Remove a specific entry from the cache.
//
void CloudEnvImpl::FileCacheErase(const std::string& fname) {
// We erase from the cache even if the cache size is zero. This is needed
// to protect against the when the cache size was dynamically reduced to zero
// on a running database.
if (!cloud_env_options.sst_file_cache) {
return;
}
Slice key(fname);
cloud_env_options.sst_file_cache->Erase(key);
log(InfoLogLevel::INFO_LEVEL, fname, "erased");
}
//
// When the cache is full, delete files from local store
//
void CloudEnvImpl::FileCacheDeleter(const std::string& fname) {
Status st = base_env_->DeleteFile(fname);
log(InfoLogLevel::INFO_LEVEL, fname, "purged");
}
//
// Get total charge in the cache.
// This is not thread-safe and is used only for unit tests.
//
uint64_t CloudEnvImpl::FileCacheGetCharge() {
clear_callback_state();
cloud_env_options.sst_file_cache->ApplyToAllCacheEntries(callback, true);
uint64_t total = 0;
for (auto& it : callback_state) {
total += it.second;
}
return total;
}
//
// Get total number of items in the cache.
// This is not thread-safe and is used only for unit tests.
//
uint64_t CloudEnvImpl::FileCacheGetNumItems() {
clear_callback_state();
cloud_env_options.sst_file_cache->ApplyToAllCacheEntries(callback, true);
return callback_state.size();
}
// Removes all items for the env from the cache.
// This is not thread-safe.
void CloudEnvImpl::FileCachePurge() {
// We erase from the cache even if the cache size is zero. This is needed
// to protect against the when the cache size was dynamically reduced to zero
// on a running database.
if (!cloud_env_options.sst_file_cache) {
return;
}
// fetch all items from cache
clear_callback_state();
cloud_env_options.sst_file_cache->ApplyToAllCacheEntries(callback, true);
// for all those items that have a matching cenv, remove them from cache.
uint64_t count = 0;
for (auto& it : callback_state) {
Value* value = it.first;
if (value->cenv == this) {
Slice key(value->path);
cloud_env_options.sst_file_cache->Erase(key);
count++;
}
}
log(InfoLogLevel::INFO_LEVEL, "ENV-DELETE", "purged");
}
void CloudEnvImpl::log(InfoLogLevel level, const std::string& fname,
const std::string& msg) {
uint64_t usage = cloud_env_options.sst_file_cache->GetUsage();
uint64_t capacity = cloud_env_options.sst_file_cache->GetCapacity();
auto percent = (capacity > 0 ? (100L * usage / capacity) : 0);
Log(level, info_log_,
"[%s] FileCache %s %s cache-used %" PRIu64 "/%" PRIu64 "(%ld%%) bytes",
Name(), fname.c_str(), msg.c_str(), usage, capacity, percent);
}
} // namespace ROCKSDB_NAMESPACE
#endif // ROCKSDB_LITE