]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_metadata.cc
import ceph 15.2.10
[ceph.git] / ceph / src / rgw / rgw_rest_metadata.cc
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 /*
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 */
15
16 #include "include/page.h"
17
18 #include "rgw_rest.h"
19 #include "rgw_op.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 "common/errno.h"
25 #include "common/strtol.h"
26 #include "rgw/rgw_b64.h"
27 #include "include/ceph_assert.h"
28
29 #define dout_context g_ceph_context
30 #define dout_subsys ceph_subsys_rgw
31
32 static inline void frame_metadata_key(req_state *s, string& out) {
33 bool exists;
34 string key = s->info.args.get("key", &exists);
35
36 string section;
37 if (!s->init_state.url_bucket.empty()) {
38 section = s->init_state.url_bucket;
39 } else {
40 section = key;
41 key.clear();
42 }
43
44 out = section;
45
46 if (!key.empty()) {
47 out += string(":") + key;
48 }
49 }
50
51 void RGWOp_Metadata_Get::execute() {
52 string metadata_key;
53
54 frame_metadata_key(s, metadata_key);
55
56 auto meta_mgr = store->ctl()->meta.mgr;
57
58 /* Get keys */
59 http_ret = meta_mgr->get(metadata_key, s->formatter, s->yield);
60 if (http_ret < 0) {
61 dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl;
62 return;
63 }
64
65 http_ret = 0;
66 }
67
68 void RGWOp_Metadata_Get_Myself::execute() {
69 string owner_id;
70
71 owner_id = s->owner.get_id().to_str();
72 s->info.args.append("key", owner_id);
73
74 return RGWOp_Metadata_Get::execute();
75 }
76
77 void RGWOp_Metadata_List::execute() {
78 string marker;
79 ldout(s->cct, 16) << __func__
80 << " raw marker " << s->info.args.get("marker")
81 << dendl;
82
83 try {
84 marker = s->info.args.get("marker");
85 if (!marker.empty()) {
86 marker = rgw::from_base64(marker);
87 }
88 ldout(s->cct, 16) << __func__
89 << " marker " << marker << dendl;
90 } catch (...) {
91 marker = std::string("");
92 }
93
94 bool max_entries_specified;
95 string max_entries_str =
96 s->info.args.get("max-entries", &max_entries_specified);
97
98 bool extended_response = (max_entries_specified); /* for backward compatibility, if max-entries is not specified
99 we will send the old response format */
100 uint64_t max_entries = 0;
101
102 if (max_entries_specified) {
103 string err;
104 max_entries = (unsigned)strict_strtol(max_entries_str.c_str(), 10, &err);
105 if (!err.empty()) {
106 dout(5) << "Error parsing max-entries " << max_entries_str << dendl;
107 http_ret = -EINVAL;
108 return;
109 }
110 }
111
112 string metadata_key;
113
114 frame_metadata_key(s, metadata_key);
115 /* List keys */
116 void *handle;
117 int max = 1000;
118
119 /* example markers:
120 marker = "3:b55a9110:root::bu_9:head";
121 marker = "3:b9a8b2a6:root::sorry_janefonda_890:head";
122 marker = "3:bf885d8f:root::sorry_janefonda_665:head";
123 */
124
125 http_ret = store->ctl()->meta.mgr->list_keys_init(metadata_key, marker, &handle);
126 if (http_ret < 0) {
127 dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl;
128 return;
129 }
130
131 bool truncated;
132 uint64_t count = 0;
133
134 if (extended_response) {
135 s->formatter->open_object_section("result");
136 }
137
138 s->formatter->open_array_section("keys");
139
140 auto meta_mgr = store->ctl()->meta.mgr;
141
142 uint64_t left;
143 do {
144 list<string> keys;
145 left = (max_entries_specified ? max_entries - count : max);
146 http_ret = meta_mgr->list_keys_next(handle, left, keys, &truncated);
147 if (http_ret < 0) {
148 dout(5) << "ERROR: lists_keys_next(): " << cpp_strerror(http_ret)
149 << dendl;
150 return;
151 }
152
153 for (list<string>::iterator iter = keys.begin(); iter != keys.end();
154 ++iter) {
155 s->formatter->dump_string("key", *iter);
156 ++count;
157 }
158
159 } while (truncated && left > 0);
160
161 s->formatter->close_section();
162
163 if (extended_response) {
164 encode_json("truncated", truncated, s->formatter);
165 encode_json("count", count, s->formatter);
166 if (truncated) {
167 string esc_marker =
168 rgw::to_base64(meta_mgr->get_marker(handle));
169 encode_json("marker", esc_marker, s->formatter);
170 }
171 s->formatter->close_section();
172 }
173 meta_mgr->list_keys_complete(handle);
174
175 http_ret = 0;
176 }
177
178 int RGWOp_Metadata_Put::get_data(bufferlist& bl) {
179 size_t cl = 0;
180 char *data;
181 int read_len;
182
183 if (s->length)
184 cl = atoll(s->length);
185 if (cl) {
186 data = (char *)malloc(cl + 1);
187 if (!data) {
188 return -ENOMEM;
189 }
190 read_len = recv_body(s, data, cl);
191 if (cl != (size_t)read_len) {
192 dout(10) << "recv_body incomplete" << dendl;
193 }
194 if (read_len < 0) {
195 free(data);
196 return read_len;
197 }
198 bl.append(data, read_len);
199 } else {
200 int chunk_size = CEPH_PAGE_SIZE;
201 const char *enc = s->info.env->get("HTTP_TRANSFER_ENCODING");
202 if (!enc || strcmp(enc, "chunked")) {
203 return -ERR_LENGTH_REQUIRED;
204 }
205 data = (char *)malloc(chunk_size);
206 if (!data) {
207 return -ENOMEM;
208 }
209 do {
210 read_len = recv_body(s, data, chunk_size);
211 if (read_len < 0) {
212 free(data);
213 return read_len;
214 }
215 bl.append(data, read_len);
216 } while (read_len == chunk_size);
217 }
218
219 free(data);
220 return 0;
221 }
222
223 static bool string_to_sync_type(const string& sync_string,
224 RGWMDLogSyncType& type) {
225 if (sync_string.compare("update-by-version") == 0)
226 type = APPLY_UPDATES;
227 else if (sync_string.compare("update-by-timestamp") == 0)
228 type = APPLY_NEWER;
229 else if (sync_string.compare("always") == 0)
230 type = APPLY_ALWAYS;
231 else
232 return false;
233 return true;
234 }
235
236 void RGWOp_Metadata_Put::execute() {
237 bufferlist bl;
238 string metadata_key;
239
240 http_ret = get_data(bl);
241 if (http_ret < 0) {
242 return;
243 }
244
245 http_ret = do_aws4_auth_completion();
246 if (http_ret < 0) {
247 return;
248 }
249
250 frame_metadata_key(s, metadata_key);
251
252 RGWMDLogSyncType sync_type = RGWMDLogSyncType::APPLY_ALWAYS;
253
254 bool mode_exists = false;
255 string mode_string = s->info.args.get("update-type", &mode_exists);
256 if (mode_exists) {
257 bool parsed = string_to_sync_type(mode_string,
258 sync_type);
259 if (!parsed) {
260 http_ret = -EINVAL;
261 return;
262 }
263 }
264
265 http_ret = store->ctl()->meta.mgr->put(metadata_key, bl, s->yield, sync_type,
266 &ondisk_version);
267 if (http_ret < 0) {
268 dout(5) << "ERROR: can't put key: " << cpp_strerror(http_ret) << dendl;
269 return;
270 }
271 // translate internal codes into return header
272 if (http_ret == STATUS_NO_APPLY)
273 update_status = "skipped";
274 else if (http_ret == STATUS_APPLIED)
275 update_status = "applied";
276 }
277
278 void RGWOp_Metadata_Put::send_response() {
279 int http_return_code = http_ret;
280 if ((http_ret == STATUS_NO_APPLY) || (http_ret == STATUS_APPLIED))
281 http_return_code = STATUS_NO_CONTENT;
282 set_req_state_err(s, http_return_code);
283 dump_errno(s);
284 stringstream ver_stream;
285 ver_stream << "ver:" << ondisk_version.ver
286 <<",tag:" << ondisk_version.tag;
287 dump_header_if_nonempty(s, "RGWX_UPDATE_STATUS", update_status);
288 dump_header_if_nonempty(s, "RGWX_UPDATE_VERSION", ver_stream.str());
289 end_header(s);
290 }
291
292 void RGWOp_Metadata_Delete::execute() {
293 string metadata_key;
294
295 frame_metadata_key(s, metadata_key);
296 http_ret = store->ctl()->meta.mgr->remove(metadata_key, s->yield);
297 if (http_ret < 0) {
298 dout(5) << "ERROR: can't remove key: " << cpp_strerror(http_ret) << dendl;
299 return;
300 }
301 http_ret = 0;
302 }
303
304 RGWOp *RGWHandler_Metadata::op_get() {
305 if (s->info.args.exists("myself"))
306 return new RGWOp_Metadata_Get_Myself;
307 if (s->info.args.exists("key"))
308 return new RGWOp_Metadata_Get;
309 else
310 return new RGWOp_Metadata_List;
311 }
312
313 RGWOp *RGWHandler_Metadata::op_put() {
314 return new RGWOp_Metadata_Put;
315 }
316
317 RGWOp *RGWHandler_Metadata::op_delete() {
318 return new RGWOp_Metadata_Delete;
319 }
320