1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
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 "include/page.h"
20 #include "rgw_rest_s3.h"
21 #include "rgw_rest_metadata.h"
22 #include "rgw_client_io.h"
23 #include "rgw_mdlog_types.h"
24 #include "rgw_sal_rados.h"
25 #include "common/errno.h"
26 #include "common/strtol.h"
27 #include "rgw/rgw_b64.h"
28 #include "include/ceph_assert.h"
30 #define dout_context g_ceph_context
31 #define dout_subsys ceph_subsys_rgw
35 static inline void frame_metadata_key(req_state
*s
, string
& out
) {
37 string key
= s
->info
.args
.get("key", &exists
);
40 if (!s
->init_state
.url_bucket
.empty()) {
41 section
= s
->init_state
.url_bucket
;
50 out
+= string(":") + key
;
54 void RGWOp_Metadata_Get::execute(optional_yield y
) {
57 frame_metadata_key(s
, metadata_key
);
59 auto meta_mgr
= static_cast<rgw::sal::RadosStore
*>(store
)->ctl()->meta
.mgr
;
62 op_ret
= meta_mgr
->get(metadata_key
, s
->formatter
, s
->yield
, s
);
64 ldpp_dout(s
, 5) << "ERROR: can't get key: " << cpp_strerror(op_ret
) << dendl
;
71 void RGWOp_Metadata_Get_Myself::execute(optional_yield y
) {
74 owner_id
= s
->owner
.get_id().to_str();
75 s
->info
.args
.append("key", owner_id
);
77 return RGWOp_Metadata_Get::execute(y
);
80 void RGWOp_Metadata_List::execute(optional_yield y
) {
82 ldpp_dout(this, 16) << __func__
83 << " raw marker " << s
->info
.args
.get("marker")
87 marker
= s
->info
.args
.get("marker");
88 if (!marker
.empty()) {
89 marker
= rgw::from_base64(marker
);
91 ldpp_dout(this, 16) << __func__
92 << " marker " << marker
<< dendl
;
94 marker
= std::string("");
97 bool max_entries_specified
;
98 string max_entries_str
=
99 s
->info
.args
.get("max-entries", &max_entries_specified
);
101 bool extended_response
= (max_entries_specified
); /* for backward compatibility, if max-entries is not specified
102 we will send the old response format */
103 uint64_t max_entries
= 0;
105 if (max_entries_specified
) {
107 max_entries
= (unsigned)strict_strtol(max_entries_str
.c_str(), 10, &err
);
109 ldpp_dout(this, 5) << "Error parsing max-entries " << max_entries_str
<< dendl
;
117 frame_metadata_key(s
, metadata_key
);
123 marker = "3:b55a9110:root::bu_9:head";
124 marker = "3:b9a8b2a6:root::sorry_janefonda_890:head";
125 marker = "3:bf885d8f:root::sorry_janefonda_665:head";
128 op_ret
= store
->meta_list_keys_init(this, metadata_key
, marker
, &handle
);
130 ldpp_dout(this, 5) << "ERROR: can't get key: " << cpp_strerror(op_ret
) << dendl
;
137 if (extended_response
) {
138 s
->formatter
->open_object_section("result");
141 s
->formatter
->open_array_section("keys");
146 left
= (max_entries_specified
? max_entries
- count
: max
);
147 op_ret
= store
->meta_list_keys_next(this, handle
, left
, keys
, &truncated
);
149 ldpp_dout(this, 5) << "ERROR: lists_keys_next(): " << cpp_strerror(op_ret
)
154 for (list
<string
>::iterator iter
= keys
.begin(); iter
!= keys
.end();
156 s
->formatter
->dump_string("key", *iter
);
160 } while (truncated
&& left
> 0);
162 s
->formatter
->close_section();
164 if (extended_response
) {
165 encode_json("truncated", truncated
, s
->formatter
);
166 encode_json("count", count
, s
->formatter
);
169 rgw::to_base64(store
->meta_get_marker(handle
));
170 encode_json("marker", esc_marker
, s
->formatter
);
172 s
->formatter
->close_section();
174 store
->meta_list_keys_complete(handle
);
179 int RGWOp_Metadata_Put::get_data(bufferlist
& bl
) {
185 cl
= atoll(s
->length
);
187 data
= (char *)malloc(cl
+ 1);
191 read_len
= recv_body(s
, data
, cl
);
192 if (cl
!= (size_t)read_len
) {
193 ldpp_dout(this, 10) << "recv_body incomplete" << dendl
;
199 bl
.append(data
, read_len
);
201 int chunk_size
= CEPH_PAGE_SIZE
;
202 const char *enc
= s
->info
.env
->get("HTTP_TRANSFER_ENCODING");
203 if (!enc
|| strcmp(enc
, "chunked")) {
204 return -ERR_LENGTH_REQUIRED
;
206 data
= (char *)malloc(chunk_size
);
211 read_len
= recv_body(s
, data
, chunk_size
);
216 bl
.append(data
, read_len
);
217 } while (read_len
== chunk_size
);
224 static bool string_to_sync_type(const string
& sync_string
,
225 RGWMDLogSyncType
& type
) {
226 if (sync_string
.compare("update-by-version") == 0)
227 type
= APPLY_UPDATES
;
228 else if (sync_string
.compare("update-by-timestamp") == 0)
230 else if (sync_string
.compare("always") == 0)
237 void RGWOp_Metadata_Put::execute(optional_yield y
) {
241 op_ret
= get_data(bl
);
246 op_ret
= do_aws4_auth_completion();
251 frame_metadata_key(s
, metadata_key
);
253 RGWMDLogSyncType sync_type
= RGWMDLogSyncType::APPLY_ALWAYS
;
255 bool mode_exists
= false;
256 string mode_string
= s
->info
.args
.get("update-type", &mode_exists
);
258 bool parsed
= string_to_sync_type(mode_string
,
266 op_ret
= static_cast<rgw::sal::RadosStore
*>(store
)->ctl()->meta
.mgr
->put(metadata_key
, bl
, s
->yield
, s
, sync_type
,
267 false, &ondisk_version
);
269 ldpp_dout(s
, 5) << "ERROR: can't put key: " << cpp_strerror(op_ret
) << dendl
;
272 // translate internal codes into return header
273 if (op_ret
== STATUS_NO_APPLY
)
274 update_status
= "skipped";
275 else if (op_ret
== STATUS_APPLIED
)
276 update_status
= "applied";
279 void RGWOp_Metadata_Put::send_response() {
280 int op_return_code
= op_ret
;
281 if ((op_ret
== STATUS_NO_APPLY
) || (op_ret
== STATUS_APPLIED
))
282 op_return_code
= STATUS_NO_CONTENT
;
283 set_req_state_err(s
, op_return_code
);
285 stringstream ver_stream
;
286 ver_stream
<< "ver:" << ondisk_version
.ver
287 <<",tag:" << ondisk_version
.tag
;
288 dump_header_if_nonempty(s
, "RGWX_UPDATE_STATUS", update_status
);
289 dump_header_if_nonempty(s
, "RGWX_UPDATE_VERSION", ver_stream
.str());
293 void RGWOp_Metadata_Delete::execute(optional_yield y
) {
296 frame_metadata_key(s
, metadata_key
);
297 op_ret
= static_cast<rgw::sal::RadosStore
*>(store
)->ctl()->meta
.mgr
->remove(metadata_key
, s
->yield
, s
);
299 ldpp_dout(s
, 5) << "ERROR: can't remove key: " << cpp_strerror(op_ret
) << dendl
;
305 RGWOp
*RGWHandler_Metadata::op_get() {
306 if (s
->info
.args
.exists("myself"))
307 return new RGWOp_Metadata_Get_Myself
;
308 if (s
->info
.args
.exists("key"))
309 return new RGWOp_Metadata_Get
;
311 return new RGWOp_Metadata_List
;
314 RGWOp
*RGWHandler_Metadata::op_put() {
315 return new RGWOp_Metadata_Put
;
318 RGWOp
*RGWHandler_Metadata::op_delete() {
319 return new RGWOp_Metadata_Delete
;