do_queues();
}
+ /**
+ * Update the priority of a reservation
+ *
+ * Note, on_reserved may be called following update_priority. Thus,
+ * the callback must be safe in that case. Callback will be called
+ * with no locks held. cancel_reservation must be called to release the
+ * reservation slot.
+ *
+ * Cases
+ * 1. Item is queued, re-queue with new priority
+ * 2. Item is queued, re-queue and preempt if new priority higher than an in progress item
+ * 3. Item is in progress, just adjust priority if no higher priority waiting
+ * 4. Item is in progress, adjust priority if higher priority items waiting preempt item
+ *
+ */
+ void update_priority(T item, unsigned newprio) {
+ std::lock_guard l(lock);
+ auto i = queue_pointers.find(item);
+ if (i != queue_pointers.end()) {
+ unsigned prio = i->second.first;
+ if (newprio == prio)
+ return;
+ Reservation r = *i->second.second;
+ rdout(10) << __func__ << " update " << r << " (was queued)" << dendl;
+ // Like cancel_reservation() without preempting
+ queues[prio].erase(i->second.second);
+ if (queues[prio].empty()) {
+ queues.erase(prio);
+ }
+ queue_pointers.erase(i);
+
+ // Like request_reservation() to re-queue it but with new priority
+ ceph_assert(!queue_pointers.count(item) &&
+ !in_progress.count(item));
+ r.prio = newprio;
+ queues[newprio].push_back(r);
+ queue_pointers.insert(make_pair(item,
+ make_pair(newprio,--(queues[newprio]).end())));
+ } else {
+ auto p = in_progress.find(item);
+ if (p != in_progress.end()) {
+ if (p->second.prio == newprio)
+ return;
+ rdout(10) << __func__ << " update " << p->second
+ << " (in progress)" << dendl;
+ // We want to preempt if priority goes down
+ // and smaller then highest priority waiting
+ if (p->second.preempt) {
+ if (newprio < p->second.prio && !queues.empty()) {
+ // choose highest priority queue
+ auto it = queues.end();
+ --it;
+ ceph_assert(!it->second.empty());
+ if (it->first > newprio) {
+ rdout(10) << __func__ << " update " << p->second
+ << " lowered priority let do_queues() preempt it" << dendl;
+ }
+ }
+ preempt_by_prio.erase(make_pair(p->second.prio, p->second.item));
+ p->second.prio = newprio;
+ preempt_by_prio.insert(make_pair(p->second.prio, p->second.item));
+ } else {
+ p->second.prio = newprio;
+ }
+ } else {
+ rdout(10) << __func__ << " update " << item << " (not found)" << dendl;
+ }
+ }
+ do_queues();
+ return;
+ }
+
void dump(Formatter *f) {
std::lock_guard l(lock);
_dump(f);