typedef std::list<std::pair<cost_t, T> > ListPairs;
- static unsigned filter_list_pairs(ListPairs *l,
- std::function<bool (T&&)> f) {
- unsigned ret = 0;
+ static void filter_list_pairs(ListPairs *l,
+ std::function<bool (T&&)> f) {
for (typename ListPairs::iterator i = l->end();
i != l->begin();
/* no inc */
auto next = i;
--next;
if (f(std::move(next->second))) {
- ++ret;
l->erase(next);
} else {
i = next;
}
}
- return ret;
}
struct SubQueue {
Classes q;
unsigned tokens, max_tokens;
- int64_t size; // XXX: this is only for the sake of dump().
typename Classes::iterator cur;
: q(other.q),
tokens(other.tokens),
max_tokens(other.max_tokens),
- size(other.size),
cur(q.begin()) {}
SubQueue()
: tokens(0),
max_tokens(0),
- size(0), cur(q.begin()) {}
+ cur(q.begin()) {}
void set_max_tokens(unsigned mt) {
max_tokens = mt;
q[cl].emplace_back(cost, std::move(item));
if (cur == q.end())
cur = q.begin();
- size++;
}
void enqueue_front(K cl, cost_t cost, T&& item) {
q[cl].emplace_front(cost, std::move(item));
if (cur == q.end())
cur = q.begin();
- size++;
}
const std::pair<cost_t, T>& front() const {
if (cur == q.end()) {
cur = q.begin();
}
- size--;
}
- unsigned length() const {
- ceph_assert(size >= 0);
- return (unsigned)size;
+ unsigned get_size_slow() const {
+ unsigned count = 0;
+ for (const auto& cls : q) {
+ count += cls.second.size();
+ }
+ return count;
}
bool empty() const {
for (typename Classes::iterator i = q.begin();
i != q.end();
/* no-inc */) {
- size -= filter_list_pairs(&(i->second), f);
+ filter_list_pairs(&(i->second), f);
if (i->second.empty()) {
if (cur == i) {
++cur;
if (i == q.end()) {
return;
}
- size -= i->second.size();
if (i == cur) {
++cur;
}
}
void dump(ceph::Formatter *f) const {
- f->dump_int("size", length());
+ f->dump_int("size", get_size_slow());
f->dump_int("num_keys", q.size());
}
};
// empty
}
- // XXX: used only by the unitest?
- unsigned length() const {
+ unsigned get_size_slow() const {
unsigned total = 0;
total += queue_front.size();
total += queue.request_count();
for (auto i = high_queue.cbegin(); i != high_queue.cend(); ++i) {
- ceph_assert(i->second.length());
- total += i->second.length();
+ ceph_assert(i->second.get_size_slow());
+ total += i->second.get_size_slow();
}
return total;
}
const crimson::dmclock::ClientInfo* op_class_client_info_f(const InnerClient& client);
+ inline unsigned get_size_slow() const {
+ return queue.get_size_slow();
+ }
+
// Ops of this priority should be deleted immediately
inline void remove_by_class(Client cl,
std::list<Request> *out) override final {
const crimson::dmclock::ClientInfo*
op_class_client_info_f(const osd_op_type_t& op_type);
+ inline unsigned get_size_slow() const {
+ return queue.get_size_slow();
+ }
+
// Ops of this priority should be deleted immediately
inline void remove_by_class(Client cl,
std::list<Request> *out) override final {
ceph::mClockQueue<Request,Client> q(&client_info_func);
ASSERT_TRUE(q.empty());
- ASSERT_EQ(0u, q.length());
+ ASSERT_EQ(0u, q.get_size_slow());
Client c1(1);
Client c2(2);
q.enqueue_strict(c2, 1, Request(6));
ASSERT_FALSE(q.empty());
- ASSERT_EQ(6u, q.length());
+ ASSERT_EQ(6u, q.get_size_slow());
for (int i = 0; i < 6; ++i) {
}
ASSERT_TRUE(q.empty());
- ASSERT_EQ(0u, q.length());
+ ASSERT_EQ(0u, q.get_size_slow());
}
out.pop_front();
}
- ASSERT_EQ(6u, q.length()) << "after removal of three from client c2";
+ ASSERT_EQ(6u, q.get_size_slow()) << "after removal of three from client c2";
q.remove_by_class(c3);
- ASSERT_EQ(3u, q.length()) << "after removal of three from client c3";
+ ASSERT_EQ(3u, q.get_size_slow()) << "after removal of three from client c3";
while (!q.empty()) {
Request r = q.dequeue();
ASSERT_TRUE((r.value & in_mask) > 0) <<
filtered.pop_front();
}
- ASSERT_EQ(5u, q.length()) <<
+ ASSERT_EQ(5u, q.get_size_slow()) <<
"filter should have left five remaining elements";
while (!q.empty()) {
Request r = q.dequeue();
TEST_F(MClockClientQueueTest, TestSize) {
ASSERT_TRUE(q.empty());
- ASSERT_EQ(0u, q.length());
+ ASSERT_EQ(0u, q.get_size_slow());
q.enqueue(client1, 12, 1u, create_snaptrim(100, client1));
q.enqueue_strict(client2, 12, create_snaptrim(101, client2));
q.enqueue(client1, 12, 1u, create_snaptrim(104, client1));
ASSERT_FALSE(q.empty());
- ASSERT_EQ(5u, q.length());
+ ASSERT_EQ(5u, q.get_size_slow());
std::list<Request> reqs;
reqs.push_back(q.dequeue());
ASSERT_FALSE(q.empty());
- ASSERT_EQ(2u, q.length());
+ ASSERT_EQ(2u, q.get_size_slow());
q.enqueue_front(client2, 12, 1u, std::move(reqs.back()));
reqs.pop_back();
reqs.pop_back();
ASSERT_FALSE(q.empty());
- ASSERT_EQ(5u, q.length());
+ ASSERT_EQ(5u, q.get_size_slow());
for (int i = 0; i < 5; ++i) {
(void) q.dequeue();
}
ASSERT_TRUE(q.empty());
- ASSERT_EQ(0u, q.length());
+ ASSERT_EQ(0u, q.get_size_slow());
}
filtered_out.pop_front();
}
- ASSERT_EQ(3u, q.length());
+ ASSERT_EQ(3u, q.get_size_slow());
Request r = q.dequeue();
ASSERT_EQ(103u, r.get_map_epoch());
TEST_F(MClockOpClassQueueTest, TestSize) {
ASSERT_TRUE(q.empty());
- ASSERT_EQ(0u, q.length());
+ ASSERT_EQ(0u, q.get_size_slow());
q.enqueue(client1, 12, 0, create_snaptrim(100, client1));
q.enqueue_strict(client2, 12, create_snaptrim(101, client2));
q.enqueue(client1, 12, 0, create_snaptrim(104, client1));
ASSERT_FALSE(q.empty());
- ASSERT_EQ(5u, q.length());
+ ASSERT_EQ(5u, q.get_size_slow());
std::list<Request> reqs;
reqs.push_back(q.dequeue());
ASSERT_FALSE(q.empty());
- ASSERT_EQ(2u, q.length());
+ ASSERT_EQ(2u, q.get_size_slow());
q.enqueue_front(client2, 12, 0, std::move(reqs.back()));
reqs.pop_back();
reqs.pop_back();
ASSERT_FALSE(q.empty());
- ASSERT_EQ(5u, q.length());
+ ASSERT_EQ(5u, q.get_size_slow());
for (int i = 0; i < 5; ++i) {
(void) q.dequeue();
}
ASSERT_TRUE(q.empty());
- ASSERT_EQ(0u, q.length());
+ ASSERT_EQ(0u, q.get_size_slow());
}
filtered_out.pop_front();
}
- ASSERT_EQ(3u, q.length());
+ ASSERT_EQ(3u, q.get_size_slow());
Request r = q.dequeue();
ASSERT_EQ(103u, r.get_map_epoch());