send_partial_response(o, del_op->result.delete_marker, del_op->result.version_id, op_ret);
}
+void RGWDeleteMultiObj::handle_objects(const std::vector<RGWMultiDelObject>& objects,
+ uint32_t max_aio,
+ boost::asio::yield_context yield)
+{
+ auto group = ceph::async::spawn_throttle{yield, max_aio};
+
+ for (const auto& object : objects) {
+ group.spawn([this, &object] (boost::asio::yield_context yield) {
+ handle_individual_object(object, yield);
+ });
+
+ rgw_flush_formatter(s, s->formatter);
+ }
+ group.wait();
+}
+
void RGWDeleteMultiObj::execute(optional_yield y)
{
const char* buf = data.c_str();
// process up to max_aio object deletes in parallel
const uint32_t max_aio = std::max<uint32_t>(1, s->cct->_conf->rgw_multi_obj_del_max_aio);
- auto group = ceph::async::spawn_throttle{y, max_aio};
- for (const auto& object : multi_delete->objects) {
- group.spawn([this, &object] (boost::asio::yield_context yield) {
- handle_individual_object(object, yield);
- });
-
- rgw_flush_formatter(s, s->formatter);
+ // if we're not already running in a coroutine, spawn one
+ if (!y) {
+ auto& objects = multi_delete->objects;
+
+ boost::asio::io_context context;
+ boost::asio::spawn(context,
+ [this, &objects, max_aio] (boost::asio::yield_context yield) {
+ handle_objects(objects, max_aio, yield);
+ },
+ [] (std::exception_ptr eptr) {
+ if (eptr) std::rethrow_exception(eptr);
+ });
+ context.run();
+ } else {
+ // use the existing coroutine's yield context
+ handle_objects(multi_delete->objects, max_aio,
+ y.get_yield_context());
}
- group.wait();
/* set the return code to zero, errors at this point will be
dumped to the response */