]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
7c673cae FG |
3 | |
4 | #ifndef CEPH_RGWCACHE_H | |
5 | #define CEPH_RGWCACHE_H | |
6 | ||
7c673cae FG |
7 | #include <string> |
8 | #include <map> | |
11fdf7f2 | 9 | #include <unordered_map> |
7c673cae FG |
10 | #include "include/types.h" |
11 | #include "include/utime.h" | |
11fdf7f2 | 12 | #include "include/ceph_assert.h" |
9f95a23c TL |
13 | #include "common/ceph_mutex.h" |
14 | ||
15 | #include "cls/version/cls_version_types.h" | |
16 | #include "rgw_common.h" | |
7c673cae FG |
17 | |
18 | enum { | |
19 | UPDATE_OBJ, | |
20 | REMOVE_OBJ, | |
21 | }; | |
22 | ||
23 | #define CACHE_FLAG_DATA 0x01 | |
24 | #define CACHE_FLAG_XATTRS 0x02 | |
25 | #define CACHE_FLAG_META 0x04 | |
26 | #define CACHE_FLAG_MODIFY_XATTRS 0x08 | |
27 | #define CACHE_FLAG_OBJV 0x10 | |
28 | ||
7c673cae FG |
29 | struct ObjectMetaInfo { |
30 | uint64_t size; | |
31 | real_time mtime; | |
32 | ||
33 | ObjectMetaInfo() : size(0) {} | |
34 | ||
35 | void encode(bufferlist& bl) const { | |
36 | ENCODE_START(2, 2, bl); | |
11fdf7f2 TL |
37 | encode(size, bl); |
38 | encode(mtime, bl); | |
7c673cae FG |
39 | ENCODE_FINISH(bl); |
40 | } | |
11fdf7f2 | 41 | void decode(bufferlist::const_iterator& bl) { |
7c673cae | 42 | DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl); |
11fdf7f2 TL |
43 | decode(size, bl); |
44 | decode(mtime, bl); | |
7c673cae FG |
45 | DECODE_FINISH(bl); |
46 | } | |
47 | void dump(Formatter *f) const; | |
48 | static void generate_test_instances(list<ObjectMetaInfo*>& o); | |
49 | }; | |
50 | WRITE_CLASS_ENCODER(ObjectMetaInfo) | |
51 | ||
52 | struct ObjectCacheInfo { | |
b32b8144 FG |
53 | int status = 0; |
54 | uint32_t flags = 0; | |
55 | uint64_t epoch = 0; | |
7c673cae FG |
56 | bufferlist data; |
57 | map<string, bufferlist> xattrs; | |
58 | map<string, bufferlist> rm_xattrs; | |
59 | ObjectMetaInfo meta; | |
b32b8144 | 60 | obj_version version = {}; |
28e407b8 | 61 | ceph::coarse_mono_time time_added; |
7c673cae | 62 | |
b32b8144 | 63 | ObjectCacheInfo() = default; |
7c673cae FG |
64 | |
65 | void encode(bufferlist& bl) const { | |
66 | ENCODE_START(5, 3, bl); | |
11fdf7f2 TL |
67 | encode(status, bl); |
68 | encode(flags, bl); | |
69 | encode(data, bl); | |
70 | encode(xattrs, bl); | |
71 | encode(meta, bl); | |
72 | encode(rm_xattrs, bl); | |
73 | encode(epoch, bl); | |
74 | encode(version, bl); | |
7c673cae FG |
75 | ENCODE_FINISH(bl); |
76 | } | |
11fdf7f2 | 77 | void decode(bufferlist::const_iterator& bl) { |
7c673cae | 78 | DECODE_START_LEGACY_COMPAT_LEN(5, 3, 3, bl); |
11fdf7f2 TL |
79 | decode(status, bl); |
80 | decode(flags, bl); | |
81 | decode(data, bl); | |
82 | decode(xattrs, bl); | |
83 | decode(meta, bl); | |
7c673cae | 84 | if (struct_v >= 2) |
11fdf7f2 | 85 | decode(rm_xattrs, bl); |
7c673cae | 86 | if (struct_v >= 4) |
11fdf7f2 | 87 | decode(epoch, bl); |
7c673cae | 88 | if (struct_v >= 5) |
11fdf7f2 | 89 | decode(version, bl); |
7c673cae FG |
90 | DECODE_FINISH(bl); |
91 | } | |
92 | void dump(Formatter *f) const; | |
93 | static void generate_test_instances(list<ObjectCacheInfo*>& o); | |
94 | }; | |
95 | WRITE_CLASS_ENCODER(ObjectCacheInfo) | |
96 | ||
97 | struct RGWCacheNotifyInfo { | |
98 | uint32_t op; | |
99 | rgw_raw_obj obj; | |
100 | ObjectCacheInfo obj_info; | |
101 | off_t ofs; | |
102 | string ns; | |
103 | ||
104 | RGWCacheNotifyInfo() : op(0), ofs(0) {} | |
105 | ||
106 | void encode(bufferlist& obl) const { | |
107 | ENCODE_START(2, 2, obl); | |
11fdf7f2 TL |
108 | encode(op, obl); |
109 | encode(obj, obl); | |
110 | encode(obj_info, obl); | |
111 | encode(ofs, obl); | |
112 | encode(ns, obl); | |
7c673cae FG |
113 | ENCODE_FINISH(obl); |
114 | } | |
11fdf7f2 | 115 | void decode(bufferlist::const_iterator& ibl) { |
7c673cae | 116 | DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, ibl); |
11fdf7f2 TL |
117 | decode(op, ibl); |
118 | decode(obj, ibl); | |
119 | decode(obj_info, ibl); | |
120 | decode(ofs, ibl); | |
121 | decode(ns, ibl); | |
7c673cae FG |
122 | DECODE_FINISH(ibl); |
123 | } | |
124 | void dump(Formatter *f) const; | |
125 | static void generate_test_instances(list<RGWCacheNotifyInfo*>& o); | |
126 | }; | |
127 | WRITE_CLASS_ENCODER(RGWCacheNotifyInfo) | |
128 | ||
11fdf7f2 TL |
129 | class RGWChainedCache { |
130 | public: | |
131 | virtual ~RGWChainedCache() {} | |
132 | virtual void chain_cb(const string& key, void *data) = 0; | |
133 | virtual void invalidate(const string& key) = 0; | |
134 | virtual void invalidate_all() = 0; | |
135 | virtual void unregistered() {} | |
136 | ||
137 | struct Entry { | |
138 | RGWChainedCache *cache; | |
139 | const string& key; | |
140 | void *data; | |
141 | ||
142 | Entry(RGWChainedCache *_c, const string& _k, void *_d) : cache(_c), key(_k), data(_d) {} | |
143 | }; | |
144 | }; | |
145 | ||
146 | ||
7c673cae FG |
147 | struct ObjectCacheEntry { |
148 | ObjectCacheInfo info; | |
149 | std::list<string>::iterator lru_iter; | |
150 | uint64_t lru_promotion_ts; | |
151 | uint64_t gen; | |
11fdf7f2 | 152 | std::vector<pair<RGWChainedCache *, string> > chained_entries; |
7c673cae FG |
153 | |
154 | ObjectCacheEntry() : lru_promotion_ts(0), gen(0) {} | |
155 | }; | |
156 | ||
157 | class ObjectCache { | |
11fdf7f2 | 158 | std::unordered_map<string, ObjectCacheEntry> cache_map; |
7c673cae FG |
159 | std::list<string> lru; |
160 | unsigned long lru_size; | |
161 | unsigned long lru_counter; | |
162 | unsigned long lru_window; | |
9f95a23c | 163 | ceph::shared_mutex lock = ceph::make_shared_mutex("ObjectCache"); |
7c673cae FG |
164 | CephContext *cct; |
165 | ||
11fdf7f2 | 166 | vector<RGWChainedCache *> chained_cache; |
7c673cae FG |
167 | |
168 | bool enabled; | |
b32b8144 | 169 | ceph::timespan expiry; |
7c673cae | 170 | |
11fdf7f2 TL |
171 | void touch_lru(const string& name, ObjectCacheEntry& entry, |
172 | std::list<string>::iterator& lru_iter); | |
3a9019d9 | 173 | void remove_lru(const string& name, std::list<string>::iterator& lru_iter); |
b32b8144 | 174 | void invalidate_lru(ObjectCacheEntry& entry); |
7c673cae FG |
175 | |
176 | void do_invalidate_all(); | |
11fdf7f2 | 177 | |
7c673cae | 178 | public: |
9f95a23c | 179 | ObjectCache() : lru_size(0), lru_counter(0), lru_window(0), cct(NULL), enabled(false) { } |
11fdf7f2 | 180 | ~ObjectCache(); |
3a9019d9 | 181 | int get(const std::string& name, ObjectCacheInfo& bl, uint32_t mask, rgw_cache_entry_info *cache_info); |
11fdf7f2 TL |
182 | std::optional<ObjectCacheInfo> get(const std::string& name) { |
183 | std::optional<ObjectCacheInfo> info{std::in_place}; | |
3a9019d9 | 184 | auto r = get(name, *info, 0, nullptr); |
11fdf7f2 | 185 | return r < 0 ? std::nullopt : info; |
3a9019d9 FG |
186 | } |
187 | ||
188 | template<typename F> | |
189 | void for_each(const F& f) { | |
9f95a23c | 190 | std::shared_lock l{lock}; |
3a9019d9 FG |
191 | if (enabled) { |
192 | auto now = ceph::coarse_mono_clock::now(); | |
11fdf7f2 TL |
193 | for (const auto& [name, entry] : cache_map) { |
194 | if (expiry.count() && (now - entry.info.time_added) < expiry) { | |
195 | f(name, entry); | |
3a9019d9 FG |
196 | } |
197 | } | |
198 | } | |
199 | } | |
200 | ||
201 | void put(const std::string& name, ObjectCacheInfo& bl, rgw_cache_entry_info *cache_info); | |
202 | bool remove(const std::string& name); | |
7c673cae FG |
203 | void set_ctx(CephContext *_cct) { |
204 | cct = _cct; | |
205 | lru_window = cct->_conf->rgw_cache_lru_size / 2; | |
11fdf7f2 | 206 | expiry = std::chrono::seconds(cct->_conf.get_val<uint64_t>( |
b32b8144 | 207 | "rgw_cache_expiry_interval")); |
7c673cae | 208 | } |
11fdf7f2 TL |
209 | bool chain_cache_entry(std::initializer_list<rgw_cache_entry_info*> cache_info_entries, |
210 | RGWChainedCache::Entry *chained_entry); | |
7c673cae FG |
211 | |
212 | void set_enabled(bool status); | |
213 | ||
214 | void chain_cache(RGWChainedCache *cache); | |
11fdf7f2 | 215 | void unchain_cache(RGWChainedCache *cache); |
7c673cae FG |
216 | void invalidate_all(); |
217 | }; | |
218 | ||
7c673cae | 219 | #endif |