void TorrentSession::update() { std::deque<lt::alert*> alerts; mSessionHandle->pop_alerts(&alerts); for (const lt::alert *alert : alerts) { // Set the handle if a torrent was added. Torrent *t = nullptr; if (alert->type() == lt::torrent_added_alert::alert_type || alert->type() == lt::add_torrent_alert::alert_type) { const lt::torrent_alert *a = static_cast<const lt::torrent_alert*>(alert); t = mTorrentMap[a->handle.info_hash()].get(); assert(t); t->mHandle.reset(new lt::torrent_handle(a->handle)); } // Update info hash in map if it changed if (alert->type() == lt::torrent_update_alert::alert_type) { const lt::torrent_update_alert *a = static_cast<const lt::torrent_update_alert*>(alert); auto &newPos = mTorrentMap[a->new_ih]; auto it = mTorrentMap.find(a->old_ih); assert(newPos == nullptr); assert(it != mTorrentMap.end()); newPos = std::move(it->second); mTorrentMap.erase(it); } // Check whether it is an torrent alert and set `t`. if (t == nullptr) { const lt::torrent_alert *ta = dynamic_cast<const lt::torrent_alert*>(alert); if (ta) { t = mTorrentMap[ta->handle.info_hash()].get(); assert(t); } } // Fire the alert signal. this->alert(*alert, t); // Do private handling switch (alert->type()) { case lt::add_torrent_alert::alert_type: { const lt::add_torrent_alert *a = static_cast<const lt::add_torrent_alert*>(alert); assert(t); if (a->error) { t->addFailed(a->error); t->removed(); // TODO should I call this signal ? int ret = mTorrentMap.erase(a->params.ti ? a->params.ti->info_hash() : a->params.info_hash); assert(ret); } else { t->mAdded = true; t->added(); if (t->mDeleting) { mSessionHandle->remove_torrent(*t->mHandle, lt::session::delete_files); } else if (t->mRemoving) { mSessionHandle->remove_torrent(*t->mHandle); } } break; } case lt::torrent_removed_alert::alert_type: { const lt::torrent_removed_alert *a = static_cast<const lt::torrent_removed_alert*>(alert); assert(t); assert(t->mHandle->info_hash() == a->info_hash); t->removed(); int ret = mTorrentMap.erase(a->info_hash); assert(ret); break; } case lt::torrent_deleted_alert::alert_type: { const lt::torrent_deleted_alert *a = static_cast<const lt::torrent_deleted_alert*>(alert); assert(t); assert(t->mHandle->info_hash() == a->info_hash); t->deleted(); break; } case lt::torrent_delete_failed_alert::alert_type: { const lt::torrent_delete_failed_alert *a = static_cast<const lt::torrent_delete_failed_alert*>(alert); assert(t); assert(t->mHandle->info_hash() == a->info_hash); t->deleteFailed(a->error); break; } case lt::metadata_received_alert::alert_type: { const lt::metadata_received_alert *a = static_cast<const lt::metadata_received_alert*>(alert); assert(t); assert(*t->mHandle == a->handle); t->mMetadata.reset(new TorrentInfo(*t->mHandle->torrent_file())); t->metadataReceived(); break; } case lt::metadata_failed_alert::alert_type: { const lt::metadata_failed_alert *a = static_cast<const lt::metadata_failed_alert*>(alert); assert(t); assert(*t->mHandle == a->handle); t->metadataFailed(a->error); break; } case lt::state_update_alert::alert_type: { const lt::state_update_alert *a = static_cast<const lt::state_update_alert*>(alert); mNoUpdateCounter = 0; for (const lt::torrent_status &nts : a->status) { Torrent *t = mTorrentMap[nts.info_hash].get(); assert(t); assert(nts.info_hash == nts.handle.info_hash()); assert(*t->mHandle == nts.handle); t->mStatus->loadFromLibtorrent(nts); t->statusUpdated(); } mStatus->loadFromLibtorrent(mSessionHandle->status()); statusUpdated(); break; } } delete alert; } // get torrent states every 10 updates if (++mNoUpdateCounter == 10) { mSessionHandle->post_torrent_updates(); } }