]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/common/test_mclock_priority_queue.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2017 Red Hat Inc.
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.
18 #include "gtest/gtest.h"
19 #include "common/mClockPriorityQueue.h"
25 Request(const Request
& o
) = default;
37 Client(int client_num
) :
38 client_num(client_num
)
40 friend bool operator<(const Client
& r1
, const Client
& r2
) {
41 return r1
.client_num
< r2
.client_num
;
43 friend bool operator==(const Client
& r1
, const Client
& r2
) {
44 return r1
.client_num
== r2
.client_num
;
49 crimson::dmclock::ClientInfo
client_info_func(const Client
& c
) {
50 static const crimson::dmclock::ClientInfo
51 the_info(10.0, 10.0, 10.0);
56 TEST(mClockPriorityQueue
, Create
)
58 ceph::mClockQueue
<Request
,Client
> q(&client_info_func
);
62 TEST(mClockPriorityQueue
, Sizes
)
64 ceph::mClockQueue
<Request
,Client
> q(&client_info_func
);
66 ASSERT_TRUE(q
.empty());
67 ASSERT_EQ(0u, q
.length());
72 q
.enqueue_strict(c1
, 1, Request(1));
73 q
.enqueue_strict(c2
, 2, Request(2));
74 q
.enqueue_strict(c1
, 2, Request(3));
75 q
.enqueue(c2
, 1, 0, Request(4));
76 q
.enqueue(c1
, 2, 0, Request(5));
77 q
.enqueue_strict(c2
, 1, Request(6));
79 ASSERT_FALSE(q
.empty());
80 ASSERT_EQ(6u, q
.length());
83 for (int i
= 0; i
< 6; ++i
) {
87 ASSERT_TRUE(q
.empty());
88 ASSERT_EQ(0u, q
.length());
92 TEST(mClockPriorityQueue
, JustStrict
)
94 ceph::mClockQueue
<Request
,Client
> q(&client_info_func
);
99 q
.enqueue_strict(c1
, 1, Request(1));
100 q
.enqueue_strict(c2
, 2, Request(2));
101 q
.enqueue_strict(c1
, 2, Request(3));
102 q
.enqueue_strict(c2
, 1, Request(4));
107 ASSERT_EQ(2, r
.value
);
109 ASSERT_EQ(3, r
.value
);
111 ASSERT_EQ(1, r
.value
);
113 ASSERT_EQ(4, r
.value
);
117 TEST(mClockPriorityQueue
, StrictPriorities
)
119 ceph::mClockQueue
<Request
,Client
> q(&client_info_func
);
124 q
.enqueue_strict(c1
, 1, Request(1));
125 q
.enqueue_strict(c2
, 2, Request(2));
126 q
.enqueue_strict(c1
, 3, Request(3));
127 q
.enqueue_strict(c2
, 4, Request(4));
132 ASSERT_EQ(4, r
.value
);
134 ASSERT_EQ(3, r
.value
);
136 ASSERT_EQ(2, r
.value
);
138 ASSERT_EQ(1, r
.value
);
142 TEST(mClockPriorityQueue
, JustNotStrict
)
144 ceph::mClockQueue
<Request
,Client
> q(&client_info_func
);
149 // non-strict queue ignores priorites, but will divide between
150 // clients evenly and maintain orders between clients
151 q
.enqueue(c1
, 1, 0, Request(1));
152 q
.enqueue(c1
, 2, 0, Request(2));
153 q
.enqueue(c2
, 3, 0, Request(3));
154 q
.enqueue(c2
, 4, 0, Request(4));
159 ASSERT_TRUE(1 == r1
.value
|| 3 == r1
.value
);
162 ASSERT_TRUE(1 == r2
.value
|| 3 == r2
.value
);
164 ASSERT_NE(r1
.value
, r2
.value
);
167 ASSERT_TRUE(2 == r1
.value
|| 4 == r1
.value
);
170 ASSERT_TRUE(2 == r2
.value
|| 4 == r2
.value
);
172 ASSERT_NE(r1
.value
, r2
.value
);
176 TEST(mClockPriorityQueue
, EnqueuFront
)
178 ceph::mClockQueue
<Request
,Client
> q(&client_info_func
);
183 // non-strict queue ignores priorites, but will divide between
184 // clients evenly and maintain orders between clients
185 q
.enqueue(c1
, 1, 0, Request(1));
186 q
.enqueue(c1
, 2, 0, Request(2));
187 q
.enqueue(c2
, 3, 0, Request(3));
188 q
.enqueue(c2
, 4, 0, Request(4));
189 q
.enqueue_strict(c2
, 6, Request(6));
190 q
.enqueue_strict(c1
, 7, Request(7));
192 std::list
<Request
> reqs
;
194 for (uint i
= 0; i
< 4; ++i
) {
195 reqs
.emplace_back(q
.dequeue());
198 for (uint i
= 0; i
< 4; ++i
) {
199 Request
& r
= reqs
.front();
201 q
.enqueue_strict_front(r
.value
== 6 ? c2
: 1, r
.value
, r
);
203 q
.enqueue_front(r
.value
<= 2 ? c1
: c2
, r
.value
, 0, r
);
211 ASSERT_EQ(7, r
.value
);
214 ASSERT_EQ(6, r
.value
);
217 ASSERT_TRUE(1 == r
.value
|| 3 == r
.value
);
220 ASSERT_TRUE(1 == r
.value
|| 3 == r
.value
);
223 ASSERT_TRUE(2 == r
.value
|| 4 == r
.value
);
226 ASSERT_TRUE(2 == r
.value
|| 4 == r
.value
);
230 TEST(mClockPriorityQueue
, RemoveByClass
)
232 ceph::mClockQueue
<Request
,Client
> q(&client_info_func
);
238 q
.enqueue(c1
, 1, 0, Request(1));
239 q
.enqueue(c2
, 1, 0, Request(2));
240 q
.enqueue(c3
, 1, 0, Request(4));
241 q
.enqueue_strict(c1
, 2, Request(8));
242 q
.enqueue_strict(c2
, 1, Request(16));
243 q
.enqueue_strict(c3
, 3, Request(32));
244 q
.enqueue(c3
, 1, 0, Request(64));
245 q
.enqueue(c2
, 1, 0, Request(128));
246 q
.enqueue(c1
, 1, 0, Request(256));
248 int out_mask
= 2 | 16 | 128;
249 int in_mask
= 1 | 8 | 256;
251 std::list
<Request
> out
;
252 q
.remove_by_class(c2
, &out
);
254 ASSERT_EQ(3u, out
.size());
255 while (!out
.empty()) {
256 ASSERT_TRUE((out
.front().value
& out_mask
) > 0) <<
257 "had value that was not expected after first removal";
261 ASSERT_EQ(6u, q
.length()) << "after removal of three from client c2";
263 q
.remove_by_class(c3
);
265 ASSERT_EQ(3u, q
.length()) << "after removal of three from client c3";
267 Request r
= q
.dequeue();
268 ASSERT_TRUE((r
.value
& in_mask
) > 0) <<
269 "had value that was not expected after two removals";
274 TEST(mClockPriorityQueue
, RemoveByFilter
)
276 ceph::mClockQueue
<Request
,Client
> q(&client_info_func
);
282 q
.enqueue(c1
, 1, 0, Request(1));
283 q
.enqueue(c2
, 1, 0, Request(2));
284 q
.enqueue(c3
, 1, 0, Request(3));
285 q
.enqueue_strict(c1
, 2, Request(4));
286 q
.enqueue_strict(c2
, 1, Request(5));
287 q
.enqueue_strict(c3
, 3, Request(6));
288 q
.enqueue(c3
, 1, 0, Request(7));
289 q
.enqueue(c2
, 1, 0, Request(8));
290 q
.enqueue(c1
, 1, 0, Request(9));
292 std::list
<Request
> filtered
;
294 q
.remove_by_filter([&](const Request
& r
) -> bool {
296 filtered
.push_back(r
);
303 ASSERT_EQ(4u, filtered
.size()) <<
304 "filter should have removed four elements";
305 while (!filtered
.empty()) {
306 ASSERT_TRUE((filtered
.front().value
& 2) > 0) <<
307 "expect this value to have been filtered out";
308 filtered
.pop_front();
311 ASSERT_EQ(5u, q
.length()) <<
312 "filter should have left five remaining elements";
314 Request r
= q
.dequeue();
315 ASSERT_TRUE((r
.value
& 2) == 0) <<
316 "expect this value to have been left in";