]> git.sesse.net Git - plocate/blob - io_uring_engine.h
Release plocate 1.1.7.
[plocate] / io_uring_engine.h
1 #ifndef IO_URING_ENGINE_H
2 #define IO_URING_ENGINE_H 1
3
4 #include <functional>
5 #include <queue>
6 #include <stddef.h>
7 #include <string_view>
8 #include <sys/socket.h>
9 #include <sys/types.h>
10
11 struct io_uring_sqe;
12 #ifndef WITHOUT_URING
13 #include <liburing.h>
14 #endif
15
16 class IOUringEngine {
17 public:
18         IOUringEngine(size_t slop_bytes);
19         void submit_read(int fd, size_t len, off_t offset, std::function<void(std::string_view)> cb);
20
21         // NOTE: We just do the stat() to get the data into the dentry cache for fast access;
22         // we don't care about the return value. Thus, the callback has no parameter lists.
23         // If we have no io_uring, the callback will be made immediately, with no stat() call
24         // being done.
25         void submit_stat(const char *path, std::function<void()> cb);
26         bool get_supports_stat() { return supports_stat; }
27
28         void finish();
29         size_t get_waiting_reads() const { return pending_reads + queued_reads.size(); }
30
31 private:
32 #ifndef WITHOUT_URING
33         void submit_read_internal(io_uring_sqe *sqe, int fd, size_t len, off_t offset, std::function<void(std::string_view)> cb);
34         void submit_stat_internal(io_uring_sqe *sqe, char *path, std::function<void()> cb);
35
36         io_uring ring;
37 #endif
38         size_t pending_reads = 0;  // Number of requests we have going in the ring.
39         bool using_uring, supports_stat = false;
40         const size_t slop_bytes;
41
42         struct QueuedRead {
43                 int fd;
44                 size_t len;
45                 off_t offset;
46                 std::function<void(std::string_view)> cb;
47         };
48         std::queue<QueuedRead> queued_reads;
49
50         struct QueuedStat {
51                 char *pathname;  // Owned by us.
52                 std::function<void()> cb;
53         };
54         std::queue<QueuedStat> queued_stats;
55
56         enum Op { OP_READ,
57                   OP_STAT };
58
59         struct PendingRead {
60                 Op op;
61
62                 std::function<void(std::string_view)> read_cb;
63                 std::function<void()> stat_cb;
64
65                 union {
66                         struct {
67                                 void *buf;
68                                 size_t len;
69
70                                 // For re-submission.
71                                 int fd;
72                                 off_t offset;
73                                 iovec iov;
74                         } read;
75                         struct {
76                                 char *pathname;
77                                 struct statx *buf;
78                         } stat;
79                 };
80         };
81
82         // 256 simultaneous requests should be ample, for slow and fast media alike.
83         static constexpr size_t queue_depth = 256;
84 };
85
86 #endif  // !defined(IO_URING_ENGINE_H)