]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/common/test_mclock_priority_queue.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / common / test_mclock_priority_queue.cc
CommitLineData
224ce89b
WB
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2017 Red Hat Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include <thread>
16#include <chrono>
17#include <iostream>
18#include "gtest/gtest.h"
19#include "common/mClockPriorityQueue.h"
20
21
22struct Request {
23 int value;
11fdf7f2
TL
24 Request() :
25 value(0)
26 {}
224ce89b 27 Request(const Request& o) = default;
11fdf7f2 28 explicit Request(int value) :
224ce89b
WB
29 value(value)
30 {}
31};
32
33
34struct Client {
35 int client_num;
36 Client() :
37 Client(-1)
38 {}
39 Client(int client_num) :
40 client_num(client_num)
41 {}
42 friend bool operator<(const Client& r1, const Client& r2) {
43 return r1.client_num < r2.client_num;
44 }
45 friend bool operator==(const Client& r1, const Client& r2) {
46 return r1.client_num == r2.client_num;
47 }
48};
49
50
11fdf7f2 51const crimson::dmclock::ClientInfo* client_info_func(const Client& c) {
224ce89b
WB
52 static const crimson::dmclock::ClientInfo
53 the_info(10.0, 10.0, 10.0);
11fdf7f2 54 return &the_info;
224ce89b
WB
55}
56
57
58TEST(mClockPriorityQueue, Create)
59{
60 ceph::mClockQueue<Request,Client> q(&client_info_func);
61}
62
63
64TEST(mClockPriorityQueue, Sizes)
65{
66 ceph::mClockQueue<Request,Client> q(&client_info_func);
67
68 ASSERT_TRUE(q.empty());
11fdf7f2 69 ASSERT_EQ(0u, q.get_size_slow());
224ce89b
WB
70
71 Client c1(1);
72 Client c2(2);
73
74 q.enqueue_strict(c1, 1, Request(1));
75 q.enqueue_strict(c2, 2, Request(2));
76 q.enqueue_strict(c1, 2, Request(3));
11fdf7f2
TL
77 q.enqueue(c2, 1, 1u, Request(4));
78 q.enqueue(c1, 2, 1u, Request(5));
224ce89b
WB
79 q.enqueue_strict(c2, 1, Request(6));
80
81 ASSERT_FALSE(q.empty());
11fdf7f2 82 ASSERT_EQ(6u, q.get_size_slow());
224ce89b
WB
83
84
85 for (int i = 0; i < 6; ++i) {
86 (void) q.dequeue();
87 }
88
89 ASSERT_TRUE(q.empty());
11fdf7f2 90 ASSERT_EQ(0u, q.get_size_slow());
224ce89b
WB
91}
92
93
94TEST(mClockPriorityQueue, JustStrict)
95{
96 ceph::mClockQueue<Request,Client> q(&client_info_func);
97
98 Client c1(1);
99 Client c2(2);
100
101 q.enqueue_strict(c1, 1, Request(1));
102 q.enqueue_strict(c2, 2, Request(2));
103 q.enqueue_strict(c1, 2, Request(3));
104 q.enqueue_strict(c2, 1, Request(4));
105
106 Request r;
107
108 r = q.dequeue();
109 ASSERT_EQ(2, r.value);
110 r = q.dequeue();
111 ASSERT_EQ(3, r.value);
112 r = q.dequeue();
113 ASSERT_EQ(1, r.value);
114 r = q.dequeue();
115 ASSERT_EQ(4, r.value);
116}
117
118
119TEST(mClockPriorityQueue, StrictPriorities)
120{
121 ceph::mClockQueue<Request,Client> q(&client_info_func);
122
123 Client c1(1);
124 Client c2(2);
125
126 q.enqueue_strict(c1, 1, Request(1));
127 q.enqueue_strict(c2, 2, Request(2));
128 q.enqueue_strict(c1, 3, Request(3));
129 q.enqueue_strict(c2, 4, Request(4));
130
131 Request r;
132
133 r = q.dequeue();
134 ASSERT_EQ(4, r.value);
135 r = q.dequeue();
136 ASSERT_EQ(3, r.value);
137 r = q.dequeue();
138 ASSERT_EQ(2, r.value);
139 r = q.dequeue();
140 ASSERT_EQ(1, r.value);
141}
142
143
144TEST(mClockPriorityQueue, JustNotStrict)
145{
146 ceph::mClockQueue<Request,Client> q(&client_info_func);
147
148 Client c1(1);
149 Client c2(2);
150
151 // non-strict queue ignores priorites, but will divide between
152 // clients evenly and maintain orders between clients
11fdf7f2
TL
153 q.enqueue(c1, 1, 1u, Request(1));
154 q.enqueue(c1, 2, 1u, Request(2));
155 q.enqueue(c2, 3, 1u, Request(3));
156 q.enqueue(c2, 4, 1u, Request(4));
224ce89b
WB
157
158 Request r1, r2;
159
160 r1 = q.dequeue();
161 ASSERT_TRUE(1 == r1.value || 3 == r1.value);
162
163 r2 = q.dequeue();
164 ASSERT_TRUE(1 == r2.value || 3 == r2.value);
165
166 ASSERT_NE(r1.value, r2.value);
167
168 r1 = q.dequeue();
169 ASSERT_TRUE(2 == r1.value || 4 == r1.value);
170
171 r2 = q.dequeue();
172 ASSERT_TRUE(2 == r2.value || 4 == r2.value);
173
174 ASSERT_NE(r1.value, r2.value);
175}
176
177
178TEST(mClockPriorityQueue, EnqueuFront)
179{
180 ceph::mClockQueue<Request,Client> q(&client_info_func);
181
182 Client c1(1);
183 Client c2(2);
184
185 // non-strict queue ignores priorites, but will divide between
186 // clients evenly and maintain orders between clients
11fdf7f2
TL
187 q.enqueue(c1, 1, 1u, Request(1));
188 q.enqueue(c1, 2, 1u, Request(2));
189 q.enqueue(c2, 3, 1u, Request(3));
190 q.enqueue(c2, 4, 1u, Request(4));
224ce89b
WB
191 q.enqueue_strict(c2, 6, Request(6));
192 q.enqueue_strict(c1, 7, Request(7));
193
194 std::list<Request> reqs;
195
196 for (uint i = 0; i < 4; ++i) {
197 reqs.emplace_back(q.dequeue());
198 }
199
200 for (uint i = 0; i < 4; ++i) {
201 Request& r = reqs.front();
202 if (r.value > 5) {
11fdf7f2 203 q.enqueue_strict_front(r.value == 6 ? c2 : 1, r.value, std::move(r));
224ce89b 204 } else {
11fdf7f2 205 q.enqueue_front(r.value <= 2 ? c1 : c2, r.value, 0, std::move(r));
224ce89b
WB
206 }
207 reqs.pop_front();
208 }
209
210 Request r;
211
212 r = q.dequeue();
213 ASSERT_EQ(7, r.value);
214
215 r = q.dequeue();
216 ASSERT_EQ(6, r.value);
217
218 r = q.dequeue();
219 ASSERT_TRUE(1 == r.value || 3 == r.value);
220
221 r = q.dequeue();
222 ASSERT_TRUE(1 == r.value || 3 == r.value);
223
224 r = q.dequeue();
225 ASSERT_TRUE(2 == r.value || 4 == r.value);
226
227 r = q.dequeue();
228 ASSERT_TRUE(2 == r.value || 4 == r.value);
229}
230
231
232TEST(mClockPriorityQueue, RemoveByClass)
233{
234 ceph::mClockQueue<Request,Client> q(&client_info_func);
235
236 Client c1(1);
237 Client c2(2);
238 Client c3(3);
239
11fdf7f2
TL
240 q.enqueue(c1, 1, 1u, Request(1));
241 q.enqueue(c2, 1, 1u, Request(2));
242 q.enqueue(c3, 1, 1u, Request(4));
224ce89b
WB
243 q.enqueue_strict(c1, 2, Request(8));
244 q.enqueue_strict(c2, 1, Request(16));
245 q.enqueue_strict(c3, 3, Request(32));
11fdf7f2
TL
246 q.enqueue(c3, 1, 1u, Request(64));
247 q.enqueue(c2, 1, 1u, Request(128));
248 q.enqueue(c1, 1, 1u, Request(256));
224ce89b
WB
249
250 int out_mask = 2 | 16 | 128;
251 int in_mask = 1 | 8 | 256;
252
253 std::list<Request> out;
254 q.remove_by_class(c2, &out);
255
256 ASSERT_EQ(3u, out.size());
257 while (!out.empty()) {
258 ASSERT_TRUE((out.front().value & out_mask) > 0) <<
259 "had value that was not expected after first removal";
260 out.pop_front();
261 }
262
11fdf7f2 263 ASSERT_EQ(6u, q.get_size_slow()) << "after removal of three from client c2";
224ce89b
WB
264
265 q.remove_by_class(c3);
266
11fdf7f2 267 ASSERT_EQ(3u, q.get_size_slow()) << "after removal of three from client c3";
224ce89b
WB
268 while (!q.empty()) {
269 Request r = q.dequeue();
270 ASSERT_TRUE((r.value & in_mask) > 0) <<
271 "had value that was not expected after two removals";
272 }
273}
274
275
276TEST(mClockPriorityQueue, RemoveByFilter)
277{
278 ceph::mClockQueue<Request,Client> q(&client_info_func);
279
280 Client c1(1);
281 Client c2(2);
282 Client c3(3);
283
11fdf7f2
TL
284 q.enqueue(c1, 1, 1u, Request(1));
285 q.enqueue(c2, 1, 1u, Request(2));
286 q.enqueue(c3, 1, 1u, Request(3));
224ce89b
WB
287 q.enqueue_strict(c1, 2, Request(4));
288 q.enqueue_strict(c2, 1, Request(5));
289 q.enqueue_strict(c3, 3, Request(6));
11fdf7f2
TL
290 q.enqueue(c3, 1, 1u, Request(7));
291 q.enqueue(c2, 1, 1u, Request(8));
292 q.enqueue(c1, 1, 1u, Request(9));
224ce89b
WB
293
294 std::list<Request> filtered;
295
296 q.remove_by_filter([&](const Request& r) -> bool {
297 if (r.value & 2) {
298 filtered.push_back(r);
299 return true;
300 } else {
301 return false;
302 }
303 });
304
305 ASSERT_EQ(4u, filtered.size()) <<
306 "filter should have removed four elements";
307 while (!filtered.empty()) {
308 ASSERT_TRUE((filtered.front().value & 2) > 0) <<
309 "expect this value to have been filtered out";
310 filtered.pop_front();
311 }
312
11fdf7f2 313 ASSERT_EQ(5u, q.get_size_slow()) <<
224ce89b
WB
314 "filter should have left five remaining elements";
315 while (!q.empty()) {
316 Request r = q.dequeue();
317 ASSERT_TRUE((r.value & 2) == 0) <<
318 "expect this value to have been left in";
319 }
320}