]>
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 |
11fdf7f2 | 3 | |
7c673cae FG |
4 | /* |
5 | * Ceph - scalable distributed file system | |
6 | * | |
7 | * Copyright (C) 2013 eNovance SAS <licensing@enovance.com> | |
8 | * | |
9 | * This is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License version 2.1, as published by the Free Software | |
12 | * Foundation. See file COPYING. | |
13 | * | |
14 | */ | |
11fdf7f2 | 15 | |
7c673cae FG |
16 | #include "common/ceph_json.h" |
17 | #include "common/strtol.h" | |
18 | #include "rgw_rest.h" | |
19 | #include "rgw_op.h" | |
20 | #include "rgw_rest_s3.h" | |
21 | #include "rgw_rest_log.h" | |
22 | #include "rgw_client_io.h" | |
23 | #include "rgw_sync.h" | |
24 | #include "rgw_data_sync.h" | |
31f18b77 | 25 | #include "rgw_common.h" |
11fdf7f2 | 26 | #include "rgw_zone.h" |
9f95a23c | 27 | #include "rgw_mdlog.h" |
11fdf7f2 TL |
28 | |
29 | #include "services/svc_zone.h" | |
9f95a23c TL |
30 | #include "services/svc_mdlog.h" |
31 | #include "services/svc_bilog_rados.h" | |
11fdf7f2 | 32 | |
7c673cae | 33 | #include "common/errno.h" |
11fdf7f2 | 34 | #include "include/ceph_assert.h" |
7c673cae FG |
35 | |
36 | #define dout_context g_ceph_context | |
37 | #define LOG_CLASS_LIST_MAX_ENTRIES (1000) | |
38 | #define dout_subsys ceph_subsys_rgw | |
39 | ||
20effc67 TL |
40 | using namespace std; |
41 | ||
f67539c2 | 42 | void RGWOp_MDLog_List::execute(optional_yield y) { |
7c673cae FG |
43 | string period = s->info.args.get("period"); |
44 | string shard = s->info.args.get("id"); | |
45 | string max_entries_str = s->info.args.get("max-entries"); | |
f67539c2 | 46 | string marker = s->info.args.get("marker"), |
7c673cae | 47 | err; |
7c673cae FG |
48 | void *handle; |
49 | unsigned shard_id, max_entries = LOG_CLASS_LIST_MAX_ENTRIES; | |
50 | ||
f67539c2 TL |
51 | if (s->info.args.exists("start-time") || |
52 | s->info.args.exists("end-time")) { | |
b3b6e05e | 53 | ldpp_dout(this, 5) << "start-time and end-time are no longer accepted" << dendl; |
f67539c2 | 54 | op_ret = -EINVAL; |
7c673cae FG |
55 | return; |
56 | } | |
57 | ||
f67539c2 TL |
58 | shard_id = (unsigned)strict_strtol(shard.c_str(), 10, &err); |
59 | if (!err.empty()) { | |
b3b6e05e | 60 | ldpp_dout(this, 5) << "Error parsing shard_id " << shard << dendl; |
f67539c2 | 61 | op_ret = -EINVAL; |
7c673cae FG |
62 | return; |
63 | } | |
64 | ||
65 | if (!max_entries_str.empty()) { | |
66 | max_entries = (unsigned)strict_strtol(max_entries_str.c_str(), 10, &err); | |
67 | if (!err.empty()) { | |
b3b6e05e | 68 | ldpp_dout(this, 5) << "Error parsing max-entries " << max_entries_str << dendl; |
f67539c2 | 69 | op_ret = -EINVAL; |
7c673cae FG |
70 | return; |
71 | } | |
224ce89b WB |
72 | if (max_entries > LOG_CLASS_LIST_MAX_ENTRIES) { |
73 | max_entries = LOG_CLASS_LIST_MAX_ENTRIES; | |
74 | } | |
f67539c2 | 75 | } |
7c673cae FG |
76 | |
77 | if (period.empty()) { | |
b3b6e05e | 78 | ldpp_dout(this, 5) << "Missing period id trying to use current" << dendl; |
20effc67 | 79 | period = store->get_zone()->get_current_period_id(); |
7c673cae | 80 | if (period.empty()) { |
b3b6e05e | 81 | ldpp_dout(this, 5) << "Missing period id" << dendl; |
f67539c2 | 82 | op_ret = -EINVAL; |
7c673cae FG |
83 | return; |
84 | } | |
85 | } | |
86 | ||
20effc67 | 87 | RGWMetadataLog meta_log{s->cct, static_cast<rgw::sal::RadosStore*>(store)->svc()->zone, static_cast<rgw::sal::RadosStore*>(store)->svc()->cls, period}; |
7c673cae | 88 | |
f67539c2 | 89 | meta_log.init_list_entries(shard_id, {}, {}, marker, &handle); |
7c673cae | 90 | |
b3b6e05e | 91 | op_ret = meta_log.list_entries(this, handle, max_entries, entries, |
224ce89b | 92 | &last_marker, &truncated); |
7c673cae FG |
93 | |
94 | meta_log.complete_list_entries(handle); | |
95 | } | |
96 | ||
97 | void RGWOp_MDLog_List::send_response() { | |
f67539c2 | 98 | set_req_state_err(s, op_ret); |
7c673cae FG |
99 | dump_errno(s); |
100 | end_header(s); | |
101 | ||
f67539c2 | 102 | if (op_ret < 0) |
7c673cae FG |
103 | return; |
104 | ||
105 | s->formatter->open_object_section("log_entries"); | |
106 | s->formatter->dump_string("marker", last_marker); | |
107 | s->formatter->dump_bool("truncated", truncated); | |
108 | { | |
109 | s->formatter->open_array_section("entries"); | |
110 | for (list<cls_log_entry>::iterator iter = entries.begin(); | |
111 | iter != entries.end(); ++iter) { | |
112 | cls_log_entry& entry = *iter; | |
20effc67 | 113 | static_cast<rgw::sal::RadosStore*>(store)->ctl()->meta.mgr->dump_log_entry(entry, s->formatter); |
7c673cae FG |
114 | flusher.flush(); |
115 | } | |
116 | s->formatter->close_section(); | |
117 | } | |
118 | s->formatter->close_section(); | |
119 | flusher.flush(); | |
120 | } | |
121 | ||
f67539c2 | 122 | void RGWOp_MDLog_Info::execute(optional_yield y) { |
7c673cae | 123 | num_objects = s->cct->_conf->rgw_md_log_max_shards; |
20effc67 | 124 | period = static_cast<rgw::sal::RadosStore*>(store)->svc()->mdlog->read_oldest_log_period(y, s); |
f67539c2 | 125 | op_ret = period.get_error(); |
7c673cae FG |
126 | } |
127 | ||
128 | void RGWOp_MDLog_Info::send_response() { | |
f67539c2 | 129 | set_req_state_err(s, op_ret); |
7c673cae FG |
130 | dump_errno(s); |
131 | end_header(s); | |
132 | ||
133 | s->formatter->open_object_section("mdlog"); | |
134 | s->formatter->dump_unsigned("num_objects", num_objects); | |
135 | if (period) { | |
136 | s->formatter->dump_string("period", period.get_period().get_id()); | |
137 | s->formatter->dump_unsigned("realm_epoch", period.get_epoch()); | |
138 | } | |
139 | s->formatter->close_section(); | |
140 | flusher.flush(); | |
141 | } | |
142 | ||
f67539c2 | 143 | void RGWOp_MDLog_ShardInfo::execute(optional_yield y) { |
7c673cae FG |
144 | string period = s->info.args.get("period"); |
145 | string shard = s->info.args.get("id"); | |
146 | string err; | |
147 | ||
148 | unsigned shard_id = (unsigned)strict_strtol(shard.c_str(), 10, &err); | |
149 | if (!err.empty()) { | |
b3b6e05e | 150 | ldpp_dout(this, 5) << "Error parsing shard_id " << shard << dendl; |
f67539c2 | 151 | op_ret = -EINVAL; |
7c673cae FG |
152 | return; |
153 | } | |
154 | ||
155 | if (period.empty()) { | |
b3b6e05e | 156 | ldpp_dout(this, 5) << "Missing period id trying to use current" << dendl; |
20effc67 | 157 | period = store->get_zone()->get_current_period_id(); |
7c673cae FG |
158 | |
159 | if (period.empty()) { | |
b3b6e05e | 160 | ldpp_dout(this, 5) << "Missing period id" << dendl; |
f67539c2 | 161 | op_ret = -EINVAL; |
7c673cae FG |
162 | return; |
163 | } | |
164 | } | |
20effc67 | 165 | RGWMetadataLog meta_log{s->cct, static_cast<rgw::sal::RadosStore*>(store)->svc()->zone, static_cast<rgw::sal::RadosStore*>(store)->svc()->cls, period}; |
7c673cae | 166 | |
b3b6e05e | 167 | op_ret = meta_log.get_info(this, shard_id, &info); |
7c673cae FG |
168 | } |
169 | ||
170 | void RGWOp_MDLog_ShardInfo::send_response() { | |
f67539c2 | 171 | set_req_state_err(s, op_ret); |
7c673cae FG |
172 | dump_errno(s); |
173 | end_header(s); | |
174 | ||
175 | encode_json("info", info, s->formatter); | |
176 | flusher.flush(); | |
177 | } | |
178 | ||
f67539c2 TL |
179 | void RGWOp_MDLog_Delete::execute(optional_yield y) { |
180 | string marker = s->info.args.get("marker"), | |
7c673cae FG |
181 | period = s->info.args.get("period"), |
182 | shard = s->info.args.get("id"), | |
183 | err; | |
7c673cae FG |
184 | unsigned shard_id; |
185 | ||
7c673cae | 186 | |
f67539c2 TL |
187 | if (s->info.args.exists("start-time") || |
188 | s->info.args.exists("end-time")) { | |
b3b6e05e | 189 | ldpp_dout(this, 5) << "start-time and end-time are no longer accepted" << dendl; |
f67539c2 | 190 | op_ret = -EINVAL; |
7c673cae | 191 | } |
f67539c2 TL |
192 | |
193 | if (s->info.args.exists("start-marker")) { | |
b3b6e05e | 194 | ldpp_dout(this, 5) << "start-marker is no longer accepted" << dendl; |
f67539c2 TL |
195 | op_ret = -EINVAL; |
196 | } | |
197 | ||
198 | if (s->info.args.exists("end-marker")) { | |
199 | if (!s->info.args.exists("marker")) { | |
200 | marker = s->info.args.get("end-marker"); | |
201 | } else { | |
b3b6e05e | 202 | ldpp_dout(this, 5) << "end-marker and marker cannot both be provided" << dendl; |
f67539c2 TL |
203 | op_ret = -EINVAL; |
204 | } | |
7c673cae FG |
205 | } |
206 | ||
f67539c2 TL |
207 | op_ret = 0; |
208 | ||
209 | shard_id = (unsigned)strict_strtol(shard.c_str(), 10, &err); | |
210 | if (!err.empty()) { | |
b3b6e05e | 211 | ldpp_dout(this, 5) << "Error parsing shard_id " << shard << dendl; |
f67539c2 | 212 | op_ret = -EINVAL; |
7c673cae FG |
213 | return; |
214 | } | |
215 | ||
f67539c2 TL |
216 | if (marker.empty()) { /* bounding end */ |
217 | op_ret = -EINVAL; | |
7c673cae FG |
218 | return; |
219 | } | |
220 | ||
221 | if (period.empty()) { | |
b3b6e05e | 222 | ldpp_dout(this, 5) << "Missing period id trying to use current" << dendl; |
20effc67 | 223 | period = store->get_zone()->get_current_period_id(); |
7c673cae FG |
224 | |
225 | if (period.empty()) { | |
b3b6e05e | 226 | ldpp_dout(this, 5) << "Missing period id" << dendl; |
f67539c2 | 227 | op_ret = -EINVAL; |
7c673cae FG |
228 | return; |
229 | } | |
230 | } | |
20effc67 | 231 | RGWMetadataLog meta_log{s->cct, static_cast<rgw::sal::RadosStore*>(store)->svc()->zone, static_cast<rgw::sal::RadosStore*>(store)->svc()->cls, period}; |
7c673cae | 232 | |
b3b6e05e | 233 | op_ret = meta_log.trim(this, shard_id, {}, {}, {}, marker); |
7c673cae FG |
234 | } |
235 | ||
f67539c2 | 236 | void RGWOp_MDLog_Lock::execute(optional_yield y) { |
7c673cae FG |
237 | string period, shard_id_str, duration_str, locker_id, zone_id; |
238 | unsigned shard_id; | |
239 | ||
f67539c2 | 240 | op_ret = 0; |
7c673cae FG |
241 | |
242 | period = s->info.args.get("period"); | |
243 | shard_id_str = s->info.args.get("id"); | |
244 | duration_str = s->info.args.get("length"); | |
245 | locker_id = s->info.args.get("locker-id"); | |
246 | zone_id = s->info.args.get("zone-id"); | |
247 | ||
248 | if (period.empty()) { | |
b3b6e05e | 249 | ldpp_dout(this, 5) << "Missing period id trying to use current" << dendl; |
20effc67 | 250 | period = store->get_zone()->get_current_period_id(); |
7c673cae FG |
251 | } |
252 | ||
253 | if (period.empty() || | |
254 | shard_id_str.empty() || | |
255 | (duration_str.empty()) || | |
256 | locker_id.empty() || | |
257 | zone_id.empty()) { | |
b3b6e05e | 258 | ldpp_dout(this, 5) << "Error invalid parameter list" << dendl; |
f67539c2 | 259 | op_ret = -EINVAL; |
7c673cae FG |
260 | return; |
261 | } | |
262 | ||
263 | string err; | |
264 | shard_id = (unsigned)strict_strtol(shard_id_str.c_str(), 10, &err); | |
265 | if (!err.empty()) { | |
b3b6e05e | 266 | ldpp_dout(this, 5) << "Error parsing shard_id param " << shard_id_str << dendl; |
f67539c2 | 267 | op_ret = -EINVAL; |
7c673cae FG |
268 | return; |
269 | } | |
270 | ||
20effc67 | 271 | RGWMetadataLog meta_log{s->cct, static_cast<rgw::sal::RadosStore*>(store)->svc()->zone, static_cast<rgw::sal::RadosStore*>(store)->svc()->cls, period}; |
7c673cae FG |
272 | unsigned dur; |
273 | dur = (unsigned)strict_strtol(duration_str.c_str(), 10, &err); | |
274 | if (!err.empty() || dur <= 0) { | |
b3b6e05e | 275 | ldpp_dout(this, 5) << "invalid length param " << duration_str << dendl; |
f67539c2 | 276 | op_ret = -EINVAL; |
7c673cae FG |
277 | return; |
278 | } | |
b3b6e05e | 279 | op_ret = meta_log.lock_exclusive(s, shard_id, make_timespan(dur), zone_id, |
7c673cae | 280 | locker_id); |
f67539c2 TL |
281 | if (op_ret == -EBUSY) |
282 | op_ret = -ERR_LOCKED; | |
7c673cae FG |
283 | } |
284 | ||
f67539c2 | 285 | void RGWOp_MDLog_Unlock::execute(optional_yield y) { |
7c673cae FG |
286 | string period, shard_id_str, locker_id, zone_id; |
287 | unsigned shard_id; | |
288 | ||
f67539c2 | 289 | op_ret = 0; |
7c673cae FG |
290 | |
291 | period = s->info.args.get("period"); | |
292 | shard_id_str = s->info.args.get("id"); | |
293 | locker_id = s->info.args.get("locker-id"); | |
294 | zone_id = s->info.args.get("zone-id"); | |
295 | ||
296 | if (period.empty()) { | |
b3b6e05e | 297 | ldpp_dout(this, 5) << "Missing period id trying to use current" << dendl; |
20effc67 | 298 | period = store->get_zone()->get_current_period_id(); |
7c673cae FG |
299 | } |
300 | ||
301 | if (period.empty() || | |
302 | shard_id_str.empty() || | |
303 | locker_id.empty() || | |
304 | zone_id.empty()) { | |
b3b6e05e | 305 | ldpp_dout(this, 5) << "Error invalid parameter list" << dendl; |
f67539c2 | 306 | op_ret = -EINVAL; |
7c673cae FG |
307 | return; |
308 | } | |
309 | ||
310 | string err; | |
311 | shard_id = (unsigned)strict_strtol(shard_id_str.c_str(), 10, &err); | |
312 | if (!err.empty()) { | |
b3b6e05e | 313 | ldpp_dout(this, 5) << "Error parsing shard_id param " << shard_id_str << dendl; |
f67539c2 | 314 | op_ret = -EINVAL; |
7c673cae FG |
315 | return; |
316 | } | |
317 | ||
20effc67 | 318 | RGWMetadataLog meta_log{s->cct, static_cast<rgw::sal::RadosStore*>(store)->svc()->zone, static_cast<rgw::sal::RadosStore*>(store)->svc()->cls, period}; |
b3b6e05e | 319 | op_ret = meta_log.unlock(s, shard_id, zone_id, locker_id); |
7c673cae FG |
320 | } |
321 | ||
f67539c2 | 322 | void RGWOp_MDLog_Notify::execute(optional_yield y) { |
7c673cae | 323 | #define LARGE_ENOUGH_BUF (128 * 1024) |
11fdf7f2 TL |
324 | |
325 | int r = 0; | |
326 | bufferlist data; | |
20effc67 | 327 | std::tie(r, data) = read_all_input(s, LARGE_ENOUGH_BUF); |
7c673cae | 328 | if (r < 0) { |
f67539c2 | 329 | op_ret = r; |
7c673cae FG |
330 | return; |
331 | } | |
332 | ||
11fdf7f2 | 333 | char* buf = data.c_str(); |
b3b6e05e | 334 | ldpp_dout(this, 20) << __func__ << "(): read data: " << buf << dendl; |
7c673cae FG |
335 | |
336 | JSONParser p; | |
11fdf7f2 | 337 | r = p.parse(buf, data.length()); |
7c673cae | 338 | if (r < 0) { |
b3b6e05e | 339 | ldpp_dout(this, 0) << "ERROR: failed to parse JSON" << dendl; |
f67539c2 | 340 | op_ret = r; |
7c673cae FG |
341 | return; |
342 | } | |
343 | ||
344 | set<int> updated_shards; | |
345 | try { | |
346 | decode_json_obj(updated_shards, &p); | |
347 | } catch (JSONDecoder::err& err) { | |
b3b6e05e | 348 | ldpp_dout(this, 0) << "ERROR: failed to decode JSON" << dendl; |
f67539c2 | 349 | op_ret = -EINVAL; |
7c673cae FG |
350 | return; |
351 | } | |
352 | ||
11fdf7f2 | 353 | if (store->ctx()->_conf->subsys.should_gather<ceph_subsys_rgw, 20>()) { |
7c673cae | 354 | for (set<int>::iterator iter = updated_shards.begin(); iter != updated_shards.end(); ++iter) { |
b3b6e05e | 355 | ldpp_dout(this, 20) << __func__ << "(): updated shard=" << *iter << dendl; |
7c673cae FG |
356 | } |
357 | } | |
358 | ||
20effc67 | 359 | store->wakeup_meta_sync_shards(updated_shards); |
7c673cae | 360 | |
f67539c2 | 361 | op_ret = 0; |
7c673cae FG |
362 | } |
363 | ||
f67539c2 | 364 | void RGWOp_BILog_List::execute(optional_yield y) { |
7c673cae FG |
365 | string tenant_name = s->info.args.get("tenant"), |
366 | bucket_name = s->info.args.get("bucket"), | |
367 | marker = s->info.args.get("marker"), | |
368 | max_entries_str = s->info.args.get("max-entries"), | |
369 | bucket_instance = s->info.args.get("bucket-instance"); | |
20effc67 TL |
370 | std::unique_ptr<rgw::sal::Bucket> bucket; |
371 | rgw_bucket b(rgw_bucket_key(tenant_name, bucket_name)); | |
7c673cae FG |
372 | unsigned max_entries; |
373 | ||
7c673cae | 374 | if (bucket_name.empty() && bucket_instance.empty()) { |
b3b6e05e | 375 | ldpp_dout(this, 5) << "ERROR: neither bucket nor bucket instance specified" << dendl; |
f67539c2 | 376 | op_ret = -EINVAL; |
7c673cae FG |
377 | return; |
378 | } | |
379 | ||
380 | int shard_id; | |
9f95a23c | 381 | string bn; |
f67539c2 TL |
382 | op_ret = rgw_bucket_parse_bucket_instance(bucket_instance, &bn, &bucket_instance, &shard_id); |
383 | if (op_ret < 0) { | |
7c673cae FG |
384 | return; |
385 | } | |
386 | ||
387 | if (!bucket_instance.empty()) { | |
20effc67 TL |
388 | b.name = bn; |
389 | b.bucket_id = bucket_instance; | |
390 | } | |
391 | op_ret = store->get_bucket(s, nullptr, b, &bucket, y); | |
392 | if (op_ret < 0) { | |
393 | ldpp_dout(this, 5) << "could not get bucket info for bucket=" << bucket_name << dendl; | |
394 | return; | |
7c673cae FG |
395 | } |
396 | ||
397 | bool truncated; | |
398 | unsigned count = 0; | |
399 | string err; | |
400 | ||
401 | max_entries = (unsigned)strict_strtol(max_entries_str.c_str(), 10, &err); | |
402 | if (!err.empty()) | |
403 | max_entries = LOG_CLASS_LIST_MAX_ENTRIES; | |
404 | ||
405 | send_response(); | |
406 | do { | |
407 | list<rgw_bi_log_entry> entries; | |
20effc67 | 408 | int ret = static_cast<rgw::sal::RadosStore*>(store)->svc()->bilog_rados->log_list(s, bucket->get_info(), shard_id, |
9f95a23c TL |
409 | marker, max_entries - count, |
410 | entries, &truncated); | |
7c673cae | 411 | if (ret < 0) { |
b3b6e05e | 412 | ldpp_dout(this, 5) << "ERROR: list_bi_log_entries()" << dendl; |
7c673cae FG |
413 | return; |
414 | } | |
415 | ||
416 | count += entries.size(); | |
417 | ||
418 | send_response(entries, marker); | |
419 | } while (truncated && count < max_entries); | |
420 | ||
421 | send_response_end(); | |
422 | } | |
423 | ||
424 | void RGWOp_BILog_List::send_response() { | |
425 | if (sent_header) | |
426 | return; | |
427 | ||
f67539c2 | 428 | set_req_state_err(s, op_ret); |
7c673cae FG |
429 | dump_errno(s); |
430 | end_header(s); | |
431 | ||
432 | sent_header = true; | |
433 | ||
f67539c2 | 434 | if (op_ret < 0) |
7c673cae FG |
435 | return; |
436 | ||
437 | s->formatter->open_array_section("entries"); | |
438 | } | |
439 | ||
440 | void RGWOp_BILog_List::send_response(list<rgw_bi_log_entry>& entries, string& marker) | |
441 | { | |
442 | for (list<rgw_bi_log_entry>::iterator iter = entries.begin(); iter != entries.end(); ++iter) { | |
443 | rgw_bi_log_entry& entry = *iter; | |
444 | encode_json("entry", entry, s->formatter); | |
445 | ||
446 | marker = entry.id; | |
447 | flusher.flush(); | |
448 | } | |
449 | } | |
450 | ||
451 | void RGWOp_BILog_List::send_response_end() { | |
452 | s->formatter->close_section(); | |
453 | flusher.flush(); | |
454 | } | |
455 | ||
f67539c2 | 456 | void RGWOp_BILog_Info::execute(optional_yield y) { |
7c673cae FG |
457 | string tenant_name = s->info.args.get("tenant"), |
458 | bucket_name = s->info.args.get("bucket"), | |
459 | bucket_instance = s->info.args.get("bucket-instance"); | |
20effc67 TL |
460 | std::unique_ptr<rgw::sal::Bucket> bucket; |
461 | rgw_bucket b(rgw_bucket_key(tenant_name, bucket_name)); | |
7c673cae | 462 | |
7c673cae | 463 | if (bucket_name.empty() && bucket_instance.empty()) { |
b3b6e05e | 464 | ldpp_dout(this, 5) << "ERROR: neither bucket nor bucket instance specified" << dendl; |
f67539c2 | 465 | op_ret = -EINVAL; |
7c673cae FG |
466 | return; |
467 | } | |
468 | ||
469 | int shard_id; | |
9f95a23c | 470 | string bn; |
f67539c2 TL |
471 | op_ret = rgw_bucket_parse_bucket_instance(bucket_instance, &bn, &bucket_instance, &shard_id); |
472 | if (op_ret < 0) { | |
7c673cae FG |
473 | return; |
474 | } | |
475 | ||
476 | if (!bucket_instance.empty()) { | |
20effc67 TL |
477 | b.name = bn; |
478 | b.bucket_id = bucket_instance; | |
7c673cae | 479 | } |
20effc67 TL |
480 | op_ret = store->get_bucket(s, nullptr, b, &bucket, y); |
481 | if (op_ret < 0) { | |
482 | ldpp_dout(this, 5) << "could not get bucket info for bucket=" << bucket_name << dendl; | |
483 | return; | |
484 | } | |
485 | ||
7c673cae | 486 | map<RGWObjCategory, RGWStorageStats> stats; |
20effc67 | 487 | int ret = bucket->read_stats(s, shard_id, &bucket_ver, &master_ver, stats, &max_marker, &syncstopped); |
7c673cae | 488 | if (ret < 0 && ret != -ENOENT) { |
f67539c2 | 489 | op_ret = ret; |
7c673cae FG |
490 | return; |
491 | } | |
492 | } | |
493 | ||
494 | void RGWOp_BILog_Info::send_response() { | |
f67539c2 | 495 | set_req_state_err(s, op_ret); |
7c673cae FG |
496 | dump_errno(s); |
497 | end_header(s); | |
498 | ||
f67539c2 | 499 | if (op_ret < 0) |
7c673cae FG |
500 | return; |
501 | ||
502 | s->formatter->open_object_section("info"); | |
503 | encode_json("bucket_ver", bucket_ver, s->formatter); | |
504 | encode_json("master_ver", master_ver, s->formatter); | |
505 | encode_json("max_marker", max_marker, s->formatter); | |
c07f9fc5 | 506 | encode_json("syncstopped", syncstopped, s->formatter); |
7c673cae FG |
507 | s->formatter->close_section(); |
508 | ||
509 | flusher.flush(); | |
510 | } | |
511 | ||
f67539c2 | 512 | void RGWOp_BILog_Delete::execute(optional_yield y) { |
7c673cae FG |
513 | string tenant_name = s->info.args.get("tenant"), |
514 | bucket_name = s->info.args.get("bucket"), | |
515 | start_marker = s->info.args.get("start-marker"), | |
516 | end_marker = s->info.args.get("end-marker"), | |
517 | bucket_instance = s->info.args.get("bucket-instance"); | |
518 | ||
20effc67 TL |
519 | std::unique_ptr<rgw::sal::Bucket> bucket; |
520 | rgw_bucket b(rgw_bucket_key(tenant_name, bucket_name)); | |
7c673cae | 521 | |
f67539c2 | 522 | op_ret = 0; |
7c673cae FG |
523 | if ((bucket_name.empty() && bucket_instance.empty()) || |
524 | end_marker.empty()) { | |
b3b6e05e | 525 | ldpp_dout(this, 5) << "ERROR: one of bucket and bucket instance, and also end-marker is mandatory" << dendl; |
f67539c2 | 526 | op_ret = -EINVAL; |
7c673cae FG |
527 | return; |
528 | } | |
529 | ||
530 | int shard_id; | |
9f95a23c | 531 | string bn; |
f67539c2 TL |
532 | op_ret = rgw_bucket_parse_bucket_instance(bucket_instance, &bn, &bucket_instance, &shard_id); |
533 | if (op_ret < 0) { | |
7c673cae FG |
534 | return; |
535 | } | |
536 | ||
537 | if (!bucket_instance.empty()) { | |
20effc67 TL |
538 | b.name = bn; |
539 | b.bucket_id = bucket_instance; | |
540 | } | |
541 | op_ret = store->get_bucket(s, nullptr, b, &bucket, y); | |
542 | if (op_ret < 0) { | |
543 | ldpp_dout(this, 5) << "could not get bucket info for bucket=" << bucket_name << dendl; | |
544 | return; | |
7c673cae | 545 | } |
20effc67 TL |
546 | |
547 | op_ret = static_cast<rgw::sal::RadosStore*>(store)->svc()->bilog_rados->log_trim(s, bucket->get_info(), shard_id, start_marker, end_marker); | |
f67539c2 | 548 | if (op_ret < 0) { |
b3b6e05e | 549 | ldpp_dout(this, 5) << "ERROR: trim_bi_log_entries() " << dendl; |
7c673cae FG |
550 | } |
551 | return; | |
552 | } | |
553 | ||
f67539c2 | 554 | void RGWOp_DATALog_List::execute(optional_yield y) { |
7c673cae FG |
555 | string shard = s->info.args.get("id"); |
556 | ||
f67539c2 | 557 | string max_entries_str = s->info.args.get("max-entries"), |
7c673cae FG |
558 | marker = s->info.args.get("marker"), |
559 | err; | |
7c673cae FG |
560 | unsigned shard_id, max_entries = LOG_CLASS_LIST_MAX_ENTRIES; |
561 | ||
f67539c2 TL |
562 | if (s->info.args.exists("start-time") || |
563 | s->info.args.exists("end-time")) { | |
b3b6e05e | 564 | ldpp_dout(this, 5) << "start-time and end-time are no longer accepted" << dendl; |
f67539c2 TL |
565 | op_ret = -EINVAL; |
566 | } | |
567 | ||
7c673cae FG |
568 | s->info.args.get_bool("extra-info", &extra_info, false); |
569 | ||
570 | shard_id = (unsigned)strict_strtol(shard.c_str(), 10, &err); | |
571 | if (!err.empty()) { | |
b3b6e05e | 572 | ldpp_dout(this, 5) << "Error parsing shard_id " << shard << dendl; |
f67539c2 | 573 | op_ret = -EINVAL; |
7c673cae FG |
574 | return; |
575 | } | |
576 | ||
577 | if (!max_entries_str.empty()) { | |
578 | max_entries = (unsigned)strict_strtol(max_entries_str.c_str(), 10, &err); | |
579 | if (!err.empty()) { | |
b3b6e05e | 580 | ldpp_dout(this, 5) << "Error parsing max-entries " << max_entries_str << dendl; |
f67539c2 | 581 | op_ret = -EINVAL; |
7c673cae FG |
582 | return; |
583 | } | |
224ce89b WB |
584 | if (max_entries > LOG_CLASS_LIST_MAX_ENTRIES) { |
585 | max_entries = LOG_CLASS_LIST_MAX_ENTRIES; | |
586 | } | |
587 | } | |
588 | ||
589 | // Note that last_marker is updated to be the marker of the last | |
590 | // entry listed | |
20effc67 | 591 | op_ret = static_cast<rgw::sal::RadosStore*>(store)->svc()->datalog_rados->list_entries(this, shard_id, |
f67539c2 TL |
592 | max_entries, entries, |
593 | marker, &last_marker, | |
594 | &truncated); | |
7c673cae FG |
595 | } |
596 | ||
597 | void RGWOp_DATALog_List::send_response() { | |
f67539c2 | 598 | set_req_state_err(s, op_ret); |
7c673cae FG |
599 | dump_errno(s); |
600 | end_header(s); | |
601 | ||
f67539c2 | 602 | if (op_ret < 0) |
7c673cae FG |
603 | return; |
604 | ||
605 | s->formatter->open_object_section("log_entries"); | |
606 | s->formatter->dump_string("marker", last_marker); | |
607 | s->formatter->dump_bool("truncated", truncated); | |
608 | { | |
609 | s->formatter->open_array_section("entries"); | |
f67539c2 | 610 | for (const auto& entry : entries) { |
7c673cae FG |
611 | if (!extra_info) { |
612 | encode_json("entry", entry.entry, s->formatter); | |
613 | } else { | |
614 | encode_json("entry", entry, s->formatter); | |
615 | } | |
616 | flusher.flush(); | |
617 | } | |
618 | s->formatter->close_section(); | |
619 | } | |
620 | s->formatter->close_section(); | |
621 | flusher.flush(); | |
622 | } | |
623 | ||
624 | ||
f67539c2 | 625 | void RGWOp_DATALog_Info::execute(optional_yield y) { |
7c673cae | 626 | num_objects = s->cct->_conf->rgw_data_log_num_shards; |
f67539c2 | 627 | op_ret = 0; |
7c673cae FG |
628 | } |
629 | ||
630 | void RGWOp_DATALog_Info::send_response() { | |
f67539c2 | 631 | set_req_state_err(s, op_ret); |
7c673cae FG |
632 | dump_errno(s); |
633 | end_header(s); | |
634 | ||
635 | s->formatter->open_object_section("num_objects"); | |
636 | s->formatter->dump_unsigned("num_objects", num_objects); | |
637 | s->formatter->close_section(); | |
638 | flusher.flush(); | |
639 | } | |
640 | ||
f67539c2 | 641 | void RGWOp_DATALog_ShardInfo::execute(optional_yield y) { |
7c673cae FG |
642 | string shard = s->info.args.get("id"); |
643 | string err; | |
644 | ||
645 | unsigned shard_id = (unsigned)strict_strtol(shard.c_str(), 10, &err); | |
646 | if (!err.empty()) { | |
b3b6e05e | 647 | ldpp_dout(this, 5) << "Error parsing shard_id " << shard << dendl; |
f67539c2 | 648 | op_ret = -EINVAL; |
7c673cae FG |
649 | return; |
650 | } | |
651 | ||
20effc67 | 652 | op_ret = static_cast<rgw::sal::RadosStore*>(store)->svc()->datalog_rados->get_info(this, shard_id, &info); |
7c673cae FG |
653 | } |
654 | ||
655 | void RGWOp_DATALog_ShardInfo::send_response() { | |
f67539c2 | 656 | set_req_state_err(s, op_ret); |
7c673cae FG |
657 | dump_errno(s); |
658 | end_header(s); | |
659 | ||
660 | encode_json("info", info, s->formatter); | |
661 | flusher.flush(); | |
662 | } | |
663 | ||
f67539c2 | 664 | void RGWOp_DATALog_Notify::execute(optional_yield y) { |
7c673cae | 665 | string source_zone = s->info.args.get("source-zone"); |
7c673cae | 666 | #define LARGE_ENOUGH_BUF (128 * 1024) |
11fdf7f2 TL |
667 | |
668 | int r = 0; | |
669 | bufferlist data; | |
20effc67 | 670 | std::tie(r, data) = read_all_input(s, LARGE_ENOUGH_BUF); |
7c673cae | 671 | if (r < 0) { |
f67539c2 | 672 | op_ret = r; |
7c673cae FG |
673 | return; |
674 | } | |
675 | ||
11fdf7f2 | 676 | char* buf = data.c_str(); |
b3b6e05e | 677 | ldpp_dout(this, 20) << __func__ << "(): read data: " << buf << dendl; |
7c673cae FG |
678 | |
679 | JSONParser p; | |
11fdf7f2 | 680 | r = p.parse(buf, data.length()); |
7c673cae | 681 | if (r < 0) { |
b3b6e05e | 682 | ldpp_dout(this, 0) << "ERROR: failed to parse JSON" << dendl; |
f67539c2 | 683 | op_ret = r; |
7c673cae FG |
684 | return; |
685 | } | |
686 | ||
687 | map<int, set<string> > updated_shards; | |
688 | try { | |
689 | decode_json_obj(updated_shards, &p); | |
690 | } catch (JSONDecoder::err& err) { | |
b3b6e05e | 691 | ldpp_dout(this, 0) << "ERROR: failed to decode JSON" << dendl; |
f67539c2 | 692 | op_ret = -EINVAL; |
7c673cae FG |
693 | return; |
694 | } | |
695 | ||
11fdf7f2 | 696 | if (store->ctx()->_conf->subsys.should_gather<ceph_subsys_rgw, 20>()) { |
7c673cae | 697 | for (map<int, set<string> >::iterator iter = updated_shards.begin(); iter != updated_shards.end(); ++iter) { |
b3b6e05e | 698 | ldpp_dout(this, 20) << __func__ << "(): updated shard=" << iter->first << dendl; |
7c673cae FG |
699 | set<string>& keys = iter->second; |
700 | for (set<string>::iterator kiter = keys.begin(); kiter != keys.end(); ++kiter) { | |
b3b6e05e | 701 | ldpp_dout(this, 20) << __func__ << "(): modified key=" << *kiter << dendl; |
7c673cae FG |
702 | } |
703 | } | |
704 | } | |
705 | ||
20effc67 | 706 | store->wakeup_data_sync_shards(this, source_zone, updated_shards); |
7c673cae | 707 | |
f67539c2 | 708 | op_ret = 0; |
7c673cae FG |
709 | } |
710 | ||
f67539c2 TL |
711 | void RGWOp_DATALog_Delete::execute(optional_yield y) { |
712 | string marker = s->info.args.get("marker"), | |
7c673cae FG |
713 | shard = s->info.args.get("id"), |
714 | err; | |
7c673cae FG |
715 | unsigned shard_id; |
716 | ||
f67539c2 | 717 | op_ret = 0; |
7c673cae | 718 | |
f67539c2 TL |
719 | if (s->info.args.exists("start-time") || |
720 | s->info.args.exists("end-time")) { | |
b3b6e05e | 721 | ldpp_dout(this, 5) << "start-time and end-time are no longer accepted" << dendl; |
f67539c2 | 722 | op_ret = -EINVAL; |
7c673cae | 723 | } |
f67539c2 TL |
724 | |
725 | if (s->info.args.exists("start-marker")) { | |
b3b6e05e | 726 | ldpp_dout(this, 5) << "start-marker is no longer accepted" << dendl; |
f67539c2 | 727 | op_ret = -EINVAL; |
7c673cae FG |
728 | } |
729 | ||
f67539c2 TL |
730 | if (s->info.args.exists("end-marker")) { |
731 | if (!s->info.args.exists("marker")) { | |
732 | marker = s->info.args.get("end-marker"); | |
733 | } else { | |
b3b6e05e | 734 | ldpp_dout(this, 5) << "end-marker and marker cannot both be provided" << dendl; |
f67539c2 TL |
735 | op_ret = -EINVAL; |
736 | } | |
7c673cae FG |
737 | } |
738 | ||
f67539c2 TL |
739 | shard_id = (unsigned)strict_strtol(shard.c_str(), 10, &err); |
740 | if (!err.empty()) { | |
b3b6e05e | 741 | ldpp_dout(this, 5) << "Error parsing shard_id " << shard << dendl; |
f67539c2 TL |
742 | op_ret = -EINVAL; |
743 | return; | |
744 | } | |
745 | if (marker.empty()) { /* bounding end */ | |
746 | op_ret = -EINVAL; | |
7c673cae FG |
747 | return; |
748 | } | |
749 | ||
20effc67 | 750 | op_ret = static_cast<rgw::sal::RadosStore*>(store)->svc()->datalog_rados->trim_entries(this, shard_id, marker); |
7c673cae FG |
751 | } |
752 | ||
753 | // not in header to avoid pulling in rgw_sync.h | |
754 | class RGWOp_MDLog_Status : public RGWRESTOp { | |
755 | rgw_meta_sync_status status; | |
756 | public: | |
9f95a23c | 757 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
758 | return caps.check_cap("mdlog", RGW_CAP_READ); |
759 | } | |
f67539c2 | 760 | int verify_permission(optional_yield) override { |
9f95a23c | 761 | return check_caps(s->user->get_caps()); |
7c673cae | 762 | } |
f67539c2 | 763 | void execute(optional_yield y) override; |
7c673cae | 764 | void send_response() override; |
11fdf7f2 | 765 | const char* name() const override { return "get_metadata_log_status"; } |
7c673cae FG |
766 | }; |
767 | ||
f67539c2 | 768 | void RGWOp_MDLog_Status::execute(optional_yield y) |
7c673cae | 769 | { |
20effc67 | 770 | auto sync = static_cast<rgw::sal::RadosStore*>(store)->getRados()->get_meta_sync_manager(); |
7c673cae | 771 | if (sync == nullptr) { |
b3b6e05e | 772 | ldpp_dout(this, 1) << "no sync manager" << dendl; |
f67539c2 | 773 | op_ret = -ENOENT; |
7c673cae FG |
774 | return; |
775 | } | |
b3b6e05e | 776 | op_ret = sync->read_sync_status(this, &status); |
7c673cae FG |
777 | } |
778 | ||
779 | void RGWOp_MDLog_Status::send_response() | |
780 | { | |
f67539c2 | 781 | set_req_state_err(s, op_ret); |
7c673cae FG |
782 | dump_errno(s); |
783 | end_header(s); | |
784 | ||
f67539c2 | 785 | if (op_ret >= 0) { |
7c673cae FG |
786 | encode_json("status", status, s->formatter); |
787 | } | |
788 | flusher.flush(); | |
789 | } | |
790 | ||
b32b8144 FG |
791 | // not in header to avoid pulling in rgw_data_sync.h |
792 | class RGWOp_BILog_Status : public RGWRESTOp { | |
793 | std::vector<rgw_bucket_shard_sync_info> status; | |
794 | public: | |
9f95a23c | 795 | int check_caps(const RGWUserCaps& caps) override { |
b32b8144 FG |
796 | return caps.check_cap("bilog", RGW_CAP_READ); |
797 | } | |
f67539c2 | 798 | int verify_permission(optional_yield y) override { |
9f95a23c | 799 | return check_caps(s->user->get_caps()); |
b32b8144 | 800 | } |
f67539c2 | 801 | void execute(optional_yield y) override; |
b32b8144 | 802 | void send_response() override; |
11fdf7f2 | 803 | const char* name() const override { return "get_bucket_index_log_status"; } |
b32b8144 FG |
804 | }; |
805 | ||
f67539c2 | 806 | void RGWOp_BILog_Status::execute(optional_yield y) |
b32b8144 | 807 | { |
9f95a23c TL |
808 | const auto options = s->info.args.get("options"); |
809 | bool merge = (options == "merge"); | |
b32b8144 | 810 | const auto source_zone = s->info.args.get("source-zone"); |
9f95a23c TL |
811 | const auto source_key = s->info.args.get("source-bucket"); |
812 | auto key = s->info.args.get("bucket"); | |
813 | if (key.empty()) { | |
814 | key = source_key; | |
815 | } | |
b32b8144 | 816 | if (key.empty()) { |
b3b6e05e | 817 | ldpp_dout(this, 4) << "no 'bucket' provided" << dendl; |
f67539c2 | 818 | op_ret = -EINVAL; |
b32b8144 FG |
819 | return; |
820 | } | |
821 | ||
20effc67 | 822 | rgw_bucket b; |
b32b8144 | 823 | int shard_id{-1}; // unused |
20effc67 | 824 | op_ret = rgw_bucket_parse_bucket_key(s->cct, key, &b, &shard_id); |
f67539c2 | 825 | if (op_ret < 0) { |
b3b6e05e | 826 | ldpp_dout(this, 4) << "invalid 'bucket' provided" << dendl; |
f67539c2 | 827 | op_ret = -EINVAL; |
b32b8144 FG |
828 | return; |
829 | } | |
830 | ||
28e407b8 | 831 | // read the bucket instance info for num_shards |
20effc67 TL |
832 | std::unique_ptr<rgw::sal::Bucket> bucket; |
833 | op_ret = store->get_bucket(s, nullptr, b, &bucket, y); | |
f67539c2 | 834 | if (op_ret < 0) { |
b3b6e05e | 835 | ldpp_dout(this, 4) << "failed to read bucket info: " << cpp_strerror(op_ret) << dendl; |
28e407b8 AA |
836 | return; |
837 | } | |
9f95a23c TL |
838 | |
839 | rgw_bucket source_bucket; | |
840 | ||
841 | if (source_key.empty() || | |
842 | source_key == key) { | |
20effc67 | 843 | source_bucket = bucket->get_key(); |
9f95a23c | 844 | } else { |
f67539c2 TL |
845 | op_ret = rgw_bucket_parse_bucket_key(s->cct, source_key, &source_bucket, nullptr); |
846 | if (op_ret < 0) { | |
b3b6e05e | 847 | ldpp_dout(this, 4) << "invalid 'source-bucket' provided (key=" << source_key << ")" << dendl; |
9f95a23c TL |
848 | return; |
849 | } | |
850 | } | |
851 | ||
20effc67 | 852 | const auto& local_zone_id = store->get_zone()->get_id(); |
9f95a23c TL |
853 | |
854 | if (!merge) { | |
855 | rgw_sync_bucket_pipe pipe; | |
856 | pipe.source.zone = source_zone; | |
857 | pipe.source.bucket = source_bucket; | |
858 | pipe.dest.zone = local_zone_id; | |
20effc67 | 859 | pipe.dest.bucket = bucket->get_key(); |
9f95a23c | 860 | |
b3b6e05e | 861 | ldpp_dout(this, 20) << "RGWOp_BILog_Status::execute(optional_yield y): getting sync status for pipe=" << pipe << dendl; |
9f95a23c | 862 | |
20effc67 | 863 | op_ret = rgw_bucket_sync_status(this, static_cast<rgw::sal::RadosStore*>(store), pipe, bucket->get_info(), nullptr, &status); |
9f95a23c | 864 | |
f67539c2 | 865 | if (op_ret < 0) { |
b3b6e05e | 866 | ldpp_dout(this, -1) << "ERROR: rgw_bucket_sync_status() on pipe=" << pipe << " returned ret=" << op_ret << dendl; |
9f95a23c TL |
867 | } |
868 | return; | |
869 | } | |
870 | ||
871 | rgw_zone_id source_zone_id(source_zone); | |
872 | ||
873 | RGWBucketSyncPolicyHandlerRef source_handler; | |
20effc67 | 874 | op_ret = store->get_sync_policy_handler(s, source_zone_id, source_bucket, &source_handler, y); |
f67539c2 | 875 | if (op_ret < 0) { |
b3b6e05e | 876 | ldpp_dout(this, -1) << "could not get bucket sync policy handler (r=" << op_ret << ")" << dendl; |
9f95a23c TL |
877 | return; |
878 | } | |
879 | ||
880 | auto local_dests = source_handler->get_all_dests_in_zone(local_zone_id); | |
881 | ||
882 | std::vector<rgw_bucket_shard_sync_info> current_status; | |
883 | for (auto& entry : local_dests) { | |
884 | auto pipe = entry.second; | |
885 | ||
b3b6e05e | 886 | ldpp_dout(this, 20) << "RGWOp_BILog_Status::execute(optional_yield y): getting sync status for pipe=" << pipe << dendl; |
9f95a23c | 887 | |
20effc67 | 888 | RGWBucketInfo *pinfo = &bucket->get_info(); |
9f95a23c TL |
889 | std::optional<RGWBucketInfo> opt_dest_info; |
890 | ||
891 | if (!pipe.dest.bucket) { | |
892 | /* Uh oh, something went wrong */ | |
b3b6e05e | 893 | ldpp_dout(this, 20) << "ERROR: RGWOp_BILog_Status::execute(optional_yield y): BUG: pipe.dest.bucket was not initialized" << pipe << dendl; |
f67539c2 | 894 | op_ret = -EIO; |
9f95a23c TL |
895 | return; |
896 | } | |
897 | ||
20effc67 | 898 | if (*pipe.dest.bucket != pinfo->bucket) { |
9f95a23c | 899 | opt_dest_info.emplace(); |
20effc67 TL |
900 | std::unique_ptr<rgw::sal::Bucket> dest_bucket; |
901 | op_ret = store->get_bucket(s, nullptr, *pipe.dest.bucket, &dest_bucket, y); | |
f67539c2 | 902 | if (op_ret < 0) { |
b3b6e05e | 903 | ldpp_dout(this, 4) << "failed to read target bucket info (bucket=: " << cpp_strerror(op_ret) << dendl; |
9f95a23c TL |
904 | return; |
905 | } | |
906 | ||
20effc67 TL |
907 | *opt_dest_info = dest_bucket->get_info(); |
908 | pinfo = &(*opt_dest_info); | |
9f95a23c TL |
909 | pipe.dest.bucket = pinfo->bucket; |
910 | } | |
911 | ||
20effc67 | 912 | int r = rgw_bucket_sync_status(this, static_cast<rgw::sal::RadosStore*>(store), pipe, *pinfo, &bucket->get_info(), ¤t_status); |
9f95a23c | 913 | if (r < 0) { |
b3b6e05e | 914 | ldpp_dout(this, -1) << "ERROR: rgw_bucket_sync_status() on pipe=" << pipe << " returned ret=" << r << dendl; |
f67539c2 | 915 | op_ret = r; |
9f95a23c TL |
916 | return; |
917 | } | |
918 | ||
919 | if (status.empty()) { | |
920 | status = std::move(current_status); | |
921 | } else { | |
922 | if (current_status.size() != | |
923 | status.size()) { | |
f67539c2 | 924 | op_ret = -EINVAL; |
b3b6e05e | 925 | ldpp_dout(this, -1) << "ERROR: different number of shards for sync status of buckets syncing from the same source: status.size()= " << status.size() << " current_status.size()=" << current_status.size() << dendl; |
9f95a23c TL |
926 | return; |
927 | } | |
928 | auto m = status.begin(); | |
929 | for (auto& cur_shard_status : current_status) { | |
930 | auto& result_shard_status = *m++; | |
931 | // always take the first marker, or any later marker that's smaller | |
932 | if (cur_shard_status.inc_marker.position < result_shard_status.inc_marker.position) { | |
933 | result_shard_status = std::move(cur_shard_status); | |
934 | } | |
935 | } | |
936 | } | |
937 | } | |
b32b8144 FG |
938 | } |
939 | ||
940 | void RGWOp_BILog_Status::send_response() | |
941 | { | |
f67539c2 | 942 | set_req_state_err(s, op_ret); |
b32b8144 FG |
943 | dump_errno(s); |
944 | end_header(s); | |
945 | ||
f67539c2 | 946 | if (op_ret >= 0) { |
b32b8144 FG |
947 | encode_json("status", status, s->formatter); |
948 | } | |
949 | flusher.flush(); | |
950 | } | |
951 | ||
7c673cae FG |
952 | // not in header to avoid pulling in rgw_data_sync.h |
953 | class RGWOp_DATALog_Status : public RGWRESTOp { | |
954 | rgw_data_sync_status status; | |
955 | public: | |
9f95a23c | 956 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
957 | return caps.check_cap("datalog", RGW_CAP_READ); |
958 | } | |
f67539c2 | 959 | int verify_permission(optional_yield y) override { |
9f95a23c | 960 | return check_caps(s->user->get_caps()); |
7c673cae | 961 | } |
f67539c2 | 962 | void execute(optional_yield y) override ; |
7c673cae | 963 | void send_response() override; |
11fdf7f2 | 964 | const char* name() const override { return "get_data_changes_log_status"; } |
7c673cae FG |
965 | }; |
966 | ||
f67539c2 | 967 | void RGWOp_DATALog_Status::execute(optional_yield y) |
7c673cae FG |
968 | { |
969 | const auto source_zone = s->info.args.get("source-zone"); | |
20effc67 | 970 | auto sync = store->get_data_sync_manager(source_zone); |
7c673cae | 971 | if (sync == nullptr) { |
b3b6e05e | 972 | ldpp_dout(this, 1) << "no sync manager for source-zone " << source_zone << dendl; |
f67539c2 | 973 | op_ret = -ENOENT; |
7c673cae FG |
974 | return; |
975 | } | |
b3b6e05e | 976 | op_ret = sync->read_sync_status(this, &status); |
7c673cae FG |
977 | } |
978 | ||
979 | void RGWOp_DATALog_Status::send_response() | |
980 | { | |
f67539c2 | 981 | set_req_state_err(s, op_ret); |
7c673cae FG |
982 | dump_errno(s); |
983 | end_header(s); | |
984 | ||
f67539c2 | 985 | if (op_ret >= 0) { |
7c673cae FG |
986 | encode_json("status", status, s->formatter); |
987 | } | |
988 | flusher.flush(); | |
989 | } | |
990 | ||
991 | ||
992 | RGWOp *RGWHandler_Log::op_get() { | |
993 | bool exists; | |
994 | string type = s->info.args.get("type", &exists); | |
995 | ||
996 | if (!exists) { | |
997 | return NULL; | |
998 | } | |
999 | ||
1000 | if (type.compare("metadata") == 0) { | |
1001 | if (s->info.args.exists("id")) { | |
1002 | if (s->info.args.exists("info")) { | |
1003 | return new RGWOp_MDLog_ShardInfo; | |
1004 | } else { | |
1005 | return new RGWOp_MDLog_List; | |
1006 | } | |
1007 | } else if (s->info.args.exists("status")) { | |
1008 | return new RGWOp_MDLog_Status; | |
1009 | } else { | |
1010 | return new RGWOp_MDLog_Info; | |
1011 | } | |
1012 | } else if (type.compare("bucket-index") == 0) { | |
1013 | if (s->info.args.exists("info")) { | |
1014 | return new RGWOp_BILog_Info; | |
b32b8144 FG |
1015 | } else if (s->info.args.exists("status")) { |
1016 | return new RGWOp_BILog_Status; | |
7c673cae FG |
1017 | } else { |
1018 | return new RGWOp_BILog_List; | |
1019 | } | |
1020 | } else if (type.compare("data") == 0) { | |
1021 | if (s->info.args.exists("id")) { | |
1022 | if (s->info.args.exists("info")) { | |
1023 | return new RGWOp_DATALog_ShardInfo; | |
1024 | } else { | |
1025 | return new RGWOp_DATALog_List; | |
1026 | } | |
1027 | } else if (s->info.args.exists("status")) { | |
1028 | return new RGWOp_DATALog_Status; | |
1029 | } else { | |
1030 | return new RGWOp_DATALog_Info; | |
1031 | } | |
1032 | } | |
1033 | return NULL; | |
1034 | } | |
1035 | ||
1036 | RGWOp *RGWHandler_Log::op_delete() { | |
1037 | bool exists; | |
1038 | string type = s->info.args.get("type", &exists); | |
1039 | ||
1040 | if (!exists) { | |
1041 | return NULL; | |
1042 | } | |
1043 | ||
1044 | if (type.compare("metadata") == 0) | |
1045 | return new RGWOp_MDLog_Delete; | |
1046 | else if (type.compare("bucket-index") == 0) | |
1047 | return new RGWOp_BILog_Delete; | |
1048 | else if (type.compare("data") == 0) | |
1049 | return new RGWOp_DATALog_Delete; | |
1050 | return NULL; | |
1051 | } | |
1052 | ||
1053 | RGWOp *RGWHandler_Log::op_post() { | |
1054 | bool exists; | |
1055 | string type = s->info.args.get("type", &exists); | |
1056 | ||
1057 | if (!exists) { | |
1058 | return NULL; | |
1059 | } | |
1060 | ||
1061 | if (type.compare("metadata") == 0) { | |
1062 | if (s->info.args.exists("lock")) | |
1063 | return new RGWOp_MDLog_Lock; | |
1064 | else if (s->info.args.exists("unlock")) | |
1065 | return new RGWOp_MDLog_Unlock; | |
1066 | else if (s->info.args.exists("notify")) | |
1067 | return new RGWOp_MDLog_Notify; | |
1068 | } else if (type.compare("data") == 0) { | |
9f95a23c | 1069 | if (s->info.args.exists("notify")) |
7c673cae FG |
1070 | return new RGWOp_DATALog_Notify; |
1071 | } | |
1072 | return NULL; | |
1073 | } | |
1074 |