]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab ft=cpp | |
3 | ||
4 | #include "rgw_metadata.h" | |
5 | ||
6 | #include "rgw_zone.h" | |
7 | #include "rgw_mdlog.h" | |
8 | ||
9 | #include "services/svc_zone.h" | |
10 | #include "services/svc_cls.h" | |
11 | ||
12 | #define dout_subsys ceph_subsys_rgw | |
13 | ||
14 | using namespace std; | |
15 | ||
16 | const std::string RGWMetadataLogHistory::oid = "meta.history"; | |
17 | ||
18 | struct obj_version; | |
19 | ||
20 | void rgw_shard_name(const string& prefix, unsigned max_shards, const string& key, string& name, int *shard_id) | |
21 | { | |
22 | uint32_t val = ceph_str_hash_linux(key.c_str(), key.size()); | |
23 | char buf[16]; | |
24 | if (shard_id) { | |
25 | *shard_id = val % max_shards; | |
26 | } | |
27 | snprintf(buf, sizeof(buf), "%u", (unsigned)(val % max_shards)); | |
28 | name = prefix + buf; | |
29 | } | |
30 | ||
31 | void rgw_shard_name(const string& prefix, unsigned max_shards, const string& section, const string& key, string& name) | |
32 | { | |
33 | uint32_t val = ceph_str_hash_linux(key.c_str(), key.size()); | |
34 | val ^= ceph_str_hash_linux(section.c_str(), section.size()); | |
35 | char buf[16]; | |
36 | snprintf(buf, sizeof(buf), "%u", (unsigned)(val % max_shards)); | |
37 | name = prefix + buf; | |
38 | } | |
39 | ||
40 | void rgw_shard_name(const string& prefix, unsigned shard_id, string& name) | |
41 | { | |
42 | char buf[16]; | |
43 | snprintf(buf, sizeof(buf), "%u", shard_id); | |
44 | name = prefix + buf; | |
45 | } | |
46 | ||
47 | int RGWMetadataLog::add_entry(const DoutPrefixProvider *dpp, const string& hash_key, const string& section, const string& key, bufferlist& bl) { | |
48 | if (!svc.zone->need_to_log_metadata()) | |
49 | return 0; | |
50 | ||
51 | string oid; | |
52 | int shard_id; | |
53 | ||
54 | rgw_shard_name(prefix, cct->_conf->rgw_md_log_max_shards, hash_key, oid, &shard_id); | |
55 | mark_modified(shard_id); | |
56 | real_time now = real_clock::now(); | |
57 | return svc.cls->timelog.add(dpp, oid, now, section, key, bl, null_yield); | |
58 | } | |
59 | ||
60 | int RGWMetadataLog::get_shard_id(const string& hash_key, int *shard_id) | |
61 | { | |
62 | string oid; | |
63 | ||
64 | rgw_shard_name(prefix, cct->_conf->rgw_md_log_max_shards, hash_key, oid, shard_id); | |
65 | return 0; | |
66 | } | |
67 | ||
68 | int RGWMetadataLog::store_entries_in_shard(const DoutPrefixProvider *dpp, list<cls_log_entry>& entries, int shard_id, librados::AioCompletion *completion) | |
69 | { | |
70 | string oid; | |
71 | ||
72 | mark_modified(shard_id); | |
73 | rgw_shard_name(prefix, shard_id, oid); | |
74 | return svc.cls->timelog.add(dpp, oid, entries, completion, false, null_yield); | |
75 | } | |
76 | ||
77 | void RGWMetadataLog::init_list_entries(int shard_id, const real_time& from_time, const real_time& end_time, | |
78 | const string& marker, void **handle) | |
79 | { | |
80 | LogListCtx *ctx = new LogListCtx(); | |
81 | ||
82 | ctx->cur_shard = shard_id; | |
83 | ctx->from_time = from_time; | |
84 | ctx->end_time = end_time; | |
85 | ctx->marker = marker; | |
86 | ||
87 | get_shard_oid(ctx->cur_shard, ctx->cur_oid); | |
88 | ||
89 | *handle = (void *)ctx; | |
90 | } | |
91 | ||
92 | void RGWMetadataLog::complete_list_entries(void *handle) { | |
93 | LogListCtx *ctx = static_cast<LogListCtx *>(handle); | |
94 | delete ctx; | |
95 | } | |
96 | ||
97 | int RGWMetadataLog::list_entries(const DoutPrefixProvider *dpp, void *handle, | |
98 | int max_entries, | |
99 | list<cls_log_entry>& entries, | |
100 | string *last_marker, | |
101 | bool *truncated) { | |
102 | LogListCtx *ctx = static_cast<LogListCtx *>(handle); | |
103 | ||
104 | if (!max_entries) { | |
105 | *truncated = false; | |
106 | return 0; | |
107 | } | |
108 | ||
109 | std::string next_marker; | |
110 | int ret = svc.cls->timelog.list(dpp, ctx->cur_oid, ctx->from_time, ctx->end_time, | |
111 | max_entries, entries, ctx->marker, | |
112 | &next_marker, truncated, null_yield); | |
113 | if ((ret < 0) && (ret != -ENOENT)) | |
114 | return ret; | |
115 | ||
116 | ctx->marker = std::move(next_marker); | |
117 | if (last_marker) { | |
118 | *last_marker = ctx->marker; | |
119 | } | |
120 | ||
121 | if (ret == -ENOENT) | |
122 | *truncated = false; | |
123 | ||
124 | return 0; | |
125 | } | |
126 | ||
127 | int RGWMetadataLog::get_info(const DoutPrefixProvider *dpp, int shard_id, RGWMetadataLogInfo *info) | |
128 | { | |
129 | string oid; | |
130 | get_shard_oid(shard_id, oid); | |
131 | ||
132 | cls_log_header header; | |
133 | ||
134 | int ret = svc.cls->timelog.info(dpp, oid, &header, null_yield); | |
135 | if ((ret < 0) && (ret != -ENOENT)) | |
136 | return ret; | |
137 | ||
138 | info->marker = header.max_marker; | |
139 | info->last_update = header.max_time.to_real_time(); | |
140 | ||
141 | return 0; | |
142 | } | |
143 | ||
144 | static void _mdlog_info_completion(librados::completion_t cb, void *arg) | |
145 | { | |
146 | auto infoc = static_cast<RGWMetadataLogInfoCompletion *>(arg); | |
147 | infoc->finish(cb); | |
148 | infoc->put(); // drop the ref from get_info_async() | |
149 | } | |
150 | ||
151 | RGWMetadataLogInfoCompletion::RGWMetadataLogInfoCompletion(info_callback_t cb) | |
152 | : completion(librados::Rados::aio_create_completion((void *)this, | |
153 | _mdlog_info_completion)), | |
154 | callback(cb) | |
155 | { | |
156 | } | |
157 | ||
158 | RGWMetadataLogInfoCompletion::~RGWMetadataLogInfoCompletion() | |
159 | { | |
160 | completion->release(); | |
161 | } | |
162 | ||
163 | int RGWMetadataLog::get_info_async(const DoutPrefixProvider *dpp, int shard_id, RGWMetadataLogInfoCompletion *completion) | |
164 | { | |
165 | string oid; | |
166 | get_shard_oid(shard_id, oid); | |
167 | ||
168 | completion->get(); // hold a ref until the completion fires | |
169 | ||
170 | return svc.cls->timelog.info_async(dpp, completion->get_io_obj(), oid, | |
171 | &completion->get_header(), | |
172 | completion->get_completion()); | |
173 | } | |
174 | ||
175 | int RGWMetadataLog::trim(const DoutPrefixProvider *dpp, int shard_id, const real_time& from_time, const real_time& end_time, | |
176 | const string& start_marker, const string& end_marker) | |
177 | { | |
178 | string oid; | |
179 | get_shard_oid(shard_id, oid); | |
180 | ||
181 | return svc.cls->timelog.trim(dpp, oid, from_time, end_time, start_marker, | |
182 | end_marker, nullptr, null_yield); | |
183 | } | |
184 | ||
185 | int RGWMetadataLog::lock_exclusive(const DoutPrefixProvider *dpp, int shard_id, timespan duration, string& zone_id, string& owner_id) { | |
186 | string oid; | |
187 | get_shard_oid(shard_id, oid); | |
188 | ||
189 | return svc.cls->lock.lock_exclusive(dpp, svc.zone->get_zone_params().log_pool, oid, duration, zone_id, owner_id); | |
190 | } | |
191 | ||
192 | int RGWMetadataLog::unlock(const DoutPrefixProvider *dpp, int shard_id, string& zone_id, string& owner_id) { | |
193 | string oid; | |
194 | get_shard_oid(shard_id, oid); | |
195 | ||
196 | return svc.cls->lock.unlock(dpp, svc.zone->get_zone_params().log_pool, oid, zone_id, owner_id); | |
197 | } | |
198 | ||
199 | void RGWMetadataLog::mark_modified(int shard_id) | |
200 | { | |
201 | lock.get_read(); | |
202 | if (modified_shards.find(shard_id) != modified_shards.end()) { | |
203 | lock.unlock(); | |
204 | return; | |
205 | } | |
206 | lock.unlock(); | |
207 | ||
208 | std::unique_lock wl{lock}; | |
209 | modified_shards.insert(shard_id); | |
210 | } | |
211 | ||
212 | void RGWMetadataLog::read_clear_modified(set<int> &modified) | |
213 | { | |
214 | std::unique_lock wl{lock}; | |
215 | modified.swap(modified_shards); | |
216 | modified_shards.clear(); | |
217 | } | |
218 | ||
219 | void RGWMetadataLogInfo::dump(Formatter *f) const | |
220 | { | |
221 | encode_json("marker", marker, f); | |
222 | utime_t ut(last_update); | |
223 | encode_json("last_update", ut, f); | |
224 | } | |
225 | ||
226 | void RGWMetadataLogInfo::decode_json(JSONObj *obj) | |
227 | { | |
228 | JSONDecoder::decode_json("marker", marker, obj); | |
229 | utime_t ut; | |
230 | JSONDecoder::decode_json("last_update", ut, obj); | |
231 | last_update = ut.to_real_time(); | |
232 | } | |
233 |