QList<QSharedPointer<IChunkDownloader>> DownloadManager::getTheFirstUnfinishedChunks(int n) { QList<QSharedPointer<IChunkDownloader>> unfinishedChunks; DownloadQueue::ScanningIterator<IsDownloable> i(this->downloadQueue); FileDownload* fileDownload; while (unfinishedChunks.size() < n && (fileDownload = static_cast<FileDownload*>(i.next()))) { fileDownload->getUnfinishedChunks(unfinishedChunks, n - unfinishedChunks.size(), false); // 'false' because we always want the first (unfinished) chunks. } return unfinishedChunks; }
QList< QSharedPointer<IChunkDownload> > DownloadManager::getTheFirstUnfinishedChunks(int n) { QList< QSharedPointer<IChunkDownload> > unfinishedChunks; FileDownload* fileDownload = 0; DownloadQueue::ScanningIterator<IsDownloable> i(this->downloadQueue); while (unfinishedChunks.size() < n) { if (!(fileDownload = static_cast<FileDownload*>(i.next()))) break; fileDownload->getUnfinishedChunks(unfinishedChunks, n - unfinishedChunks.size()); } return unfinishedChunks; }
/** * Search a chunk to download. */ void DownloadManager::scanTheQueue() { L_DEBU("Scanning the queue . . ."); int numberOfDownloadThreadRunningCopy = this->numberOfDownloadThreadRunning; QSharedPointer<ChunkDownloader> chunkDownloader; FileDownload* fileDownload = nullptr; // To know the number of peers not occupied that own at least one chunk in the queue. QSet<PM::IPeer*> linkedPeersNotOccupied = this->linkedPeers.getPeers().toSet(); linkedPeersNotOccupied -= this->occupiedPeersDownloadingChunk.getOccupiedPeers(); DownloadQueue::ScanningIterator<IsDownloable> i(this->downloadQueue); while (numberOfDownloadThreadRunningCopy < NUMBER_OF_DOWNLOADER && !linkedPeersNotOccupied.isEmpty()) { if (chunkDownloader.isNull()) // We can ask many chunks to download from the same file. if (!(fileDownload = static_cast<FileDownload*>(i.next()))) break; if (fileDownload->isStatusErroneous()) continue; chunkDownloader = fileDownload->getAChunkToDownload(); if (chunkDownloader.isNull()) continue; if (PM::IPeer* currentPeer = chunkDownloader->startDownloading()) { connect(chunkDownloader.data(), SIGNAL(downloadFinished()), this, SLOT(chunkDownloaderFinished()), Qt::DirectConnection); linkedPeersNotOccupied -= currentPeer; this->numberOfDownloadThreadRunning++; numberOfDownloadThreadRunningCopy = this->numberOfDownloadThreadRunning; } } L_DEBU("Scanning terminated"); }
/** * This function will be called by libevent when the client socket is * ready for reading. If we are on linux, sendfile is available so we will use * that instead of copying the data to buffers */ inline void FileClient::on_read(int fd, short ev, void *arg) { FileDownload * download = static_cast<FileDownload*>(arg); auto buf = download->buf(); if(!download->ready()){ auto len = read(fd, buf->head(), buf->nbytes_rem()); if(len != -1) { if(len < buf->nbytes_rem()){ // still more bytes to be read buf->decr_nbytes_rem(len); } else { // all bytes read if(!download->fsize_rcvd()) { download->SetFsizeRcvd(true); LOG_DEBUG("Received file size: " + std::to_string(download->fsize())); } else { download->SetHashRcvd(true); LOG_DEBUG("Received file hash: " + get_md5_str(download->hash())); } } } else { LOG_INFO("Problem reading from socket to filesize buffer"); download->client()->DownloadCompleted(download, false); } } else { #ifdef __linux auto len = sendfile(fd, download->file_fd(), download->foffset_ptr(), BUFLEN);//, download->fsize() - download->foffset()); #else // read into the buffer uint8_t buf[BUFLEN]; auto len = read(fd, buf, BUFLEN); #endif if (len == 0) { /* Client disconnected, remove the read event and the * free the client structure. */ LOG_ERR("Client disconnected.\n"); download->FileRcvd(); download->client()->DownloadCompleted(download); } else if (len == -1) { /* Some other error occurred, close the socket, remove * the event and free the client structure. */ LOG_ERR("Socket failure, disconnecting client: " + std::string(strerror(errno))); download->client()->DownloadCompleted(download, false); } else { #ifndef __linux //fwrite(buf, sizeof(char), len, download->pfile()); write(download->file_fd(), buf, len); download->incr_foffset(len); // offset is incremented by sendfile #endif if(download->foffset() == download->fsize()) { // must close the file descriptor to save the written bytes download->FileRcvd(); download->client()->DownloadCompleted(download); } } } }
void DownloadQueue::fileDownloadTimeChanged(QTime oldTime) { FileDownload* fileDownload = static_cast<FileDownload*>(this->sender()); this->downloadsSortedByTime.remove(oldTime, fileDownload); this->downloadsSortedByTime.insert(fileDownload->getLastTimeGetAllUnfinishedChunks(), fileDownload); }