]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_metadata.cc
795382dbc91d8f2d0617ed6ce470be06d60c2993
[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 "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"
29
30 #define dout_context g_ceph_context
31 #define dout_subsys ceph_subsys_rgw
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(optional_yield y) {
53 string metadata_key;
54
55 frame_metadata_key(s, metadata_key);
56
57 auto meta_mgr = store->ctl()->meta.mgr;
58
59 /* Get keys */
60 op_ret = meta_mgr->get(metadata_key, s->formatter, s->yield);
61 if (op_ret < 0) {
62 dout(5) << "ERROR: can't get key: " << cpp_strerror(op_ret) << dendl;
63 return;
64 }
65
66 op_ret = 0;
67 }
68
69 void RGWOp_Metadata_Get_Myself::execute(optional_yield y) {
70 string owner_id;
71
72 owner_id = s->owner.get_id().to_str();
73 s->info.args.append("key", owner_id);
74
75 return RGWOp_Metadata_Get::execute(y);
76 }
77
78 void RGWOp_Metadata_List::execute(optional_yield y) {
79 string marker;
80 ldout(s->cct, 16) << __func__
81 << " raw marker " << s->info.args.get("marker")
82 << dendl;
83
84 try {
85 marker = s->info.args.get("marker");
86 if (!marker.empty()) {
87 marker = rgw::from_base64(marker);
88 }
89 ldout(s->cct, 16) << __func__
90 << " marker " << marker << dendl;
91 } catch (...) {
92 marker = std::string("");
93 }
94
95 bool max_entries_specified;
96 string max_entries_str =
97 s->info.args.get("max-entries", &max_entries_specified);
98
99 bool extended_response = (max_entries_specified); /* for backward compatibility, if max-entries is not specified
100 we will send the old response format */
101 uint64_t max_entries = 0;
102
103 if (max_entries_specified) {
104 string err;
105 max_entries = (unsigned)strict_strtol(max_entries_str.c_str(), 10, &err);
106 if (!err.empty()) {
107 dout(5) << "Error parsing max-entries " << max_entries_str << dendl;
108 op_ret = -EINVAL;
109 return;
110 }
111 }
112
113 string metadata_key;
114
115 frame_metadata_key(s, metadata_key);
116 /* List keys */
117 void *handle;
118 int max = 1000;
119
120 /* example markers:
121 marker = "3:b55a9110:root::bu_9:head";
122 marker = "3:b9a8b2a6:root::sorry_janefonda_890:head";
123 marker = "3:bf885d8f:root::sorry_janefonda_665:head";
124 */
125
126 op_ret = store->ctl()->meta.mgr->list_keys_init(metadata_key, marker, &handle);
127 if (op_ret < 0) {
128 dout(5) << "ERROR: can't get key: " << cpp_strerror(op_ret) << dendl;
129 return;
130 }
131
132 bool truncated;
133 uint64_t count = 0;
134
135 if (extended_response) {
136 s->formatter->open_object_section("result");
137 }
138
139 s->formatter->open_array_section("keys");
140
141 auto meta_mgr = store->ctl()->meta.mgr;
142
143 uint64_t left;
144 do {
145 list<string> keys;
146 left = (max_entries_specified ? max_entries - count : max);
147 op_ret = meta_mgr->list_keys_next(handle, left, keys, &truncated);
148 if (op_ret < 0) {
149 dout(5) << "ERROR: lists_keys_next(): " << cpp_strerror(op_ret)
150 << dendl;
151 return;
152 }
153
154 for (list<string>::iterator iter = keys.begin(); iter != keys.end();
155 ++iter) {
156 s->formatter->dump_string("key", *iter);
157 ++count;
158 }
159
160 } while (truncated && left > 0);
161
162 s->formatter->close_section();
163
164 if (extended_response) {
165 encode_json("truncated", truncated, s->formatter);
166 encode_json("count", count, s->formatter);
167 if (truncated) {
168 string esc_marker =
169 rgw::to_base64(meta_mgr->get_marker(handle));
170 encode_json("marker", esc_marker, s->formatter);
171 }
172 s->formatter->close_section();
173 }
174 meta_mgr->list_keys_complete(handle);
175
176 op_ret = 0;
177 }
178
179 int RGWOp_Metadata_Put::get_data(bufferlist& bl) {
180 size_t cl = 0;
181 char *data;
182 int read_len;
183
184 if (s->length)
185 cl = atoll(s->length);
186 if (cl) {
187 data = (char *)malloc(cl + 1);
188 if (!data) {
189 return -ENOMEM;
190 }
191 read_len = recv_body(s, data, cl);
192 if (cl != (size_t)read_len) {
193 dout(10) << "recv_body incomplete" << dendl;
194 }
195 if (read_len < 0) {
196 free(data);
197 return read_len;
198 }
199 bl.append(data, read_len);
200 } else {
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;
205 }
206 data = (char *)malloc(chunk_size);
207 if (!data) {
208 return -ENOMEM;
209 }
210 do {
211 read_len = recv_body(s, data, chunk_size);
212 if (read_len < 0) {
213 free(data);
214 return read_len;
215 }
216 bl.append(data, read_len);
217 } while (read_len == chunk_size);
218 }
219
220 free(data);
221 return 0;
222 }
223
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)
229 type = APPLY_NEWER;
230 else if (sync_string.compare("always") == 0)
231 type = APPLY_ALWAYS;
232 else
233 return false;
234 return true;
235 }
236
237 void RGWOp_Metadata_Put::execute(optional_yield y) {
238 bufferlist bl;
239 string metadata_key;
240
241 op_ret = get_data(bl);
242 if (op_ret < 0) {
243 return;
244 }
245
246 op_ret = do_aws4_auth_completion();
247 if (op_ret < 0) {
248 return;
249 }
250
251 frame_metadata_key(s, metadata_key);
252
253 RGWMDLogSyncType sync_type = RGWMDLogSyncType::APPLY_ALWAYS;
254
255 bool mode_exists = false;
256 string mode_string = s->info.args.get("update-type", &mode_exists);
257 if (mode_exists) {
258 bool parsed = string_to_sync_type(mode_string,
259 sync_type);
260 if (!parsed) {
261 op_ret = -EINVAL;
262 return;
263 }
264 }
265
266 op_ret = store->ctl()->meta.mgr->put(metadata_key, bl, s->yield, sync_type,
267 false, &ondisk_version);
268 if (op_ret < 0) {
269 dout(5) << "ERROR: can't put key: " << cpp_strerror(op_ret) << dendl;
270 return;
271 }
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";
277 }
278
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);
284 dump_errno(s);
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());
290 end_header(s);
291 }
292
293 void RGWOp_Metadata_Delete::execute(optional_yield y) {
294 string metadata_key;
295
296 frame_metadata_key(s, metadata_key);
297 op_ret = store->ctl()->meta.mgr->remove(metadata_key, s->yield);
298 if (op_ret < 0) {
299 dout(5) << "ERROR: can't remove key: " << cpp_strerror(op_ret) << dendl;
300 return;
301 }
302 op_ret = 0;
303 }
304
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;
310 else
311 return new RGWOp_Metadata_List;
312 }
313
314 RGWOp *RGWHandler_Metadata::op_put() {
315 return new RGWOp_Metadata_Put;
316 }
317
318 RGWOp *RGWHandler_Metadata::op_delete() {
319 return new RGWOp_Metadata_Delete;
320 }
321