void AssetDownloadTask::textureDownloaded(Transfer::URI uri, ResourceDownloadTaskPtr taskptr, Transfer::TransferRequestPtr request, Transfer::DenseDataPtr response) { // This could be triggered by any CDN thread, protect access // (mActiveDownloads, mDependencies) boost::mutex::scoped_lock lok(mDependentDownloadMutex); if (!taskptr) { SILOG(ogre, warn, "failed request dependent callback"); failDownload(); return; } if (!request) { SILOG(ogre, warn, "failed request dependent callback " << taskptr->getIdentifier()); failDownload(); return; } // Clear the download task mActiveDownloads.erase(taskptr->getIdentifier()); mFinishedDownloads.push_back(taskptr->getIdentifier()); // Lack of response data means failure of some sort if (!response) { SILOG(ogre, warn, "failed response dependent callback " << taskptr->getIdentifier()); failDownload(); return; } // Store data for later use mDependencies[uri].request = request; mDependencies[uri].response = response; if (mActiveDownloads.size() == 0) mCB(); }
void DownloadManager::onFailed(UserConnection* aSource, const string& aError) { { Lock l(cs); idlers.erase(remove(idlers.begin(), idlers.end(), aSource), idlers.end()); } failDownload(aSource, aError); }
void AssetDownloadTask::assetFileDownloaded(ResourceDownloadTaskPtr taskptr, Transfer::ChunkRequestPtr request, Transfer::DenseDataPtr response) { boost::mutex::scoped_lock lok(mDependentDownloadMutex); // Clear from the active download list assert(mActiveDownloads.size() == 1); mActiveDownloads.erase(taskptr->getIdentifier()); mFinishedDownloads.push_back(taskptr->getIdentifier()); // Lack of response data means failure of some sort if (!response) { SILOG(ogre, warn, "Failed to download resource for " << taskptr->getIdentifier()); failDownload(); return; } // FIXME here we could have another callback which lets them get // at the hash to try to use an existing copy. Even with the // eventual centralized loading we want, this may still be // beneficial since Ogre may have a copy even if we don't have a // copy of the raw data any more. mParseMeshHandle = mScene->parseMesh( request->getMetadata(), request->getMetadata().getFingerprint(), response, mIsAggregate, std::tr1::bind(&AssetDownloadTask::weakHandleAssetParsed, getWeakPtr(), _1) ); }
void DownloadManager::noSlots(UserConnection* aSource) { if(aSource->getState() != UserConnection::STATE_SND) { dcdebug("DM::noSlots Bad state, disconnecting\n"); aSource->disconnect(); return; } failDownload(aSource, _("No slots available")); }
/** Download finished! */ void DownloadManager::endData(UserConnection* aSource) { dcassert(aSource->getState() == UserConnection::STATE_RUNNING); Download* d = aSource->getDownload(); dcassert(d != NULL); if(d->getType() == Transfer::TYPE_TREE) { d->getFile()->flush(); int64_t bl = 1024; while(bl * (int64_t)d->getTigerTree().getLeaves().size() < d->getTigerTree().getFileSize()) bl *= 2; d->getTigerTree().setBlockSize(bl); d->getTigerTree().calcRoot(); if(!(d->getTTH() == d->getTigerTree().getRoot())) { // This tree is for a different file, remove from queue... removeDownload(d); fire(DownloadManagerListener::Failed(), d, _("Full tree does not match TTH root")); QueueManager::getInstance()->removeSource(d->getPath(), aSource->getUser(), QueueItem::Source::FLAG_BAD_TREE, false); QueueManager::getInstance()->putDownload(d, false); checkDownloads(aSource); return; } d->setTreeValid(true); } else { // First, finish writing the file (flushing the buffers and closing the file...) try { d->getFile()->flush(); } catch(const Exception& e) { d->resetPos(); failDownload(aSource, e.getError()); return; } aSource->setSpeed(d->getAverageSpeed()); aSource->updateChunkSize(d->getTigerTree().getBlockSize(), d->getSize(), GET_TICK() - d->getStart()); dcdebug("Download finished: %s, size " I64_FMT ", downloaded " I64_FMT "\n", d->getPath().c_str(), static_cast<long long int>(d->getSize()), static_cast<long long int>(d->getPos())); if(BOOLSETTING(LOG_DOWNLOADS) && (BOOLSETTING(LOG_FILELIST_TRANSFERS) || d->getType() == Transfer::TYPE_FILE)) { logDownload(aSource, d); } } removeDownload(d); fire(DownloadManagerListener::Complete(), d); QueueManager::getInstance()->putDownload(d, true); checkDownloads(aSource); }
void DownloadManager::on(UserConnectionListener::Data, UserConnection* aSource, const uint8_t* aData, size_t aLen) noexcept { Download* d = aSource->getDownload(); dcassert(d != NULL); try { d->addPos(d->getFile()->write(aData, aLen), aLen); d->tick(); if(d->getFile()->eof()) { endData(aSource); aSource->setLineMode(0); } } catch(const Exception& e) { failDownload(aSource, e.getError()); } }
void AssetDownloadTask::textureDownloaded(std::tr1::shared_ptr<ChunkRequest> request, std::tr1::shared_ptr<const DenseData> response) { // Clear the download task mActiveDownloads.erase(request->getURI()); // Lack of response data means failure of some sort if (!response) { failDownload(); return; } // Store data for later use mDependencies[request->getURI()].request = request; mDependencies[request->getURI()].response = response; mRemainingDownloads--; if (mRemainingDownloads == 0) mCB(); }
void AssetDownloadTask::assetFileDownloaded(std::tr1::shared_ptr<ChunkRequest> request, std::tr1::shared_ptr<const DenseData> response) { // Clear from the active download list assert(mActiveDownloads.size() == 1); mActiveDownloads.erase(mAssetURI); // Lack of response data means failure of some sort if (!response) { failDownload(); return; } // FIXME here we could have another callback which lets them get // at the hash to try to use an existing copy. Even with the // eventual centralized loading we want, this may still be // beneficial since Ogre may have a copy even if we don't have a // copy of the raw data any more. mScene->parseMesh( mAssetURI, request->getMetadata().getFingerprint(), response, std::tr1::bind(&AssetDownloadTask::weakHandleAssetParsed, getWeakPtr(), _1) ); }
void DownloadManager::startData(UserConnection* aSource, int64_t start, int64_t bytes, bool z) { Download* d = aSource->getDownload(); dcassert(d != NULL); dcdebug("Preparing " I64_FMT ":" I64_FMT ", " I64_FMT ":" I64_FMT"\n", static_cast<long long int>(d->getStartPos()), static_cast<long long int>(start), static_cast<long long int>(d->getSize()), static_cast<long long int>(bytes)); if(d->getSize() == -1) { if(bytes >= 0) { d->setSize(bytes); } else { failDownload(aSource, _("Invalid size")); return; } } else if(d->getSize() != bytes || d->getStartPos() != start) { // This is not what we requested... failDownload(aSource, _("Response does not match request")); return; } try { QueueManager::getInstance()->setFile(d); } catch(const FileException& e) { failDownload(aSource, str(F_("Could not open target file: %1%") % e.getError())); return; } catch(const Exception& e) { failDownload(aSource, e.getError()); return; } if((d->getType() == Transfer::TYPE_FILE || d->getType() == Transfer::TYPE_FULL_LIST) && SETTING(BUFFER_SIZE) > 0 ) { d->setFile(new BufferedOutputStream<true>(d->getFile())); } if(d->getType() == Transfer::TYPE_FILE) { typedef MerkleCheckOutputStream<TigerTree, true> MerkleStream; d->setFile(new MerkleStream(d->getTigerTree(), d->getFile(), d->getStartPos())); d->setFlag(Download::FLAG_TTH_CHECK); } // Check that we don't get too many bytes d->setFile(new LimitedOutputStream<true>(d->getFile(), bytes)); if(z) { d->setFlag(Download::FLAG_ZDOWNLOAD); d->setFile(new FilteredOutputStream<UnZFilter, true>(d->getFile())); } d->setStart(GET_TICK()); d->tick(); aSource->setState(UserConnection::STATE_RUNNING); fire(DownloadManagerListener::Starting(), d); if(d->getPos() == d->getSize()) { try { // Already finished? A zero-byte file list could cause this... endData(aSource); } catch(const Exception& e) { failDownload(aSource, e.getError()); } } else { aSource->setDataMode(); } }