struct AioResult {
rgw_raw_obj obj;
+ uint64_t id = 0; // id allows caller to associate a result with its request
bufferlist data; // result buffer for reads
int result = 0;
};
virtual AioResultList submit(RGWSI_RADOS::Obj& obj,
const rgw_raw_obj& raw_obj,
librados::ObjectReadOperation *op,
- uint64_t cost) = 0;
+ uint64_t cost, uint64_t id) = 0;
virtual AioResultList submit(RGWSI_RADOS::Obj& obj,
const rgw_raw_obj& raw_obj,
librados::ObjectWriteOperation *op,
- uint64_t cost) = 0;
+ uint64_t cost, uint64_t id) = 0;
// poll for any ready completions without waiting
virtual AioResultList poll() = 0;
AioResultList AioThrottle::submit(RGWSI_RADOS::Obj& obj,
const rgw_raw_obj& raw_obj,
librados::ObjectWriteOperation *op,
- uint64_t cost)
+ uint64_t cost, uint64_t id)
{
auto p = std::make_unique<Pending>();
p->obj = raw_obj;
+ p->id = id;
p->cost = cost;
if (cost > window) {
AioResultList AioThrottle::submit(RGWSI_RADOS::Obj& obj,
const rgw_raw_obj& raw_obj,
librados::ObjectReadOperation *op,
- uint64_t cost)
+ uint64_t cost, uint64_t id)
{
auto p = std::make_unique<Pending>();
p->obj = raw_obj;
+ p->id = id;
p->cost = cost;
if (cost > window) {
AioResultList submit(RGWSI_RADOS::Obj& obj, const rgw_raw_obj& raw_obj,
librados::ObjectReadOperation *op,
- uint64_t cost) override;
+ uint64_t cost, uint64_t id) override;
AioResultList submit(RGWSI_RADOS::Obj& obj, const rgw_raw_obj& raw_obj,
librados::ObjectWriteOperation *op,
- uint64_t cost) override;
+ uint64_t cost, uint64_t id) override;
AioResultList poll() override;
} else {
op.write(offset, data);
}
- auto c = aio->submit(stripe_obj, stripe_raw, &op, cost);
+ constexpr uint64_t id = 0; // unused
+ auto c = aio->submit(stripe_obj, stripe_raw, &op, cost, id);
return process_completed(c, &written);
}
op.create(true); // exclusive create
op.write_full(data);
- auto c = aio->submit(stripe_obj, stripe_raw, &op, cost);
+ constexpr uint64_t id = 0; // unused
+ auto c = aio->submit(stripe_obj, stripe_raw, &op, cost, id);
auto d = aio->drain();
c.splice(c.end(), d);
return process_completed(c, &written);
namespace rgw {
-inline bool operator==(const AioResult& lhs, const AioResult& rhs) {
- return lhs.obj == rhs.obj && lhs.result == rhs.result;
-}
-std::ostream& operator<<(std::ostream& out, const AioResult& r) {
- return out << "{r=" << r.result << " obj='" << r.obj << "'";
-}
-
TEST_F(Aio_Throttle, NoThrottleUpToMax)
{
AioThrottle throttle(4);
auto obj = make_obj(raw);
{
librados::ObjectWriteOperation op1;
- auto c1 = throttle.submit(obj, raw, &op1, 1);
+ auto c1 = throttle.submit(obj, raw, &op1, 1, 0);
EXPECT_TRUE(c1.empty());
librados::ObjectWriteOperation op2;
- auto c2 = throttle.submit(obj, raw, &op2, 1);
+ auto c2 = throttle.submit(obj, raw, &op2, 1, 0);
EXPECT_TRUE(c2.empty());
librados::ObjectWriteOperation op3;
- auto c3 = throttle.submit(obj, raw, &op3, 1);
+ auto c3 = throttle.submit(obj, raw, &op3, 1, 0);
EXPECT_TRUE(c3.empty());
librados::ObjectWriteOperation op4;
- auto c4 = throttle.submit(obj, raw, &op4, 1);
+ auto c4 = throttle.submit(obj, raw, &op4, 1, 0);
EXPECT_TRUE(c4.empty());
// no completions because no ops had to wait
auto c5 = throttle.poll();
auto completions = throttle.drain();
ASSERT_EQ(4u, completions.size());
for (auto& c : completions) {
- EXPECT_EQ(AioResult({raw, -EINVAL}), c);
+ EXPECT_EQ(-EINVAL, c.result);
}
}
auto obj = make_obj(raw);
librados::ObjectWriteOperation op;
- auto c = throttle.submit(obj, raw, &op, 8);
+ auto c = throttle.submit(obj, raw, &op, 8, 0);
ASSERT_EQ(1u, c.size());
- EXPECT_EQ(AioResult({raw, -EDEADLK}), c.front());
+ EXPECT_EQ(-EDEADLK, c.front().result);
}
TEST_F(Aio_Throttle, ThrottleOverMax)
for (uint64_t i = 0; i < total; i++) {
librados::ObjectWriteOperation op;
- auto c = throttle.submit(obj, raw, &op, 1);
+ auto c = throttle.submit(obj, raw, &op, 1, 0);
outstanding++;
outstanding -= c.size();
if (max_outstanding < outstanding) {