1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
14 #include "include/page.h"
18 #include "rgw_rest_s3.h"
19 #include "rgw_rest_metadata.h"
20 #include "rgw_client_io.h"
21 #include "common/errno.h"
22 #include "common/strtol.h"
23 #include "include/assert.h"
25 #define dout_context g_ceph_context
26 #define dout_subsys ceph_subsys_rgw
28 const string RGWOp_Metadata_Get::name() {
29 return "get_metadata";
32 static inline void frame_metadata_key(req_state *s, string& out) {
34 string key = s->info.args.get("key", &exists);
37 if (!s->init_state.url_bucket.empty()) {
38 section = s->init_state.url_bucket;
47 out += string(":") + key;
51 void RGWOp_Metadata_Get::execute() {
54 frame_metadata_key(s, metadata_key);
57 http_ret = store->meta_mgr->get(metadata_key, s->formatter);
59 dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl;
66 const string RGWOp_Metadata_List::name() {
67 return "list_metadata";
70 void RGWOp_Metadata_List::execute() {
71 string marker = s->info.args.get("marker");
72 bool max_entries_specified;
73 string max_entries_str = s->info.args.get("max-entries", &max_entries_specified);
75 bool extended_response = (max_entries_specified); /* for backward compatibility, if max-entries is not specified
76 we will send the old response format */
77 uint64_t max_entries = 0;
79 if (max_entries_specified) {
81 max_entries = (unsigned)strict_strtol(max_entries_str.c_str(), 10, &err);
83 dout(5) << "Error parsing max-entries " << max_entries_str << dendl;
91 frame_metadata_key(s, metadata_key);
96 http_ret = store->meta_mgr->list_keys_init(metadata_key, marker, &handle);
98 dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl;
105 if (extended_response) {
106 s->formatter->open_object_section("result");
109 s->formatter->open_array_section("keys");
114 left = (max_entries_specified ? max_entries - count : max);
115 http_ret = store->meta_mgr->list_keys_next(handle, left, keys, &truncated);
117 dout(5) << "ERROR: lists_keys_next(): " << cpp_strerror(http_ret)
122 for (list<string>::iterator iter = keys.begin(); iter != keys.end();
124 s->formatter->dump_string("key", *iter);
128 } while (truncated && left > 0);
130 s->formatter->close_section();
132 if (extended_response) {
133 encode_json("truncated", truncated, s->formatter);
134 encode_json("count", count, s->formatter);
136 encode_json("marker", store->meta_mgr->get_marker(handle), s->formatter);
138 s->formatter->close_section();
140 store->meta_mgr->list_keys_complete(handle);
145 int RGWOp_Metadata_Put::get_data(bufferlist& bl) {
151 cl = atoll(s->length);
153 data = (char *)malloc(cl + 1);
157 read_len = recv_body(s, data, cl);
158 if (cl != (size_t)read_len) {
159 dout(10) << "recv_body incomplete" << dendl;
165 bl.append(data, read_len);
167 int chunk_size = CEPH_PAGE_SIZE;
168 const char *enc = s->info.env->get("HTTP_TRANSFER_ENCODING");
169 if (!enc || strcmp(enc, "chunked")) {
170 return -ERR_LENGTH_REQUIRED;
172 data = (char *)malloc(chunk_size);
177 read_len = recv_body(s, data, chunk_size);
182 bl.append(data, read_len);
183 } while (read_len == chunk_size);
190 void RGWOp_Metadata_Put::execute() {
194 http_ret = get_data(bl);
199 http_ret = do_aws4_auth_completion();
204 frame_metadata_key(s, metadata_key);
206 RGWMetadataHandler::sync_type_t sync_type = RGWMetadataHandler::APPLY_ALWAYS;
208 bool mode_exists = false;
209 string mode_string = s->info.args.get("update-type", &mode_exists);
211 bool parsed = RGWMetadataHandler::string_to_sync_type(mode_string,
219 http_ret = store->meta_mgr->put(metadata_key, bl, sync_type,
222 dout(5) << "ERROR: can't put key: " << cpp_strerror(http_ret) << dendl;
225 // translate internal codes into return header
226 if (http_ret == STATUS_NO_APPLY)
227 update_status = "skipped";
228 else if (http_ret == STATUS_APPLIED)
229 update_status = "applied";
232 void RGWOp_Metadata_Put::send_response() {
233 int http_return_code = http_ret;
234 if ((http_ret == STATUS_NO_APPLY) || (http_ret == STATUS_APPLIED))
235 http_return_code = STATUS_NO_CONTENT;
236 set_req_state_err(s, http_return_code);
238 stringstream ver_stream;
239 ver_stream << "ver:" << ondisk_version.ver
240 <<",tag:" << ondisk_version.tag;
241 dump_header_if_nonempty(s, "RGWX_UPDATE_STATUS", update_status);
242 dump_header_if_nonempty(s, "RGWX_UPDATE_VERSION", ver_stream.str());
246 void RGWOp_Metadata_Delete::execute() {
249 frame_metadata_key(s, metadata_key);
250 http_ret = store->meta_mgr->remove(metadata_key);
252 dout(5) << "ERROR: can't remove key: " << cpp_strerror(http_ret) << dendl;
258 void RGWOp_Metadata_Lock::execute() {
259 string duration_str, lock_id;
262 frame_metadata_key(s, metadata_key);
266 duration_str = s->info.args.get("length");
267 lock_id = s->info.args.get("lock_id");
269 if ((!s->info.args.exists("key")) ||
270 (duration_str.empty()) ||
272 dout(5) << "Error invalid parameter list" << dendl;
280 dur = strict_strtol(duration_str.c_str(), 10, &err);
281 if (!err.empty() || dur <= 0) {
282 dout(5) << "invalid length param " << duration_str << dendl;
286 http_ret = store->meta_mgr->lock_exclusive(metadata_key, make_timespan(dur), lock_id);
287 if (http_ret == -EBUSY)
288 http_ret = -ERR_LOCKED;
291 void RGWOp_Metadata_Unlock::execute() {
295 frame_metadata_key(s, metadata_key);
299 lock_id = s->info.args.get("lock_id");
301 if ((!s->info.args.exists("key")) ||
303 dout(5) << "Error invalid parameter list" << dendl;
308 http_ret = store->meta_mgr->unlock(metadata_key, lock_id);
311 RGWOp *RGWHandler_Metadata::op_get() {
312 if (s->info.args.exists("key"))
313 return new RGWOp_Metadata_Get;
315 return new RGWOp_Metadata_List;
318 RGWOp *RGWHandler_Metadata::op_put() {
319 return new RGWOp_Metadata_Put;
322 RGWOp *RGWHandler_Metadata::op_delete() {
323 return new RGWOp_Metadata_Delete;
326 RGWOp *RGWHandler_Metadata::op_post() {
327 if (s->info.args.exists("lock"))
328 return new RGWOp_Metadata_Lock;
329 else if (s->info.args.exists("unlock"))
330 return new RGWOp_Metadata_Unlock;