[core] add logic of high and low priority requests to OnlineFileSource

- only process low priority requests (=offline requests) if there are no outstanding regular requests
- favour regular requests over low priority ones
This commit is contained in:
Huyen Chau Nguyen
2018-10-17 20:13:44 +02:00
parent 1e3a744d22
commit 40693e00a8

View File

@@ -89,13 +89,8 @@ public:
if (activeRequests.erase(request)) {
activatePendingRequest();
} else {
auto it = pendingRequestsMap.find(request);
if (it != pendingRequestsMap.end()) {
pendingRequestsList.erase(it->second);
pendingRequestsMap.erase(it);
}
pendingRequests.remove(request);
}
assert(pendingRequestsMap.size() == pendingRequestsList.size());
}
void activateOrQueueRequest(OnlineFileRequest* request) {
@@ -111,9 +106,7 @@ public:
}
void queueRequest(OnlineFileRequest* request) {
auto it = pendingRequestsList.insert(pendingRequestsList.end(), request);
pendingRequestsMap.emplace(request, std::move(it));
assert(pendingRequestsMap.size() == pendingRequestsList.size());
pendingRequests.insert(request);
}
void activateRequest(OnlineFileRequest* request) {
@@ -135,25 +128,17 @@ public:
callback(response);
}
assert(pendingRequestsMap.size() == pendingRequestsList.size());
}
void activatePendingRequest() {
if (pendingRequestsList.empty()) {
return;
}
OnlineFileRequest* request = pendingRequestsList.front();
pendingRequestsList.pop_front();
auto request = pendingRequests.pop();
pendingRequestsMap.erase(request);
activateRequest(request);
assert(pendingRequestsMap.size() == pendingRequestsList.size());
if (request) activateRequest(*request);
}
bool isPending(OnlineFileRequest* request) {
return pendingRequestsMap.find(request) != pendingRequestsMap.end();
return pendingRequests.contains(request);
}
bool isActive(OnlineFileRequest* request) {
@@ -169,13 +154,90 @@ public:
networkIsReachableAgain();
}
void setMaximumConcurrentRequestsOverride(const uint32_t override) {
maximumConcurrentRequestsOverride = override;
}
private:
uint32_t getMaximumConcurrentRequests() {
if (maximumConcurrentRequestsOverride > 0) return maximumConcurrentRequestsOverride;
else return HTTPFileSource::maximumConcurrentRequests();
}
void networkIsReachableAgain() {
for (auto& request : allRequests) {
request->networkIsReachableAgain();
}
}
// Using Pending Requests as an priority queue which processes
// file requests in a FIFO manner but prefers regular requests
// over offline requests with a low priority such that low priority
// requests do not throttle regular requests.
//
// The order of a queue is therefore:
//
// hi0 -- hi1 -- hi2 -- hi3 -- lo0 -- lo1 --lo2
// ^
// firstLowPriorityRequest
struct PendingRequests {
PendingRequests() : queue(), firstLowPriorityRequest(queue.begin()) {}
std::list<OnlineFileRequest*> queue;
std::list<OnlineFileRequest*>::iterator firstLowPriorityRequest;
void remove(OnlineFileRequest* request) {
auto it = std::find(queue.begin(), queue.end(), request);
if (it != queue.end()) {
if (it == firstLowPriorityRequest) {
firstLowPriorityRequest++;
}
queue.erase(it);
if (queue.empty()) {
first_low = queue.begin();
}
}
}
void insert(OnlineFileRequest* request) {
if (request->resource.priority == Resource::Priority::Regular) {
firstLowPriorityRequest = queue.insert(firstLowPriorityRequest, request);
firstLowPriorityRequest++;
}
else {
if (firstLowPriorityRequest == queue.end()) {
firstLowPriorityRequest = queue.insert(queue.end(), request);
}
else {
queue.insert(queue.end(), request);
}
}
}
optional<OnlineFileRequest*> pop() {
if (queue.empty()) {
return optional<OnlineFileRequest*>();
}
if (queue.begin() == firstLowPriorityRequest) {
firstLowPriorityRequest++;
}
OnlineFileRequest* next = queue.front();
queue.pop_front();
return optional<OnlineFileRequest*>(next);
}
bool contains(OnlineFileRequest* request) {
return (std::find(queue.begin(), queue.end(), request) != queue.end());
}
};
optional<ActorRef<ResourceTransform>> resourceTransform;
/**
@@ -190,8 +252,9 @@ private:
* `pendingRequests`. Requests in the active state are in `activeRequests`.
*/
std::unordered_set<OnlineFileRequest*> allRequests;
std::list<OnlineFileRequest*> pendingRequestsList;
std::unordered_map<OnlineFileRequest*, std::list<OnlineFileRequest*>::iterator> pendingRequestsMap;
PendingRequests pendingRequests;
std::unordered_set<OnlineFileRequest*> activeRequests;
bool online = true;