// Squawk messenger. // Copyright (C) 2019 Yury Gubich // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "delaymanager.h" Core::DelayManager::DelayManager(uint16_t mpj, QObject* parent) : QObject(parent), maxParallelJobs(mpj), nextJobId(0), scheduledJobs(), runningJobs(), pendingVCards(), requestedVCards() { } Core::DelayManager::~DelayManager() {} void Core::DelayManager::requestInfo(const QString& jid) { bool needToRequest = false; std::pair::const_iterator, bool> result = pendingVCards.insert(jid); if (result.second) { //if there is a clear evidence that we have not alredy been asked to request a VCard - just request it needToRequest = true; } else { std::map::const_iterator itr = requestedVCards.find(jid); if (itr != requestedVCards.end()) { //first check if the card is already requested, and if it is make sure we reply to user after we receive it runningJobs[itr->second].first = TaskType::infoForUser; } else { needToRequest = true; for (Job& job : scheduledJobs) { //looks like we need to manually check all the scheduled job and find the one with that jid there if (job.first == TaskType::cardInternal || job.first == TaskType::infoForUser) { //to make sure we reply to user after we receive it QString* jobJid = static_cast(job.second); if (*jobJid == jid) { needToRequest = false; job.first = TaskType::infoForUser; break; } } } if (needToRequest) { throw 8573; //something went terribly wrong here, the state is not correct; } } } if (needToRequest) scheduleJob(TaskType::infoForUser, new QString(jid)); } void Core::DelayManager::requestVCard(const QString& jid) { std::pair::const_iterator, bool> result = pendingVCards.insert(jid); if (result.second) scheduleJob(TaskType::cardInternal, new QString(jid)); } void Core::DelayManager::scheduleJob(Core::DelayManager::TaskType type, void* data) { if (runningJobs.size() < maxParallelJobs) { uint16_t currentJobId = nextJobId++; runningJobs.emplace(currentJobId, std::make_pair(type, data)); switch (type) { case TaskType::cardInternal: case TaskType::infoForUser: { QString* jid = static_cast(data); requestedVCards.emplace(*jid, currentJobId); emit requestVCard(*jid); } break; } } else { scheduledJobs.emplace_back(type, data); } } void Core::DelayManager::executeJob(Core::DelayManager::Job job) { uint16_t currentJobId = nextJobId++; runningJobs.emplace(currentJobId, job); switch (job.first) { case TaskType::cardInternal: case TaskType::infoForUser: { QString* jid = static_cast(job.second); requestedVCards.emplace(*jid, currentJobId); emit requestVCard(*jid); } break; } } void Core::DelayManager::jobIsDone(uint16_t jobId) { std::map::const_iterator itr = runningJobs.find(jobId); if (itr == runningJobs.end()) { throw 8574; //not supposed to happen, never } runningJobs.erase(itr); if (scheduledJobs.size() > 0) { Job job = scheduledJobs.front(); scheduledJobs.pop_front(); executeJob(job); } } void Core::DelayManager::receivedVCard(const QString& jid, const Shared::VCard& card) { std::map::const_iterator cardItr = requestedVCards.find(jid); if (cardItr == requestedVCards.end()) { throw 8575; //never supposed to happen, the state is not correct; } else { uint16_t jobId = cardItr->second; requestedVCards.erase(cardItr); pendingVCards.erase(jid); const Job& job = runningJobs[jobId]; switch (job.first) { case TaskType::cardInternal: jobIsDone(jobId); break; case TaskType::infoForUser: //all that stuff with further requesting break; default: throw 8576; } } }