]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_d3n_cacherequest.h
import quincy 17.2.0
[ceph.git] / ceph / src / rgw / rgw_d3n_cacherequest.h
CommitLineData
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
23struct D3nGetObjData {
24 std::mutex d3n_lock;
25};
26
27struct 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