rgw/rgw_formats.cc \
rgw/rgw_log.cc \
rgw/rgw_multi.cc \
+ rgw/rgw_multi_del.cc \
rgw/rgw_env.cc
librgw_a_CFLAGS = ${CRYPTO_CFLAGS} ${AM_CFLAGS}
librgw_a_CXXFLAGS = ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS}
rgw/rgw_formats.h\
rgw/rgw_log.h\
rgw/rgw_multi.h\
+ rgw/rgw_multi_del.h\
rgw/rgw_op.h\
rgw/rgw_swift.h\
rgw/rgw_swift_auth.h\
if ((name.compare("acl") == 0) ||
(name.compare("location") == 0) ||
+ (name.compare("delete") == 0) ||
(name.compare("uploads") == 0) ||
(name.compare("partNumber") == 0) ||
(name.compare("uploadId") == 0) ||
--- /dev/null
+#ifndef RGW_HTML_ERRORS_H_
+#define RGW_HTML_ERRORS_H_
+
+#include "rgw_common.h"
+
+struct rgw_html_errors {
+ int err_no;
+ int http_ret;
+ const char *s3_code;
+};
+
+const static struct rgw_html_errors RGW_HTML_ERRORS[] = {
+ { 0, 200, "" },
+ { STATUS_CREATED, 201, "Created" },
+ { STATUS_ACCEPTED, 202, "Accepted" },
+ { STATUS_NO_CONTENT, 204, "NoContent" },
+ { STATUS_PARTIAL_CONTENT, 206, "" },
+ { ERR_NOT_MODIFIED, 304, "NotModified" },
+ { EINVAL, 400, "InvalidArgument" },
+ { ERR_INVALID_REQUEST, 400, "InvalidRequest" },
+ { ERR_INVALID_DIGEST, 400, "InvalidDigest" },
+ { ERR_BAD_DIGEST, 400, "BadDigest" },
+ { ERR_INVALID_BUCKET_NAME, 400, "InvalidBucketName" },
+ { ERR_INVALID_OBJECT_NAME, 400, "InvalidObjectName" },
+ { ERR_UNRESOLVABLE_EMAIL, 400, "UnresolvableGrantByEmailAddress" },
+ { ERR_INVALID_PART, 400, "InvalidPart" },
+ { ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" },
+ { ERR_REQUEST_TIMEOUT, 400, "RequestTimeout" },
+ { ERR_TOO_LARGE, 400, "EntityTooLarge" },
+ { ERR_TOO_MANY_BUCKETS, 400, "TooManyBuckets" },
+ { ERR_LENGTH_REQUIRED, 411, "MissingContentLength" },
+ { EACCES, 403, "AccessDenied" },
+ { EPERM, 403, "AccessDenied" },
+ { ERR_USER_SUSPENDED, 403, "UserSuspended" },
+ { ERR_REQUEST_TIME_SKEWED, 403, "RequestTimeTooSkewed" },
+ { ENOENT, 404, "NoSuchKey" },
+ { ERR_NO_SUCH_BUCKET, 404, "NoSuchBucket" },
+ { ERR_NO_SUCH_UPLOAD, 404, "NoSuchUpload" },
+ { ERR_METHOD_NOT_ALLOWED, 405, "MethodNotAllowed" },
+ { ETIMEDOUT, 408, "RequestTimeout" },
+ { EEXIST, 409, "BucketAlreadyExists" },
+ { ENOTEMPTY, 409, "BucketNotEmpty" },
+ { ERR_PRECONDITION_FAILED, 412, "PreconditionFailed" },
+ { ERANGE, 416, "InvalidRange" },
+ { ERR_UNPROCESSABLE_ENTITY, 422, "UnprocessableEntity" },
+ { ERR_INTERNAL_ERROR, 500, "InternalError" },
+};
+
+const static struct rgw_html_errors RGW_HTML_SWIFT_ERRORS[] = {
+ { EACCES, 401, "AccessDenied" },
+ { EPERM, 401, "AccessDenied" },
+ { ERR_USER_SUSPENDED, 401, "UserSuspended" },
+ { ERR_INVALID_UTF8, 412, "Invalid UTF8" },
+ { ERR_BAD_URL, 412, "Bad URL" },
+};
+
+#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
+
+static const struct rgw_html_errors *search_err(int err_no, const struct rgw_html_errors *errs, int len)
+{
+ for (int i = 0; i < len; ++i, ++errs) {
+ if (err_no == errs->err_no)
+ return errs;
+ }
+ return NULL;
+}
+
+
+
+#endif
--- /dev/null
+#include <string.h>
+
+#include <iostream>
+
+#include "include/types.h"
+
+#include "rgw_xml.h"
+#include "rgw_multi_del.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+using namespace std;
+
+
+bool RGWMultiDelObject::xml_end(const char *el)
+{
+ RGWMultiDelKey *key_obj = (RGWMultiDelKey *)find_first("Key");
+
+ if (!key_obj)
+ return false;
+
+ string s = key_obj->get_data();
+ if (s.empty())
+ return false;
+
+ key = s;
+
+ return true;
+}
+
+bool RGWMultiDelDelete::xml_end(const char *el) {
+ RGWMultiDelQuiet *quiet_set = (RGWMultiDelQuiet *)find_first("Quiet");
+ if (quiet_set) {
+ string quiet_val = quiet_set->get_data();
+ quiet = (strcasecmp(quiet_val.c_str(), "true") == 0);
+ }
+
+ XMLObjIter iter = find("Object");
+ RGWMultiDelObject *object = (RGWMultiDelObject *)iter.get_next();
+ while (object) {
+ string key = object->get_key();
+ objects.push_back(key);
+ object = (RGWMultiDelObject *)iter.get_next();
+ }
+ return true;
+}
+
+XMLObj *RGWMultiDelXMLParser::alloc_obj(const char *el) {
+ XMLObj *obj = NULL;
+ if (strcmp(el, "Delete") == 0) {
+ obj = new RGWMultiDelDelete();
+ } else if (strcmp(el, "Quiet") == 0) {
+ obj = new RGWMultiDelQuiet();
+ } else if (strcmp(el, "Object") == 0) {
+ obj = new RGWMultiDelObject ();
+ } else if (strcmp(el, "Key") == 0) {
+ obj = new RGWMultiDelKey();
+ } else if (strcmp(el, "VersionID") == 0) {
+ /*do nothing*/
+ }
+
+ return obj;
+}
+
--- /dev/null
+#ifndef RGW_MULTI_DELETE_H_
+#define RGW_MULTI_DELETE_H_
+
+#include <vector>
+#include "rgw_xml.h"
+
+class RGWMultiDelDelete : public XMLObj
+{
+public:
+ RGWMultiDelDelete() :quiet(false) {}
+ ~RGWMultiDelDelete() {}
+ bool xml_end(const char *el);
+
+ std::vector<string> objects;
+ bool quiet;
+ bool is_quiet() { return quiet; };
+};
+
+class RGWMultiDelQuiet : public XMLObj
+{
+public:
+ RGWMultiDelQuiet() {}
+ ~RGWMultiDelQuiet() {}
+};
+
+class RGWMultiDelObject : public XMLObj
+{
+ string key;
+ string versionID;
+public:
+ RGWMultiDelObject() {}
+ ~RGWMultiDelObject() {}
+ bool xml_end(const char *el);
+
+ string get_key() { return key; }
+};
+
+class RGWMultiDelKey : public XMLObj
+{
+public:
+ RGWMultiDelKey() {}
+ ~RGWMultiDelKey() {}
+};
+
+class RGWMultiDelXMLParser : public RGWXMLParser
+{
+ XMLObj *alloc_obj(const char *el);
+public:
+ RGWMultiDelXMLParser() {}
+ ~RGWMultiDelXMLParser() {}
+};
+
+
+#endif
#include "rgw_user.h"
#include "rgw_log.h"
#include "rgw_multi.h"
+#include "rgw_multi_del.h"
#ifdef FASTCGI_INCLUDE_DIR
# include "fastcgi/fcgiapp.h"
send_response();
}
+int RGWDeleteMultiObj::verify_permission()
+{
+ if (!verify_bucket_permission(s, RGW_PERM_WRITE))
+ return -EACCES;
+
+ return 0;
+}
+
+void RGWDeleteMultiObj::execute()
+{
+ RGWMultiDelDelete *multi_delete;
+ vector<string>::iterator iter;
+ RGWMultiDelXMLParser parser;
+ pair<string,int> result;
+ int num_processed = 0;
+
+ ret = get_params();
+ if (ret < 0) {
+ goto error;
+ }
+
+ if (!data) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (!parser.init()) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (!parser.parse(data, len, 1)) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ multi_delete = (RGWMultiDelDelete *)parser.find_first("Delete");
+ if (!multi_delete) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (multi_delete->is_quiet())
+ quiet = true;
+
+ begin_response();
+ if (multi_delete->objects.size() == 0) {
+ goto done;
+ }
+
+ for (iter = multi_delete->objects.begin();
+ iter != multi_delete->objects.end() && num_processed < max_to_delete;
+ ++iter, num_processed++) {
+
+ rgw_obj obj(bucket,(*iter));
+ rgwstore->set_atomic(s->obj_ctx, obj);
+ ret = rgwstore->delete_obj(s->obj_ctx, obj);
+ result = make_pair(*iter, ret);
+
+ send_partial_response(result);
+ }
+
+ /* set the return code to zero, errors at this point will be
+ dumped to the response */
+ ret = 0;
+
+done:
+ // will likely segfault if begin_response() has not been called
+ end_response();
+ free(data);
+ return;
+
+error:
+ send_status();
+ free(data);
+ return;
+
+}
+
int RGWHandler::init(struct req_state *_s, FCGX_Request *fcgx)
{
s = _s;
virtual const char *name() { return "list_bucket_multiparts"; }
};
+class RGWDeleteMultiObj : public RGWOp {
+protected:
+ int ret;
+ int max_to_delete;
+ size_t len;
+ char *data;
+ string bucket_name;
+ rgw_bucket bucket;
+ bool quiet;
+ bool status_dumped;
+
+
+public:
+ RGWDeleteMultiObj() {}
+
+ virtual void init(struct req_state *s, RGWHandler *h) {
+ RGWOp::init(s, h);
+ ret = 0;
+ max_to_delete = 1000;
+ len = 0;
+ data = NULL;
+ bucket_name = "";
+ quiet = false;
+ status_dumped = false;
+ }
+ int verify_permission();
+ void execute();
+
+ virtual int get_params() = 0;
+ virtual void send_status() = 0;
+ virtual void begin_response() = 0;
+ virtual void send_partial_response(pair<string,int>& result) = 0;
+ virtual void end_response() = 0;
+ virtual const char *name() { return "multi_object_delete"; }
+};
+
+
class RGWHandler {
protected:
struct req_state *s;
CGI_PRINTF(s,"Status: %s\n", status);
}
-struct rgw_html_errors {
- int err_no;
- int http_ret;
- const char *s3_code;
-};
-
-const static struct rgw_html_errors RGW_HTML_ERRORS[] = {
- { 0, 200, "" },
- { STATUS_CREATED, 201, "Created" },
- { STATUS_ACCEPTED, 202, "Accepted" },
- { STATUS_NO_CONTENT, 204, "NoContent" },
- { STATUS_PARTIAL_CONTENT, 206, "" },
- { ERR_NOT_MODIFIED, 304, "NotModified" },
- { EINVAL, 400, "InvalidArgument" },
- { ERR_INVALID_REQUEST, 400, "InvalidRequest" },
- { ERR_INVALID_DIGEST, 400, "InvalidDigest" },
- { ERR_BAD_DIGEST, 400, "BadDigest" },
- { ERR_INVALID_BUCKET_NAME, 400, "InvalidBucketName" },
- { ERR_INVALID_OBJECT_NAME, 400, "InvalidObjectName" },
- { ERR_UNRESOLVABLE_EMAIL, 400, "UnresolvableGrantByEmailAddress" },
- { ERR_INVALID_PART, 400, "InvalidPart" },
- { ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" },
- { ERR_REQUEST_TIMEOUT, 400, "RequestTimeout" },
- { ERR_TOO_LARGE, 400, "EntityTooLarge" },
- { ERR_TOO_MANY_BUCKETS, 400, "TooManyBuckets" },
- { ERR_LENGTH_REQUIRED, 411, "MissingContentLength" },
- { EACCES, 403, "AccessDenied" },
- { EPERM, 403, "AccessDenied" },
- { ERR_USER_SUSPENDED, 403, "UserSuspended" },
- { ERR_REQUEST_TIME_SKEWED, 403, "RequestTimeTooSkewed" },
- { ENOENT, 404, "NoSuchKey" },
- { ERR_NO_SUCH_BUCKET, 404, "NoSuchBucket" },
- { ERR_NO_SUCH_UPLOAD, 404, "NoSuchUpload" },
- { ERR_METHOD_NOT_ALLOWED, 405, "MethodNotAllowed" },
- { ETIMEDOUT, 408, "RequestTimeout" },
- { EEXIST, 409, "BucketAlreadyExists" },
- { ENOTEMPTY, 409, "BucketNotEmpty" },
- { ERR_PRECONDITION_FAILED, 412, "PreconditionFailed" },
- { ERANGE, 416, "InvalidRange" },
- { ERR_UNPROCESSABLE_ENTITY, 422, "UnprocessableEntity" },
- { ERR_INTERNAL_ERROR, 500, "InternalError" },
-};
-
-const static struct rgw_html_errors RGW_HTML_SWIFT_ERRORS[] = {
- { EACCES, 401, "AccessDenied" },
- { EPERM, 401, "AccessDenied" },
- { ERR_USER_SUSPENDED, 401, "UserSuspended" },
- { ERR_INVALID_UTF8, 412, "Invalid UTF8" },
- { ERR_BAD_URL, 412, "Bad URL" },
-};
-
-#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
-
-static const struct rgw_html_errors *search_err(int err_no, const struct rgw_html_errors *errs, int len)
+void rgw_flush_formatter_and_reset(struct req_state *s, Formatter *formatter)
{
- for (int i = 0; i < len; ++i, ++errs) {
- if (err_no == errs->err_no)
- return errs;
+ std::ostringstream oss;
+ formatter->flush(oss);
+ std::string outs(oss.str());
+ if (!outs.empty()) {
+ CGI_PutStr(s, outs.c_str(), outs.size());
}
- return NULL;
+
+ s->formatter->reset();
}
-void flush_formatter_to_req_state(struct req_state *s, Formatter *formatter)
+void rgw_flush_formatter(struct req_state *s, Formatter *formatter)
{
std::ostringstream oss;
formatter->flush(oss);
if (!outs.empty()) {
CGI_PutStr(s, outs.c_str(), outs.size());
}
- s->formatter->reset();
}
void set_req_state_err(struct req_state *s, int err_no)
}
CGI_PRINTF(s,"Content-type: %s\r\n\r\n", content_type);
s->header_ended = true;
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
void abort_early(struct req_state *s, int err_no)
set_req_state_err(s, err_no);
dump_errno(s);
end_header(s);
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
perfcounter->inc(l_rgw_failed_req);
}
return 0;
}
+int RGWDeleteMultiObj_REST::get_params()
+{
+ static rgw_bucket pi_buckets_rados = RGW_ROOT_BUCKET;
+ bufferlist bl;
+ RGWBucketInfo info;
+
+ bucket_name = s->bucket_name;
+
+ if (bucket_name.empty()) {
+ ret = -EINVAL;
+ return ret;
+ }
+
+ ret = rgw_get_obj(NULL, pi_buckets_rados, bucket_name, bl, NULL);
+ if (ret < 0)
+ return ret;
+
+ bufferlist::iterator iter = bl.begin();
+ try {
+ ::decode(info, iter);
+ } catch (buffer::error& err) {
+ cerr << "ERROR: could not decode buffer info, caught buffer::error" << std::endl;
+ return -EIO;
+ }
+
+ // everything is probably fine, set the bucket
+ bucket = s->bucket;
+
+ size_t cl = 0;
+
+ if (s->length)
+ cl = atoll(s->length);
+ if (cl) {
+ data = (char *)malloc(cl + 1);
+ if (!data) {
+ ret = -ENOMEM;
+ return ret;
+ }
+ CGI_GetStr(s, data, cl, len);
+ data[len] = '\0';
+ } else {
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
static void next_tok(string& str, string& tok, char delim)
{
if (str.size() == 0) {
break;
case OP_PUT:
case OP_POST:
+ /* is it a 'multi-object delete' request? */
+ if (s->request_params == "delete") {
+ only_bucket = true;
+ break;
+ }
if (is_obj_update_op()) {
only_bucket = false;
break;
#include "rgw_op.h"
-extern void flush_formatter_to_req_state(struct req_state *s,
+extern void rgw_flush_formatter_and_reset(struct req_state *s,
ceph::Formatter *formatter);
+extern void rgw_flush_formatter(struct req_state *s,
+ ceph::Formatter *formatter);
class RGWGetObj_REST : public RGWGetObj
{
int get_params();
};
+class RGWDeleteMultiObj_REST : public RGWDeleteMultiObj {
+public:
+ RGWDeleteMultiObj_REST() {}
+ ~RGWDeleteMultiObj_REST() {}
+
+ int get_params();
+};
+
class RGWHandler_REST : public RGWHandler {
protected:
virtual bool is_acl_op() = 0;
s->formatter->close_section();
}
+void rgw_get_errno_s3(rgw_html_errors *e , int err_no)
+{
+ const struct rgw_html_errors *r;
+ r = search_err(err_no, RGW_HTML_ERRORS, ARRAY_LEN(RGW_HTML_ERRORS));
+
+ if (r) {
+ e->http_ret = r->http_ret;
+ e->s3_code = r->s3_code;
+ } else {
+ e->http_ret = 500;
+ e->s3_code = "UnknownError";
+ }
+}
+
int RGWGetObj_REST_S3::send_response(bufferlist& bl)
{
string content_type_str;
list_all_buckets_end(s);
dump_content_length(s, s->formatter->get_len());
end_header(s, "application/xml");
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
int RGWListBucket_REST_S3::get_params()
}
}
s->formatter->close_section();
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
static void dump_bucket_metadata(struct req_state *s, RGWBucketEnt& bucket)
}
}
s->formatter->close_section();
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
}
s->formatter->dump_string("Key", s->object);
s->formatter->dump_string("UploadId", upload_id);
s->formatter->close_section();
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
}
s->formatter->dump_string("Key", s->object);
s->formatter->dump_string("ETag", etag);
s->formatter->close_section();
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
}
s->formatter->close_section();
}
s->formatter->close_section();
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
}
}
}
s->formatter->close_section();
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
+}
+
+void RGWDeleteMultiObj_REST_S3::send_status()
+{
+ if (!status_dumped) {
+ if (ret < 0)
+ set_req_state_err(s, ret);
+ dump_errno(s);
+ status_dumped = true;
+ }
+}
+
+void RGWDeleteMultiObj_REST_S3::begin_response()
+{
+
+ if (!status_dumped) {
+ send_status();
+ }
+
+ dump_start(s);
+ end_header(s, "application/xml");
+ s->formatter->open_object_section_in_ns("DeleteResult",
+ "http://s3.amazonaws.com/doc/2006-03-01/");
+
+ rgw_flush_formatter(s, s->formatter);
+}
+
+void RGWDeleteMultiObj_REST_S3::send_partial_response(pair<string,int>& result)
+{
+ if (!result.first.empty()) {
+ if (result.second == 0 && !quiet) {
+ s->formatter->open_object_section("Deleted");
+ s->formatter->dump_string("Key", result.first);
+ s->formatter->close_section();
+ } else if (result.first < 0) {
+ struct rgw_html_errors *r = new rgw_html_errors;
+ int err_no;
+
+ s->formatter->open_object_section("Error");
+
+ err_no = -(result.second);
+ rgw_get_errno_s3(r, err_no);
+
+ s->formatter->dump_string("Key", result.first);
+ s->formatter->dump_int("Code", r->http_ret);
+ s->formatter->dump_string("Message", r->s3_code);
+ s->formatter->close_section();
+ }
+
+ rgw_flush_formatter(s, s->formatter);
+ }
+}
+
+void RGWDeleteMultiObj_REST_S3::end_response()
+{
+
+ s->formatter->close_section();
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
RGWOp *RGWHandler_REST_S3::get_retrieve_obj_op(bool get_data)
else
return new RGWInitMultipart_REST_S3;
}
+ else if ( s->request_params == "delete" ) {
+ return new RGWDeleteMultiObj_REST_S3;
+ }
return NULL;
}
#define TIME_BUF_SIZE 128
#include "rgw_op.h"
+#include "rgw_html_errors.h"
#include "rgw_acl_s3.h"
#define RGW_AUTH_GRACE_MINS 15
+void rgw_get_errno_s3(struct rgw_html_errors *e, int err_no);
+
class RGWGetObj_REST_S3 : public RGWGetObj_REST
{
public:
void send_response();
};
+class RGWDeleteMultiObj_REST_S3 : public RGWDeleteMultiObj_REST {
+public:
+ RGWDeleteMultiObj_REST_S3() {}
+ ~RGWDeleteMultiObj_REST_S3() {}
+
+ void send_status();
+ void begin_response();
+ void send_partial_response(pair<string,int>& result);
+ void end_response();
+};
+
+
class RGWHandler_REST_S3 : public RGWHandler_REST {
protected:
bool is_acl_op() {
return;
}
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
int RGWListBucket_REST_SWIFT::get_params()
return;
}
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
static void dump_container_metadata(struct req_state *s, RGWBucketEnt& bucket)
set_req_state_err(s, ret);
dump_errno(s);
end_header(s);
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
void RGWDeleteBucket_REST_SWIFT::send_response()
set_req_state_err(s, r);
dump_errno(s);
end_header(s);
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
int RGWPutObj_REST_SWIFT::get_params()
set_req_state_err(s, ret);
dump_errno(s);
end_header(s);
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
int RGWPutMetadata_REST_SWIFT::get_params()
set_req_state_err(s, ret);
dump_errno(s);
end_header(s);
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
void RGWDeleteObj_REST_SWIFT::send_response()
set_req_state_err(s, r);
dump_errno(s);
end_header(s);
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
}
int RGWCopyObj_REST_SWIFT::init_dest_policy()
if (get_data && !orig_ret) {
CGI_PutStr(s, bl.c_str(), len);
}
- flush_formatter_to_req_state(s, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
return 0;
}