Skip to content

Commit 5cc7cf4

Browse files
committed
librados/asio: add version_t to completion signatures
IoCtx::aio_operate() doesn't update IoCtx::get_last_version(). to make the resulting version_t available to the caller, we have to read it out of the AioCompletionImpl and return it to the caller Signed-off-by: Casey Bodley <[email protected]>
1 parent 4f09b38 commit 5cc7cf4

File tree

2 files changed

+97
-68
lines changed

2 files changed

+97
-68
lines changed

src/librados/librados_asio.h

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "include/rados/librados.hpp"
1818
#include "common/async/completion.h"
19+
#include "librados/AioCompletionImpl.h"
1920

2021
/// Defines asynchronous librados operations that satisfy all of the
2122
/// "Requirements on asynchronous operations" imposed by the C++ Networking TS
@@ -53,20 +54,20 @@ using unique_aio_completion_ptr =
5354
/// argument to the handler.
5455
template <typename Result>
5556
struct Invoker {
56-
using Signature = void(boost::system::error_code, Result);
57+
using Signature = void(boost::system::error_code, version_t, Result);
5758
Result result;
5859
template <typename Completion>
59-
void dispatch(Completion&& completion, boost::system::error_code ec) {
60-
ceph::async::dispatch(std::move(completion), ec, std::move(result));
60+
void dispatch(Completion&& completion, boost::system::error_code ec, version_t ver) {
61+
ceph::async::dispatch(std::move(completion), ec, ver, std::move(result));
6162
}
6263
};
6364
// specialization for Result=void
6465
template <>
6566
struct Invoker<void> {
66-
using Signature = void(boost::system::error_code);
67+
using Signature = void(boost::system::error_code, version_t);
6768
template <typename Completion>
68-
void dispatch(Completion&& completion, boost::system::error_code ec) {
69-
ceph::async::dispatch(std::move(completion), ec);
69+
void dispatch(Completion&& completion, boost::system::error_code ec, version_t ver) {
70+
ceph::async::dispatch(std::move(completion), ec, ver);
7071
}
7172
};
7273

@@ -82,12 +83,15 @@ struct AsyncOp : Invoker<Result> {
8283
auto p = std::unique_ptr<Completion>{static_cast<Completion*>(arg)};
8384
// move result out of Completion memory being freed
8485
auto op = std::move(p->user_data);
85-
const int ret = op.aio_completion->get_return_value();
86+
// access AioCompletionImpl directly to avoid locking
87+
const librados::AioCompletionImpl* pc = op.aio_completion->pc;
88+
const int ret = pc->rval;
89+
const version_t ver = pc->objver;
8690
boost::system::error_code ec;
8791
if (ret < 0) {
8892
ec.assign(-ret, librados::detail::err_category());
8993
}
90-
op.dispatch(std::move(p), ec);
94+
op.dispatch(std::move(p), ec, ver);
9195
}
9296

9397
template <typename Executor1, typename CompletionHandler>
@@ -103,7 +107,7 @@ struct AsyncOp : Invoker<Result> {
103107

104108

105109
/// Calls IoCtx::aio_read() and arranges for the AioCompletion to call a
106-
/// given handler with signature (boost::system::error_code, bufferlist).
110+
/// given handler with signature (error_code, version_t, bufferlist).
107111
template <typename ExecutionContext, typename CompletionToken>
108112
auto async_read(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
109113
size_t len, uint64_t off, CompletionToken&& token)
@@ -119,40 +123,40 @@ auto async_read(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
119123
int ret = io.aio_read(oid, op.aio_completion.get(), &op.result, len, off);
120124
if (ret < 0) {
121125
auto ec = boost::system::error_code{-ret, librados::detail::err_category()};
122-
ceph::async::post(std::move(p), ec, bufferlist{});
126+
ceph::async::post(std::move(p), ec, 0, bufferlist{});
123127
} else {
124128
p.release(); // release ownership until completion
125129
}
126130
}, token, ctx.get_executor(), io, oid, len, off);
127131
}
128132

129133
/// Calls IoCtx::aio_write() and arranges for the AioCompletion to call a
130-
/// given handler with signature (boost::system::error_code).
134+
/// given handler with signature (error_code, version_t).
131135
template <typename ExecutionContext, typename CompletionToken>
132136
auto async_write(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
133-
bufferlist &bl, size_t len, uint64_t off,
137+
const bufferlist &bl, size_t len, uint64_t off,
134138
CompletionToken&& token)
135139
{
136140
using Op = detail::AsyncOp<void>;
137141
using Signature = typename Op::Signature;
138142
return boost::asio::async_initiate<CompletionToken, Signature>(
139143
[] (auto handler, auto ex, IoCtx& io, const std::string& oid,
140-
bufferlist &bl, size_t len, uint64_t off) {
144+
const bufferlist &bl, size_t len, uint64_t off) {
141145
auto p = Op::create(ex, std::move(handler));
142146
auto& op = p->user_data;
143147

144148
int ret = io.aio_write(oid, op.aio_completion.get(), bl, len, off);
145149
if (ret < 0) {
146150
auto ec = boost::system::error_code{-ret, librados::detail::err_category()};
147-
ceph::async::post(std::move(p), ec);
151+
ceph::async::post(std::move(p), ec, 0);
148152
} else {
149153
p.release(); // release ownership until completion
150154
}
151155
}, token, ctx.get_executor(), io, oid, bl, len, off);
152156
}
153157

154158
/// Calls IoCtx::aio_operate() and arranges for the AioCompletion to call a
155-
/// given handler with signature (boost::system::error_code, bufferlist).
159+
/// given handler with signature (error_code, version_t, bufferlist).
156160
template <typename ExecutionContext, typename CompletionToken>
157161
auto async_operate(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
158162
ObjectReadOperation *read_op, int flags,
@@ -170,15 +174,15 @@ auto async_operate(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
170174
flags, &op.result);
171175
if (ret < 0) {
172176
auto ec = boost::system::error_code{-ret, librados::detail::err_category()};
173-
ceph::async::post(std::move(p), ec, bufferlist{});
177+
ceph::async::post(std::move(p), ec, 0, bufferlist{});
174178
} else {
175179
p.release(); // release ownership until completion
176180
}
177181
}, token, ctx.get_executor(), io, oid, read_op, flags);
178182
}
179183

