summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_rest_metadata.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/rgw/rgw_rest_metadata.cc
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/rgw/rgw_rest_metadata.cc')
-rw-r--r--src/rgw/rgw_rest_metadata.cc363
1 files changed, 363 insertions, 0 deletions
diff --git a/src/rgw/rgw_rest_metadata.cc b/src/rgw/rgw_rest_metadata.cc
new file mode 100644
index 00000000..0f81d54c
--- /dev/null
+++ b/src/rgw/rgw_rest_metadata.cc
@@ -0,0 +1,363 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "include/page.h"
+
+#include "rgw_rest.h"
+#include "rgw_op.h"
+#include "rgw_rest_s3.h"
+#include "rgw_rest_metadata.h"
+#include "rgw_client_io.h"
+#include "common/errno.h"
+#include "common/strtol.h"
+#include "rgw/rgw_b64.h"
+#include "include/ceph_assert.h"
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_rgw
+
+static inline void frame_metadata_key(req_state *s, string& out) {
+ bool exists;
+ string key = s->info.args.get("key", &exists);
+
+ string section;
+ if (!s->init_state.url_bucket.empty()) {
+ section = s->init_state.url_bucket;
+ } else {
+ section = key;
+ key.clear();
+ }
+
+ out = section;
+
+ if (!key.empty()) {
+ out += string(":") + key;
+ }
+}
+
+void RGWOp_Metadata_Get::execute() {
+ string metadata_key;
+
+ frame_metadata_key(s, metadata_key);
+
+ /* Get keys */
+ http_ret = store->meta_mgr->get(metadata_key, s->formatter);
+ if (http_ret < 0) {
+ dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl;
+ return;
+ }
+
+ http_ret = 0;
+}
+
+void RGWOp_Metadata_Get_Myself::execute() {
+ string owner_id;
+
+ owner_id = s->owner.get_id().to_str();
+ s->info.args.append("key", owner_id);
+
+ return RGWOp_Metadata_Get::execute();
+}
+
+void RGWOp_Metadata_List::execute() {
+ string marker;
+ ldout(s->cct, 16) << __func__
+ << " raw marker " << s->info.args.get("marker")
+ << dendl;
+
+ try {
+ marker = s->info.args.get("marker");
+ if (!marker.empty()) {
+ marker = rgw::from_base64(marker);
+ }
+ ldout(s->cct, 16) << __func__
+ << " marker " << marker << dendl;
+ } catch (...) {
+ marker = std::string("");
+ }
+
+ bool max_entries_specified;
+ string max_entries_str =
+ s->info.args.get("max-entries", &max_entries_specified);
+
+ bool extended_response = (max_entries_specified); /* for backward compatibility, if max-entries is not specified
+ we will send the old response format */
+ uint64_t max_entries = 0;
+
+ if (max_entries_specified) {
+ string err;
+ max_entries = (unsigned)strict_strtol(max_entries_str.c_str(), 10, &err);
+ if (!err.empty()) {
+ dout(5) << "Error parsing max-entries " << max_entries_str << dendl;
+ http_ret = -EINVAL;
+ return;
+ }
+ }
+
+ string metadata_key;
+
+ frame_metadata_key(s, metadata_key);
+ /* List keys */
+ void *handle;
+ int max = 1000;
+
+ /* example markers:
+ marker = "3:b55a9110:root::bu_9:head";
+ marker = "3:b9a8b2a6:root::sorry_janefonda_890:head";
+ marker = "3:bf885d8f:root::sorry_janefonda_665:head";
+ */
+
+ http_ret = store->meta_mgr->list_keys_init(metadata_key, marker, &handle);
+ if (http_ret < 0) {
+ dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl;
+ return;
+ }
+
+ bool truncated;
+ uint64_t count = 0;
+
+ if (extended_response) {
+ s->formatter->open_object_section("result");
+ }
+
+ s->formatter->open_array_section("keys");
+
+ uint64_t left;
+ do {
+ list<string> keys;
+ left = (max_entries_specified ? max_entries - count : max);
+ http_ret = store->meta_mgr->list_keys_next(handle, left, keys, &truncated);
+ if (http_ret < 0) {
+ dout(5) << "ERROR: lists_keys_next(): " << cpp_strerror(http_ret)
+ << dendl;
+ return;
+ }
+
+ for (list<string>::iterator iter = keys.begin(); iter != keys.end();
+ ++iter) {
+ s->formatter->dump_string("key", *iter);
+ ++count;
+ }
+
+ } while (truncated && left > 0);
+
+ s->formatter->close_section();
+
+ if (extended_response) {
+ encode_json("truncated", truncated, s->formatter);
+ encode_json("count", count, s->formatter);
+ if (truncated) {
+ string esc_marker =
+ rgw::to_base64(store->meta_mgr->get_marker(handle));
+ encode_json("marker", esc_marker, s->formatter);
+ }
+ s->formatter->close_section();
+ }
+ store->meta_mgr->list_keys_complete(handle);
+
+ http_ret = 0;
+}
+
+int RGWOp_Metadata_Put::get_data(bufferlist& bl) {
+ size_t cl = 0;
+ char *data;
+ int read_len;
+
+ if (s->length)
+ cl = atoll(s->length);
+ if (cl) {
+ data = (char *)malloc(cl + 1);
+ if (!data) {
+ return -ENOMEM;
+ }
+ read_len = recv_body(s, data, cl);
+ if (cl != (size_t)read_len) {
+ dout(10) << "recv_body incomplete" << dendl;
+ }
+ if (read_len < 0) {
+ free(data);
+ return read_len;
+ }
+ bl.append(data, read_len);
+ } else {
+ int chunk_size = CEPH_PAGE_SIZE;
+ const char *enc = s->info.env->get("HTTP_TRANSFER_ENCODING");
+ if (!enc || strcmp(enc, "chunked")) {
+ return -ERR_LENGTH_REQUIRED;
+ }
+ data = (char *)malloc(chunk_size);
+ if (!data) {
+ return -ENOMEM;
+ }
+ do {
+ read_len = recv_body(s, data, chunk_size);
+ if (read_len < 0) {
+ free(data);
+ return read_len;
+ }
+ bl.append(data, read_len);
+ } while (read_len == chunk_size);
+ }
+
+ free(data);
+ return 0;
+}
+
+void RGWOp_Metadata_Put::execute() {
+ bufferlist bl;
+ string metadata_key;
+
+ http_ret = get_data(bl);
+ if (http_ret < 0) {
+ return;
+ }
+
+ http_ret = do_aws4_auth_completion();
+ if (http_ret < 0) {
+ return;
+ }
+
+ frame_metadata_key(s, metadata_key);
+
+ RGWMetadataHandler::sync_type_t sync_type = RGWMetadataHandler::APPLY_ALWAYS;
+
+ bool mode_exists = false;
+ string mode_string = s->info.args.get("update-type", &mode_exists);
+ if (mode_exists) {
+ bool parsed = RGWMetadataHandler::string_to_sync_type(mode_string,
+ sync_type);
+ if (!parsed) {
+ http_ret = -EINVAL;
+ return;
+ }
+ }
+
+ http_ret = store->meta_mgr->put(metadata_key, bl, sync_type,
+ &ondisk_version);
+ if (http_ret < 0) {
+ dout(5) << "ERROR: can't put key: " << cpp_strerror(http_ret) << dendl;
+ return;
+ }
+ // translate internal codes into return header
+ if (http_ret == STATUS_NO_APPLY)
+ update_status = "skipped";
+ else if (http_ret == STATUS_APPLIED)
+ update_status = "applied";
+}
+
+void RGWOp_Metadata_Put::send_response() {
+ int http_return_code = http_ret;
+ if ((http_ret == STATUS_NO_APPLY) || (http_ret == STATUS_APPLIED))
+ http_return_code = STATUS_NO_CONTENT;
+ set_req_state_err(s, http_return_code);
+ dump_errno(s);
+ stringstream ver_stream;
+ ver_stream << "ver:" << ondisk_version.ver
+ <<",tag:" << ondisk_version.tag;
+ dump_header_if_nonempty(s, "RGWX_UPDATE_STATUS", update_status);
+ dump_header_if_nonempty(s, "RGWX_UPDATE_VERSION", ver_stream.str());
+ end_header(s);
+}
+
+void RGWOp_Metadata_Delete::execute() {
+ string metadata_key;
+
+ frame_metadata_key(s, metadata_key);
+ http_ret = store->meta_mgr->remove(metadata_key);
+ if (http_ret < 0) {
+ dout(5) << "ERROR: can't remove key: " << cpp_strerror(http_ret) << dendl;
+ return;
+ }
+ http_ret = 0;
+}
+
+void RGWOp_Metadata_Lock::execute() {
+ string duration_str, lock_id;
+ string metadata_key;
+
+ frame_metadata_key(s, metadata_key);
+
+ http_ret = 0;
+
+ duration_str = s->info.args.get("length");
+ lock_id = s->info.args.get("lock_id");
+
+ if ((!s->info.args.exists("key")) ||
+ (duration_str.empty()) ||
+ lock_id.empty()) {
+ dout(5) << "Error invalid parameter list" << dendl;
+ http_ret = -EINVAL;
+ return;
+ }
+
+ int dur;
+ string err;
+
+ dur = strict_strtol(duration_str.c_str(), 10, &err);
+ if (!err.empty() || dur <= 0) {
+ dout(5) << "invalid length param " << duration_str << dendl;
+ http_ret = -EINVAL;
+ return;
+ }
+ http_ret = store->meta_mgr->lock_exclusive(metadata_key, make_timespan(dur), lock_id);
+ if (http_ret == -EBUSY)
+ http_ret = -ERR_LOCKED;
+}
+
+void RGWOp_Metadata_Unlock::execute() {
+ string lock_id;
+ string metadata_key;
+
+ frame_metadata_key(s, metadata_key);
+
+ http_ret = 0;
+
+ lock_id = s->info.args.get("lock_id");
+
+ if ((!s->info.args.exists("key")) ||
+ lock_id.empty()) {
+ dout(5) << "Error invalid parameter list" << dendl;
+ http_ret = -EINVAL;
+ return;
+ }
+
+ http_ret = store->meta_mgr->unlock(metadata_key, lock_id);
+}
+
+RGWOp *RGWHandler_Metadata::op_get() {
+ if (s->info.args.exists("myself"))
+ return new RGWOp_Metadata_Get_Myself;
+ if (s->info.args.exists("key"))
+ return new RGWOp_Metadata_Get;
+ else
+ return new RGWOp_Metadata_List;
+}
+
+RGWOp *RGWHandler_Metadata::op_put() {
+ return new RGWOp_Metadata_Put;
+}
+
+RGWOp *RGWHandler_Metadata::op_delete() {
+ return new RGWOp_Metadata_Delete;
+}
+
+RGWOp *RGWHandler_Metadata::op_post() {
+ if (s->info.args.exists("lock"))
+ return new RGWOp_Metadata_Lock;
+ else if (s->info.args.exists("unlock"))
+ return new RGWOp_Metadata_Unlock;
+
+ return NULL;
+}