diff --git a/libretroshare/src/ft/ftchunkmap.cc b/libretroshare/src/ft/ftchunkmap.cc index d60052aee..d6782f5ef 100644 --- a/libretroshare/src/ft/ftchunkmap.cc +++ b/libretroshare/src/ft/ftchunkmap.cc @@ -38,6 +38,7 @@ static const uint32_t SOURCE_CHUNK_MAP_UPDATE_PERIOD = 60 ; //! TTL for chunkmap info static const uint32_t INACTIVE_CHUNK_TIME_LAPSE = 300 ; //! TTL for an inactive chunk +static const uint32_t FT_CHUNKMAP_MAX_CHUNK_JUMP = 50 ; //! Maximum chunk jump in progressive DL mode std::ostream& operator<<(std::ostream& o,const ftChunk& c) { @@ -74,7 +75,7 @@ ChunkMap::ChunkMap(uint64_t s,bool availability) ++n ; _map.resize(n,FileChunksInfo::CHUNK_OUTSTANDING) ; - _strategy = FileChunksInfo::CHUNK_STRATEGY_RANDOM ; + _strategy = FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE ; _total_downloaded = 0 ; _file_is_complete = false ; #ifdef DEBUG_FTCHUNK @@ -537,27 +538,45 @@ uint32_t ChunkMap::getAvailableChunk(const std::string& peer_id,bool& map_is_too map_is_too_old = false ;// the map is not too old uint32_t available_chunks = 0 ; + uint32_t available_chunks_before_max_dist = 0 ; + uint32_t max_dist = 0; // id of the highest downloaded chunk for(unsigned int i=0;i<_map.size();++i) - if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING && (peer_chunks->is_full || peer_chunks->cmap[i])) + if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING) { - if(_strategy == FileChunksInfo::CHUNK_STRATEGY_STREAMING) - { -#ifdef DEBUG_FTCHUNK - std::cerr << "ChunkMap::getAvailableChunk: returning chunk " << i << " for peer " << peer_id << std::endl; -#endif - return i ; - } - else + if(peer_chunks->is_full || peer_chunks->cmap[i]) ++available_chunks ; } + else + { + max_dist = i ; + available_chunks_before_max_dist = available_chunks ; + } if(available_chunks > 0) { - uint32_t chosen_chunk_number = rand() % available_chunks ; + uint32_t chunk_jump ; + uint32_t chosen_chunk_number ; + + switch(_strategy) + { + case FileChunksInfo::CHUNK_STRATEGY_STREAMING: chunk_jump = 1 ; + chosen_chunk_number = 0 ; + break ; + case FileChunksInfo::CHUNK_STRATEGY_RANDOM: chunk_jump = _map.size() ; + chosen_chunk_number = rand() % available_chunks ; + break ; + case FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE: chunk_jump = FT_CHUNKMAP_MAX_CHUNK_JUMP ; + chosen_chunk_number = rand() % std::min(available_chunks, available_chunks_before_max_dist+FT_CHUNKMAP_MAX_CHUNK_JUMP) ; + break ; + default: + chunk_jump = _map.size() ; + chosen_chunk_number = 0 ; + } + uint32_t max_chunk = std::min((uint32_t)_map.size(),max_dist + chunk_jump) ; uint32_t j=0 ; - for(uint32_t i=0;i<_map.size();++i) + for(uint32_t i=0;iis_full || peer_chunks->cmap[i])) { if(j == chosen_chunk_number) diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc index a9feac0a4..c423a0d36 100644 --- a/libretroshare/src/ft/ftcontroller.cc +++ b/libretroshare/src/ft/ftcontroller.cc @@ -104,7 +104,7 @@ ftController::ftController(CacheStrapper *cs, ftDataMultiplex *dm, std::string / ctrlMutex("ftController"), doneMutex("ftController"), mFtActive(false), - mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) + mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) { _max_active_downloads = 5 ; // default queue size _min_prioritized_transfers = 3 ; @@ -2235,6 +2235,11 @@ bool ftController::loadConfigMap(std::map &configMap) setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; std::cerr << "Note: loading default value for chunk strategy: random" << std::endl; } + else if(mit->second == "PROGRESSIVE") + { + setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; + std::cerr << "Note: loading default value for chunk strategy: progressive" << std::endl; + } else std::cerr << "**** ERROR ***: Unknown value for default chunk strategy in keymap." << std::endl ; } diff --git a/libretroshare/src/ft/ftfilecreator.cc b/libretroshare/src/ft/ftfilecreator.cc index 233e7a8d7..8d9163ce3 100644 --- a/libretroshare/src/ft/ftfilecreator.cc +++ b/libretroshare/src/ft/ftfilecreator.cc @@ -416,10 +416,10 @@ void ftFileCreator::setChunkStrategy(FileChunksInfo::ChunkStrategy s) RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ // Let's check, for safety. - if(s != FileChunksInfo::CHUNK_STRATEGY_STREAMING && s != FileChunksInfo::CHUNK_STRATEGY_RANDOM) + if(s != FileChunksInfo::CHUNK_STRATEGY_STREAMING && s != FileChunksInfo::CHUNK_STRATEGY_RANDOM && s != FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) { std::cerr << "ftFileCreator::ERROR: invalid chunk strategy " << s << "!" << " setting default value " << FileChunksInfo::CHUNK_STRATEGY_STREAMING << std::endl ; - s = FileChunksInfo::CHUNK_STRATEGY_STREAMING ; + s = FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE ; } #ifdef FILE_DEBUG diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h index 035c4a0e7..ec7e8f875 100644 --- a/libretroshare/src/retroshare/rstypes.h +++ b/libretroshare/src/retroshare/rstypes.h @@ -311,7 +311,7 @@ class FileChunksInfo { public: enum ChunkState { CHUNK_CHECKING=3, CHUNK_DONE=2, CHUNK_ACTIVE=1, CHUNK_OUTSTANDING=0 } ; - enum ChunkStrategy { CHUNK_STRATEGY_STREAMING, CHUNK_STRATEGY_RANDOM } ; + enum ChunkStrategy { CHUNK_STRATEGY_STREAMING, CHUNK_STRATEGY_RANDOM, CHUNK_STRATEGY_PROGRESSIVE } ; struct SliceInfo { diff --git a/libretroshare/src/tests/ft/ftcrossprovidercreatortest.cc b/libretroshare/src/tests/ft/ftcrossprovidercreatortest.cc index 41152da04..ed940a98d 100644 --- a/libretroshare/src/tests/ft/ftcrossprovidercreatortest.cc +++ b/libretroshare/src/tests/ft/ftcrossprovidercreatortest.cc @@ -76,7 +76,7 @@ int main() std::string fname = "source_tmp.bin" ; std::string fname_copy_1 = "copy_1_tmp.bin" ; std::string fname_copy_2 = "copy_2_tmp.bin" ; - uint64_t size = 5000000 ; + uint64_t size = 100000000 ; std::string hash = "" ; pthread_t seed = 8;//getpid() ; @@ -92,6 +92,9 @@ int main() ftFileCreator *client1 = new ftFileCreator(fname_copy_1,size,hash,false) ; ftFileCreator *client2 = new ftFileCreator(fname_copy_2,size,hash,false) ; + client1->setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; + client2->setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; + // 3 - Exchange chunks, and build two copies of the file. // std::string peer_id_1("client peer id 1") ; diff --git a/retroshare-gui/src/gui/FileTransferInfoWidget.cpp b/retroshare-gui/src/gui/FileTransferInfoWidget.cpp index 0937ffcb2..d49c96998 100644 --- a/retroshare-gui/src/gui/FileTransferInfoWidget.cpp +++ b/retroshare-gui/src/gui/FileTransferInfoWidget.cpp @@ -260,7 +260,14 @@ void FileTransferInfoWidget::draw(const FileInfo& nfo,const FileChunksInfo& info y += block_sep ; y += text_height ; painter->drawText(20,y,tr("Number of sources") + ":") ; painter->drawText(tab_size,y,QString::number(info.compressed_peer_availability_maps.size())) ; y += block_sep ; - y += text_height ; painter->drawText(20,y,tr("Chunk strategy") + ":") ; painter->drawText(tab_size,y,(info.strategy==FileChunksInfo::CHUNK_STRATEGY_RANDOM)?"Random":"Streaming") ; + y += text_height ; painter->drawText(20,y,tr("Chunk strategy") + ":") ; + switch(info.strategy) + { + case FileChunksInfo::CHUNK_STRATEGY_RANDOM: painter->drawText(tab_size,y,"Random") ; break ; + case FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE: painter->drawText(tab_size,y,"Progressive") ; break ; + default: + case FileChunksInfo::CHUNK_STRATEGY_STREAMING: painter->drawText(tab_size,y,"Streaming") ; break ; + } y += block_sep ; y += text_height ; painter->drawText(20,y,tr("Transfer type") + ":") ; if(nfo.transfer_info_flags & RS_FILE_REQ_ANONYMOUS_ROUTING) painter->drawText(tab_size,y,tr("Anonymous F2F")) ; diff --git a/retroshare-gui/src/gui/TransfersDialog.cpp b/retroshare-gui/src/gui/TransfersDialog.cpp index e7c5d62ce..e13a6b9dd 100644 --- a/retroshare-gui/src/gui/TransfersDialog.cpp +++ b/retroshare-gui/src/gui/TransfersDialog.cpp @@ -397,6 +397,8 @@ TransfersDialog::TransfersDialog(QWidget *parent) connect(priorityFastAct, SIGNAL(triggered()), this, SLOT(speedFast())); chunkRandomAct = new QAction(QIcon(IMAGE_PRIORITYAUTO), tr("Random"), this); connect(chunkRandomAct, SIGNAL(triggered()), this, SLOT(chunkRandom())); + chunkProgressiveAct = new QAction(QIcon(IMAGE_PRIORITYAUTO), tr("Progressive"), this); + connect(chunkProgressiveAct, SIGNAL(triggered()), this, SLOT(chunkProgressive())); playAct = new QAction(QIcon(IMAGE_PLAY), tr( "Play" ), this ); connect( playAct , SIGNAL( triggered() ), this, SLOT( openTransfer() ) ); renameFileAct = new QAction(QIcon(IMAGE_PRIORITYNORMAL), tr("Rename file..."), this); @@ -547,6 +549,7 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ ) QMenu chunkMenu(tr("Chunk strategy"), this); chunkMenu.setIcon(QIcon(IMAGE_PRIORITY)); chunkMenu.addAction(chunkStreamingAct); + chunkMenu.addAction(chunkProgressiveAct); chunkMenu.addAction(chunkRandomAct); QMenu contextMnu( this ); @@ -1510,6 +1513,10 @@ void TransfersDialog::chunkRandom() { setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; } +void TransfersDialog::chunkProgressive() +{ + setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; +} void TransfersDialog::setChunkStrategy(FileChunksInfo::ChunkStrategy s) { std::set items; diff --git a/retroshare-gui/src/gui/TransfersDialog.h b/retroshare-gui/src/gui/TransfersDialog.h index 861e241f2..b7755eb37 100644 --- a/retroshare-gui/src/gui/TransfersDialog.h +++ b/retroshare-gui/src/gui/TransfersDialog.h @@ -116,6 +116,7 @@ private slots: void changeQueuePosition(QueueMove) ; void chunkRandom(); + void chunkProgressive(); void chunkStreaming(); void showDetailsDialog(); @@ -166,6 +167,7 @@ private: QAction *queueTopAct; QAction *queueBottomAct; QAction *chunkRandomAct; + QAction *chunkProgressiveAct; QAction *chunkStreamingAct; QAction *detailsfileAct; QAction *toggleShowCacheTransfersAct; diff --git a/retroshare-gui/src/gui/settings/TransferPage.cpp b/retroshare-gui/src/gui/settings/TransferPage.cpp index e9420bade..e5c9b709b 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.cpp +++ b/retroshare-gui/src/gui/settings/TransferPage.cpp @@ -38,10 +38,12 @@ TransferPage::TransferPage(QWidget * parent, Qt::WFlags flags) ui._queueSize_SB->setValue(rsFiles->getQueueSize()) ; ui._minPrioritized_SB->setValue(rsFiles->getMinPrioritizedTransfers()) ; - if(rsFiles->defaultChunkStrategy() == FileChunksInfo::CHUNK_STRATEGY_STREAMING) - ui._defaultStrategy_CB->setCurrentIndex(0) ; - else - ui._defaultStrategy_CB->setCurrentIndex(1) ; + switch(rsFiles->defaultChunkStrategy()) + { + case FileChunksInfo::CHUNK_STRATEGY_STREAMING: ui._defaultStrategy_CB->setCurrentIndex(0) ; break ; + case FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE: ui._defaultStrategy_CB->setCurrentIndex(1) ; break ; + case FileChunksInfo::CHUNK_STRATEGY_RANDOM: ui._defaultStrategy_CB->setCurrentIndex(2) ; break ; + } ui._diskSpaceLimit_SB->setValue(rsFiles->freeDiskSpaceLimit()) ; @@ -63,9 +65,11 @@ void TransferPage::updateDefaultStrategy(int i) case 0: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ; break ; - case 1: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; + case 2: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; break ; + case 1: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; + break ; default: ; } } diff --git a/retroshare-gui/src/gui/settings/TransferPage.ui b/retroshare-gui/src/gui/settings/TransferPage.ui index f38e73b5e..cd703924d 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.ui +++ b/retroshare-gui/src/gui/settings/TransferPage.ui @@ -97,6 +97,11 @@ It is however recommended to leave at least a few slots for cache files.Streaming + + + Progressive + + Random @@ -138,7 +143,7 @@ It is however recommended to leave at least a few slots for cache files.