180184
/// Calls IoCtx::aio_operate() and arranges for the AioCompletion to call a
181-
/// given handler with signature (boost::system::error_code).
185+
/// given handler with signature (error_code, version_t).
182186
template <typename ExecutionContext, typename CompletionToken>
183187
auto async_operate(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
184188
ObjectWriteOperation *write_op, int flags,
@@ -196,15 +200,15 @@ auto async_operate(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
196200
int ret = io.aio_operate(oid, op.aio_completion.get(), write_op, flags, trace_ctx);
197201
if (ret < 0) {
198202
auto ec = boost::system::error_code{-ret, librados::detail::err_category()};
199-
ceph::async::post(std::move(p), ec);
203+
ceph::async::post(std::move(p), ec, 0);
200204
} else {
201205
p.release(); // release ownership until completion
202206
}
203207
}, token, ctx.get_executor(), io, oid, write_op, flags, trace_ctx);
204208
}
205209

206210
/// Calls IoCtx::aio_notify() and arranges for the AioCompletion to call a
207-
/// given handler with signature (boost::system::error_code, bufferlist).
211+
/// given handler with signature (error_code, version_t, bufferlist).
208212
template <typename ExecutionContext, typename CompletionToken>
209213
auto async_notify(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
210214
bufferlist& bl, uint64_t timeout_ms, CompletionToken &&token)
@@ -221,7 +225,7 @@ auto async_notify(ExecutionContext& ctx, IoCtx& io, const std::string& oid,
221225
bl, timeout_ms, &op.result);
222226
if (ret < 0) {
223227
auto ec = boost::system::error_code{-ret, librados::detail::err_category()};
224-
ceph::async::post(std::move(p), ec, bufferlist{});
228+
ceph::async::post(std::move(p), ec, 0, bufferlist{});
225229
} else {
226230
p.release(); // release ownership until completion
227231
}

0 commit comments

Comments
 (0)