void CSSHScheduler::makeScheduleImpl(const CTopology& _topology, const CAgentChannel::weakConnectionPtrVector_t& _channels) { m_schedule.clear(); size_t nofChannels = _channels.size(); // Fill host name to channel index map in order to reduce number of regex matches and speed up scheduling. map<string, vector<size_t>> hostToChannelMap; for (size_t iChannel = 0; iChannel < nofChannels; ++iChannel) { const auto& v = _channels[iChannel]; if (v.expired()) continue; auto ptr = v.lock(); const SHostInfoCmd& hostInfo = ptr->getRemoteHostInfo(); hostToChannelMap[hostInfo.m_host].push_back(iChannel); } // TODO: before scheduling the collections we have to sort them by a number of tasks in the collection. // TODO: for the moment we are not able to schedule collection without requirements. // Collect all tasks that belong to collections set<uint64_t> tasksInCollections; CollectionMap_t collectionMap; CTopology::TaskCollectionIteratorPair_t collections = _topology.getTaskCollectionIterator(); for (auto it = collections.first; it != collections.second; it++) { const vector<uint64_t>& taskHashes = _topology.getTaskHashesByTaskCollectionHash(it->first); tasksInCollections.insert(taskHashes.begin(), taskHashes.end()); collectionMap[it->second->getNofTasks()].push_back(it->first); } set<uint64_t> scheduledTasks; scheduleCollections(_topology, _channels, hostToChannelMap, scheduledTasks, collectionMap, true); scheduleTasks(_topology, _channels, hostToChannelMap, scheduledTasks, tasksInCollections, true); scheduleCollections(_topology, _channels, hostToChannelMap, scheduledTasks, collectionMap, false); scheduleTasks(_topology, _channels, hostToChannelMap, scheduledTasks, tasksInCollections, false); size_t totalNofTasks = _topology.getMainGroup()->getTotalNofTasks(); if (totalNofTasks != m_schedule.size()) { printSchedule(); stringstream ss; ss << "Unable to make a schedule for tasks. Number of requested tasks: " << totalNofTasks << ". Number of scheduled tasks: " << m_schedule.size(); throw runtime_error(ss.str()); } printSchedule(); }
void CSSHScheduler::scheduleCollections(const CTopology& _topology, const CAgentChannel::weakConnectionPtrVector_t& _channels, map<string, vector<size_t>>& _hostToChannelMap, set<uint64_t>& _scheduledTasks, const CollectionMap_t& _collectionMap, bool useRequirement) { for (const auto& it_col : _collectionMap) { for (auto id : it_col.second) { TaskCollectionPtr_t collection = _topology.getTaskCollectionByHash(id); // First path only for collections with requirements; // Second path for collections without requirements. if ((useRequirement && collection->getRequirement() == nullptr) || (!useRequirement && collection->getRequirement() != nullptr)) continue; bool collectionAssigned = false; for (auto& v : _hostToChannelMap) { if (v.second.size() >= collection->getNofTasks() && (!useRequirement || (useRequirement && collection->getRequirement()->hostPatterMatches(v.first)))) { const vector<uint64_t>& taskHashes = _topology.getTaskHashesByTaskCollectionHash(id); for (auto hash : taskHashes) { const STaskInfo& info = _topology.getTaskInfoByHash(hash); size_t channelIndex = v.second.back(); const auto& channel = _channels[channelIndex]; SSchedule schedule; schedule.m_channel = channel; schedule.m_task = info.m_task; schedule.m_taskID = hash; schedule.m_taskIndex = info.m_taskIndex; schedule.m_collectionIndex = info.m_collectionIndex; m_schedule.push_back(schedule); v.second.pop_back(); _scheduledTasks.insert(hash); } collectionAssigned = true; break; } } if (!collectionAssigned) { printSchedule(); stringstream ss; ss << "Unable to schedule collection <" << id << "> with path " << collection->getPath(); throw runtime_error(ss.str()); } } } }