1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 * Ceph - scalable distributed file system
7 * Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
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.
16 #include "common/ceph_json.h"
17 #include "common/strtol.h"
20 #include "rgw_rest_s3.h"
21 #include "rgw_rest_log.h"
22 #include "rgw_client_io.h"
24 #include "rgw_data_sync.h"
25 #include "rgw_common.h"
28 #include "services/svc_zone.h"
30 #include "common/errno.h"
31 #include "include/ceph_assert.h"
33 #define dout_context g_ceph_context
34 #define LOG_CLASS_LIST_MAX_ENTRIES (1000)
35 #define dout_subsys ceph_subsys_rgw
37 static int parse_date_str(string
& in
, real_time
& out
) {
42 if (utime_t::parse_date(in
, &epoch
, &nsec
) < 0) {
43 dout(5) << "Error parsing date " << in
<< dendl
;
47 out
= utime_t(epoch
, nsec
).to_real_time();
51 void RGWOp_MDLog_List::execute() {
52 string period
= s
->info
.args
.get("period");
53 string shard
= s
->info
.args
.get("id");
54 string max_entries_str
= s
->info
.args
.get("max-entries");
55 string st
= s
->info
.args
.get("start-time"),
56 et
= s
->info
.args
.get("end-time"),
57 marker
= s
->info
.args
.get("marker"),
62 unsigned shard_id
, max_entries
= LOG_CLASS_LIST_MAX_ENTRIES
;
64 shard_id
= (unsigned)strict_strtol(shard
.c_str(), 10, &err
);
66 dout(5) << "Error parsing shard_id " << shard
<< dendl
;
71 if (parse_date_str(st
, ut_st
) < 0) {
76 if (parse_date_str(et
, ut_et
) < 0) {
81 if (!max_entries_str
.empty()) {
82 max_entries
= (unsigned)strict_strtol(max_entries_str
.c_str(), 10, &err
);
84 dout(5) << "Error parsing max-entries " << max_entries_str
<< dendl
;
88 if (max_entries
> LOG_CLASS_LIST_MAX_ENTRIES
) {
89 max_entries
= LOG_CLASS_LIST_MAX_ENTRIES
;
94 ldout(s
->cct
, 5) << "Missing period id trying to use current" << dendl
;
95 period
= store
->svc
.zone
->get_current_period_id();
97 ldout(s
->cct
, 5) << "Missing period id" << dendl
;
103 RGWMetadataLog meta_log
{s
->cct
, store
, period
};
105 meta_log
.init_list_entries(shard_id
, ut_st
, ut_et
, marker
, &handle
);
107 http_ret
= meta_log
.list_entries(handle
, max_entries
, entries
,
108 &last_marker
, &truncated
);
110 meta_log
.complete_list_entries(handle
);
113 void RGWOp_MDLog_List::send_response() {
114 set_req_state_err(s
, http_ret
);
121 s
->formatter
->open_object_section("log_entries");
122 s
->formatter
->dump_string("marker", last_marker
);
123 s
->formatter
->dump_bool("truncated", truncated
);
125 s
->formatter
->open_array_section("entries");
126 for (list
<cls_log_entry
>::iterator iter
= entries
.begin();
127 iter
!= entries
.end(); ++iter
) {
128 cls_log_entry
& entry
= *iter
;
129 store
->meta_mgr
->dump_log_entry(entry
, s
->formatter
);
132 s
->formatter
->close_section();
134 s
->formatter
->close_section();
138 void RGWOp_MDLog_Info::execute() {
139 num_objects
= s
->cct
->_conf
->rgw_md_log_max_shards
;
140 period
= store
->meta_mgr
->read_oldest_log_period();
141 http_ret
= period
.get_error();
144 void RGWOp_MDLog_Info::send_response() {
145 set_req_state_err(s
, http_ret
);
149 s
->formatter
->open_object_section("mdlog");
150 s
->formatter
->dump_unsigned("num_objects", num_objects
);
152 s
->formatter
->dump_string("period", period
.get_period().get_id());
153 s
->formatter
->dump_unsigned("realm_epoch", period
.get_epoch());
155 s
->formatter
->close_section();
159 void RGWOp_MDLog_ShardInfo::execute() {
160 string period
= s
->info
.args
.get("period");
161 string shard
= s
->info
.args
.get("id");
164 unsigned shard_id
= (unsigned)strict_strtol(shard
.c_str(), 10, &err
);
166 dout(5) << "Error parsing shard_id " << shard
<< dendl
;
171 if (period
.empty()) {
172 ldout(s
->cct
, 5) << "Missing period id trying to use current" << dendl
;
173 period
= store
->svc
.zone
->get_current_period_id();
175 if (period
.empty()) {
176 ldout(s
->cct
, 5) << "Missing period id" << dendl
;
181 RGWMetadataLog meta_log
{s
->cct
, store
, period
};
183 http_ret
= meta_log
.get_info(shard_id
, &info
);
186 void RGWOp_MDLog_ShardInfo::send_response() {
187 set_req_state_err(s
, http_ret
);
191 encode_json("info", info
, s
->formatter
);
195 void RGWOp_MDLog_Delete::execute() {
196 string st
= s
->info
.args
.get("start-time"),
197 et
= s
->info
.args
.get("end-time"),
198 start_marker
= s
->info
.args
.get("start-marker"),
199 end_marker
= s
->info
.args
.get("end-marker"),
200 period
= s
->info
.args
.get("period"),
201 shard
= s
->info
.args
.get("id"),
209 shard_id
= (unsigned)strict_strtol(shard
.c_str(), 10, &err
);
211 dout(5) << "Error parsing shard_id " << shard
<< dendl
;
215 if (et
.empty() && end_marker
.empty()) { /* bounding end */
220 if (parse_date_str(st
, ut_st
) < 0) {
225 if (parse_date_str(et
, ut_et
) < 0) {
230 if (period
.empty()) {
231 ldout(s
->cct
, 5) << "Missing period id trying to use current" << dendl
;
232 period
= store
->svc
.zone
->get_current_period_id();
234 if (period
.empty()) {
235 ldout(s
->cct
, 5) << "Missing period id" << dendl
;
240 RGWMetadataLog meta_log
{s
->cct
, store
, period
};
242 http_ret
= meta_log
.trim(shard_id
, ut_st
, ut_et
, start_marker
, end_marker
);
245 void RGWOp_MDLog_Lock::execute() {
246 string period
, shard_id_str
, duration_str
, locker_id
, zone_id
;
251 period
= s
->info
.args
.get("period");
252 shard_id_str
= s
->info
.args
.get("id");
253 duration_str
= s
->info
.args
.get("length");
254 locker_id
= s
->info
.args
.get("locker-id");
255 zone_id
= s
->info
.args
.get("zone-id");
257 if (period
.empty()) {
258 ldout(s
->cct
, 5) << "Missing period id trying to use current" << dendl
;
259 period
= store
->svc
.zone
->get_current_period_id();
262 if (period
.empty() ||
263 shard_id_str
.empty() ||
264 (duration_str
.empty()) ||
267 dout(5) << "Error invalid parameter list" << dendl
;
273 shard_id
= (unsigned)strict_strtol(shard_id_str
.c_str(), 10, &err
);
275 dout(5) << "Error parsing shard_id param " << shard_id_str
<< dendl
;
280 RGWMetadataLog meta_log
{s
->cct
, store
, period
};
282 dur
= (unsigned)strict_strtol(duration_str
.c_str(), 10, &err
);
283 if (!err
.empty() || dur
<= 0) {
284 dout(5) << "invalid length param " << duration_str
<< dendl
;
288 http_ret
= meta_log
.lock_exclusive(shard_id
, make_timespan(dur
), zone_id
,
290 if (http_ret
== -EBUSY
)
291 http_ret
= -ERR_LOCKED
;
294 void RGWOp_MDLog_Unlock::execute() {
295 string period
, shard_id_str
, locker_id
, zone_id
;
300 period
= s
->info
.args
.get("period");
301 shard_id_str
= s
->info
.args
.get("id");
302 locker_id
= s
->info
.args
.get("locker-id");
303 zone_id
= s
->info
.args
.get("zone-id");
305 if (period
.empty()) {
306 ldout(s
->cct
, 5) << "Missing period id trying to use current" << dendl
;
307 period
= store
->svc
.zone
->get_current_period_id();
310 if (period
.empty() ||
311 shard_id_str
.empty() ||
314 dout(5) << "Error invalid parameter list" << dendl
;
320 shard_id
= (unsigned)strict_strtol(shard_id_str
.c_str(), 10, &err
);
322 dout(5) << "Error parsing shard_id param " << shard_id_str
<< dendl
;
327 RGWMetadataLog meta_log
{s
->cct
, store
, period
};
328 http_ret
= meta_log
.unlock(shard_id
, zone_id
, locker_id
);
331 void RGWOp_MDLog_Notify::execute() {
332 #define LARGE_ENOUGH_BUF (128 * 1024)
336 std::tie(r
, data
) = rgw_rest_read_all_input(s
, LARGE_ENOUGH_BUF
);
342 char* buf
= data
.c_str();
343 ldout(s
->cct
, 20) << __func__
<< "(): read data: " << buf
<< dendl
;
346 r
= p
.parse(buf
, data
.length());
348 ldout(s
->cct
, 0) << "ERROR: failed to parse JSON" << dendl
;
353 set
<int> updated_shards
;
355 decode_json_obj(updated_shards
, &p
);
356 } catch (JSONDecoder::err
& err
) {
357 ldout(s
->cct
, 0) << "ERROR: failed to decode JSON" << dendl
;
362 if (store
->ctx()->_conf
->subsys
.should_gather
<ceph_subsys_rgw
, 20>()) {
363 for (set
<int>::iterator iter
= updated_shards
.begin(); iter
!= updated_shards
.end(); ++iter
) {
364 ldout(s
->cct
, 20) << __func__
<< "(): updated shard=" << *iter
<< dendl
;
368 store
->wakeup_meta_sync_shards(updated_shards
);
373 void RGWOp_BILog_List::execute() {
374 string tenant_name
= s
->info
.args
.get("tenant"),
375 bucket_name
= s
->info
.args
.get("bucket"),
376 marker
= s
->info
.args
.get("marker"),
377 max_entries_str
= s
->info
.args
.get("max-entries"),
378 bucket_instance
= s
->info
.args
.get("bucket-instance");
379 RGWBucketInfo bucket_info
;
380 unsigned max_entries
;
382 if (bucket_name
.empty() && bucket_instance
.empty()) {
383 dout(5) << "ERROR: neither bucket nor bucket instance specified" << dendl
;
389 http_ret
= rgw_bucket_parse_bucket_instance(bucket_instance
, &bucket_instance
, &shard_id
);
394 if (!bucket_instance
.empty()) {
395 http_ret
= store
->get_bucket_instance_info(*s
->sysobj_ctx
, bucket_instance
, bucket_info
, NULL
, NULL
);
397 dout(5) << "could not get bucket instance info for bucket instance id=" << bucket_instance
<< dendl
;
400 } else { /* !bucket_name.empty() */
401 http_ret
= store
->get_bucket_info(*s
->sysobj_ctx
, tenant_name
, bucket_name
, bucket_info
, NULL
, NULL
);
403 dout(5) << "could not get bucket info for bucket=" << bucket_name
<< dendl
;
412 max_entries
= (unsigned)strict_strtol(max_entries_str
.c_str(), 10, &err
);
414 max_entries
= LOG_CLASS_LIST_MAX_ENTRIES
;
418 list
<rgw_bi_log_entry
> entries
;
419 int ret
= store
->list_bi_log_entries(bucket_info
, shard_id
,
420 marker
, max_entries
- count
,
421 entries
, &truncated
);
423 dout(5) << "ERROR: list_bi_log_entries()" << dendl
;
427 count
+= entries
.size();
429 send_response(entries
, marker
);
430 } while (truncated
&& count
< max_entries
);
435 void RGWOp_BILog_List::send_response() {
439 set_req_state_err(s
, http_ret
);
448 s
->formatter
->open_array_section("entries");
451 void RGWOp_BILog_List::send_response(list
<rgw_bi_log_entry
>& entries
, string
& marker
)
453 for (list
<rgw_bi_log_entry
>::iterator iter
= entries
.begin(); iter
!= entries
.end(); ++iter
) {
454 rgw_bi_log_entry
& entry
= *iter
;
455 encode_json("entry", entry
, s
->formatter
);
462 void RGWOp_BILog_List::send_response_end() {
463 s
->formatter
->close_section();
467 void RGWOp_BILog_Info::execute() {
468 string tenant_name
= s
->info
.args
.get("tenant"),
469 bucket_name
= s
->info
.args
.get("bucket"),
470 bucket_instance
= s
->info
.args
.get("bucket-instance");
471 RGWBucketInfo bucket_info
;
473 if (bucket_name
.empty() && bucket_instance
.empty()) {
474 dout(5) << "ERROR: neither bucket nor bucket instance specified" << dendl
;
480 http_ret
= rgw_bucket_parse_bucket_instance(bucket_instance
, &bucket_instance
, &shard_id
);
485 if (!bucket_instance
.empty()) {
486 http_ret
= store
->get_bucket_instance_info(*s
->sysobj_ctx
, bucket_instance
, bucket_info
, NULL
, NULL
);
488 dout(5) << "could not get bucket instance info for bucket instance id=" << bucket_instance
<< dendl
;
491 } else { /* !bucket_name.empty() */
492 http_ret
= store
->get_bucket_info(*s
->sysobj_ctx
, tenant_name
, bucket_name
, bucket_info
, NULL
, NULL
);
494 dout(5) << "could not get bucket info for bucket=" << bucket_name
<< dendl
;
498 map
<RGWObjCategory
, RGWStorageStats
> stats
;
499 int ret
= store
->get_bucket_stats(bucket_info
, shard_id
, &bucket_ver
, &master_ver
, stats
, &max_marker
, &syncstopped
);
500 if (ret
< 0 && ret
!= -ENOENT
) {
506 void RGWOp_BILog_Info::send_response() {
507 set_req_state_err(s
, http_ret
);
514 s
->formatter
->open_object_section("info");
515 encode_json("bucket_ver", bucket_ver
, s
->formatter
);
516 encode_json("master_ver", master_ver
, s
->formatter
);
517 encode_json("max_marker", max_marker
, s
->formatter
);
518 encode_json("syncstopped", syncstopped
, s
->formatter
);
519 s
->formatter
->close_section();
524 void RGWOp_BILog_Delete::execute() {
525 string tenant_name
= s
->info
.args
.get("tenant"),
526 bucket_name
= s
->info
.args
.get("bucket"),
527 start_marker
= s
->info
.args
.get("start-marker"),
528 end_marker
= s
->info
.args
.get("end-marker"),
529 bucket_instance
= s
->info
.args
.get("bucket-instance");
531 RGWBucketInfo bucket_info
;
534 if ((bucket_name
.empty() && bucket_instance
.empty()) ||
535 end_marker
.empty()) {
536 dout(5) << "ERROR: one of bucket and bucket instance, and also end-marker is mandatory" << dendl
;
542 http_ret
= rgw_bucket_parse_bucket_instance(bucket_instance
, &bucket_instance
, &shard_id
);
547 if (!bucket_instance
.empty()) {
548 http_ret
= store
->get_bucket_instance_info(*s
->sysobj_ctx
, bucket_instance
, bucket_info
, NULL
, NULL
);
550 dout(5) << "could not get bucket instance info for bucket instance id=" << bucket_instance
<< dendl
;
553 } else { /* !bucket_name.empty() */
554 http_ret
= store
->get_bucket_info(*s
->sysobj_ctx
, tenant_name
, bucket_name
, bucket_info
, NULL
, NULL
);
556 dout(5) << "could not get bucket info for bucket=" << bucket_name
<< dendl
;
560 http_ret
= store
->trim_bi_log_entries(bucket_info
, shard_id
, start_marker
, end_marker
);
562 dout(5) << "ERROR: trim_bi_log_entries() " << dendl
;
567 void RGWOp_DATALog_List::execute() {
568 string shard
= s
->info
.args
.get("id");
570 string st
= s
->info
.args
.get("start-time"),
571 et
= s
->info
.args
.get("end-time"),
572 max_entries_str
= s
->info
.args
.get("max-entries"),
573 marker
= s
->info
.args
.get("marker"),
577 unsigned shard_id
, max_entries
= LOG_CLASS_LIST_MAX_ENTRIES
;
579 s
->info
.args
.get_bool("extra-info", &extra_info
, false);
581 shard_id
= (unsigned)strict_strtol(shard
.c_str(), 10, &err
);
583 dout(5) << "Error parsing shard_id " << shard
<< dendl
;
588 if (parse_date_str(st
, ut_st
) < 0) {
593 if (parse_date_str(et
, ut_et
) < 0) {
598 if (!max_entries_str
.empty()) {
599 max_entries
= (unsigned)strict_strtol(max_entries_str
.c_str(), 10, &err
);
601 dout(5) << "Error parsing max-entries " << max_entries_str
<< dendl
;
605 if (max_entries
> LOG_CLASS_LIST_MAX_ENTRIES
) {
606 max_entries
= LOG_CLASS_LIST_MAX_ENTRIES
;
610 // Note that last_marker is updated to be the marker of the last
612 http_ret
= store
->data_log
->list_entries(shard_id
, ut_st
, ut_et
,
613 max_entries
, entries
, marker
,
614 &last_marker
, &truncated
);
617 void RGWOp_DATALog_List::send_response() {
618 set_req_state_err(s
, http_ret
);
625 s
->formatter
->open_object_section("log_entries");
626 s
->formatter
->dump_string("marker", last_marker
);
627 s
->formatter
->dump_bool("truncated", truncated
);
629 s
->formatter
->open_array_section("entries");
630 for (list
<rgw_data_change_log_entry
>::iterator iter
= entries
.begin();
631 iter
!= entries
.end(); ++iter
) {
632 rgw_data_change_log_entry
& entry
= *iter
;
634 encode_json("entry", entry
.entry
, s
->formatter
);
636 encode_json("entry", entry
, s
->formatter
);
640 s
->formatter
->close_section();
642 s
->formatter
->close_section();
647 void RGWOp_DATALog_Info::execute() {
648 num_objects
= s
->cct
->_conf
->rgw_data_log_num_shards
;
652 void RGWOp_DATALog_Info::send_response() {
653 set_req_state_err(s
, http_ret
);
657 s
->formatter
->open_object_section("num_objects");
658 s
->formatter
->dump_unsigned("num_objects", num_objects
);
659 s
->formatter
->close_section();
663 void RGWOp_DATALog_ShardInfo::execute() {
664 string shard
= s
->info
.args
.get("id");
667 unsigned shard_id
= (unsigned)strict_strtol(shard
.c_str(), 10, &err
);
669 dout(5) << "Error parsing shard_id " << shard
<< dendl
;
674 http_ret
= store
->data_log
->get_info(shard_id
, &info
);
677 void RGWOp_DATALog_ShardInfo::send_response() {
678 set_req_state_err(s
, http_ret
);
682 encode_json("info", info
, s
->formatter
);
686 void RGWOp_DATALog_Lock::execute() {
687 string shard_id_str
, duration_str
, locker_id
, zone_id
;
692 shard_id_str
= s
->info
.args
.get("id");
693 duration_str
= s
->info
.args
.get("length");
694 locker_id
= s
->info
.args
.get("locker-id");
695 zone_id
= s
->info
.args
.get("zone-id");
697 if (shard_id_str
.empty() ||
698 (duration_str
.empty()) ||
701 dout(5) << "Error invalid parameter list" << dendl
;
707 shard_id
= (unsigned)strict_strtol(shard_id_str
.c_str(), 10, &err
);
709 dout(5) << "Error parsing shard_id param " << shard_id_str
<< dendl
;
715 dur
= (unsigned)strict_strtol(duration_str
.c_str(), 10, &err
);
716 if (!err
.empty() || dur
<= 0) {
717 dout(5) << "invalid length param " << duration_str
<< dendl
;
721 http_ret
= store
->data_log
->lock_exclusive(shard_id
, make_timespan(dur
), zone_id
, locker_id
);
722 if (http_ret
== -EBUSY
)
723 http_ret
= -ERR_LOCKED
;
726 void RGWOp_DATALog_Unlock::execute() {
727 string shard_id_str
, locker_id
, zone_id
;
732 shard_id_str
= s
->info
.args
.get("id");
733 locker_id
= s
->info
.args
.get("locker-id");
734 zone_id
= s
->info
.args
.get("zone-id");
736 if (shard_id_str
.empty() ||
739 dout(5) << "Error invalid parameter list" << dendl
;
745 shard_id
= (unsigned)strict_strtol(shard_id_str
.c_str(), 10, &err
);
747 dout(5) << "Error parsing shard_id param " << shard_id_str
<< dendl
;
752 http_ret
= store
->data_log
->unlock(shard_id
, zone_id
, locker_id
);
755 void RGWOp_DATALog_Notify::execute() {
756 string source_zone
= s
->info
.args
.get("source-zone");
757 #define LARGE_ENOUGH_BUF (128 * 1024)
761 std::tie(r
, data
) = rgw_rest_read_all_input(s
, LARGE_ENOUGH_BUF
);
767 char* buf
= data
.c_str();
768 ldout(s
->cct
, 20) << __func__
<< "(): read data: " << buf
<< dendl
;
771 r
= p
.parse(buf
, data
.length());
773 ldout(s
->cct
, 0) << "ERROR: failed to parse JSON" << dendl
;
778 map
<int, set
<string
> > updated_shards
;
780 decode_json_obj(updated_shards
, &p
);
781 } catch (JSONDecoder::err
& err
) {
782 ldout(s
->cct
, 0) << "ERROR: failed to decode JSON" << dendl
;
787 if (store
->ctx()->_conf
->subsys
.should_gather
<ceph_subsys_rgw
, 20>()) {
788 for (map
<int, set
<string
> >::iterator iter
= updated_shards
.begin(); iter
!= updated_shards
.end(); ++iter
) {
789 ldout(s
->cct
, 20) << __func__
<< "(): updated shard=" << iter
->first
<< dendl
;
790 set
<string
>& keys
= iter
->second
;
791 for (set
<string
>::iterator kiter
= keys
.begin(); kiter
!= keys
.end(); ++kiter
) {
792 ldout(s
->cct
, 20) << __func__
<< "(): modified key=" << *kiter
<< dendl
;
797 store
->wakeup_data_sync_shards(source_zone
, updated_shards
);
802 void RGWOp_DATALog_Delete::execute() {
803 string st
= s
->info
.args
.get("start-time"),
804 et
= s
->info
.args
.get("end-time"),
805 start_marker
= s
->info
.args
.get("start-marker"),
806 end_marker
= s
->info
.args
.get("end-marker"),
807 shard
= s
->info
.args
.get("id"),
815 shard_id
= (unsigned)strict_strtol(shard
.c_str(), 10, &err
);
817 dout(5) << "Error parsing shard_id " << shard
<< dendl
;
821 if (et
.empty() && end_marker
.empty()) { /* bounding end */
826 if (parse_date_str(st
, ut_st
) < 0) {
831 if (parse_date_str(et
, ut_et
) < 0) {
836 http_ret
= store
->data_log
->trim_entries(shard_id
, ut_st
, ut_et
, start_marker
, end_marker
);
839 // not in header to avoid pulling in rgw_sync.h
840 class RGWOp_MDLog_Status
: public RGWRESTOp
{
841 rgw_meta_sync_status status
;
843 int check_caps(RGWUserCaps
& caps
) override
{
844 return caps
.check_cap("mdlog", RGW_CAP_READ
);
846 int verify_permission() override
{
847 return check_caps(s
->user
->caps
);
849 void execute() override
;
850 void send_response() override
;
851 const char* name() const override
{ return "get_metadata_log_status"; }
854 void RGWOp_MDLog_Status::execute()
856 auto sync
= store
->get_meta_sync_manager();
857 if (sync
== nullptr) {
858 ldout(s
->cct
, 1) << "no sync manager" << dendl
;
862 http_ret
= sync
->read_sync_status(&status
);
865 void RGWOp_MDLog_Status::send_response()
867 set_req_state_err(s
, http_ret
);
872 encode_json("status", status
, s
->formatter
);
877 // not in header to avoid pulling in rgw_data_sync.h
878 class RGWOp_BILog_Status
: public RGWRESTOp
{
879 std::vector
<rgw_bucket_shard_sync_info
> status
;
881 int check_caps(RGWUserCaps
& caps
) override
{
882 return caps
.check_cap("bilog", RGW_CAP_READ
);
884 int verify_permission() override
{
885 return check_caps(s
->user
->caps
);
887 void execute() override
;
888 void send_response() override
;
889 const char* name() const override
{ return "get_bucket_index_log_status"; }
892 void RGWOp_BILog_Status::execute()
894 const auto source_zone
= s
->info
.args
.get("source-zone");
895 const auto key
= s
->info
.args
.get("bucket");
897 ldout(s
->cct
, 4) << "no 'bucket' provided" << dendl
;
903 int shard_id
{-1}; // unused
904 http_ret
= rgw_bucket_parse_bucket_key(s
->cct
, key
, &bucket
, &shard_id
);
906 ldout(s
->cct
, 4) << "no 'bucket' provided" << dendl
;
911 // read the bucket instance info for num_shards
912 auto ctx
= store
->svc
.sysobj
->init_obj_ctx();
914 http_ret
= store
->get_bucket_instance_info(ctx
, bucket
, info
, nullptr, nullptr);
916 ldout(s
->cct
, 4) << "failed to read bucket info: " << cpp_strerror(http_ret
) << dendl
;
919 http_ret
= rgw_bucket_sync_status(this, store
, source_zone
, info
, &status
);
922 void RGWOp_BILog_Status::send_response()
924 set_req_state_err(s
, http_ret
);
929 encode_json("status", status
, s
->formatter
);
934 // not in header to avoid pulling in rgw_data_sync.h
935 class RGWOp_DATALog_Status
: public RGWRESTOp
{
936 rgw_data_sync_status status
;
938 int check_caps(RGWUserCaps
& caps
) override
{
939 return caps
.check_cap("datalog", RGW_CAP_READ
);
941 int verify_permission() override
{
942 return check_caps(s
->user
->caps
);
944 void execute() override
;
945 void send_response() override
;
946 const char* name() const override
{ return "get_data_changes_log_status"; }
949 void RGWOp_DATALog_Status::execute()
951 const auto source_zone
= s
->info
.args
.get("source-zone");
952 auto sync
= store
->get_data_sync_manager(source_zone
);
953 if (sync
== nullptr) {
954 ldout(s
->cct
, 1) << "no sync manager for source-zone " << source_zone
<< dendl
;
958 http_ret
= sync
->read_sync_status(&status
);
961 void RGWOp_DATALog_Status::send_response()
963 set_req_state_err(s
, http_ret
);
968 encode_json("status", status
, s
->formatter
);
974 RGWOp
*RGWHandler_Log::op_get() {
976 string type
= s
->info
.args
.get("type", &exists
);
982 if (type
.compare("metadata") == 0) {
983 if (s
->info
.args
.exists("id")) {
984 if (s
->info
.args
.exists("info")) {
985 return new RGWOp_MDLog_ShardInfo
;
987 return new RGWOp_MDLog_List
;
989 } else if (s
->info
.args
.exists("status")) {
990 return new RGWOp_MDLog_Status
;
992 return new RGWOp_MDLog_Info
;
994 } else if (type
.compare("bucket-index") == 0) {
995 if (s
->info
.args
.exists("info")) {
996 return new RGWOp_BILog_Info
;
997 } else if (s
->info
.args
.exists("status")) {
998 return new RGWOp_BILog_Status
;
1000 return new RGWOp_BILog_List
;
1002 } else if (type
.compare("data") == 0) {
1003 if (s
->info
.args
.exists("id")) {
1004 if (s
->info
.args
.exists("info")) {
1005 return new RGWOp_DATALog_ShardInfo
;
1007 return new RGWOp_DATALog_List
;
1009 } else if (s
->info
.args
.exists("status")) {
1010 return new RGWOp_DATALog_Status
;
1012 return new RGWOp_DATALog_Info
;
1018 RGWOp
*RGWHandler_Log::op_delete() {
1020 string type
= s
->info
.args
.get("type", &exists
);
1026 if (type
.compare("metadata") == 0)
1027 return new RGWOp_MDLog_Delete
;
1028 else if (type
.compare("bucket-index") == 0)
1029 return new RGWOp_BILog_Delete
;
1030 else if (type
.compare("data") == 0)
1031 return new RGWOp_DATALog_Delete
;
1035 RGWOp
*RGWHandler_Log::op_post() {
1037 string type
= s
->info
.args
.get("type", &exists
);
1043 if (type
.compare("metadata") == 0) {
1044 if (s
->info
.args
.exists("lock"))
1045 return new RGWOp_MDLog_Lock
;
1046 else if (s
->info
.args
.exists("unlock"))
1047 return new RGWOp_MDLog_Unlock
;
1048 else if (s
->info
.args
.exists("notify"))
1049 return new RGWOp_MDLog_Notify
;
1050 } else if (type
.compare("data") == 0) {
1051 if (s
->info
.args
.exists("lock"))
1052 return new RGWOp_DATALog_Lock
;
1053 else if (s
->info
.args
.exists("unlock"))
1054 return new RGWOp_DATALog_Unlock
;
1055 else if (s
->info
.args
.exists("notify"))
1056 return new RGWOp_DATALog_Notify
;