Esempio n. 1
0
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();
	}
}