int QueueBundleUtils::compareBundles(const BundlePtr& a, const BundlePtr& b, int aPropertyName) noexcept { switch (aPropertyName) { case PROP_NAME: { COMPARE_TYPE(a, b); return Util::stricmp(a->getName(), b->getName()); } case PROP_TYPE: { COMPARE_TYPE(a, b); if (!a->isFileBundle() && !b->isFileBundle()) { // Directory bundles RLock l(QueueManager::getInstance()->getCS()); auto dirsA = QueueManager::getInstance()->bundleQueue.getDirectoryCount(a); auto dirsB = QueueManager::getInstance()->bundleQueue.getDirectoryCount(b); if (dirsA != dirsB) { return compare(dirsA, dirsB); } auto filesA = a->getQueueItems().size() + a->getFinishedFiles().size(); auto filesB = b->getQueueItems().size() + b->getFinishedFiles().size(); return compare(filesA, filesB); } return Util::stricmp(Util::getFileExt(a->getTarget()), Util::getFileExt(b->getTarget())); } case PROP_PRIORITY: { COMPARE_FINISHED(a, b); if (a->isFinished() != b->isFinished()) { return a->isFinished() ? 1 : -1; } return compare(static_cast<int>(a->getPriority()), static_cast<int>(b->getPriority())); } case PROP_STATUS: { if (a->getStatus() != b->getStatus()) { return compare(a->getStatus(), b->getStatus()); } return compare( a->getPercentage(a->getDownloadedBytes()), b->getPercentage(b->getDownloadedBytes()) ); } case PROP_SOURCES: { COMPARE_FINISHED(a, b); auto countsA = QueueManager::getInstance()->getSourceCount(a); auto countsB = QueueManager::getInstance()->getSourceCount(b); return QueueItemBase::SourceCount::compare(countsA, countsB); } default: dcassert(0); } return 0; }
QueueItemList BundleQueue::getSearchItems(const BundlePtr& aBundle) const noexcept { if (aBundle->getQueueItems().size() <= 1) { return aBundle->getQueueItems(); } // File bundles shouldn't come here QueueItemList searchItems; auto pathInfos = getPathInfos(aBundle->getTarget()); if (!pathInfos) { return searchItems; } { // Get the main directories inside this bundle // We'll choose a single search item from each main directory later // This helps with getting best coverage for complex bundles that aren't // shared with same structure by most users StringSet mainBundlePaths; for (const auto& pathInfo : *pathInfos) { if (pathInfo->queuedFiles == 0) { continue; } mainBundlePaths.insert(AirUtil::getReleaseDirLocal(pathInfo->path, false)); } auto searchPaths = pickRandomItems(mainBundlePaths, 5); for (const auto& path : searchPaths) { QueueItemList ql; // Get all queued files inside this directory // This doesn't scale so well for large bundles but shouldn't cause issues with maximum of 5 paths aBundle->getDirQIs(path, ql); auto searchItem = QueueItem::pickSearchItem(ql); // We'll also get search items for parent directories that have no files directly inside them // so we need to filter duplicate items as well if (searchItem && find_if(searchItems, QueueItem::HashComp(searchItem->getTTH())) == searchItems.end()) { searchItems.push_back(searchItem); } } } #if 0 StringList targets; for (const auto& qi : searchItems) { targets.push_back(qi->getTarget()); } LogManager::getInstance()->message("Search items from bundle " + aBundle->getName() + ": " + Util::listToString(targets), LogMessage::SEV_INFO); #endif return searchItems; }
std::string QueueUtils::getStringInfo(const BundlePtr& b, int aPropertyName) noexcept { switch (aPropertyName) { case QueueApi::PROP_NAME: return b->getName(); case QueueApi::PROP_TARGET: return b->getTarget(); case QueueApi::PROP_TYPE: return formatBundleType(b); case QueueApi::PROP_STATUS: return formatBundleStatus(b); case QueueApi::PROP_PRIORITY: return AirUtil::getPrioText(b->getPriority()); case QueueApi::PROP_SOURCES: return formatBundleSources(b); default: dcassert(0); return Util::emptyString; } }
int QueueUtils::compareBundles(const BundlePtr& a, const BundlePtr& b, int aPropertyName) noexcept { switch (aPropertyName) { case QueueApi::PROP_NAME: { if (a->isFileBundle() && !b->isFileBundle()) return 1; if (!a->isFileBundle() && b->isFileBundle()) return -1; return Util::stricmp(a->getName(), b->getName()); } case QueueApi::PROP_TYPE: { if (a->isFileBundle() != b->isFileBundle()) { // Directories go first return a->isFileBundle() ? 1 : -1; } if (!a->isFileBundle() && !b->isFileBundle()) { // Directory bundles RLock l(QueueManager::getInstance()->getCS()); auto dirsA = a->getDirectories().size(); auto dirsB = a->getDirectories().size(); if (dirsA != dirsB) { return compare(dirsA, dirsB); } auto filesA = a->getQueueItems().size() + a->getFinishedFiles().size(); auto filesB = b->getQueueItems().size() + b->getFinishedFiles().size(); return compare(filesA, filesB); } return Util::stricmp(Util::getFileExt(a->getTarget()), Util::getFileExt(b->getTarget())); } case QueueApi::PROP_PRIORITY: { if (a->isFinished() != b->isFinished()) { return a->isFinished() ? 1 : -1; } return compare(static_cast<int>(a->getPriority()), static_cast<int>(b->getPriority())); } case QueueApi::PROP_STATUS: { if (a->getStatus() != b->getStatus()) { return compare(a->getStatus(), b->getStatus()); } return compare(a->getDownloadedBytes(), b->getDownloadedBytes()); } case QueueApi::PROP_SOURCES: { if (a->isFinished() != b->isFinished()) { return a->isFinished() ? 1 : -1; } int onlineA = 0, totalA = 0, onlineB = 0, totalB = 0; std::string str; getBundleSourceInfo(a, onlineA, totalA, str); getBundleSourceInfo(b, onlineB, totalB, str); if (onlineA != onlineB) { return compare(onlineA, onlineB); } return compare(totalA, totalB); } default: dcassert(0); } return 0; }