summaryrefslogtreecommitdiffstats
path: root/src/seastar/include/seastar/core/io_queue.hh
blob: dd7c1b1ab619dc8b64c94fc87931a432464ce2bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright 2019 ScyllaDB
 */

#pragma once

#include <seastar/core/sstring.hh>
#include <seastar/core/fair_queue.hh>
#include <seastar/core/metrics_registration.hh>
#include <seastar/core/future.hh>
#include <seastar/core/internal/io_request.hh>
#include <mutex>
#include <array>

namespace seastar {

class io_priority_class;

/// Renames an io priority class
///
/// Renames an `io_priority_class` previously created with register_one_priority_class().
///
/// The operation is global and affects all shards.
/// The operation affects the exported statistics labels.
///
/// \param pc The io priority class to be renamed
/// \param new_name The new name for the io priority class
/// \return a future that is ready when the io priority class have been renamed
future<>
rename_priority_class(io_priority_class pc, sstring new_name);

namespace internal {
namespace linux_abi {

struct io_event;
struct iocb;

}
}

using shard_id = unsigned;

class io_priority_class;

class io_queue {
private:
    struct priority_class_data {
        priority_class_ptr ptr;
        size_t bytes;
        uint64_t ops;
        uint32_t nr_queued;
        std::chrono::duration<double> queue_time;
        metrics::metric_groups _metric_groups;
        priority_class_data(sstring name, sstring mountpoint, priority_class_ptr ptr, shard_id owner);
        void rename(sstring new_name, sstring mountpoint, shard_id owner);
    private:
        void register_stats(sstring name, sstring mountpoint, shard_id owner);
    };

    std::vector<std::vector<std::unique_ptr<priority_class_data>>> _priority_classes;
    fair_queue _fq;

    static constexpr unsigned _max_classes = 2048;
    static std::mutex _register_lock;
    static std::array<uint32_t, _max_classes> _registered_shares;
    static std::array<sstring, _max_classes> _registered_names;

public:
    static io_priority_class register_one_priority_class(sstring name, uint32_t shares);
    static bool rename_one_priority_class(io_priority_class pc, sstring name);

private:
    priority_class_data& find_or_create_class(const io_priority_class& pc, shard_id owner);

    fair_queue_ticket request_fq_ticket(const internal::io_request& req, size_t len) const;

    // The fields below are going away, they are just here so we can implement deprecated
    // functions that used to be provided by the fair_queue and are going away (from both
    // the fair_queue and the io_queue). Double-accounting for now will allow for easier
    // decoupling and is temporary
    size_t _queued_requests = 0;
    size_t _requests_executing = 0;
public:
    // We want to represent the fact that write requests are (maybe) more expensive
    // than read requests. To avoid dealing with floating point math we will scale one
    // read request to be counted by this amount.
    //
    // A write request that is 30% more expensive than a read will be accounted as
    // (read_request_base_count * 130) / 100.
    // It is also technically possible for reads to be the expensive ones, in which case
    // writes will have an integer value lower than read_request_base_count.
    static constexpr unsigned read_request_base_count = 128;

    struct config {
        dev_t devid;
        shard_id coordinator;
        unsigned capacity = std::numeric_limits<unsigned>::max();
        unsigned max_req_count = std::numeric_limits<unsigned>::max();
        unsigned max_bytes_count = std::numeric_limits<unsigned>::max();
        unsigned disk_req_write_to_read_multiplier = read_request_base_count;
        unsigned disk_bytes_write_to_read_multiplier = read_request_base_count;
        sstring mountpoint = "undefined";
    };

    io_queue(config cfg);
    ~io_queue();

    future<size_t>
    queue_request(const io_priority_class& pc, size_t len, internal::io_request req) noexcept;

    [[deprecated("modern I/O queues should use a property file")]] size_t capacity() const {
        return _config.capacity;
    }

    [[deprecated("I/O queue users should not track individual requests, but resources (weight, size) passing through the queue")]]
    size_t queued_requests() const {
        return _queued_requests;
    }

    // How many requests are sent to disk but not yet returned.
    [[deprecated("I/O queue users should not track individual requests, but resources (weight, size) passing through the queue")]]
    size_t requests_currently_executing() const {
        return _requests_executing;
    }

    void notify_requests_finished(fair_queue_ticket& desc) noexcept;

    // Dispatch requests that are pending in the I/O queue
    void poll_io_queue() {
        _fq.dispatch_requests();
    }

    sstring mountpoint() const {
        return _config.mountpoint;
    }

    shard_id coordinator() const {
        return _config.coordinator;
    }

    dev_t dev_id() const noexcept {
        return _config.devid;
    }

    future<> update_shares_for_class(io_priority_class pc, size_t new_shares);
    void rename_priority_class(io_priority_class pc, sstring new_name);

private:
    config _config;
    static fair_queue::config make_fair_queue_config(config cfg);
};

}