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