]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_metadata.cc
add subtree-ish sources for 12.0.3
[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 "include/assert.h"
24
25 #define dout_context g_ceph_context
26 #define dout_subsys ceph_subsys_rgw
27
28 const string RGWOp_Metadata_Get::name() {
29 return "get_metadata";
30 }
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 /* Get keys */
57 http_ret = store->meta_mgr->get(metadata_key, s->formatter);
58 if (http_ret < 0) {
59 dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl;
60 return;
61 }
62
63 http_ret = 0;
64 }
65
66 const string RGWOp_Metadata_List::name() {
67 return "list_metadata";
68 }
69
70 void RGWOp_Metadata_List::execute() {
71 string metadata_key;
72
73 frame_metadata_key(s, metadata_key);
74 /* List keys */
75 void *handle;
76 int max = 1000;
77
78 http_ret = store->meta_mgr->list_keys_init(metadata_key, &handle);
79 if (http_ret < 0) {
80 dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl;
81 return;
82 }
83
84 bool truncated;
85
86 s->formatter->open_array_section("keys");
87
88 do {
89 list<string> keys;
90 http_ret = store->meta_mgr->list_keys_next(handle, max, keys, &truncated);
91 if (http_ret < 0) {
92 dout(5) << "ERROR: lists_keys_next(): " << cpp_strerror(http_ret)
93 << dendl;
94 return;
95 }
96
97 for (list<string>::iterator iter = keys.begin(); iter != keys.end();
98 ++iter) {
99 s->formatter->dump_string("key", *iter);
100 }
101
102 } while (truncated);
103
104 s->formatter->close_section();
105
106 store->meta_mgr->list_keys_complete(handle);
107
108 http_ret = 0;
109 }
110
111 int RGWOp_Metadata_Put::get_data(bufferlist& bl) {
112 size_t cl = 0;
113 char *data;
114 int read_len;
115
116 if (s->length)
117 cl = atoll(s->length);
118 if (cl) {
119 data = (char *)malloc(cl + 1);
120 if (!data) {
121 return -ENOMEM;
122 }
123 read_len = recv_body(s, data, cl);
124 if (cl != (size_t)read_len) {
125 dout(10) << "recv_body incomplete" << dendl;
126 }
127 if (read_len < 0) {
128 free(data);
129 return read_len;
130 }
131 bl.append(data, read_len);
132 } else {
133 int chunk_size = CEPH_PAGE_SIZE;
134 const char *enc = s->info.env->get("HTTP_TRANSFER_ENCODING");
135 if (!enc || strcmp(enc, "chunked")) {
136 return -ERR_LENGTH_REQUIRED;
137 }
138 data = (char *)malloc(chunk_size);
139 if (!data) {
140 return -ENOMEM;
141 }
142 do {
143 read_len = recv_body(s, data, chunk_size);
144 if (read_len < 0) {
145 free(data);
146 return read_len;
147 }
148 bl.append(data, read_len);
149 } while (read_len == chunk_size);
150 }
151
152 free(data);
153 return 0;
154 }
155
156 void RGWOp_Metadata_Put::execute() {
157 bufferlist bl;
158 string metadata_key;
159
160 http_ret = get_data(bl);
161 if (http_ret < 0) {
162 return;
163 }
164
165 if (s->aws4_auth_needs_complete) {
166 http_ret = do_aws4_auth_completion();
167 if (http_ret < 0) {
168 return;
169 }
170 }
171
172 frame_metadata_key(s, metadata_key);
173
174 RGWMetadataHandler::sync_type_t sync_type = RGWMetadataHandler::APPLY_ALWAYS;
175
176 bool mode_exists = false;
177 string mode_string = s->info.args.get("update-type", &mode_exists);
178 if (mode_exists) {
179 bool parsed = RGWMetadataHandler::string_to_sync_type(mode_string,
180 sync_type);
181 if (!parsed) {
182 http_ret = -EINVAL;
183 return;
184 }
185 }
186
187 http_ret = store->meta_mgr->put(metadata_key, bl, sync_type,
188 &ondisk_version);
189 if (http_ret < 0) {
190 dout(5) << "ERROR: can't put key: " << cpp_strerror(http_ret) << dendl;
191 return;
192 }
193 // translate internal codes into return header
194 if (http_ret == STATUS_NO_APPLY)
195 update_status = "skipped";
196 else if (http_ret == STATUS_APPLIED)
197 update_status = "applied";
198 }
199
200 void RGWOp_Metadata_Put::send_response() {
201 int http_return_code = http_ret;
202 if ((http_ret == STATUS_NO_APPLY) || (http_ret == STATUS_APPLIED))
203 http_return_code = STATUS_NO_CONTENT;
204 set_req_state_err(s, http_return_code);
205 dump_errno(s);
206 stringstream ver_stream;
207 ver_stream << "ver:" << ondisk_version.ver
208 <<",tag:" << ondisk_version.tag;
209 dump_header_if_nonempty(s, "RGWX_UPDATE_STATUS", update_status);
210 dump_header_if_nonempty(s, "RGWX_UPDATE_VERSION", ver_stream.str());
211 end_header(s);
212 }
213
214 void RGWOp_Metadata_Delete::execute() {
215 string metadata_key;
216
217 frame_metadata_key(s, metadata_key);
218 http_ret = store->meta_mgr->remove(metadata_key);
219 if (http_ret < 0) {
220 dout(5) << "ERROR: can't remove key: " << cpp_strerror(http_ret) << dendl;
221 return;
222 }
223 http_ret = 0;
224 }
225
226 void RGWOp_Metadata_Lock::execute() {
227 string duration_str, lock_id;
228 string metadata_key;
229
230 frame_metadata_key(s, metadata_key);
231
232 http_ret = 0;
233
234 duration_str = s->info.args.get("length");
235 lock_id = s->info.args.get("lock_id");
236
237 if ((!s->info.args.exists("key")) ||
238 (duration_str.empty()) ||
239 lock_id.empty()) {
240 dout(5) << "Error invalid parameter list" << dendl;
241 http_ret = -EINVAL;
242 return;
243 }
244
245 int dur;
246 string err;
247
248 dur = strict_strtol(duration_str.c_str(), 10, &err);
249 if (!err.empty() || dur <= 0) {
250 dout(5) << "invalid length param " << duration_str << dendl;
251 http_ret = -EINVAL;
252 return;
253 }
254 http_ret = store->meta_mgr->lock_exclusive(metadata_key, make_timespan(dur), lock_id);
255 if (http_ret == -EBUSY)
256 http_ret = -ERR_LOCKED;
257 }
258
259 void RGWOp_Metadata_Unlock::execute() {
260 string lock_id;
261 string metadata_key;
262
263 frame_metadata_key(s, metadata_key);
264
265 http_ret = 0;
266
267 lock_id = s->info.args.get("lock_id");
268
269 if ((!s->info.args.exists("key")) ||
270 lock_id.empty()) {
271 dout(5) << "Error invalid parameter list" << dendl;
272 http_ret = -EINVAL;
273 return;
274 }
275
276 http_ret = store->meta_mgr->unlock(metadata_key, lock_id);
277 }
278
279 RGWOp *RGWHandler_Metadata::op_get() {
280 if (s->info.args.exists("key"))
281 return new RGWOp_Metadata_Get;
282 else
283 return new RGWOp_Metadata_List;
284 }
285
286 RGWOp *RGWHandler_Metadata::op_put() {
287 return new RGWOp_Metadata_Put;
288 }
289
290 RGWOp *RGWHandler_Metadata::op_delete() {
291 return new RGWOp_Metadata_Delete;
292 }
293
294 RGWOp *RGWHandler_Metadata::op_post() {
295 if (s->info.args.exists("lock"))
296 return new RGWOp_Metadata_Lock;
297 else if (s->info.args.exists("unlock"))
298 return new RGWOp_Metadata_Unlock;
299
300 return NULL;
301 }