From 35cd5f3c945211bea637d07dc4c435b50deb112a Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 13 Sep 2012 18:08:06 -0700 Subject: [PATCH] rgw: clean up ops initialization, completion ops init() was a reminiscent of an old design. Since we're allocating new op for every request we can just init everything in the constructor. We now add a new complete() stage in request processing. By default complete() will call send_response(). Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_common.cc | 9 +++ src/rgw/rgw_main.cc | 1 + src/rgw/rgw_op.cc | 93 ++++++++------------------ src/rgw/rgw_op.h | 148 ++++++++++++++---------------------------- src/rgw/rgw_rest.cc | 90 ++++++++++--------------- 5 files changed, 118 insertions(+), 223 deletions(-) diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index fbb446e8254f9..f35ef4a3ae949 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -94,6 +94,15 @@ req_state::req_state(CephContext *_cct, struct RGWEnv *e) : cct(_cct), os_auth_t object_acl = NULL; expect_cont = false; + bucket_name = NULL; + object = NULL; + + header_ended = false; + bytes_sent = 0; + bytes_received = 0; + obj_size = 0; + prot_flags = 0; + os_auth_token = NULL; os_user = NULL; os_groups = NULL; diff --git a/src/rgw/rgw_main.cc b/src/rgw/rgw_main.cc index 93bae66fe2e96..e4b81a63bf6f2 100644 --- a/src/rgw/rgw_main.cc +++ b/src/rgw/rgw_main.cc @@ -317,6 +317,7 @@ void RGWProcess::handle_request(RGWRequest *req) req->log(s, "executing"); op->execute(); + op->complete(); done: rgw_log_op(s, (op ? op->name() : "unknown")); diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index dd9a535fcde42..0bb8c7fd50368 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -642,7 +642,7 @@ void RGWListBuckets::execute() { ret = get_params(); if (ret < 0) - goto done; + return; ret = rgw_read_user_buckets(s->user.user_id, buckets, !!(s->prot_flags & RGW_REST_SWIFT)); if (ret < 0) { @@ -659,9 +659,6 @@ void RGWListBuckets::execute() */ } - -done: - send_response(); } int RGWStatAccount::verify_permission() @@ -698,8 +695,6 @@ void RGWStatAccount::execute() } buckets_count = m.size(); } - - send_response(); } int RGWStatBucket::verify_permission() @@ -728,8 +723,6 @@ void RGWStatBucket::execute() ret = -EINVAL; } } - - send_response(); } int RGWListBucket::verify_permission() @@ -765,13 +758,10 @@ void RGWListBucket::execute() ret = get_params(); if (ret < 0) - goto done; + return; ret = rgwstore->list_objects(s->bucket, max, prefix, delimiter, marker, objs, common_prefixes, !!(s->prot_flags & RGW_REST_SWIFT), no_ns, &is_truncated, NULL); - -done: - send_response(); } int RGWCreateBucket::verify_permission() @@ -804,14 +794,14 @@ void RGWCreateBucket::execute() ret = get_params(); if (ret < 0) - goto done; + return; s->bucket_owner = s->user.user_id; r = get_policy_from_attr(s->cct, s->obj_ctx, &old_policy, obj); if (r >= 0) { if (old_policy.get_owner().get_id().compare(s->user.user_id) != 0) { ret = -EEXIST; - goto done; + return; } } policy.encode(aclbl); @@ -826,7 +816,7 @@ void RGWCreateBucket::execute() ldout(s->cct, 20) << "rgw_create_bucket returned ret=" << ret << " bucket=" << s->bucket << dendl; if (ret && ret != -EEXIST) - goto done; + return; existed = (ret == -EEXIST); @@ -836,9 +826,6 @@ void RGWCreateBucket::execute() if (ret == -EEXIST) ret = -ERR_BUCKET_EXISTS; - -done: - send_response(); } int RGWDeleteBucket::verify_permission() @@ -863,8 +850,6 @@ void RGWDeleteBucket::execute() } } } - - send_response(); } struct put_obj_aio_info { @@ -1285,8 +1270,6 @@ done: dispose_processor(processor); perfcounter->finc(l_rgw_put_lat, (ceph_clock_now(s->cct) - s->time)); - send_response(); - return; } int RGWPutMetadata::verify_permission() @@ -1311,14 +1294,14 @@ void RGWPutMetadata::execute() ret = get_params(); if (ret < 0) - goto done; + return; rgw_get_request_metadata(s, attrs); /* check if obj exists, read orig attrs */ ret = get_obj_attrs(s, obj, orig_attrs, NULL); if (ret < 0) - goto done; + return; /* only remove meta attrs */ for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) { @@ -1335,9 +1318,6 @@ void RGWPutMetadata::execute() attrs[RGW_ATTR_ACL] = bl; } ret = rgwstore->set_attrs(s->obj_ctx, obj, attrs, &rmattrs); - -done: - send_response(); } int RGWDeleteObj::verify_permission() @@ -1356,8 +1336,6 @@ void RGWDeleteObj::execute() rgwstore->set_atomic(s->obj_ctx, obj); ret = rgwstore->delete_obj(s->obj_ctx, obj); } - - send_response(); } bool RGWCopyObj::parse_copy_location(const char *src, string& bucket_name, string& object) @@ -1479,7 +1457,7 @@ void RGWCopyObj::execute() rgw_obj src_obj, dst_obj; if (init_common() < 0) - goto done; + return; src_obj.init(src_bucket, src_object); dst_obj.init(dest_bucket, dest_object); @@ -1496,9 +1474,6 @@ void RGWCopyObj::execute() if_nomatch, replace_attrs, attrs, RGW_OBJ_CATEGORY_MAIN, &s->err); - -done: - send_response(); } int RGWGetACLs::verify_permission() @@ -1522,7 +1497,6 @@ void RGWGetACLs::execute() RGWAccessControlPolicy_S3 *s3policy = static_cast(acl); s3policy->to_xml(ss); acls = ss.str(); - send_response(); } @@ -1618,8 +1592,6 @@ void RGWPutACLs::execute() done: free(orig_data); free(new_data); - - send_response(); } int RGWInitMultipart::verify_permission() @@ -1637,10 +1609,10 @@ void RGWInitMultipart::execute() rgw_obj obj; if (get_params() < 0) - goto done; + return; ret = -EINVAL; if (!s->object) - goto done; + return; policy.encode(aclbl); @@ -1667,8 +1639,6 @@ void RGWInitMultipart::execute() // the meta object will be indexed with 0 size, we c ret = rgwstore->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL, NULL, NULL); } while (ret == -EEXIST); -done: - send_response(); } static int get_multiparts_info(struct req_state *s, string& meta_oid, map& parts, @@ -1766,27 +1736,27 @@ void RGWCompleteMultipart::execute() ret = get_params(); if (ret < 0) - goto done; + return; if (!data) { ret = -EINVAL; - goto done; + return; } if (!parser.init()) { ret = -EINVAL; - goto done; + return; } if (!parser.parse(data, len, 1)) { ret = -EINVAL; - goto done; + return; } parts = (RGWMultiCompleteUpload *)parser.find_first("CompleteMultipartUpload"); if (!parts) { ret = -EINVAL; - goto done; + return; } mp.init(s->object_str, upload_id); @@ -1798,7 +1768,7 @@ void RGWCompleteMultipart::execute() if (parts->parts.size() != obj_parts.size()) ret = -ERR_INVALID_PART; if (ret < 0) - goto done; + return; for (iter = parts->parts.begin(), obj_iter = obj_parts.begin(); iter != parts->parts.end() && obj_iter != obj_parts.end(); @@ -1807,13 +1777,13 @@ void RGWCompleteMultipart::execute() if (iter->first != (int)obj_iter->first) { ldout(s->cct, 0) << "NOTICE: parts num mismatch: next requested: " << iter->first << " next uploaded: " << obj_iter->first << dendl; ret = -ERR_INVALID_PART; - goto done; + return; } string part_etag = string_unquote(iter->second); if (part_etag.compare(obj_iter->second.etag) != 0) { ldout(s->cct, 0) << "NOTICE: etag mismatch: part: " << iter->first << " etag: " << iter->second << dendl; ret = -ERR_INVALID_PART; - goto done; + return; } hex_to_buf(obj_iter->second.etag.c_str(), etag, CEPH_CRYPTO_MD5_DIGESTSIZE); @@ -1834,7 +1804,7 @@ void RGWCompleteMultipart::execute() rgwstore->set_atomic(s->obj_ctx, target_obj); ret = rgwstore->put_obj_meta(s->obj_ctx, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL); if (ret < 0) - goto done; + return; for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) { string oid = mp.get_part(obj_iter->second.num); @@ -1857,14 +1827,11 @@ void RGWCompleteMultipart::execute() ret = rgwstore->put_obj_meta(s->obj_ctx, target_obj, ofs, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, &manifest); if (ret < 0) - goto done; + return; // remove the upload obj meta_obj.init_ns(s->bucket, meta_oid, mp_ns); rgwstore->delete_obj(s->obj_ctx, meta_obj); - -done: - send_response(); } int RGWAbortMultipart::verify_permission() @@ -1890,14 +1857,14 @@ void RGWAbortMultipart::execute() RGWMPObj mp; if (upload_id.empty() || s->object_str.empty()) - goto done; + return; mp.init(s->object_str, upload_id); meta_oid = mp.get_meta(); ret = get_multiparts_info(s, meta_oid, obj_parts, policy, attrs); if (ret < 0) - goto done; + return; for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) { string oid = mp.get_part(obj_iter->second.num); @@ -1905,7 +1872,7 @@ void RGWAbortMultipart::execute() obj.init_ns(s->bucket, oid, mp_ns); ret = rgwstore->delete_obj(s->obj_ctx, obj); if (ret < 0 && ret != -ENOENT) - goto done; + return; } // and also remove the metadata obj meta_obj.init_ns(s->bucket, meta_oid, mp_ns); @@ -1913,9 +1880,6 @@ void RGWAbortMultipart::execute() if (ret == -ENOENT) { ret = -ERR_NO_SUCH_BUCKET; } -done: - - send_response(); } int RGWListMultipart::verify_permission() @@ -1934,15 +1898,12 @@ void RGWListMultipart::execute() ret = get_params(); if (ret < 0) - goto done; + return; mp.init(s->object_str, upload_id); meta_oid = mp.get_meta(); ret = get_multiparts_info(s, meta_oid, parts, policy, xattrs); - -done: - send_response(); } int RGWListBucketMultiparts::verify_permission() @@ -1960,7 +1921,7 @@ void RGWListBucketMultiparts::execute() ret = get_params(); if (ret < 0) - goto done; + return; if (s->prot_flags & RGW_REST_SWIFT) { string path_args; @@ -1968,7 +1929,7 @@ void RGWListBucketMultiparts::execute() if (!path_args.empty()) { if (!delimiter.empty() || !prefix.empty()) { ret = -EINVAL; - goto done; + return; } prefix = path_args; delimiter="/"; @@ -1989,8 +1950,6 @@ void RGWListBucketMultiparts::execute() } next_marker = entry; } -done: - send_response(); } int RGWDeleteMultiObj::verify_permission() diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index d82d07b11401d..73aae396e1a7c 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -42,6 +42,8 @@ public: virtual bool prefetch_data() { return false; } virtual int verify_permission() = 0; virtual void execute() = 0; + virtual void send_response() {} + virtual void complete() { send_response(); } virtual const char *name() = 0; }; @@ -70,12 +72,7 @@ protected: int init_common(); public: - RGWGetObj() {} - - virtual bool prefetch_data() { return true; } - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWGetObj() { range_str = NULL; if_mod = NULL; if_unmod = NULL; @@ -91,12 +88,12 @@ public: unmod_time = 0; mod_ptr = NULL; unmod_ptr = NULL; - attrs.clear(); partial_content = false; ret = 0; + } + + virtual bool prefetch_data() { return true; } - /* get_data should not be initialized here! */ - } void set_get_data(bool get_data) { this->get_data = get_data; } @@ -119,16 +116,12 @@ protected: RGWUserBuckets buckets; public: - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); - buckets.clear(); - } RGWListBuckets() {} int verify_permission(); void execute(); - virtual int get_params()= 0; + virtual int get_params() = 0; virtual void send_response() = 0; virtual const char *name() { return "list_buckets"; } @@ -143,15 +136,13 @@ protected: uint64_t buckets_size_rounded; public: - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWStatAccount() { ret = 0; buckets_count = 0; buckets_objcount = 0; buckets_size = 0; buckets_size_rounded = 0; } - RGWStatAccount() {} int verify_permission(); void execute(); @@ -177,18 +168,9 @@ protected: int parse_max_keys(); public: - RGWListBucket() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); - prefix.clear(); - marker.clear(); - max_keys.clear(); - delimiter.clear(); + RGWListBucket() { max = 0; ret = 0; - objs.clear(); - common_prefixes.clear(); is_truncated = false; } int verify_permission(); @@ -205,12 +187,7 @@ protected: RGWBucketEnt bucket; public: - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); - ret = 0; - bucket.clear(); - } - RGWStatBucket() {} + RGWStatBucket() : ret(0) {} ~RGWStatBucket() {} int verify_permission(); @@ -226,14 +203,13 @@ protected: RGWAccessControlPolicy policy; public: - RGWCreateBucket() {} + RGWCreateBucket() : ret(0) {} int verify_permission(); void execute(); virtual void init(struct req_state *s, RGWHandler *h) { RGWOp::init(s, h); policy.set_ctx(s->cct); - ret = 0; } virtual int get_params() { return 0; } virtual void send_response() = 0; @@ -245,12 +221,10 @@ protected: int ret; public: - RGWDeleteBucket() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWDeleteBucket() { ret = 0; } + int verify_permission(); void execute(); @@ -288,17 +262,17 @@ protected: const char *obj_manifest; public: - RGWPutObj() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWPutObj() { ret = 0; ofs = 0; supplied_md5_b64 = NULL; supplied_etag = NULL; - etag = ""; chunked_upload = false; obj_manifest = NULL; + } + + virtual void init(struct req_state *s, RGWHandler *h) { + RGWOp::init(s, h); policy.set_ctx(s->cct); } @@ -322,12 +296,13 @@ protected: RGWAccessControlPolicy policy; public: - RGWPutMetadata() {} + RGWPutMetadata() { + has_policy = false; + ret = 0; + } virtual void init(struct req_state *s, RGWHandler *h) { RGWOp::init(s, h); - has_policy = false; - ret = 0; policy.set_ctx(s->cct); } int verify_permission(); @@ -343,12 +318,10 @@ protected: int ret; public: - RGWDeleteObj() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWDeleteObj() { ret = 0; } + int verify_permission(); void execute(); @@ -387,10 +360,7 @@ protected: bool parse_copy_location(const char *src, string& bucket_name, string& object); public: - RGWCopyObj() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWCopyObj() { if_mod = NULL; if_unmod = NULL; if_match = NULL; @@ -401,11 +371,12 @@ public: mod_ptr = NULL; unmod_ptr = NULL; ret = 0; - attrs.clear(); - src_bucket.clear(); - src_object.clear(); mtime = 0; replace_attrs = false; + } + + virtual void init(struct req_state *s, RGWHandler *h) { + RGWOp::init(s, h); dest_policy.set_ctx(s->cct); } int verify_permission(); @@ -423,13 +394,10 @@ protected: string acls; public: - RGWGetACLs() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWGetACLs() { ret = 0; - acls.clear(); } + int verify_permission(); void execute(); @@ -444,14 +412,12 @@ protected: char *data; public: - RGWPutACLs() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWPutACLs() { ret = 0; len = 0; data = NULL; } + int verify_permission(); void execute(); @@ -468,12 +434,12 @@ protected: RGWAccessControlPolicy policy; public: - RGWInitMultipart() {} + RGWInitMultipart() { + ret = 0; + } virtual void init(struct req_state *s, RGWHandler *h) { RGWOp::init(s, h); - ret = 0; - upload_id = ""; policy.set_ctx(s->cct); } int verify_permission(); @@ -493,16 +459,12 @@ protected: int len; public: - RGWCompleteMultipart() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWCompleteMultipart() { ret = 0; - upload_id = ""; - etag=""; data = NULL; len = 0; } + int verify_permission(); void execute(); @@ -516,12 +478,10 @@ protected: int ret; public: - RGWAbortMultipart() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWAbortMultipart() { ret = 0; } + int verify_permission(); void execute(); @@ -539,15 +499,14 @@ protected: RGWAccessControlPolicy policy; public: - RGWListMultipart() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWListMultipart() { ret = 0; - upload_id = ""; - parts.clear(); max_parts = 1000; marker = 0; + } + + virtual void init(struct req_state *s, RGWHandler *h) { + RGWOp::init(s, h); policy = RGWAccessControlPolicy(s->cct); } int verify_permission(); @@ -648,20 +607,11 @@ protected: int default_max; public: - RGWListBucketMultiparts() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); - prefix.clear(); - marker.clear(); - next_marker.clear(); + RGWListBucketMultiparts() { max_uploads = default_max; - delimiter.clear(); max_uploads = default_max; ret = 0; - uploads.clear(); is_truncated = false; - common_prefixes.clear(); } int verify_permission(); void execute(); @@ -684,15 +634,11 @@ protected: public: - RGWDeleteMultiObj() {} - - virtual void init(struct req_state *s, RGWHandler *h) { - RGWOp::init(s, h); + RGWDeleteMultiObj() { ret = 0; max_to_delete = 1000; len = 0; data = NULL; - bucket_name = ""; quiet = false; status_dumped = false; } diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index e5acb8d3ffbac..a7a028abaa1e8 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -462,16 +462,6 @@ static int init_entities_from_header(struct req_state *s) string req; string first; - s->bucket_name = NULL; - s->bucket.clear(); - s->object = NULL; - s->object_str = ""; - - s->header_ended = false; - s->bytes_sent = 0; - s->bytes_received = 0; - s->obj_size = 0; - /* this is the default, might change in a few lines */ s->format = RGW_FORMAT_XML; s->formatter = new XMLFormatter(false); @@ -656,7 +646,7 @@ struct str_len meta_prefixes[] = { STR_LEN_ENTRY("HTTP_X_AMZ"), STR_LEN_ENTRY("HTTP_X_CONTAINER"), {NULL, 0} }; -static int init_auth_info(struct req_state *s) +static int init_meta_info(struct req_state *s) { const char *p; @@ -810,10 +800,28 @@ static int validate_object_name(const char *object) return 0; } -int RGWHandler_REST::preprocess(struct req_state *s, FCGX_Request *fcgx) +static http_op op_from_method(const char *method) { - int ret = 0; + if (!method) + return OP_UNKNOWN; + if (strcmp(method, "GET") == 0) + return OP_GET; + if (strcmp(method, "PUT") == 0) + return OP_PUT; + if (strcmp(method, "DELETE") == 0) + return OP_DELETE; + if (strcmp(method, "HEAD") == 0) + return OP_HEAD; + if (strcmp(method, "POST") == 0) + return OP_POST; + if (strcmp(method, "COPY") == 0) + return OP_COPY; + + return OP_UNKNOWN; +} +int RGWHandler_REST::preprocess(struct req_state *s, FCGX_Request *fcgx) +{ s->fcgx = fcgx; s->request_uri = s->env->get("REQUEST_URI"); int pos = s->request_uri.find('?'); @@ -825,45 +833,22 @@ int RGWHandler_REST::preprocess(struct req_state *s, FCGX_Request *fcgx) s->method = s->env->get("REQUEST_METHOD"); s->host = s->env->get("HTTP_HOST"); s->length = s->env->get("CONTENT_LENGTH"); - s->content_type = s->env->get("CONTENT_TYPE"); - s->prot_flags = 0; - - if (!s->method) - s->op = OP_UNKNOWN; - else if (strcmp(s->method, "GET") == 0) - s->op = OP_GET; - else if (strcmp(s->method, "PUT") == 0) - s->op = OP_PUT; - else if (strcmp(s->method, "DELETE") == 0) - s->op = OP_DELETE; - else if (strcmp(s->method, "HEAD") == 0) - s->op = OP_HEAD; - else if (strcmp(s->method, "POST") == 0) - s->op = OP_POST; - else if (strcmp(s->method, "COPY") == 0) - s->op = OP_COPY; - else - s->op = OP_UNKNOWN; + if (s->length) { + if (*s->length == '\0') + return -EINVAL; + s->content_length = atoll(s->length); + } - ret = init_entities_from_header(s); - if (ret) - return ret; + s->content_type = s->env->get("CONTENT_TYPE"); + s->http_auth = s->env->get("HTTP_AUTHORIZATION"); - switch (s->op) { - case OP_PUT: - if (s->object && !s->args.sub_resource_exists("acl")) { - if (s->length && *s->length == '\0') - ret = -EINVAL; - } - if (s->length) - s->content_length = atoll(s->length); - else - s->content_length = 0; - break; - default: - break; + if (g_conf->rgw_print_continue) { + const char *expect = s->env->get("HTTP_EXPECT"); + s->expect_cont = (expect && !strcasecmp(expect, "100-continue")); } + s->op = op_from_method(s->method); + int ret = init_entities_from_header(s); if (ret) return ret; @@ -873,16 +858,11 @@ int RGWHandler_REST::preprocess(struct req_state *s, FCGX_Request *fcgx) ret = validate_object_name(s->object_str.c_str()); if (ret) return ret; - dout(10) << "s->object=" << (s->object ? s->object : "") << " s->bucket=" << (s->bucket_name ? s->bucket_name : "") << dendl; - init_auth_info(s); + dout(10) << "s->object=" << (s->object ? s->object : "") << " s->bucket=" << (s->bucket_name ? s->bucket_name : "") << dendl; - s->http_auth = s->env->get("HTTP_AUTHORIZATION"); + init_meta_info(s); - if (g_conf->rgw_print_continue) { - const char *expect = s->env->get("HTTP_EXPECT"); - s->expect_cont = (expect && !strcasecmp(expect, "100-continue")); - } return ret; } -- 2.39.5