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