With the introduction of a high priority queue in the mClock workflow, we no longer need a separate queue for ops that need to be processed immediately.
We will be using the high_priority queue with a very high priority for all items having op_scheduler_class as immediate.
Signed-off-by: Aishwarya Mathuria <amathuri@redhat.com>
{
// Display queue sizes
f.open_object_section("queue_sizes");
- f.dump_int("immediate", immediate.size());
f.dump_int("high_priority_queue", high_priority.size());
f.dump_int("scheduler", scheduler.request_count());
f.close_section();
// TODO: move this check into OpSchedulerItem, handle backwards compat
if (op_scheduler_class::immediate == id.class_id) {
- immediate.push_front(std::move(item));
+ enqueue_high(immediate_class_priority, std::move(item));
} else if (priority >= cutoff) {
enqueue_high(priority, std::move(item));
} else {
}
dout(20) << __func__ << " client_count: " << scheduler.client_count()
- << " queue_sizes: [ imm: " << immediate.size()
+ << " queue_sizes: [ "
<< " high_priority_queue: " << high_priority.size()
<< " sched: " << scheduler.request_count() << " ]"
<< dendl;
auto id = get_scheduler_id(item);
if (op_scheduler_class::immediate == id.class_id) {
- immediate.push_back(std::move(item));
+ enqueue_high(immediate_class_priority, std::move(item), true);
} else if (priority >= cutoff) {
enqueue_high(priority, std::move(item), true);
} else {
WorkItem mClockScheduler::dequeue()
{
- if (!immediate.empty()) {
- WorkItem work_item{std::move(immediate.back())};
- immediate.pop_back();
- return work_item;
- } else if (!high_priority.empty()) {
+ if (!high_priority.empty()) {
auto iter = high_priority.begin();
// invariant: high_priority entries are never empty
assert(!iter->second.empty());
using SubQueue = std::map<priority_t,
std::list<OpSchedulerItem>,
std::greater<priority_t>>;
- using SubQueueIter = SubQueue::iterator;
mclock_queue_t scheduler;
/**
* high_priority
* Invariant: entries are never empty
*/
SubQueue high_priority;
- std::list<OpSchedulerItem> immediate;
+ priority_t immediate_class_priority = std::numeric_limits<priority_t>::max();
static scheduler_id_t get_scheduler_id(const OpSchedulerItem &item) {
return scheduler_id_t{
// Enqueue op in the back of the regular queue
void enqueue(OpSchedulerItem &&item) final;
- // Enqueue the op in the front of the high priority queue or the immediate queue (based on priority)
+ // Enqueue the op in the front of the high priority queue
void enqueue_front(OpSchedulerItem &&item) final;
// Return an op to be dispatch
// Returns if the queue is empty
bool empty() const final {
- return immediate.empty() && scheduler.empty() && high_priority.empty();
+ return scheduler.empty() && high_priority.empty();
}
// Formatted output of the queue
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
- // Insert ops into the immediate queue
+ // Insert Immediate ops
for (unsigned i = 103; i < 105; ++i) {
q.enqueue(create_item(i, client1, op_scheduler_class::immediate));
std::this_thread::sleep_for(std::chrono::microseconds(1));
ASSERT_FALSE(q.empty());
auto r = get_item(q.dequeue());
- // Immediate queue should be dequeued first
+ // Ops classified as Immediate should be dequeued first
ASSERT_EQ(103u, r.get_map_epoch());
r = get_item(q.dequeue());
ASSERT_EQ(104u, r.get_map_epoch());