]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab ft=cpp | |
3 | ||
4 | #ifndef RGW_CACHEREQUEST_H | |
5 | #define RGW_CACHEREQUEST_H | |
6 | ||
7 | #include <fcntl.h> | |
8 | #include <stdlib.h> | |
9 | #include <aio.h> | |
10 | ||
11 | #include "include/rados/librados.hpp" | |
12 | #include "include/Context.h" | |
13 | #include "common/async/completion.h" | |
14 | ||
15 | #include <errno.h> | |
16 | #include "common/error_code.h" | |
17 | #include "common/errno.h" | |
18 | ||
19 | #include "rgw_aio.h" | |
20 | #include "rgw_cache.h" | |
21 | ||
22 | ||
23 | struct D3nGetObjData { | |
24 | std::mutex d3n_lock; | |
25 | }; | |
26 | ||
27 | struct D3nL1CacheRequest { | |
28 | ~D3nL1CacheRequest() { | |
29 | lsubdout(g_ceph_context, rgw_datacache, 30) << "D3nDataCache: " << __func__ << "(): Read From Cache, complete" << dendl; | |
30 | } | |
31 | ||
32 | // unique_ptr with custom deleter for struct aiocb | |
33 | struct libaio_aiocb_deleter { | |
34 | void operator()(struct aiocb* c) { | |
35 | if(c->aio_fildes > 0) { | |
36 | if( ::close(c->aio_fildes) != 0) { | |
37 | lsubdout(g_ceph_context, rgw_datacache, 2) << "D3nDataCache: " << __func__ << "(): Error - can't close file, errno=" << -errno << dendl; | |
38 | } | |
39 | } | |
40 | delete c; | |
41 | } | |
42 | }; | |
43 | ||
44 | using unique_aio_cb_ptr = std::unique_ptr<struct aiocb, libaio_aiocb_deleter>; | |
45 | ||
46 | struct AsyncFileReadOp { | |
47 | bufferlist result; | |
48 | unique_aio_cb_ptr aio_cb; | |
49 | using Signature = void(boost::system::error_code, bufferlist); | |
50 | using Completion = ceph::async::Completion<Signature, AsyncFileReadOp>; | |
51 | ||
52 | int init(const DoutPrefixProvider *dpp, const std::string& file_path, off_t read_ofs, off_t read_len, void* arg) { | |
53 | ldpp_dout(dpp, 20) << "D3nDataCache: " << __func__ << "(): file_path=" << file_path << dendl; | |
54 | aio_cb.reset(new struct aiocb); | |
55 | memset(aio_cb.get(), 0, sizeof(struct aiocb)); | |
56 | aio_cb->aio_fildes = TEMP_FAILURE_RETRY(::open(file_path.c_str(), O_RDONLY|O_CLOEXEC|O_BINARY)); | |
57 | if(aio_cb->aio_fildes < 0) { | |
58 | int err = errno; | |
59 | ldpp_dout(dpp, 1) << "ERROR: D3nDataCache: " << __func__ << "(): can't open " << file_path << " : " << cpp_strerror(err) << dendl; | |
60 | return -err; | |
61 | } | |
62 | if (g_conf()->rgw_d3n_l1_fadvise != POSIX_FADV_NORMAL) | |
63 | posix_fadvise(aio_cb->aio_fildes, 0, 0, g_conf()->rgw_d3n_l1_fadvise); | |
64 | ||
65 | bufferptr bp(read_len); | |
66 | aio_cb->aio_buf = bp.c_str(); | |
67 | result.append(std::move(bp)); | |
68 | ||
69 | aio_cb->aio_nbytes = read_len; | |
70 | aio_cb->aio_offset = read_ofs; | |
71 | aio_cb->aio_sigevent.sigev_notify = SIGEV_THREAD; | |
72 | aio_cb->aio_sigevent.sigev_notify_function = libaio_cb_aio_dispatch; | |
73 | aio_cb->aio_sigevent.sigev_notify_attributes = nullptr; | |
74 | aio_cb->aio_sigevent.sigev_value.sival_ptr = arg; | |
75 | ||
76 | return 0; | |
77 | } | |
78 | ||
79 | static void libaio_cb_aio_dispatch(sigval sigval) { | |
80 | lsubdout(g_ceph_context, rgw_datacache, 20) << "D3nDataCache: " << __func__ << "()" << dendl; | |
81 | auto p = std::unique_ptr<Completion>{static_cast<Completion*>(sigval.sival_ptr)}; | |
82 | auto op = std::move(p->user_data); | |
83 | const int ret = -aio_error(op.aio_cb.get()); | |
84 | boost::system::error_code ec; | |
85 | if (ret < 0) { | |
86 | ec.assign(-ret, boost::system::system_category()); | |
87 | } | |
88 | ||
89 | ceph::async::dispatch(std::move(p), ec, std::move(op.result)); | |
90 | } | |
91 | ||
92 | template <typename Executor1, typename CompletionHandler> | |
93 | static auto create(const Executor1& ex1, CompletionHandler&& handler) { | |
94 | auto p = Completion::create(ex1, std::move(handler)); | |
95 | return p; | |
96 | } | |
97 | }; | |
98 | ||
99 | template <typename ExecutionContext, typename CompletionToken> | |
100 | auto async_read(const DoutPrefixProvider *dpp, ExecutionContext& ctx, const std::string& file_path, | |
101 | off_t read_ofs, off_t read_len, CompletionToken&& token) { | |
102 | using Op = AsyncFileReadOp; | |
103 | using Signature = typename Op::Signature; | |
104 | boost::asio::async_completion<CompletionToken, Signature> init(token); | |
105 | auto p = Op::create(ctx.get_executor(), init.completion_handler); | |
106 | auto& op = p->user_data; | |
107 | ||
108 | ldpp_dout(dpp, 20) << "D3nDataCache: " << __func__ << "(): file_path=" << file_path << dendl; | |
109 | int ret = op.init(dpp, file_path, read_ofs, read_len, p.get()); | |
110 | if(0 == ret) { | |
111 | ret = ::aio_read(op.aio_cb.get()); | |
112 | } | |
113 | ldpp_dout(dpp, 20) << "D3nDataCache: " << __func__ << "(): ::aio_read(), ret=" << ret << dendl; | |
114 | if(ret < 0) { | |
115 | auto ec = boost::system::error_code{-ret, boost::system::system_category()}; | |
116 | ceph::async::post(std::move(p), ec, bufferlist{}); | |
117 | } else { | |
118 | (void)p.release(); | |
119 | } | |
120 | return init.result.get(); | |
121 | } | |
122 | ||
123 | struct d3n_libaio_handler { | |
124 | rgw::Aio* throttle = nullptr; | |
125 | rgw::AioResult& r; | |
126 | // read callback | |
127 | void operator()(boost::system::error_code ec, bufferlist bl) const { | |
128 | r.result = -ec.value(); | |
129 | r.data = std::move(bl); | |
130 | throttle->put(r); | |
131 | } | |
132 | }; | |
133 | ||
134 | void file_aio_read_abstract(const DoutPrefixProvider *dpp, boost::asio::io_context& context, yield_context yield, | |
135 | std::string& file_path, off_t read_ofs, off_t read_len, | |
136 | rgw::Aio* aio, rgw::AioResult& r) { | |
137 | using namespace boost::asio; | |
138 | async_completion<yield_context, void()> init(yield); | |
139 | auto ex = get_associated_executor(init.completion_handler); | |
140 | ||
141 | auto& ref = r.obj.get_ref(); | |
142 | ldpp_dout(dpp, 20) << "D3nDataCache: " << __func__ << "(): oid=" << ref.obj.oid << dendl; | |
143 | async_read(dpp, context, file_path+"/"+ref.obj.oid, read_ofs, read_len, bind_executor(ex, d3n_libaio_handler{aio, r})); | |
144 | } | |
145 | ||
146 | }; | |
147 | ||
148 | #endif |