mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-20 21:33:27 -07:00
WebAPI: Cache metadata using TorrentID
This is a follow up to #21015. `m_torrentMetadataCache` previously used a torrent's InfoHash as its key. However, InfoHashes for hybrid torrents fail equality checks after serialization via their TorrentID (e.g. `InfoHash(TorrentID(infoHash.toTorrentID().toString())) != infoHash`). This is due to hybrid InfoHashes containing both a v1 and v2 hash, while the serialized TorrentID only contains a single truncated v2 hash. Thus we cannot expect an InfoHash serialized by its TorrentID to construct an equivalent InfoHash. By switching to the TorrentID, we always have a single ID to use.
This commit is contained in:
parent
71af105a89
commit
a72f9eb396
2 changed files with 18 additions and 14 deletions
|
@ -1070,7 +1070,8 @@ void TorrentsController::addAction()
|
||||||
else if (const auto sourceTorrentDescr = BitTorrent::TorrentDescriptor::parse(url))
|
else if (const auto sourceTorrentDescr = BitTorrent::TorrentDescriptor::parse(url))
|
||||||
infoHash = sourceTorrentDescr.value().infoHash();
|
infoHash = sourceTorrentDescr.value().infoHash();
|
||||||
|
|
||||||
if (const BitTorrent::TorrentDescriptor &torrentDescr = m_torrentMetadataCache.value(infoHash); torrentDescr.info().has_value())
|
const BitTorrent::TorrentID torrentID = infoHash.toTorrentID();
|
||||||
|
if (const BitTorrent::TorrentDescriptor &torrentDescr = m_torrentMetadataCache.value(torrentID); torrentDescr.info().has_value())
|
||||||
{
|
{
|
||||||
if (!filePriorities.isEmpty())
|
if (!filePriorities.isEmpty())
|
||||||
{
|
{
|
||||||
|
@ -1091,7 +1092,7 @@ void TorrentsController::addAction()
|
||||||
partialSuccess |= app()->addTorrentManager()->addTorrent(url, addTorrentParams);
|
partialSuccess |= app()->addTorrentManager()->addTorrent(url, addTorrentParams);
|
||||||
}
|
}
|
||||||
m_torrentSourceCache.remove(url);
|
m_torrentSourceCache.remove(url);
|
||||||
m_torrentMetadataCache.remove(infoHash);
|
m_torrentMetadataCache.remove(torrentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process uploaded .torrent files
|
// process uploaded .torrent files
|
||||||
|
@ -1960,10 +1961,11 @@ void TorrentsController::fetchMetadataAction()
|
||||||
const auto sourceTorrentDescr = BitTorrent::TorrentDescriptor::parse(source);
|
const auto sourceTorrentDescr = BitTorrent::TorrentDescriptor::parse(source);
|
||||||
|
|
||||||
const BitTorrent::InfoHash infoHash = sourceTorrentDescr ? sourceTorrentDescr.value().infoHash() : m_torrentSourceCache.value(source);
|
const BitTorrent::InfoHash infoHash = sourceTorrentDescr ? sourceTorrentDescr.value().infoHash() : m_torrentSourceCache.value(source);
|
||||||
|
const BitTorrent::TorrentID torrentID = infoHash.toTorrentID();
|
||||||
if (infoHash.isValid())
|
if (infoHash.isValid())
|
||||||
{
|
{
|
||||||
// check metadata cache
|
// check metadata cache
|
||||||
if (const BitTorrent::TorrentDescriptor &torrentDescr = m_torrentMetadataCache.value(infoHash);
|
if (const BitTorrent::TorrentDescriptor &torrentDescr = m_torrentMetadataCache.value(torrentID);
|
||||||
torrentDescr.info().has_value())
|
torrentDescr.info().has_value())
|
||||||
{
|
{
|
||||||
setResult(serializeTorrentInfo(torrentDescr));
|
setResult(serializeTorrentInfo(torrentDescr));
|
||||||
|
@ -1984,9 +1986,9 @@ void TorrentsController::fetchMetadataAction()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!BitTorrent::Session::instance()->downloadMetadata(sourceTorrentDescr.value())) [[unlikely]]
|
if (!BitTorrent::Session::instance()->downloadMetadata(sourceTorrentDescr.value())) [[unlikely]]
|
||||||
throw APIError(APIErrorType::BadParams, tr("Unable to download metadata for '%1'").arg(infoHash.toTorrentID().toString()));
|
throw APIError(APIErrorType::BadParams, tr("Unable to download metadata for '%1'").arg(torrentID.toString()));
|
||||||
|
|
||||||
m_torrentMetadataCache.insert(infoHash, sourceTorrentDescr.value());
|
m_torrentMetadataCache.insert(torrentID, sourceTorrentDescr.value());
|
||||||
|
|
||||||
setResult(serializeInfoHash(infoHash));
|
setResult(serializeInfoHash(infoHash));
|
||||||
setStatus(APIStatus::Async);
|
setStatus(APIStatus::Async);
|
||||||
|
@ -2027,7 +2029,7 @@ void TorrentsController::parseMetadataAction()
|
||||||
if (const auto loadResult = BitTorrent::TorrentDescriptor::load(it.value()))
|
if (const auto loadResult = BitTorrent::TorrentDescriptor::load(it.value()))
|
||||||
{
|
{
|
||||||
const BitTorrent::TorrentDescriptor &torrentDescr = loadResult.value();
|
const BitTorrent::TorrentDescriptor &torrentDescr = loadResult.value();
|
||||||
m_torrentMetadataCache.insert(torrentDescr.infoHash(), torrentDescr);
|
m_torrentMetadataCache.insert(torrentDescr.infoHash().toTorrentID(), torrentDescr);
|
||||||
|
|
||||||
const QString &fileName = it.key();
|
const QString &fileName = it.key();
|
||||||
result.insert(fileName, serializeTorrentInfo(torrentDescr));
|
result.insert(fileName, serializeTorrentInfo(torrentDescr));
|
||||||
|
@ -2060,7 +2062,8 @@ void TorrentsController::saveMetadataAction()
|
||||||
if (!infoHash.isValid())
|
if (!infoHash.isValid())
|
||||||
throw APIError(APIErrorType::NotFound);
|
throw APIError(APIErrorType::NotFound);
|
||||||
|
|
||||||
const BitTorrent::TorrentDescriptor &torrentDescr = m_torrentMetadataCache.value(infoHash);
|
const BitTorrent::TorrentID torrentID = infoHash.toTorrentID();
|
||||||
|
const BitTorrent::TorrentDescriptor &torrentDescr = m_torrentMetadataCache.value(torrentID);
|
||||||
if (!torrentDescr.info().has_value())
|
if (!torrentDescr.info().has_value())
|
||||||
throw APIError(APIErrorType::Conflict, tr("Metadata is not yet available"));
|
throw APIError(APIErrorType::Conflict, tr("Metadata is not yet available"));
|
||||||
|
|
||||||
|
@ -2068,7 +2071,7 @@ void TorrentsController::saveMetadataAction()
|
||||||
if (!result)
|
if (!result)
|
||||||
throw APIError(APIErrorType::Conflict, tr("Unable to export torrent metadata. Error: %1").arg(result.error()));
|
throw APIError(APIErrorType::Conflict, tr("Unable to export torrent metadata. Error: %1").arg(result.error()));
|
||||||
|
|
||||||
setResult(result.value(), u"application/x-bittorrent"_s, (infoHash.toTorrentID().toString() + u".torrent"));
|
setResult(result.value(), u"application/x-bittorrent"_s, (torrentID.toString() + u".torrent"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentsController::onDownloadFinished(const Net::DownloadResult &result)
|
void TorrentsController::onDownloadFinished(const Net::DownloadResult &result)
|
||||||
|
@ -2085,7 +2088,7 @@ void TorrentsController::onDownloadFinished(const Net::DownloadResult &result)
|
||||||
const BitTorrent::TorrentDescriptor &torrentDescr = loadResult.value();
|
const BitTorrent::TorrentDescriptor &torrentDescr = loadResult.value();
|
||||||
const BitTorrent::InfoHash infoHash = torrentDescr.infoHash();
|
const BitTorrent::InfoHash infoHash = torrentDescr.infoHash();
|
||||||
m_torrentSourceCache.insert(source, infoHash);
|
m_torrentSourceCache.insert(source, infoHash);
|
||||||
m_torrentMetadataCache.insert(infoHash, torrentDescr);
|
m_torrentMetadataCache.insert(infoHash.toTorrentID(), torrentDescr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2099,12 +2102,13 @@ void TorrentsController::onDownloadFinished(const Net::DownloadResult &result)
|
||||||
{
|
{
|
||||||
const BitTorrent::TorrentDescriptor &torrentDescr = parseResult.value();
|
const BitTorrent::TorrentDescriptor &torrentDescr = parseResult.value();
|
||||||
const BitTorrent::InfoHash infoHash = torrentDescr.infoHash();
|
const BitTorrent::InfoHash infoHash = torrentDescr.infoHash();
|
||||||
|
const BitTorrent::TorrentID torrentID = infoHash.toTorrentID();
|
||||||
m_torrentSourceCache.insert(source, infoHash);
|
m_torrentSourceCache.insert(source, infoHash);
|
||||||
|
|
||||||
if (!m_torrentMetadataCache.contains(infoHash) && !BitTorrent::Session::instance()->isKnownTorrent(infoHash))
|
if (!m_torrentMetadataCache.contains(torrentID) && !BitTorrent::Session::instance()->isKnownTorrent(infoHash))
|
||||||
{
|
{
|
||||||
if (BitTorrent::Session::instance()->downloadMetadata(torrentDescr))
|
if (BitTorrent::Session::instance()->downloadMetadata(torrentDescr))
|
||||||
m_torrentMetadataCache.insert(infoHash, torrentDescr);
|
m_torrentMetadataCache.insert(torrentID, torrentDescr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2125,7 +2129,6 @@ void TorrentsController::onMetadataDownloaded(const BitTorrent::TorrentInfo &inf
|
||||||
if (!info.isValid()) [[unlikely]]
|
if (!info.isValid()) [[unlikely]]
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const BitTorrent::InfoHash infoHash = info.infoHash();
|
if (auto iter = m_torrentMetadataCache.find(info.infoHash().toTorrentID()); iter != m_torrentMetadataCache.end())
|
||||||
if (auto iter = m_torrentMetadataCache.find(infoHash); iter != m_torrentMetadataCache.end())
|
|
||||||
iter.value().setTorrentInfo(info);
|
iter.value().setTorrentInfo(info);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
class InfoHash;
|
class InfoHash;
|
||||||
|
class TorrentID;
|
||||||
class TorrentInfo;
|
class TorrentInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +120,6 @@ private:
|
||||||
void onMetadataDownloaded(const BitTorrent::TorrentInfo &info);
|
void onMetadataDownloaded(const BitTorrent::TorrentInfo &info);
|
||||||
|
|
||||||
QHash<QString, BitTorrent::InfoHash> m_torrentSourceCache;
|
QHash<QString, BitTorrent::InfoHash> m_torrentSourceCache;
|
||||||
QHash<BitTorrent::InfoHash, BitTorrent::TorrentDescriptor> m_torrentMetadataCache;
|
QHash<BitTorrent::TorrentID, BitTorrent::TorrentDescriptor> m_torrentMetadataCache;
|
||||||
QSet<QString> m_requestedTorrentSource;
|
QSet<QString> m_requestedTorrentSource;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue