CLS_LOG(20, "%s: updating header", __func__);
return cls_cxx_map_write_header(hctx, &bl);
-}
+} /* legacy cls_user_reset_stats */
+
+/// A method to reset the user.buckets header stats in accordance to
+/// the values seen in the user.buckets omap keys. This is not be
+/// equivalent to --sync-stats which also re-calculates the stats for
+/// each bucket.
+static int cls_user_reset_stats2(cls_method_context_t hctx,
+ buffer::list *in, buffer::list *out)
+{
+ cls_user_reset_stats2_op op;
+
+ try {
+ auto bliter = in->cbegin();
+ decode(op, bliter);
+ } catch (ceph::buffer::error& err) {
+ CLS_LOG(0, "ERROR: %s failed to decode op", __func__);
+ return -EINVAL;
+ }
+
+ cls_user_header header;
+ string from_index{op.marker}, prefix;
+ cls_user_reset_stats2_ret ret;
+
+ map<string, buffer::list> keys;
+ int rc = cls_cxx_map_get_vals(hctx, from_index, prefix, MAX_ENTRIES,
+ &keys, &ret.truncated);
+ if (rc < 0) {
+ CLS_LOG(0, "ERROR: %s failed to retrieve omap key-values", __func__);
+ return rc;
+ }
+ CLS_LOG(20, "%s: read %lu key-values, truncated=%d",
+ __func__, keys.size(), ret.truncated);
+
+ for (const auto& kv : keys) {
+ cls_user_bucket_entry e;
+ try {
+ auto& bl = kv.second;
+ auto bliter = bl.cbegin();
+ decode(e, bliter);
+ } catch (ceph::buffer::error& err) {
+ CLS_LOG(0, "ERROR: %s failed to decode bucket entry for %s",
+ __func__, kv.first.c_str());
+ return -EIO;
+ }
+ add_header_stats(&ret.acc_stats, e);
+ }
+
+ /* try-update marker */
+ if(!keys.empty())
+ ret.marker = (--keys.cend())->first;
+
+ if (! ret.truncated) {
+ buffer::list bl;
+ header.last_stats_update = op.time;
+ header.stats = ret.acc_stats;
+ encode(header, bl);
+
+ CLS_LOG(20, "%s: updating header", __func__);
+ rc = cls_cxx_map_write_header(hctx, &bl);
+
+ /* return final result */
+ encode(ret, *out);
+ return rc;
+ }
+
+ /* return partial result */
+ encode(ret, *out);
+ return 0;
+} /* cls_user_reset_stats2 */
CLS_INIT(user)
{
cls_method_handle_t h_user_list_buckets;
cls_method_handle_t h_user_get_header;
cls_method_handle_t h_user_reset_stats;
+ cls_method_handle_t h_user_reset_stats2;
cls_register("user", &h_class);
cls_register_cxx_method(h_class, "list_buckets", CLS_METHOD_RD, cls_user_list_buckets, &h_user_list_buckets);
cls_register_cxx_method(h_class, "get_header", CLS_METHOD_RD, cls_user_get_header, &h_user_get_header);
cls_register_cxx_method(h_class, "reset_user_stats", CLS_METHOD_RD | CLS_METHOD_WR, cls_user_reset_stats, &h_user_reset_stats);
+ cls_register_cxx_method(h_class, "reset_user_stats2", CLS_METHOD_RD | CLS_METHOD_WR, cls_user_reset_stats2, &h_user_reset_stats2);
+
return;
}
};
WRITE_CLASS_ENCODER(cls_user_reset_stats_op);
+struct cls_user_reset_stats2_op {
+ ceph::real_time time;
+ std::string marker;
+ cls_user_stats acc_stats;
+
+ cls_user_reset_stats2_op() {}
+
+ void encode(ceph::buffer::list& bl) const {
+ ENCODE_START(1, 1, bl);
+ encode(time, bl);
+ encode(marker, bl);
+ encode(acc_stats, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(ceph::buffer::list::const_iterator& bl) {
+ DECODE_START(1, bl);
+ decode(time, bl);
+ decode(marker, bl);
+ decode(acc_stats, bl);
+ DECODE_FINISH(bl);
+ }
+
+ void dump(ceph::Formatter *f) const;
+ static void generate_test_instances(std::list<cls_user_reset_stats2_op*>& ls);
+};
+WRITE_CLASS_ENCODER(cls_user_reset_stats2_op);
+
+struct cls_user_reset_stats2_ret {
+ std::string marker;
+ cls_user_stats acc_stats; /* 0-initialized */
+ bool truncated;
+
+ cls_user_reset_stats2_ret()
+ : truncated(false) {}
+
+ void update_call(cls_user_reset_stats2_op& call) {
+ call.marker = marker;
+ call.acc_stats = acc_stats;
+ }
+
+ void encode(ceph::buffer::list& bl) const {
+ ENCODE_START(1, 1, bl);
+ encode(marker, bl);
+ encode(acc_stats, bl);
+ encode(truncated, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(ceph::buffer::list::const_iterator& bl) {
+ DECODE_START(1, bl);
+ decode(marker, bl);
+ decode(acc_stats, bl);
+ decode(truncated, bl);
+ DECODE_FINISH(bl);
+ }
+
+ void dump(ceph::Formatter *f) const;
+ static void generate_test_instances(
+ std::list<cls_user_reset_stats2_ret*>& ls);
+};
+WRITE_CLASS_ENCODER(cls_user_reset_stats2_ret);
+
struct cls_user_get_header_ret {
cls_user_header header;
int rgw_rados_operate(librados::IoCtx& ioctx, const std::string& oid,
librados::ObjectReadOperation *op, bufferlist* pbl,
- int flags, optional_yield y)
+ optional_yield y, int flags)
{
#ifdef HAVE_BOOST_CONTEXT
// given a yield_context, call async_operate() to yield the coroutine instead
auto& context = y.get_io_context();
auto& yield = y.get_yield_context();
boost::system::error_code ec;
- auto bl = librados::async_operate(context, ioctx, oid, op, flags, yield[ec]);
+ auto bl = librados::async_operate(
+ context, ioctx, oid, op, flags, yield[ec]);
if (pbl) {
*pbl = std::move(bl);
}
}
int rgw_rados_operate(librados::IoCtx& ioctx, const std::string& oid,
- librados::ObjectReadOperation *op, bufferlist* pbl,
- optional_yield y)
-{
- return rgw_rados_operate(ioctx, oid, op, pbl, 0, y);
-}
-
-int rgw_rados_operate(librados::IoCtx& ioctx, const std::string& oid,
- librados::ObjectWriteOperation *op, int flags, optional_yield y)
+ librados::ObjectWriteOperation *op, optional_yield y,
+ int flags)
{
#ifdef HAVE_BOOST_CONTEXT
if (y) {
return ioctx.operate(oid, op, flags);
}
-int rgw_rados_operate(librados::IoCtx& ioctx, const std::string& oid,
- librados::ObjectWriteOperation *op, optional_yield y)
-{
- return rgw_rados_operate(ioctx, oid, op, 0, y);
-}
-
int rgw_rados_notify(librados::IoCtx& ioctx, const std::string& oid,
bufferlist& bl, uint64_t timeout_ms, bufferlist* pbl,
optional_yield y)
/// perform the rados operation, using the yield context when given
int rgw_rados_operate(librados::IoCtx& ioctx, const std::string& oid,
librados::ObjectReadOperation *op, bufferlist* pbl,
- optional_yield y);
+ optional_yield y, int flags = 0);
int rgw_rados_operate(librados::IoCtx& ioctx, const std::string& oid,
- librados::ObjectReadOperation *op, bufferlist* pbl,
- int flags, optional_yield y);
-int rgw_rados_operate(librados::IoCtx& ioctx, const std::string& oid,
- librados::ObjectWriteOperation *op, optional_yield y);
-int rgw_rados_operate(librados::IoCtx& ioctx, const std::string& oid,
- librados::ObjectWriteOperation *op, int flags, optional_yield y);
+ librados::ObjectWriteOperation *op, optional_yield y,
+ int flags = 0);
int rgw_rados_notify(librados::IoCtx& ioctx, const std::string& oid,
bufferlist& bl, uint64_t timeout_ms, bufferlist* pbl,
optional_yield y);
}
int RGWSI_RADOS::Obj::operate(librados::ObjectWriteOperation *op,
- optional_yield y)
+ optional_yield y, int flags)
{
- return rgw_rados_operate(ref.pool.ioctx(), ref.obj.oid, op, y);
+ return rgw_rados_operate(ref.pool.ioctx(), ref.obj.oid, op, y, flags);
}
-int RGWSI_RADOS::Obj::operate(librados::ObjectReadOperation *op, bufferlist *pbl,
- optional_yield y)
+int RGWSI_RADOS::Obj::operate(librados::ObjectReadOperation *op,
+ bufferlist *pbl, optional_yield y, int flags)
{
- return rgw_rados_operate(ref.pool.ioctx(), ref.obj.oid, op, pbl, y);
+ return rgw_rados_operate(ref.pool.ioctx(), ref.obj.oid, op, pbl, y, flags);
}
int RGWSI_RADOS::Obj::aio_operate(librados::AioCompletion *c, librados::ObjectWriteOperation *op)
int open();
- int operate(librados::ObjectWriteOperation *op, optional_yield y);
+ int operate(librados::ObjectWriteOperation *op, optional_yield y,
+ int flags = 0);
int operate(librados::ObjectReadOperation *op, bufferlist *pbl,
- optional_yield y);
+ optional_yield y, int flags = 0);
int aio_operate(librados::AioCompletion *c, librados::ObjectWriteOperation *op);
int aio_operate(librados::AioCompletion *c, librados::ObjectReadOperation *op,
bufferlist *pbl);
{
rgw_raw_obj obj = get_buckets_obj(user);
auto rados_obj = svc.rados->obj(obj);
- int r = rados_obj.open();
+ int rval, r = rados_obj.open();
if (r < 0) {
return r;
}
- librados::ObjectWriteOperation op;
- ::cls_user_reset_stats(op);
- return rados_obj.operate(&op, null_yield);
+
+ cls_user_reset_stats2_op call;
+ cls_user_reset_stats2_ret ret;
+
+ do {
+ buffer::list in, out;
+ librados::ObjectWriteOperation op;
+
+ call.time = real_clock::now();
+ ret.update_call(call);
+
+ encode(call, in);
+ op.exec("user", "reset_user_stats2", in, &out, &rval);
+ r = rados_obj.operate(&op, null_yield, librados::OPERATION_RETURNVEC);
+ if (r < 0) {
+ return r;
+ }
+ try {
+ auto bliter = out.cbegin();
+ decode(ret, bliter);
+ } catch (ceph::buffer::error& err) {
+ return -EINVAL;
+ }
+ } while (ret.truncated);
+
+ return rval;
}
int RGWSI_User_RADOS::complete_flush_stats(RGWSI_MetaBackend::Context *ctx,