Seastar
High performance C++ framework for concurrent servers
io_queue.hh
1 /*
2  * This file is open source software, licensed to you under the terms
3  * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4  * distributed with this work for additional information regarding copyright
5  * ownership. You may not use this file except in compliance with the License.
6  *
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14  * KIND, either express or implied. See the License for the
15  * specific language governing permissions and limitations
16  * under the License.
17  */
18 /*
19  * Copyright 2019 ScyllaDB
20  */
21 
22 #pragma once
23 
24 #include <seastar/core/sstring.hh>
25 #include <seastar/core/fair_queue.hh>
27 #include <seastar/core/future.hh>
28 #include <seastar/core/internal/io_request.hh>
29 #include <mutex>
30 #include <array>
31 
32 namespace seastar {
33 
34 class io_priority_class;
35 
46 future<>
47 rename_priority_class(io_priority_class pc, sstring new_name);
48 
49 namespace internal {
50 namespace linux_abi {
51 
52 struct io_event;
53 struct iocb;
54 
55 }
56 }
57 
58 using shard_id = unsigned;
59 
60 class io_priority_class;
61 
62 class io_queue {
63 private:
64  struct priority_class_data {
65  priority_class_ptr ptr;
66  size_t bytes;
67  uint64_t ops;
68  uint32_t nr_queued;
69  std::chrono::duration<double> queue_time;
70  metrics::metric_groups _metric_groups;
71  priority_class_data(sstring name, sstring mountpoint, priority_class_ptr ptr, shard_id owner);
72  void rename(sstring new_name, sstring mountpoint, shard_id owner);
73  private:
74  void register_stats(sstring name, sstring mountpoint, shard_id owner);
75  };
76 
77  std::vector<std::vector<std::unique_ptr<priority_class_data>>> _priority_classes;
78  fair_queue _fq;
79 
80  static constexpr unsigned _max_classes = 2048;
81  static std::mutex _register_lock;
82  static std::array<uint32_t, _max_classes> _registered_shares;
83  static std::array<sstring, _max_classes> _registered_names;
84 
85 public:
86  static io_priority_class register_one_priority_class(sstring name, uint32_t shares);
87  static bool rename_one_priority_class(io_priority_class pc, sstring name);
88 
89 private:
90  priority_class_data& find_or_create_class(const io_priority_class& pc, shard_id owner);
91 
92  fair_queue_ticket request_fq_ticket(const internal::io_request& req, size_t len) const;
93 
94  // The fields below are going away, they are just here so we can implement deprecated
95  // functions that used to be provided by the fair_queue and are going away (from both
96  // the fair_queue and the io_queue). Double-accounting for now will allow for easier
97  // decoupling and is temporary
98  size_t _queued_requests = 0;
99  size_t _requests_executing = 0;
100 public:
101  // We want to represent the fact that write requests are (maybe) more expensive
102  // than read requests. To avoid dealing with floating point math we will scale one
103  // read request to be counted by this amount.
104  //
105  // A write request that is 30% more expensive than a read will be accounted as
106  // (read_request_base_count * 130) / 100.
107  // It is also technically possible for reads to be the expensive ones, in which case
108  // writes will have an integer value lower than read_request_base_count.
109  static constexpr unsigned read_request_base_count = 128;
110 
111  struct config {
112  dev_t devid;
113  shard_id coordinator;
114  unsigned capacity = std::numeric_limits<unsigned>::max();
115  unsigned max_req_count = std::numeric_limits<unsigned>::max();
116  unsigned max_bytes_count = std::numeric_limits<unsigned>::max();
117  unsigned disk_req_write_to_read_multiplier = read_request_base_count;
118  unsigned disk_bytes_write_to_read_multiplier = read_request_base_count;
119  sstring mountpoint = "undefined";
120  };
121 
122  io_queue(config cfg);
123  ~io_queue();
124 
126  queue_request(const io_priority_class& pc, size_t len, internal::io_request req) noexcept;
127 
128  [[deprecated("modern I/O queues should use a property file")]] size_t capacity() const {
129  return _config.capacity;
130  }
131 
132  [[deprecated("I/O queue users should not track individual requests, but resources (weight, size) passing through the queue")]]
133  size_t queued_requests() const {
134  return _queued_requests;
135  }
136 
137  // How many requests are sent to disk but not yet returned.
138  [[deprecated("I/O queue users should not track individual requests, but resources (weight, size) passing through the queue")]]
139  size_t requests_currently_executing() const {
140  return _requests_executing;
141  }
142 
143  void notify_requests_finished(fair_queue_ticket& desc) noexcept;
144 
145  // Dispatch requests that are pending in the I/O queue
146  void poll_io_queue() {
147  _fq.dispatch_requests();
148  }
149 
150  sstring mountpoint() const {
151  return _config.mountpoint;
152  }
153 
154  shard_id coordinator() const {
155  return _config.coordinator;
156  }
157 
158  dev_t dev_id() const noexcept {
159  return _config.devid;
160  }
161 
162  future<> update_shares_for_class(io_priority_class pc, size_t new_shares);
163  void rename_priority_class(io_priority_class pc, sstring new_name);
164 
165 private:
166  config _config;
167  static fair_queue::config make_fair_queue_config(config cfg);
168 };
169 
170 }
seastar::io_queue::config
Definition: io_queue.hh:111
seastar
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
seastar::io_queue
Definition: io_queue.hh:62
seastar::fair_queue
Fair queuing class.
Definition: fair_queue.hh:150
seastar::future
A representation of a possibly not-yet-computed value.
Definition: future.hh:1337
seastar::fair_queue_ticket
describes a request that passes through the fair_queue.
Definition: fair_queue.hh:40
seastar::metrics::metric_groups
holds the metric definition.
Definition: metrics_registration.hh:89
metrics_registration.hh
holds the metric_groups definition needed by class that reports metrics
seastar::fair_queue::dispatch_requests
void dispatch_requests()
Try to execute new requests if there is capacity left in the queue.
seastar::rename_priority_class
future rename_priority_class(io_priority_class pc, sstring new_name)