2008-07-23 18:01:59 -04:00
/*
* libretroshare / src / ft : ftcontroller . cc
*
* File Transfer for RetroShare .
*
* Copyright 2008 by Robert Fernie .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
* Please report all bugs and problems to " retroshare@lunamutt.com " .
*
*/
2009-06-11 17:41:42 -04:00
/*
2008-07-23 18:01:59 -04:00
* ftController
*
* Top level download controller .
*
* inherits configuration ( save downloading files )
* inherits pqiMonitor ( knows which peers are online ) .
* inherits CacheTransfer ( transfers cache files too )
* inherits RsThread ( to control transfers )
*
*/
2010-05-16 19:26:45 -04:00
# ifdef WINDOWS_SYS
2011-10-01 09:12:28 -04:00
# include "util/rsstring.h"
2010-05-16 19:26:45 -04:00
# endif
2010-05-21 16:49:48 -04:00
# include "util/rsdiscspace.h"
2016-01-12 21:10:11 -05:00
# include "util/rsmemory.h"
2010-05-16 19:26:45 -04:00
2008-08-09 13:03:24 -04:00
# include "ft/ftcontroller.h"
# include "ft/ftfilecreator.h"
# include "ft/fttransfermodule.h"
# include "ft/ftsearch.h"
# include "ft/ftdatamultiplex.h"
2008-11-09 17:17:20 -05:00
# include "ft/ftextralist.h"
2013-04-06 05:21:01 -04:00
# include "ft/ftserver.h"
2008-08-09 13:03:24 -04:00
2009-05-26 17:42:45 -04:00
# include "turtle/p3turtle.h"
2008-08-09 13:03:24 -04:00
# include "util/rsdir.h"
2014-01-07 17:51:22 -05:00
# include "rsserver/p3face.h"
2008-07-23 18:01:59 -04:00
2011-07-09 14:39:34 -04:00
# include "pqi/p3linkmgr.h"
2008-07-23 18:01:59 -04:00
2010-11-24 19:20:25 -05:00
# include "retroshare/rsiface.h"
2013-06-05 08:57:11 -04:00
# include "retroshare/rspeers.h"
2010-11-24 19:20:25 -05:00
2008-11-15 15:00:29 -05:00
# include "serialiser/rsconfigitems.h"
2009-05-11 10:30:53 -04:00
# include <stdio.h>
2012-04-12 19:29:39 -04:00
# include <unistd.h> /* for (u)sleep() */
2013-10-21 07:00:49 -04:00
# include <time.h>
2008-08-09 13:03:24 -04:00
2008-12-07 09:53:57 -05:00
/******
* # define CONTROL_DEBUG 1
2010-03-06 18:37:42 -05:00
* # define DEBUG_DWLQUEUE 1
2008-12-07 09:53:57 -05:00
* * * * */
2008-08-09 13:03:24 -04:00
2014-09-20 15:54:04 -04:00
static const int32_t SAVE_TRANSFERS_DELAY = 301 ; // save transfer progress every 301 seconds.
2012-02-17 05:03:38 -05:00
static const int32_t INACTIVE_CHUNKS_CHECK_DELAY = 240 ; // time after which an inactive chunk is released
static const int32_t MAX_TIME_INACTIVE_REQUEUED = 120 ; // time after which an inactive ftFileControl is bt-queued
2009-12-10 17:55:27 -05:00
2012-02-17 05:03:38 -05:00
static const int32_t FT_FILECONTROL_QUEUE_ADD_END = 0 ;
2010-09-15 15:48:13 -04:00
2013-11-08 16:23:57 -05:00
const uint32_t FT_CNTRL_STANDARD_RATE = 10 * 1024 * 1024 ;
const uint32_t FT_CNTRL_SLOW_RATE = 100 * 1024 ;
2012-11-19 17:45:37 -05:00
2008-08-17 11:23:11 -04:00
ftFileControl : : ftFileControl ( )
2009-06-11 17:41:42 -04:00
: mTransfer ( NULL ) , mCreator ( NULL ) ,
2015-06-15 14:35:09 -04:00
mState ( DOWNLOADING ) , mSize ( 0 ) , mFlags ( 0 ) , mCreateTime ( 0 ) , mQueuePriority ( 0 ) , mQueuePosition ( 0 )
2008-08-17 11:23:11 -04:00
{
return ;
}
2009-06-11 17:41:42 -04:00
ftFileControl : : ftFileControl ( std : : string fname ,
std : : string tmppath , std : : string dest ,
2014-03-17 16:56:06 -04:00
uint64_t size , const RsFileHash & hash , TransferRequestFlags flags ,
2010-10-16 11:21:37 -04:00
ftFileCreator * fc , ftTransferModule * tm )
2008-10-29 16:58:23 -04:00
: mName ( fname ) , mCurrentPath ( tmppath ) , mDestination ( dest ) ,
2010-03-06 18:29:47 -05:00
mTransfer ( tm ) , mCreator ( fc ) , mState ( DOWNLOADING ) , mHash ( hash ) ,
2015-06-15 14:35:09 -04:00
mSize ( size ) , mFlags ( flags ) , mCreateTime ( 0 ) , mQueuePriority ( 0 ) , mQueuePosition ( 0 )
2008-08-17 11:23:11 -04:00
{
return ;
}
2016-07-30 15:52:42 -04:00
ftController : : ftController ( ftDataMultiplex * dm , p3ServiceControl * sc , uint32_t ftServiceId )
: p3Config ( ) ,
2010-01-11 11:00:42 -05:00
last_save_time ( 0 ) ,
2010-01-21 07:31:00 -05:00
last_clean_time ( 0 ) ,
2010-01-11 11:00:42 -05:00
mDataplex ( dm ) ,
mTurtle ( NULL ) ,
2013-04-06 05:21:01 -04:00
mFtServer ( NULL ) ,
2014-03-28 23:57:44 -04:00
mServiceCtrl ( sc ) ,
mFtServiceId ( ftServiceId ) ,
2011-07-04 18:59:39 -04:00
ctrlMutex ( " ftController " ) ,
doneMutex ( " ftController " ) ,
2010-01-11 11:00:42 -05:00
mFtActive ( false ) ,
2013-02-28 15:42:01 -05:00
mDefaultChunkStrategy ( FileChunksInfo : : CHUNK_STRATEGY_PROGRESSIVE )
2008-07-23 18:01:59 -04:00
{
2010-03-06 18:29:47 -05:00
_max_active_downloads = 5 ; // default queue size
2012-01-10 18:07:53 -05:00
_min_prioritized_transfers = 3 ;
2008-08-09 13:03:24 -04:00
/* TODO */
2015-05-22 16:54:38 -04:00
cnt = 0 ;
2008-07-23 18:01:59 -04:00
}
2013-04-06 05:21:01 -04:00
void ftController : : setTurtleRouter ( p3turtle * pt ) { mTurtle = pt ; }
void ftController : : setFtServer ( ftServer * ft ) { mFtServer = ft ; }
2008-11-09 17:17:20 -05:00
void ftController : : setFtSearchNExtra ( ftSearch * search , ftExtraList * list )
2008-08-09 13:03:24 -04:00
{
mSearch = search ;
2008-11-09 17:17:20 -05:00
mExtraList = list ;
2008-08-09 13:03:24 -04:00
}
2008-07-23 18:01:59 -04:00
2014-03-17 16:56:06 -04:00
bool ftController : : getFileDownloadChunksDetails ( const RsFileHash & hash , FileChunksInfo & info )
2009-11-18 18:02:37 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
2009-11-18 18:02:37 -05:00
2010-02-19 15:36:47 -05:00
if ( it ! = mDownloads . end ( ) )
{
2010-03-06 18:29:47 -05:00
it - > second - > mCreator - > getChunkMap ( info ) ;
2012-11-02 09:52:29 -04:00
//info.flags = it->second->mFlags ;
2009-11-18 18:02:37 -05:00
2010-02-19 15:36:47 -05:00
return true ;
}
2009-11-18 18:02:37 -05:00
2010-02-19 15:36:47 -05:00
it = mCompleted . find ( hash ) ;
if ( it ! = mCompleted . end ( ) )
{
// This should rather be done as a static method of ChunkMap.
//
2010-10-07 17:31:42 -04:00
// We do this manually, because the file creator has already been destroyed.
//
2010-03-06 18:29:47 -05:00
info . file_size = it - > second - > mSize ;
2010-10-07 17:31:42 -04:00
info . strategy = mDefaultChunkStrategy ;
2010-02-19 15:36:47 -05:00
info . chunk_size = ChunkMap : : CHUNKMAP_FIXED_CHUNK_SIZE ;
2012-11-02 09:52:29 -04:00
//info.flags = it->second->mFlags ;
2010-03-06 18:29:47 -05:00
uint32_t nb_chunks = it - > second - > mSize / ChunkMap : : CHUNKMAP_FIXED_CHUNK_SIZE ;
if ( it - > second - > mSize % ChunkMap : : CHUNKMAP_FIXED_CHUNK_SIZE ! = 0 )
2010-02-19 15:36:47 -05:00
+ + nb_chunks ;
info . chunks . resize ( nb_chunks , FileChunksInfo : : CHUNK_DONE ) ;
return true ;
}
return false ;
2009-11-18 18:02:37 -05:00
}
2014-03-17 16:56:06 -04:00
void ftController : : addFileSource ( const RsFileHash & hash , const RsPeerId & peer_id )
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
2009-05-26 17:42:45 -04:00
2015-07-09 16:55:11 -04:00
# ifdef CONTROL_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " ftController: Adding source " < < peer_id < < " to current download hash= " < < hash ;
2015-07-09 16:55:11 -04:00
# endif
2013-10-15 16:39:13 -04:00
if ( it ! = mDownloads . end ( ) )
{
it - > second - > mTransfer - > addFileSource ( peer_id ) ;
2014-03-28 23:57:44 -04:00
setPeerState ( it - > second - > mTransfer , peer_id , FT_CNTRL_STANDARD_RATE , mServiceCtrl - > isPeerConnected ( mFtServiceId , peer_id ) ) ;
2009-05-26 17:42:45 -04:00
# ifdef CONTROL_DEBUG
2013-10-15 16:39:13 -04:00
std : : cerr < < " ... added. " < < std : : endl ;
2009-05-26 17:42:45 -04:00
# endif
2013-10-15 16:39:13 -04:00
return ;
}
2009-05-26 17:42:45 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ... not added: hash not found. " < < std : : endl ;
# endif
}
2014-03-17 16:56:06 -04:00
void ftController : : removeFileSource ( const RsFileHash & hash , const RsPeerId & peer_id )
2009-06-03 14:47:14 -04:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
2009-06-03 14:47:14 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController: Adding source " < < peer_id < < " to current download hash= " < < hash ;
# endif
2013-10-15 16:39:13 -04:00
if ( it ! = mDownloads . end ( ) )
{
it - > second - > mTransfer - > removeFileSource ( peer_id ) ;
it - > second - > mCreator - > removeFileSource ( peer_id ) ;
2009-05-26 17:42:45 -04:00
2009-06-03 14:47:14 -04:00
# ifdef CONTROL_DEBUG
2013-10-15 16:39:13 -04:00
std : : cerr < < " ... added. " < < std : : endl ;
2009-06-03 14:47:14 -04:00
# endif
2013-10-15 16:39:13 -04:00
return ;
}
2009-06-03 14:47:14 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ... not added: hash not found. " < < std : : endl ;
# endif
}
2015-05-22 16:54:38 -04:00
void ftController : : data_tick ( )
2008-07-23 18:01:59 -04:00
{
2009-05-06 16:48:32 -04:00
/* check the queues */
2010-03-06 18:29:47 -05:00
2014-10-24 17:31:58 -04:00
//Waiting 1 sec before start
usleep ( 1 * 1000 * 1000 ) ; // 1 sec
2008-08-21 17:30:59 -04:00
2008-11-02 06:38:11 -05:00
# ifdef CONTROL_DEBUG
2009-05-06 16:48:32 -04:00
std : : cerr < < " ftController::run() " ;
std : : cerr < < std : : endl ;
2008-11-02 06:38:11 -05:00
# endif
2008-11-20 19:10:59 -05:00
bool doPending = false ;
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
doPending = ( mFtActive ) & & ( ! mFtPendingDone ) ;
}
2009-12-10 17:55:27 -05:00
time_t now = time ( NULL ) ;
2012-01-10 18:07:53 -05:00
if ( now > last_save_time + SAVE_TRANSFERS_DELAY )
2009-12-10 17:55:27 -05:00
{
2012-11-19 17:45:37 -05:00
searchForDirectSources ( ) ;
2010-01-26 15:40:21 -05:00
2009-12-10 17:55:27 -05:00
IndicateConfigChanged ( ) ;
last_save_time = now ;
}
2012-01-10 18:07:53 -05:00
if ( now > last_clean_time + INACTIVE_CHUNKS_CHECK_DELAY )
2010-01-21 07:31:00 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
for ( std : : map < RsFileHash , ftFileControl * > : : iterator it ( mDownloads . begin ( ) ) ; it ! = mDownloads . end ( ) ; + + it )
2010-03-06 18:29:47 -05:00
it - > second - > mCreator - > removeInactiveChunks ( ) ;
2010-01-21 07:31:00 -05:00
last_clean_time = now ;
}
2008-11-20 19:10:59 -05:00
if ( doPending )
{
if ( ! handleAPendingRequest ( ) )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
mFtPendingDone = true ;
}
}
2008-08-17 11:23:11 -04:00
2010-01-26 15:40:21 -05:00
tickTransfers ( ) ;
2008-08-21 17:30:59 -04:00
{
2014-03-17 16:56:06 -04:00
std : : list < RsFileHash > files_to_complete ;
2008-10-29 16:58:23 -04:00
2010-11-22 16:15:21 -05:00
{
RsStackMutex stack2 ( doneMutex ) ;
files_to_complete = mDone ;
mDone . clear ( ) ;
}
2014-03-17 16:56:06 -04:00
for ( std : : list < RsFileHash > : : iterator it ( files_to_complete . begin ( ) ) ; it ! = files_to_complete . end ( ) ; + + it )
2010-01-26 15:40:21 -05:00
completeFile ( * it ) ;
}
2010-03-06 18:29:47 -05:00
if ( cnt + + % 10 = = 0 )
checkDownloadQueue ( ) ;
2010-01-26 15:40:21 -05:00
}
2012-11-19 17:45:37 -05:00
void ftController : : searchForDirectSources ( )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-10-24 18:07:26 -04:00
for ( std : : map < RsFileHash , ftFileControl * > : : iterator it ( mDownloads . begin ( ) ) ; it ! = mDownloads . end ( ) ; + + it )
2012-11-19 17:45:37 -05:00
if ( it - > second - > mState ! = ftFileControl : : QUEUED & & it - > second - > mState ! = ftFileControl : : PAUSED )
2016-07-30 15:52:42 -04:00
{
FileInfo info ; // info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there)
2012-11-20 16:42:21 -05:00
2016-07-30 15:52:42 -04:00
if ( mSearch - > search ( it - > first , RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY , info ) )
for ( std : : list < TransferInfo > : : const_iterator pit = info . peers . begin ( ) ; pit ! = info . peers . end ( ) ; + + pit )
if ( rsPeers - > servicePermissionFlags ( pit - > peerId ) & RS_NODE_PERM_DIRECT_DL )
if ( it - > second - > mTransfer - > addFileSource ( pit - > peerId ) ) /* if the sources don't exist already - add in */
setPeerState ( it - > second - > mTransfer , pit - > peerId , FT_CNTRL_STANDARD_RATE , mServiceCtrl - > isPeerConnected ( mFtServiceId , pit - > peerId ) ) ;
}
2012-11-19 17:45:37 -05:00
}
2010-01-26 15:40:21 -05:00
void ftController : : tickTransfers ( )
{
// 1 - sort modules into arrays according to priority
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2010-03-06 18:29:47 -05:00
# ifdef CONTROL_DEBUG
2010-01-26 15:40:21 -05:00
std : : cerr < < " ticking transfers. " < < std : : endl ;
2010-03-06 18:29:47 -05:00
# endif
// Collect all non queued files.
//
2014-10-24 18:07:26 -04:00
for ( std : : map < RsFileHash , ftFileControl * > : : iterator it ( mDownloads . begin ( ) ) ; it ! = mDownloads . end ( ) ; + + it )
2010-03-15 08:57:08 -04:00
if ( it - > second - > mState ! = ftFileControl : : QUEUED & & it - > second - > mState ! = ftFileControl : : PAUSED )
2011-11-16 15:30:20 -05:00
it - > second - > mTransfer - > tick ( ) ;
2010-01-26 15:40:21 -05:00
}
2014-03-17 16:56:06 -04:00
bool ftController : : getPriority ( const RsFileHash & hash , DwlSpeed & p )
2010-01-26 15:40:21 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it ( mDownloads . find ( hash ) ) ;
2010-01-26 15:40:21 -05:00
if ( it ! = mDownloads . end ( ) )
{
2011-11-16 15:30:20 -05:00
p = it - > second - > mTransfer - > downloadPriority ( ) ;
2010-01-26 15:40:21 -05:00
return true ;
}
else
return false ;
}
2011-11-16 15:30:20 -05:00
2014-03-17 16:56:06 -04:00
void ftController : : setPriority ( const RsFileHash & hash , DwlSpeed p )
2010-01-26 15:40:21 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it ( mDownloads . find ( hash ) ) ;
2010-01-26 15:40:21 -05:00
if ( it ! = mDownloads . end ( ) )
2011-11-16 15:30:20 -05:00
it - > second - > mTransfer - > setDownloadPriority ( p ) ;
2010-01-26 15:40:21 -05:00
}
2008-07-23 18:01:59 -04:00
/* Called every 10 seconds or so */
void ftController : : checkDownloadQueue ( )
{
2010-03-06 18:29:47 -05:00
// We do multiple things here:
//
// 1 - are there queued files ?
// YES
// 1.1 - check for inactive files (see below).
// - select one inactive file
// - close it temporarily
// - remove it from turtle handling
// - move the ftFileControl to queued list
2011-01-10 10:30:37 -05:00
// - set the queue priority to 1+largest in the queue.
2010-03-06 18:29:47 -05:00
// 1.2 - pop from the queue the 1st file to come (according to priority)
// - enable turtle router handling for this hash
// - reset counters
// - set the file as waiting
// NO
// Do nothing, because no files are waiting.
//
// 2 - in FileRequest, if the max number of downloaded files is exceeded, put the
// file in the queue list, and don't enable the turtle router handling.
//
// Implementation:
// - locate a hash in the queue
// - move hashes in the queue up/down/top/bottom
// - now the place of each ftFileControl element in the queue to activate/desactive them
//
// So:
// - change mDownloads to be a std::map<hash,ftFileControl*>
// - sort the ftFileControl* into a std::vector
// - store the queue position of each ftFileControl* into its own structure (mQueuePosition member)
//
// We don't want the turtle router to keep openning tunnels for queued files, so we only base
// the notion of inactive on the fact that no traffic happens for the file within 5 mins.
//
// How do we detect inactive files?
// For a downld file: - no traffic for 5 min.
RsStackMutex mtx ( ctrlMutex ) ;
# ifdef DEBUG_DWLQUEUE
std : : cerr < < " Checking download queue. " < < std : : endl ;
# endif
if ( mDownloads . size ( ) < = _max_active_downloads )
return ;
// Check for inactive transfers.
//
time_t now = time ( NULL ) ;
2010-03-21 17:07:12 -04:00
uint32_t nb_moved = 0 ; // don't move more files than the size of the queue.
2010-03-06 18:29:47 -05:00
2014-03-17 16:56:06 -04:00
for ( std : : map < RsFileHash , ftFileControl * > : : const_iterator it ( mDownloads . begin ( ) ) ; it ! = mDownloads . end ( ) & & nb_moved < = _max_active_downloads ; + + it )
2010-03-15 08:57:08 -04:00
if ( it - > second - > mState ! = ftFileControl : : QUEUED
2013-08-28 17:26:27 -04:00
& & ( it - > second - > mState = = ftFileControl : : PAUSED
2013-12-04 15:26:54 -05:00
| | now > it - > second - > mTransfer - > lastActvTimeStamp ( ) + ( time_t ) MAX_TIME_INACTIVE_REQUEUED ) )
2010-03-06 18:29:47 -05:00
{
2010-03-21 17:07:12 -04:00
# ifdef DEBUG_DWLQUEUE
2013-12-04 15:26:54 -05:00
std : : cerr < < " - Inactive file " < < it - > second - > mName < < " at position " < < it - > second - > mQueuePosition < < " moved to end of the queue. mState= " < < it - > second - > mState < < " , time lapse= " < < now - it - > second - > mCreator - > lastActvTimeStamp ( ) < < std : : endl ;
2010-03-21 17:07:12 -04:00
# endif
2011-01-10 10:30:37 -05:00
locked_bottomQueue ( it - > second - > mQueuePosition ) ;
2010-03-06 18:29:47 -05:00
# ifdef DEBUG_DWLQUEUE
2010-03-21 17:07:12 -04:00
std : : cerr < < " new position: " < < it - > second - > mQueuePosition < < std : : endl ;
std : : cerr < < " new state: " < < it - > second - > mState < < std : : endl ;
2010-03-06 18:29:47 -05:00
# endif
2013-12-04 15:26:54 -05:00
it - > second - > mTransfer - > resetActvTimeStamp ( ) ; // very important!
2010-03-21 17:07:12 -04:00
+ + nb_moved ;
2010-03-06 18:29:47 -05:00
}
2012-01-10 18:07:53 -05:00
// Check that at least _min_prioritized_transfers are assigned to non cache transfers
std : : cerr < < " Asserting that at least " < < _min_prioritized_transfers < < " are dedicated to user transfers. " < < std : : endl ;
int user_transfers = 0 ;
std : : vector < uint32_t > to_move_before ;
std : : vector < uint32_t > to_move_after ;
for ( uint32_t p = 0 ; p < _queue . size ( ) ; + + p )
{
if ( p < _min_prioritized_transfers )
+ + user_transfers ; // count one more user file in the prioritized range.
else
{
if ( to_move_after . size ( ) + user_transfers > = _min_prioritized_transfers ) // we caught enough transfers to move back to the top of the queue.
break ;
2016-07-30 15:52:42 -04:00
to_move_after . push_back ( p ) ;
2012-01-10 18:07:53 -05:00
}
}
uint32_t to_move = ( uint32_t ) std : : max ( 0 , ( int ) _min_prioritized_transfers - ( int ) user_transfers ) ; // we move as many transfers as needed to get _min_prioritized_transfers user transfers.
std : : cerr < < " collected " < < to_move < < " transfers to move. " < < std : : endl ;
for ( uint32_t i = 0 ; i < to_move & & i < to_move_after . size ( ) & & i < to_move_before . size ( ) ; + + i )
locked_swapQueue ( to_move_before [ i ] , to_move_after [ i ] ) ;
2010-03-06 18:29:47 -05:00
}
2010-09-15 15:48:13 -04:00
void ftController : : locked_addToQueue ( ftFileControl * ftfc , int add_strategy )
2010-03-06 18:29:47 -05:00
{
# ifdef DEBUG_DWLQUEUE
std : : cerr < < " Queueing ftfileControl " < < ( void * ) ftfc < < " , name= " < < ftfc - > mName < < std : : endl ;
# endif
2010-09-15 15:48:13 -04:00
switch ( add_strategy )
{
2012-01-10 18:07:53 -05:00
// Different strategies for files and cache files:
// - a min number of slots is reserved to user file transfer
// - cache files are always added after this slot.
//
2010-09-15 15:48:13 -04:00
case FT_FILECONTROL_QUEUE_ADD_END : _queue . push_back ( ftfc ) ;
locked_checkQueueElement ( _queue . size ( ) - 1 ) ;
break ;
}
2010-03-06 18:29:47 -05:00
}
void ftController : : locked_queueRemove ( uint32_t pos )
{
for ( uint32_t p = pos ; p < _queue . size ( ) - 1 ; + + p )
{
_queue [ p ] = _queue [ p + 1 ] ;
locked_checkQueueElement ( p ) ;
}
_queue . pop_back ( ) ;
}
2009-01-24 10:22:08 -05:00
2012-01-10 18:07:53 -05:00
void ftController : : setMinPrioritizedTransfers ( uint32_t s )
{
RsStackMutex mtx ( ctrlMutex ) ;
_min_prioritized_transfers = s ;
}
uint32_t ftController : : getMinPrioritizedTransfers ( )
{
RsStackMutex mtx ( ctrlMutex ) ;
return _min_prioritized_transfers ;
}
2010-03-06 18:29:47 -05:00
void ftController : : setQueueSize ( uint32_t s )
{
RsStackMutex mtx ( ctrlMutex ) ;
2009-01-24 10:22:08 -05:00
2010-03-06 18:29:47 -05:00
if ( s > 0 )
{
uint32_t old_s = _max_active_downloads ;
_max_active_downloads = s ;
# ifdef DEBUG_DWLQUEUE
std : : cerr < < " Settign new queue size to " < < s < < std : : endl ;
# endif
for ( uint32_t p = std : : min ( s , old_s ) ; p < = std : : max ( s , old_s ) ; + + p )
2010-03-21 17:07:12 -04:00
if ( p < _queue . size ( ) )
locked_checkQueueElement ( p ) ;
2010-03-06 18:29:47 -05:00
}
else
std : : cerr < < " ftController::setQueueSize(): cannot set queue to size " < < s < < std : : endl ;
}
uint32_t ftController : : getQueueSize ( )
{
RsStackMutex mtx ( ctrlMutex ) ;
return _max_active_downloads ;
}
2014-03-17 16:56:06 -04:00
void ftController : : moveInQueue ( const RsFileHash & hash , QueueMove mv )
2010-03-06 18:29:47 -05:00
{
RsStackMutex mtx ( ctrlMutex ) ;
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it ( mDownloads . find ( hash ) ) ;
2010-03-06 18:29:47 -05:00
if ( it = = mDownloads . end ( ) )
{
std : : cerr < < " ftController::moveInQueue: can't find hash " < < hash < < " in the download list. " < < std : : endl ;
return ;
}
uint32_t pos = it - > second - > mQueuePosition ;
# ifdef DEBUG_DWLQUEUE
std : : cerr < < " Moving file " < < hash < < " , pos= " < < pos < < " to new pos. " < < std : : endl ;
# endif
switch ( mv )
{
case QUEUE_TOP : locked_topQueue ( pos ) ;
break ;
case QUEUE_BOTTOM : locked_bottomQueue ( pos ) ;
break ;
case QUEUE_UP : if ( pos > 0 )
locked_swapQueue ( pos , pos - 1 ) ;
break ;
case QUEUE_DOWN : if ( pos < _queue . size ( ) - 1 )
locked_swapQueue ( pos , pos + 1 ) ;
break ;
default :
std : : cerr < < " ftController::moveInQueue: unknown move " < < mv < < std : : endl ;
}
}
void ftController : : locked_topQueue ( uint32_t pos )
{
ftFileControl * tmp = _queue [ pos ] ;
for ( int p = pos ; p > 0 ; - - p )
{
_queue [ p ] = _queue [ p - 1 ] ;
locked_checkQueueElement ( p ) ;
}
_queue [ 0 ] = tmp ;
2010-04-30 17:07:21 -04:00
2010-03-06 18:29:47 -05:00
locked_checkQueueElement ( 0 ) ;
}
void ftController : : locked_bottomQueue ( uint32_t pos )
{
ftFileControl * tmp = _queue [ pos ] ;
for ( uint32_t p = pos ; p < _queue . size ( ) - 1 ; + + p )
{
_queue [ p ] = _queue [ p + 1 ] ;
locked_checkQueueElement ( p ) ;
}
_queue [ _queue . size ( ) - 1 ] = tmp ;
locked_checkQueueElement ( _queue . size ( ) - 1 ) ;
}
void ftController : : locked_swapQueue ( uint32_t pos1 , uint32_t pos2 )
{
// Swap the element at position pos with the last element of the queue
if ( pos1 = = pos2 )
return ;
ftFileControl * tmp = _queue [ pos1 ] ;
_queue [ pos1 ] = _queue [ pos2 ] ;
_queue [ pos2 ] = tmp ;
locked_checkQueueElement ( pos1 ) ;
locked_checkQueueElement ( pos2 ) ;
}
void ftController : : locked_checkQueueElement ( uint32_t pos )
{
_queue [ pos ] - > mQueuePosition = pos ;
2010-04-30 17:07:21 -04:00
if ( pos < _max_active_downloads & & _queue [ pos ] - > mState ! = ftFileControl : : PAUSED )
2010-03-06 18:29:47 -05:00
{
2010-04-30 17:07:21 -04:00
if ( _queue [ pos ] - > mState = = ftFileControl : : QUEUED )
2013-12-04 15:26:54 -05:00
_queue [ pos ] - > mTransfer - > resetActvTimeStamp ( ) ;
2010-04-30 17:07:21 -04:00
2010-03-06 18:29:47 -05:00
_queue [ pos ] - > mState = ftFileControl : : DOWNLOADING ;
2010-03-12 14:39:23 -05:00
2012-11-02 09:52:29 -04:00
if ( _queue [ pos ] - > mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING )
2015-01-22 15:25:39 -05:00
mTurtle - > monitorTunnels ( _queue [ pos ] - > mHash , mFtServer , true ) ;
2010-03-06 18:29:47 -05:00
}
2010-03-15 08:57:08 -04:00
if ( pos > = _max_active_downloads & & _queue [ pos ] - > mState ! = ftFileControl : : QUEUED & & _queue [ pos ] - > mState ! = ftFileControl : : PAUSED )
2010-03-06 18:29:47 -05:00
{
_queue [ pos ] - > mState = ftFileControl : : QUEUED ;
_queue [ pos ] - > mCreator - > closeFile ( ) ;
2010-03-12 14:39:23 -05:00
2012-11-02 09:52:29 -04:00
if ( _queue [ pos ] - > mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING )
2013-04-01 17:18:58 -04:00
mTurtle - > stopMonitoringTunnels ( _queue [ pos ] - > mHash ) ;
2010-03-06 18:29:47 -05:00
}
2008-07-23 18:01:59 -04:00
}
2014-03-17 16:56:06 -04:00
bool ftController : : FlagFileComplete ( const RsFileHash & hash )
2008-07-23 18:01:59 -04:00
{
2009-06-11 17:41:42 -04:00
RsStackMutex stack2 ( doneMutex ) ;
2008-10-29 16:58:23 -04:00
mDone . push_back ( hash ) ;
2008-08-09 13:03:24 -04:00
2009-12-14 13:10:20 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController:FlagFileComplete( " < < hash < < " ) " ;
std : : cerr < < std : : endl ;
# endif
2008-08-09 13:03:24 -04:00
2008-10-29 16:58:23 -04:00
return true ;
}
2009-03-19 08:49:11 -04:00
bool ftController : : moveFile ( const std : : string & source , const std : : string & dest )
{
// First try a rename
//
2010-05-16 19:26:45 -04:00
# ifdef WINDOWS_SYS
std : : wstring sourceW ;
std : : wstring destW ;
librs : : util : : ConvertUtf8ToUtf16 ( source , sourceW ) ;
librs : : util : : ConvertUtf8ToUtf16 ( dest , destW ) ;
2010-06-16 12:18:08 -04:00
if ( 0 ! = MoveFileW ( sourceW . c_str ( ) , destW . c_str ( ) ) )
2010-05-16 19:26:45 -04:00
# else
2009-03-19 08:49:11 -04:00
if ( 0 = = rename ( source . c_str ( ) , dest . c_str ( ) ) )
2010-05-16 19:26:45 -04:00
# endif
2009-03-19 08:49:11 -04:00
{
2009-12-14 13:10:20 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::completeFile() renaming to: " ;
std : : cerr < < dest ;
std : : cerr < < std : : endl ;
# endif
2009-03-19 08:49:11 -04:00
return true ;
}
2009-12-14 13:10:20 -05:00
# ifdef CONTROL_DEBUG
2009-03-19 08:49:11 -04:00
std : : cerr < < " ftController::completeFile() FAILED mv to: " ;
std : : cerr < < dest ;
std : : cerr < < std : : endl ;
std : : cerr < < " trying copy " < < std : : endl ;
2009-12-14 13:10:20 -05:00
# endif
2009-06-11 17:41:42 -04:00
// We could not rename, probably because we're dealing with different file systems.
2009-03-19 08:49:11 -04:00
// Let's copy then.
2010-05-16 19:26:45 -04:00
# ifdef WINDOWS_SYS
if ( CopyFileW ( sourceW . c_str ( ) , destW . c_str ( ) , FALSE ) = = 0 )
# else
2010-05-09 09:52:05 -04:00
if ( ! copyFile ( source , dest ) )
2010-05-16 19:26:45 -04:00
# endif
2010-05-09 09:52:05 -04:00
return false ;
// copy was successfull, let's delete the original
std : : cerr < < " deleting original file " < < source < < std : : endl ;
2010-05-16 19:26:45 -04:00
# ifdef WINDOWS_SYS
2010-06-16 12:18:08 -04:00
if ( 0 ! = DeleteFileW ( sourceW . c_str ( ) ) )
2010-05-16 19:26:45 -04:00
# else
2010-05-09 09:52:05 -04:00
if ( 0 = = remove ( source . c_str ( ) ) )
2010-05-16 19:26:45 -04:00
# endif
2010-05-09 09:52:05 -04:00
return true ;
else
{
2014-01-07 17:51:22 -05:00
RsServer : : notify ( ) - > AddSysMessage ( 0 , RS_SYS_WARNING , " File erase error " , " Error while removing hash file " + dest + " \n Read-only file system ? " ) ;
2010-05-09 09:52:05 -04:00
return false ;
}
}
2009-03-19 08:49:11 -04:00
2010-05-09 09:52:05 -04:00
bool ftController : : copyFile ( const std : : string & source , const std : : string & dest )
{
2011-04-03 19:11:38 -04:00
FILE * in = RsDirUtil : : rs_fopen ( source . c_str ( ) , " rb " ) ;
2009-03-19 08:49:11 -04:00
if ( in = = NULL )
{
2014-01-07 17:51:22 -05:00
//RsServer::notify()->AddSysMessage(0, RS_SYS_WARNING, "File copy error", "Error while copying file " + dest + "\nCannot open input file "+source);
2011-07-06 15:08:30 -04:00
std : : cerr < < " ******************** FT CONTROLLER ERROR ************************ " < < std : : endl ;
std : : cerr < < " Error while copying file " + dest + " \n Cannot open input file " + source < < std : : endl ;
std : : cerr < < " ***************************************************************** " < < std : : endl ;
2009-03-19 08:49:11 -04:00
return false ;
}
2011-04-03 19:11:38 -04:00
FILE * out = RsDirUtil : : rs_fopen ( dest . c_str ( ) , " wb " ) ;
2009-03-19 08:49:11 -04:00
if ( out = = NULL )
{
2014-01-07 17:51:22 -05:00
RsServer : : notify ( ) - > AddSysMessage ( 0 , RS_SYS_WARNING , " File copy error " , " Error while copying file " + dest + " \n Check for disk full, or write permission ? \n Original file kept under the name " + source ) ;
2010-05-12 16:10:22 -04:00
fclose ( in ) ;
2009-03-19 08:49:11 -04:00
return false ;
}
size_t s = 0 ;
size_t T = 0 ;
2010-05-12 16:10:22 -04:00
static const int BUFF_SIZE = 10485760 ; // 10 MB buffer to speed things up.
2016-01-12 21:43:04 -05:00
void * buffer = rs_malloc ( BUFF_SIZE ) ;
2010-05-12 16:10:22 -04:00
2016-01-11 23:49:00 -05:00
if ( buffer = = NULL )
{
fclose ( in ) ;
fclose ( out ) ;
return false ;
}
2010-05-12 16:10:22 -04:00
bool bRet = true ;
2009-03-19 08:49:11 -04:00
while ( ( s = fread ( buffer , 1 , BUFF_SIZE , in ) ) > 0 )
{
size_t t = fwrite ( buffer , 1 , s , out ) ;
T + = t ;
if ( t ! = s )
{
2014-01-07 17:51:22 -05:00
RsServer : : notify ( ) - > AddSysMessage ( 0 , RS_SYS_WARNING , " File copy error " , " Error while copying file " + dest + " \n Is your disc full ? \n Original file kept under the name " + source ) ;
2010-05-12 16:10:22 -04:00
bRet = false ;
break ;
2009-03-19 08:49:11 -04:00
}
}
fclose ( in ) ;
fclose ( out ) ;
free ( buffer ) ;
2012-02-19 10:04:56 -05:00
return bRet ;
2009-03-19 08:49:11 -04:00
}
2010-05-09 09:52:05 -04:00
2014-03-17 16:56:06 -04:00
bool ftController : : completeFile ( const RsFileHash & hash )
2008-10-29 16:58:23 -04:00
{
2008-11-09 17:17:20 -05:00
/* variables... so we can drop mutex later */
std : : string path ;
2010-11-24 19:20:25 -05:00
std : : string name ;
2010-03-06 18:29:47 -05:00
uint64_t size = 0 ;
2016-07-30 15:52:42 -04:00
uint32_t state = 0 ;
uint32_t period = 0 ;
2012-11-02 09:52:29 -04:00
TransferRequestFlags flags ;
TransferRequestFlags extraflags ;
2010-11-24 19:20:25 -05:00
uint32_t completeCount = 0 ;
2008-11-09 17:17:20 -05:00
2009-06-11 17:41:42 -04:00
{
2009-02-12 07:47:57 -05:00
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-10-29 16:58:23 -04:00
2009-12-14 13:10:34 -05:00
# ifdef CONTROL_DEBUG
2010-03-06 18:29:47 -05:00
std : : cerr < < " ftController:completeFile( " < < hash < < " ) " ;
2008-10-29 16:58:23 -04:00
std : : cerr < < std : : endl ;
2009-12-14 13:10:34 -05:00
# endif
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it ( mDownloads . find ( hash ) ) ;
2010-03-06 18:29:47 -05:00
2009-02-12 07:47:57 -05:00
if ( it = = mDownloads . end ( ) )
{
2009-12-14 13:10:34 -05:00
# ifdef CONTROL_DEBUG
2010-03-06 18:29:47 -05:00
std : : cerr < < " ftController:completeFile( " < < hash < < " ) " ;
2009-02-12 07:47:57 -05:00
std : : cerr < < " Not Found! " ;
std : : cerr < < std : : endl ;
2009-12-14 13:10:34 -05:00
# endif
2010-03-06 18:29:47 -05:00
return false ;
2009-02-12 07:47:57 -05:00
}
2008-10-29 16:58:23 -04:00
2009-02-12 07:47:57 -05:00
/* check if finished */
2010-03-06 18:29:47 -05:00
if ( ! ( it - > second ) - > mCreator - > finished ( ) )
2009-02-12 07:47:57 -05:00
{
/* not done! */
2009-12-14 13:10:34 -05:00
# ifdef CONTROL_DEBUG
2010-03-06 18:29:47 -05:00
std : : cerr < < " ftController:completeFile( " < < hash < < " ) " ;
2009-02-12 07:47:57 -05:00
std : : cerr < < " Transfer Not Done " ;
std : : cerr < < std : : endl ;
2008-10-29 16:58:23 -04:00
2009-02-12 07:47:57 -05:00
std : : cerr < < " FileSize: " ;
2010-03-06 18:29:47 -05:00
std : : cerr < < ( it - > second ) - > mCreator - > getFileSize ( ) ;
2009-02-12 07:47:57 -05:00
std : : cerr < < " and Recvd: " ;
2010-03-06 18:29:47 -05:00
std : : cerr < < ( it - > second ) - > mCreator - > getRecvd ( ) ;
2009-12-14 13:10:34 -05:00
# endif
2009-02-12 07:47:57 -05:00
return false ;
}
2008-07-23 18:01:59 -04:00
2008-10-29 16:58:23 -04:00
2010-03-06 18:29:47 -05:00
ftFileControl * fc = it - > second ;
2008-07-23 18:01:59 -04:00
2009-06-11 17:41:42 -04:00
// (csoler) I've postponed this to the end of the block because deleting the
// element from the map calls the destructor of fc->mTransfer, which
2009-02-12 07:47:57 -05:00
// makes fc to point to nothing and causes random behavior/crashes.
//
// mDataplex->removeTransferModule(fc->mTransfer->hash());
//
/* done - cleanup */
2008-10-29 16:58:23 -04:00
2009-02-12 07:47:57 -05:00
// (csoler) I'm copying this because "delete fc->mTransfer" deletes the hash string!
2014-03-17 16:56:06 -04:00
RsFileHash hash_to_suppress ( fc - > mTransfer - > hash ( ) ) ;
2008-07-23 18:01:59 -04:00
2011-09-15 15:33:58 -04:00
// This should be done that early, because once the file creator is
// deleted, it should not be accessed by the data multiplex anymore!
//
mDataplex - > removeTransferModule ( hash_to_suppress ) ;
2009-02-12 07:47:57 -05:00
if ( fc - > mTransfer )
{
delete fc - > mTransfer ;
fc - > mTransfer = NULL ;
}
2008-07-23 18:01:59 -04:00
2009-02-12 07:47:57 -05:00
if ( fc - > mCreator )
{
2010-03-17 11:34:36 -04:00
fc - > mCreator - > closeFile ( ) ;
2009-02-12 07:47:57 -05:00
delete fc - > mCreator ;
fc - > mCreator = NULL ;
}
fc - > mState = ftFileControl : : COMPLETED ;
2009-04-06 15:41:40 -04:00
// I don't know how the size can be zero, but believe me, this happens,
// and it causes an error on linux because then the file may not even exist.
//
2009-06-11 17:41:42 -04:00
if ( fc - > mSize > 0 & & moveFile ( fc - > mCurrentPath , fc - > mDestination ) )
2009-02-12 07:47:57 -05:00
fc - > mCurrentPath = fc - > mDestination ;
else
fc - > mState = ftFileControl : : ERROR_COMPLETION ;
2008-10-29 16:58:23 -04:00
2009-02-12 07:47:57 -05:00
/* for extralist additions */
path = fc - > mDestination ;
2010-11-24 19:20:25 -05:00
name = fc - > mName ;
2009-02-12 07:47:57 -05:00
//hash = fc->mHash;
size = fc - > mSize ;
state = fc - > mState ;
period = 30 * 24 * 3600 ; /* 30 days */
2012-11-02 09:52:29 -04:00
extraflags . clear ( ) ;
2008-11-09 17:17:20 -05:00
2009-04-06 15:41:40 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " CompleteFile(): size = " < < size < < std : : endl ;
# endif
2010-10-16 11:21:37 -04:00
flags = fc - > mFlags ;
2010-03-06 18:29:47 -05:00
locked_queueRemove ( it - > second - > mQueuePosition ) ;
/* switch map */
2016-07-30 15:52:42 -04:00
mCompleted [ fc - > mHash ] = fc ;
completeCount = mCompleted . size ( ) ;
2010-03-06 18:29:47 -05:00
2009-02-12 07:47:57 -05:00
mDownloads . erase ( it ) ;
2009-06-14 15:34:22 -04:00
2012-11-02 09:52:29 -04:00
if ( flags & RS_FILE_REQ_ANONYMOUS_ROUTING )
2013-04-01 17:18:58 -04:00
mTurtle - > stopMonitoringTunnels ( hash_to_suppress ) ;
2010-01-11 17:38:18 -05:00
2009-02-12 07:47:57 -05:00
} /******* UNLOCKED ********/
2008-11-09 17:17:20 -05:00
/******************** NO Mutex from Now ********************
* cos Callback can end up back in this class .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-29 16:58:23 -04:00
/* If it has a callback - do it now */
2010-10-16 11:21:37 -04:00
2016-07-30 15:52:42 -04:00
if ( flags & RS_FILE_REQ_EXTRA ) // | RS_FILE_HINTS_MEDIA))
2008-10-29 16:58:23 -04:00
{
2008-11-09 17:17:20 -05:00
# ifdef CONTROL_DEBUG
2010-10-16 11:21:37 -04:00
std : : cerr < < " ftController::completeFile() adding to ExtraList " ;
std : : cerr < < std : : endl ;
2008-11-09 17:17:20 -05:00
# endif
2010-10-16 11:21:37 -04:00
mExtraList - > addExtraFile ( path , hash , size , period , extraflags ) ;
2008-10-29 16:58:23 -04:00
}
2008-11-04 18:12:53 -05:00
else
{
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::completeFile() No callback " ;
std : : cerr < < std : : endl ;
# endif
}
2009-06-11 17:41:42 -04:00
2010-11-24 19:20:25 -05:00
/* Notify GUI */
2016-07-30 15:52:42 -04:00
RsServer : : notify ( ) - > AddPopupMessage ( RS_POPUP_DOWNLOAD , hash . toStdString ( ) , name , " " ) ;
2014-01-07 17:51:22 -05:00
2016-07-30 15:52:42 -04:00
RsServer : : notify ( ) - > notifyDownloadComplete ( hash . toStdString ( ) ) ;
RsServer : : notify ( ) - > notifyDownloadCompleteCount ( completeCount ) ;
2013-02-27 05:03:54 -05:00
2016-07-30 15:52:42 -04:00
rsFiles - > ForceDirectoryCheck ( ) ;
2010-11-24 19:20:25 -05:00
2008-11-15 15:00:29 -05:00
IndicateConfigChanged ( ) ; /* completed transfer -> save */
2008-07-23 18:01:59 -04:00
return true ;
}
/***************************************************************/
/********************** Controller Access **********************/
/***************************************************************/
2008-11-20 19:10:59 -05:00
bool ftController : : activate ( )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
mFtActive = true ;
mFtPendingDone = false ;
return true ;
}
2009-08-10 15:01:27 -04:00
bool ftController : : isActiveAndNoPending ( )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
return ( mFtActive & & mFtPendingDone ) ;
}
2008-11-20 19:10:59 -05:00
bool ftController : : handleAPendingRequest ( )
{
ftPendingRequest req ;
2009-12-10 17:55:27 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-11-20 19:10:59 -05:00
2009-12-10 17:55:27 -05:00
if ( mPendingRequests . size ( ) < 1 )
{
return false ;
}
req = mPendingRequests . front ( ) ;
mPendingRequests . pop_front ( ) ;
2008-11-20 19:10:59 -05:00
}
2010-06-29 16:51:16 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " Requesting pending hash " < < req . mHash < < std : : endl ;
# endif
2009-12-10 17:55:27 -05:00
2013-10-06 08:56:37 -04:00
FileRequest ( req . mName , req . mHash , req . mSize , req . mDest , TransferRequestFlags ( req . mFlags ) , req . mSrcIds , req . mState ) ;
2009-12-10 17:55:27 -05:00
{
// See whether there is a pendign chunk map recorded for this hash.
//
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , RsFileTransfer * > : : iterator it ( mPendingChunkMaps . find ( req . mHash ) ) ;
2009-12-10 17:55:27 -05:00
if ( it ! = mPendingChunkMaps . end ( ) )
{
RsFileTransfer * rsft = it - > second ;
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator fit = mDownloads . find ( rsft - > file . hash ) ;
2009-12-10 17:55:27 -05:00
2010-03-06 18:29:47 -05:00
if ( ( fit = = mDownloads . end ( ) | | ( fit - > second ) - > mCreator = = NULL ) )
2009-12-10 17:55:27 -05:00
{
// This should never happen, because the last call to FileRequest must have created the fileCreator!!
//
std : : cerr < < " ftController::loadList(): Error: could not find hash " < < rsft - > file . hash < < " in mDownloads list ! " < < std : : endl ;
}
else
2010-01-11 11:00:42 -05:00
{
2010-06-29 16:51:16 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " Hash " < < req . mHash < < " is in downloads " < < std : : endl ;
std : : cerr < < " setting chunk strategy to " < < rsft - > chunk_strategy < < std : : endl ;
# endif
2010-03-06 18:29:47 -05:00
( fit - > second ) - > mCreator - > setAvailabilityMap ( rsft - > compressed_chunk_map ) ;
( fit - > second ) - > mCreator - > setChunkStrategy ( ( FileChunksInfo : : ChunkStrategy ) ( rsft - > chunk_strategy ) ) ;
2013-10-06 08:56:37 -04:00
( fit - > second ) - > mState = rsft - > state ;
2010-01-11 11:00:42 -05:00
}
2009-12-10 17:55:27 -05:00
delete rsft ;
mPendingChunkMaps . erase ( it ) ;
}
2010-06-29 16:51:16 -04:00
# ifdef CONTROL_DEBUG
else
std : : cerr < < " No pending chunkmap for hash " < < req . mHash < < std : : endl ;
# endif
2009-12-10 17:55:27 -05:00
}
2009-12-28 16:11:00 -05:00
return true ;
2008-11-20 19:10:59 -05:00
}
2014-03-17 16:56:06 -04:00
bool ftController : : alreadyHaveFile ( const RsFileHash & hash , FileInfo & info )
2010-01-16 10:42:26 -05:00
{
// check for downloads
2010-10-05 16:39:14 -04:00
if ( FileDetails ( hash , info ) & & ( info . downloadStatus = = FT_STATE_COMPLETE ) )
2010-01-16 10:42:26 -05:00
return true ;
// check for file lists
2012-11-02 09:52:29 -04:00
if ( mSearch - > search ( hash , RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY , info ) )
2010-01-16 10:42:26 -05:00
return true ;
return false ;
}
2008-11-20 19:10:59 -05:00
2014-03-17 16:56:06 -04:00
bool ftController : : FileRequest ( const std : : string & fname , const RsFileHash & hash ,
2012-11-02 09:52:29 -04:00
uint64_t size , const std : : string & dest , TransferRequestFlags flags ,
2014-03-17 16:56:06 -04:00
const std : : list < RsPeerId > & _srcIds , uint16_t state )
2008-07-23 18:01:59 -04:00
{
2014-03-17 16:56:06 -04:00
std : : list < RsPeerId > srcIds ( _srcIds ) ;
2010-07-21 19:14:10 -04:00
2010-03-17 11:34:36 -04:00
/* check if we have the file */
2010-10-05 16:39:14 -04:00
FileInfo info ;
if ( alreadyHaveFile ( hash , info ) )
2010-03-17 11:34:36 -04:00
return false ;
2010-03-06 18:29:47 -05:00
if ( size = = 0 ) // we treat this special case because
{
/* if no destpath - send to download directory */
std : : string destination ;
if ( dest = = " " )
destination = mDownloadPath + " / " + fname ;
else
destination = dest + " / " + fname ;
// create void file with the target name.
2011-04-03 19:11:38 -04:00
FILE * f = RsDirUtil : : rs_fopen ( destination . c_str ( ) , " w " ) ;
2010-03-06 18:29:47 -05:00
if ( f = = NULL )
std : : cerr < < " Could not open file " < < destination < < " for writting. " < < std : : endl ;
else
fclose ( f ) ;
return true ;
}
2010-05-17 17:05:28 -04:00
// Bugs in the cache system can cause files with arbitrary size to be
// requested, causing a division by zero in ftChunkMap when size > 1MB *
// (2^32-1). I thus conservatively check for large size values.
//
if ( size > = 1024ull * 1024ull * ( ( 1ull < < 32 ) - 1 ) )
{
std : : cerr < < " FileRequest Error: unexpected size. This is probably a bug. " < < std : : endl ;
std : : cerr < < " name = " < < fname < < std : : endl ;
std : : cerr < < " flags = " < < flags < < std : : endl ;
std : : cerr < < " dest = " < < dest < < std : : endl ;
std : : cerr < < " size = " < < size < < std : : endl ;
return false ;
}
2008-11-20 19:10:59 -05:00
/* If file transfer is not enabled ....
* save request for later . This will also
2009-06-11 17:41:42 -04:00
* mean that we will have to copy local files ,
2008-11-20 19:10:59 -05:00
* or have a callback which says : local file .
*/
2009-06-11 17:41:42 -04:00
{
2009-02-12 07:47:57 -05:00
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
if ( ! mFtActive )
{
/* store in pending queue */
2013-10-06 08:56:37 -04:00
ftPendingRequest req ( fname , hash , size , dest , flags , srcIds , state ) ;
2009-02-12 07:47:57 -05:00
mPendingRequests . push_back ( req ) ;
return true ;
}
2008-11-20 19:10:59 -05:00
}
2013-11-28 15:53:03 -05:00
// remove the sources from the list, if they don't have clearance for direct transfer. This happens only for non cache files.
//
2016-07-30 15:52:42 -04:00
for ( std : : list < RsPeerId > : : iterator it = srcIds . begin ( ) ; it ! = srcIds . end ( ) ; )
if ( ! ( rsPeers - > servicePermissionFlags ( * it ) & RS_NODE_PERM_DIRECT_DL ) )
{
std : : list < RsPeerId > : : iterator tmp ( it ) ;
+ + tmp ;
srcIds . erase ( it ) ;
it = tmp ;
}
else
+ + it ;
2013-11-28 15:53:03 -05:00
2014-03-17 16:56:06 -04:00
std : : list < RsPeerId > : : const_iterator it ;
2010-07-21 19:14:10 -04:00
std : : list < TransferInfo > : : const_iterator pit ;
2008-07-23 18:01:59 -04:00
2008-08-17 11:23:11 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::FileRequest( " < < fname < < " , " ;
std : : cerr < < hash < < " , " < < size < < " , " < < dest < < " , " ;
std : : cerr < < flags < < " ,< " ;
2014-10-24 18:07:26 -04:00
for ( it = srcIds . begin ( ) ; it ! = srcIds . end ( ) ; + + it )
2008-07-23 18:01:59 -04:00
{
2008-08-17 11:23:11 -04:00
std : : cerr < < * it < < " , " ;
2008-07-23 18:01:59 -04:00
}
2008-08-17 11:23:11 -04:00
std : : cerr < < " >) " ;
std : : cerr < < std : : endl ;
# endif
2008-11-09 17:17:20 -05:00
uint32_t rate = 0 ;
2012-11-02 09:52:29 -04:00
if ( flags & RS_FILE_REQ_BACKGROUND )
2008-11-09 17:17:20 -05:00
rate = FT_CNTRL_SLOW_RATE ;
else
rate = FT_CNTRL_STANDARD_RATE ;
2009-06-11 17:41:42 -04:00
/* First check if the file is already being downloaded....
2008-11-09 17:17:20 -05:00
* This is important as some guis request duplicate files regularly .
*/
2010-01-16 10:42:26 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-11-15 15:00:29 -05:00
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : const_iterator dit = mDownloads . find ( hash ) ;
2010-03-06 18:29:47 -05:00
2010-01-16 10:42:26 -05:00
if ( dit ! = mDownloads . end ( ) )
{
/* we already have it! */
2008-11-09 17:17:20 -05:00
# ifdef CONTROL_DEBUG
2010-01-16 10:42:26 -05:00
std : : cerr < < " ftController::FileRequest() Already Downloading File " ;
std : : cerr < < std : : endl ;
std : : cerr < < " \t No need to download " ;
std : : cerr < < std : : endl ;
2008-11-09 17:17:20 -05:00
# endif
2010-01-16 10:42:26 -05:00
/* but we should add this peer - if they don't exist!
* ( needed for channels ) .
*/
2008-11-09 17:17:20 -05:00
2014-10-24 18:07:26 -04:00
for ( it = srcIds . begin ( ) ; it ! = srcIds . end ( ) ; + + it )
2015-02-18 14:07:58 -05:00
if ( rsPeers - > servicePermissionFlags ( * it ) & RS_NODE_PERM_DIRECT_DL )
2010-01-16 10:42:26 -05:00
{
2013-11-27 15:12:16 -05:00
uint32_t i , j ;
if ( ( dit - > second ) - > mTransfer - > getPeerState ( * it , i , j ) )
{
2008-11-09 17:17:20 -05:00
# ifdef CONTROL_DEBUG
2013-11-27 15:12:16 -05:00
std : : cerr < < " ftController::FileRequest() Peer Existing " ;
std : : cerr < < std : : endl ;
2008-11-09 17:17:20 -05:00
# endif
2013-11-27 15:12:16 -05:00
continue ; /* already added peer */
}
2008-11-09 17:17:20 -05:00
# ifdef CONTROL_DEBUG
2013-11-27 15:12:16 -05:00
std : : cerr < < " ftController::FileRequest() Adding Peer: " < < * it ;
std : : cerr < < std : : endl ;
2008-11-09 17:17:20 -05:00
# endif
2013-11-27 15:12:16 -05:00
( dit - > second ) - > mTransfer - > addFileSource ( * it ) ;
2014-03-28 23:57:44 -04:00
setPeerState ( dit - > second - > mTransfer , * it , rate , mServiceCtrl - > isPeerConnected ( mFtServiceId , * it ) ) ;
2013-11-27 15:12:16 -05:00
}
2008-11-09 17:17:20 -05:00
2014-10-21 18:33:02 -04:00
if ( srcIds . empty ( ) )
2010-01-16 10:42:26 -05:00
{
2008-11-13 18:03:46 -05:00
# ifdef CONTROL_DEBUG
2010-01-16 10:42:26 -05:00
std : : cerr < < " ftController::FileRequest() WARNING: No Src Peers " ;
std : : cerr < < std : : endl ;
2008-11-13 18:03:46 -05:00
# endif
2010-01-16 10:42:26 -05:00
}
2008-11-13 18:03:46 -05:00
2010-01-16 10:42:26 -05:00
return true ;
}
} /******* UNLOCKED ********/
2008-11-09 17:17:20 -05:00
2013-11-28 15:53:03 -05:00
2012-11-02 09:52:29 -04:00
if ( ! ( flags & RS_FILE_REQ_NO_SEARCH ) )
2008-07-23 18:01:59 -04:00
{
2008-08-17 11:23:11 -04:00
/* do a source search - for any extra sources */
2010-01-22 18:23:37 -05:00
// add sources only in direct mode
//
2012-11-01 06:06:12 -04:00
if ( /* (flags & RS_FILE_HINTS_BROWSABLE) && */ mSearch - > search ( hash , RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY , info ) )
2008-08-17 11:23:11 -04:00
{
/* do something with results */
2008-10-29 16:58:23 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::FileRequest() Found Other Sources " ;
std : : cerr < < std : : endl ;
# endif
/* if the sources don't exist already - add in */
2014-10-24 18:07:26 -04:00
for ( pit = info . peers . begin ( ) ; pit ! = info . peers . end ( ) ; + + pit )
2008-10-29 16:58:23 -04:00
{
2009-12-14 13:10:20 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " \t Source: " < < pit - > peerId ;
2008-10-29 16:58:23 -04:00
std : : cerr < < std : : endl ;
2009-12-14 13:10:20 -05:00
# endif
2013-06-06 16:52:24 -04:00
// Because this is auto-add, we only add sources that we allow to DL from using direct transfers.
2008-10-29 16:58:23 -04:00
2015-02-18 14:07:58 -05:00
if ( ( srcIds . end ( ) = = std : : find ( srcIds . begin ( ) , srcIds . end ( ) , pit - > peerId ) ) & & ( RS_NODE_PERM_DIRECT_DL & rsPeers - > servicePermissionFlags ( pit - > peerId ) ) )
2008-10-29 16:58:23 -04:00
{
2008-11-02 06:38:11 -05:00
srcIds . push_back ( pit - > peerId ) ;
2008-10-29 16:58:23 -04:00
2009-12-14 13:10:20 -05:00
# ifdef CONTROL_DEBUG
2013-06-06 16:52:24 -04:00
std : : cerr < < " \t Adding in: " < < pit - > peerId ;
2008-10-29 16:58:23 -04:00
std : : cerr < < std : : endl ;
2009-12-14 13:10:20 -05:00
# endif
2013-06-06 16:52:24 -04:00
}
2009-06-11 17:41:42 -04:00
}
2008-10-29 16:58:23 -04:00
}
2008-07-23 18:01:59 -04:00
}
/* add in new item for download */
2008-11-15 15:00:29 -05:00
std : : string savepath ;
std : : string destination ;
2010-01-16 10:42:26 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-11-15 15:00:29 -05:00
2014-03-17 16:56:06 -04:00
savepath = mPartialsPath + " / " + hash . toStdString ( ) ;
2010-01-16 10:42:26 -05:00
destination = dest + " / " + fname ;
2008-10-29 16:58:23 -04:00
2010-01-16 10:42:26 -05:00
/* if no destpath - send to download directory */
if ( dest = = " " )
destination = mDownloadPath + " / " + fname ;
} /******* UNLOCKED ********/
2009-06-11 17:41:42 -04:00
2010-11-10 17:05:34 -05:00
// We check that flags are consistent.
2010-01-11 17:38:18 -05:00
2012-11-02 09:52:29 -04:00
if ( flags & RS_FILE_REQ_ANONYMOUS_ROUTING )
2015-01-22 15:25:39 -05:00
mTurtle - > monitorTunnels ( hash , mFtServer , true ) ;
2010-01-11 17:38:18 -05:00
2016-07-30 15:52:42 -04:00
bool assume_availability = false ;
2010-11-22 15:57:53 -05:00
ftFileCreator * fc = new ftFileCreator ( savepath , size , hash , assume_availability ) ;
2008-09-08 10:04:10 -04:00
ftTransferModule * tm = new ftTransferModule ( fc , mDataplex , this ) ;
2008-07-23 18:01:59 -04:00
2010-04-30 17:07:21 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " Note: setting chunk strategy to " < < mDefaultChunkStrategy < < std : : endl ;
# endif
2010-03-21 17:07:12 -04:00
fc - > setChunkStrategy ( mDefaultChunkStrategy ) ;
2008-07-23 18:01:59 -04:00
/* add into maps */
2010-10-16 11:21:37 -04:00
ftFileControl * ftfc = new ftFileControl ( fname , savepath , destination , size , hash , flags , fc , tm ) ;
2010-03-06 18:29:47 -05:00
ftfc - > mCreateTime = time ( NULL ) ;
2008-07-23 18:01:59 -04:00
/* now add source peers (and their current state) */
tm - > setFileSources ( srcIds ) ;
/* get current state for transfer module */
2014-10-24 18:07:26 -04:00
for ( it = srcIds . begin ( ) ; it ! = srcIds . end ( ) ; + + it )
2008-07-23 18:01:59 -04:00
{
2008-08-21 17:30:59 -04:00
# ifdef CONTROL_DEBUG
2008-11-13 18:03:46 -05:00
std : : cerr < < " ftController::FileRequest() adding peer: " < < * it ;
std : : cerr < < std : : endl ;
2008-08-17 11:23:11 -04:00
# endif
2014-03-28 23:57:44 -04:00
setPeerState ( tm , * it , rate , mServiceCtrl - > isPeerConnected ( mFtServiceId , * it ) ) ;
2008-07-23 18:01:59 -04:00
}
2010-05-16 17:21:41 -04:00
/* add structures into the accessible data. Needs to be locked */
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2012-02-12 15:00:22 -05:00
locked_addToQueue ( ftfc , FT_FILECONTROL_QUEUE_ADD_END ) ;
2010-05-16 17:21:41 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::FileRequest() Created ftFileCreator @: " < < fc ;
std : : cerr < < std : : endl ;
std : : cerr < < " ftController::FileRequest() Created ftTransModule @: " < < tm ;
std : : cerr < < std : : endl ;
std : : cerr < < " ftController::FileRequest() Created ftFileControl. " ;
std : : cerr < < std : : endl ;
# endif
2008-11-15 15:00:29 -05:00
2010-05-16 17:21:41 -04:00
/* add to ClientModule */
mDataplex - > addTransferModule ( tm , fc ) ;
mDownloads [ hash ] = ftfc ;
}
2008-11-15 15:00:29 -05:00
IndicateConfigChanged ( ) ; /* completed transfer -> save */
2008-10-29 16:58:23 -04:00
return true ;
2008-08-09 13:03:24 -04:00
}
2014-03-17 16:56:06 -04:00
bool ftController : : setPeerState ( ftTransferModule * tm , const RsPeerId & id , uint32_t maxrate , bool online )
2008-11-13 18:03:46 -05:00
{
2014-03-28 23:57:44 -04:00
if ( id = = mServiceCtrl - > getOwnId ( ) )
2008-11-13 18:03:46 -05:00
{
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::setPeerState() is Self " ;
std : : cerr < < std : : endl ;
# endif
tm - > setPeerState ( id , PQIPEER_IDLE , maxrate ) ;
}
2009-05-26 17:42:45 -04:00
else if ( online | | mTurtle - > isOnline ( id ) )
2008-11-13 18:03:46 -05:00
{
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::setPeerState() " ;
std : : cerr < < " Peer is Online " ;
std : : cerr < < std : : endl ;
# endif
tm - > setPeerState ( id , PQIPEER_IDLE , maxrate ) ;
}
else
{
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::setPeerState() " ;
std : : cerr < < " Peer is Offline " ;
std : : cerr < < std : : endl ;
# endif
tm - > setPeerState ( id , PQIPEER_NOT_ONLINE , maxrate ) ;
}
return true ;
}
2014-03-17 16:56:06 -04:00
bool ftController : : setChunkStrategy ( const RsFileHash & hash , FileChunksInfo : : ChunkStrategy s )
2009-12-08 17:29:52 -05:00
{
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator mit = mDownloads . find ( hash ) ;
2009-12-08 17:29:52 -05:00
if ( mit = = mDownloads . end ( ) )
{
# ifdef CONTROL_DEBUG
2010-01-26 15:40:21 -05:00
std : : cerr < < " ftController::setChunkStrategy file is not found in mDownloads " < < std : : endl ;
2009-12-08 17:29:52 -05:00
# endif
return false ;
}
2010-03-06 18:29:47 -05:00
mit - > second - > mCreator - > setChunkStrategy ( s ) ;
2009-12-08 17:29:52 -05:00
return true ;
}
2008-11-04 18:12:53 -05:00
2014-03-17 16:56:06 -04:00
bool ftController : : FileCancel ( const RsFileHash & hash )
2008-08-09 13:03:24 -04:00
{
2013-04-01 17:18:58 -04:00
rsTurtle - > stopMonitoringTunnels ( hash ) ;
2010-01-11 17:38:18 -05:00
2008-09-08 04:44:37 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::FileCancel " < < std : : endl ;
# endif
/*check if the file in the download map*/
2010-01-26 15:40:21 -05:00
2008-09-08 04:44:37 -04:00
{
2010-01-26 15:40:21 -05:00
RsStackMutex mtx ( ctrlMutex ) ;
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator mit = mDownloads . find ( hash ) ;
2010-01-26 15:40:21 -05:00
if ( mit = = mDownloads . end ( ) )
{
2008-09-08 04:44:37 -04:00
# ifdef CONTROL_DEBUG
2010-01-26 15:40:21 -05:00
std : : cerr < < " ftController::FileCancel file is not found in mDownloads " < < std : : endl ;
2008-09-08 04:44:37 -04:00
# endif
2010-01-26 15:40:21 -05:00
return false ;
}
2008-09-08 04:44:37 -04:00
2010-01-26 15:40:21 -05:00
/* check if finished */
2010-03-06 18:29:47 -05:00
if ( ( mit - > second ) - > mCreator - > finished ( ) )
2010-01-26 15:40:21 -05:00
{
2008-11-29 17:03:36 -05:00
# ifdef CONTROL_DEBUG
2010-01-26 15:40:21 -05:00
std : : cerr < < " ftController:FileCancel( " < < hash < < " ) " ;
std : : cerr < < " Transfer Already finished " ;
std : : cerr < < std : : endl ;
2008-11-29 17:03:36 -05:00
2010-01-26 15:40:21 -05:00
std : : cerr < < " FileSize: " ;
2010-03-06 18:29:47 -05:00
std : : cerr < < ( mit - > second ) - > mCreator - > getFileSize ( ) ;
2010-01-26 15:40:21 -05:00
std : : cerr < < " and Recvd: " ;
2010-03-06 18:29:47 -05:00
std : : cerr < < ( mit - > second ) - > mCreator - > getRecvd ( ) ;
2008-11-29 17:03:36 -05:00
# endif
2010-01-26 15:40:21 -05:00
return false ;
}
2008-11-29 17:03:36 -05:00
2010-01-26 15:40:21 -05:00
/*find the point to transfer module*/
2010-03-06 18:29:47 -05:00
ftTransferModule * ft = ( mit - > second ) - > mTransfer ;
2010-01-26 15:40:21 -05:00
ft - > cancelTransfer ( ) ;
2008-11-29 17:03:36 -05:00
2010-03-06 18:29:47 -05:00
ftFileControl * fc = mit - > second ;
2010-01-26 15:40:21 -05:00
mDataplex - > removeTransferModule ( fc - > mTransfer - > hash ( ) ) ;
2008-11-29 17:03:36 -05:00
2010-01-26 15:40:21 -05:00
if ( fc - > mTransfer )
{
delete fc - > mTransfer ;
fc - > mTransfer = NULL ;
}
2008-11-29 17:03:36 -05:00
2010-01-26 15:40:21 -05:00
if ( fc - > mCreator )
{
delete fc - > mCreator ;
fc - > mCreator = NULL ;
}
2008-11-29 17:03:36 -05:00
2010-01-26 15:40:21 -05:00
/* delete the temporary file */
if ( 0 = = remove ( fc - > mCurrentPath . c_str ( ) ) )
{
2008-11-30 16:43:51 -05:00
# ifdef CONTROL_DEBUG
2010-01-26 15:40:21 -05:00
std : : cerr < < " ftController::FileCancel() remove temporary file " ;
std : : cerr < < fc - > mCurrentPath ;
std : : cerr < < std : : endl ;
2008-11-30 16:43:51 -05:00
# endif
2010-01-26 15:40:21 -05:00
}
else
{
2008-11-30 16:43:51 -05:00
# ifdef CONTROL_DEBUG
2010-01-26 15:40:21 -05:00
std : : cerr < < " ftController::FileCancel() fail to remove file " ;
std : : cerr < < fc - > mCurrentPath ;
std : : cerr < < std : : endl ;
2008-11-30 16:43:51 -05:00
# endif
2010-01-26 15:40:21 -05:00
}
2008-11-30 16:43:51 -05:00
2010-03-06 18:29:47 -05:00
locked_queueRemove ( fc - > mQueuePosition ) ;
delete fc ;
2010-01-26 15:40:21 -05:00
mDownloads . erase ( mit ) ;
}
2008-11-29 17:03:36 -05:00
2009-06-14 15:34:22 -04:00
IndicateConfigChanged ( ) ; /* completed transfer -> save */
2008-09-08 04:44:37 -04:00
return true ;
2008-07-23 18:01:59 -04:00
}
2014-03-17 16:56:06 -04:00
bool ftController : : FileControl ( const RsFileHash & hash , uint32_t flags )
2008-08-09 13:03:24 -04:00
{
2010-10-16 12:49:35 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::FileControl( " < < hash < < " , " ;
std : : cerr < < flags < < " ) " < < std : : endl ;
# endif
2010-03-15 08:57:08 -04:00
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-09-08 04:44:37 -04:00
/*check if the file in the download map*/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator mit = mDownloads . find ( hash ) ;
2008-09-08 04:44:37 -04:00
if ( mit = = mDownloads . end ( ) )
{
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::FileControl file is not found in mDownloads " < < std : : endl ;
# endif
return false ;
}
/*find the point to transfer module*/
switch ( flags )
{
case RS_FILE_CTRL_PAUSE :
2010-03-15 08:57:08 -04:00
mit - > second - > mState = ftFileControl : : PAUSED ;
2010-07-21 19:14:10 -04:00
std : : cerr < < " setting state to " < < ftFileControl : : PAUSED < < std : : endl ;
2008-09-08 04:44:37 -04:00
break ;
2010-07-21 19:14:10 -04:00
2008-09-08 04:44:37 -04:00
case RS_FILE_CTRL_START :
2010-03-15 08:57:08 -04:00
mit - > second - > mState = ftFileControl : : DOWNLOADING ;
2010-07-21 19:14:10 -04:00
std : : cerr < < " setting state to " < < ftFileControl : : DOWNLOADING < < std : : endl ;
2008-09-08 04:44:37 -04:00
break ;
2010-07-21 19:14:10 -04:00
case RS_FILE_CTRL_FORCE_CHECK :
mit - > second - > mTransfer - > forceCheck ( ) ;
std : : cerr < < " setting state to " < < ftFileControl : : CHECKING_HASH < < std : : endl ;
break ;
2008-09-08 04:44:37 -04:00
default :
return false ;
}
2013-10-06 08:56:37 -04:00
IndicateConfigChanged ( ) ;
2008-09-08 04:44:37 -04:00
return true ;
2008-08-09 13:03:24 -04:00
}
2008-07-23 18:01:59 -04:00
2008-08-09 13:03:24 -04:00
bool ftController : : FileClearCompleted ( )
{
2008-12-04 16:34:19 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::FileClearCompleted() " < < std : : endl ;
# endif
2010-11-24 19:20:25 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
for ( std : : map < RsFileHash , ftFileControl * > : : iterator it ( mCompleted . begin ( ) ) ; it ! = mCompleted . end ( ) ; + + it )
2010-11-24 19:20:25 -05:00
delete it - > second ;
2010-03-06 18:29:47 -05:00
2010-11-24 19:20:25 -05:00
mCompleted . clear ( ) ;
2010-03-06 18:29:47 -05:00
2010-11-24 19:20:25 -05:00
IndicateConfigChanged ( ) ;
} /******* UNLOCKED ********/
2010-03-06 18:29:47 -05:00
2014-01-07 17:51:22 -05:00
RsServer : : notify ( ) - > notifyDownloadCompleteCount ( 0 ) ;
2010-02-19 15:36:47 -05:00
2008-08-09 13:03:24 -04:00
return false ;
}
2008-07-23 18:01:59 -04:00
/* get Details of File Transfers */
2015-03-08 09:46:07 -04:00
void ftController : : FileDownloads ( std : : list < RsFileHash > & hashs )
2008-07-23 18:01:59 -04:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it ;
2014-10-24 18:07:26 -04:00
for ( it = mDownloads . begin ( ) ; it ! = mDownloads . end ( ) ; + + it )
2008-07-23 18:01:59 -04:00
{
2010-03-06 18:29:47 -05:00
hashs . push_back ( it - > second - > mHash ) ;
2008-07-23 18:01:59 -04:00
}
2014-10-24 18:07:26 -04:00
for ( it = mCompleted . begin ( ) ; it ! = mCompleted . end ( ) ; + + it )
2008-11-09 17:17:20 -05:00
{
2010-03-06 18:29:47 -05:00
hashs . push_back ( it - > second - > mHash ) ;
2008-11-09 17:17:20 -05:00
}
2008-07-23 18:01:59 -04:00
}
/* Directory Handling */
bool ftController : : setDownloadDirectory ( std : : string path )
{
2008-08-29 21:07:24 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::setDownloadDirectory( " < < path < < " ) " ;
std : : cerr < < std : : endl ;
# endif
2008-07-23 18:01:59 -04:00
/* check if it exists */
if ( RsDirUtil : : checkCreateDirectory ( path ) )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2011-05-15 08:42:55 -04:00
mDownloadPath = RsDirUtil : : convertPathToUnix ( path ) ;
2011-09-23 17:08:11 -04:00
RsDiscSpace : : setDownloadPath ( mDownloadPath ) ;
2008-08-29 21:07:24 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::setDownloadDirectory() Okay! " ;
std : : cerr < < std : : endl ;
# endif
2009-06-11 17:41:42 -04:00
IndicateConfigChanged ( ) ;
2008-07-23 18:01:59 -04:00
return true ;
}
2008-08-29 21:07:24 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::setDownloadDirectory() Failed " ;
std : : cerr < < std : : endl ;
# endif
2008-07-23 18:01:59 -04:00
return false ;
}
2008-08-09 13:03:24 -04:00
bool ftController : : setPartialsDirectory ( std : : string path )
2008-07-23 18:01:59 -04:00
{
2008-08-09 13:03:24 -04:00
2008-07-23 18:01:59 -04:00
/* check it is not a subdir of download / shared directories (BAD) - TODO */
2009-06-11 17:41:42 -04:00
{
RsStackMutex stack ( ctrlMutex ) ;
2011-05-15 08:42:55 -04:00
path = RsDirUtil : : convertPathToUnix ( path ) ;
2009-06-11 17:41:42 -04:00
if ( ! path . find ( mDownloadPath ) ) {
return false ;
}
if ( rsFiles ) {
2009-08-04 05:19:32 -04:00
std : : list < SharedDirInfo > : : iterator it ;
std : : list < SharedDirInfo > dirs ;
2009-06-11 17:41:42 -04:00
rsFiles - > getSharedDirectories ( dirs ) ;
2014-10-24 18:07:26 -04:00
for ( it = dirs . begin ( ) ; it ! = dirs . end ( ) ; + + it ) {
2009-08-04 05:19:32 -04:00
if ( ! path . find ( ( * it ) . filename ) ) {
2009-06-11 17:41:42 -04:00
return false ;
}
}
}
}
2008-07-23 18:01:59 -04:00
/* check if it exists */
if ( RsDirUtil : : checkCreateDirectory ( path ) )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-10-29 16:58:23 -04:00
mPartialsPath = path ;
2008-07-23 18:01:59 -04:00
2011-09-23 17:08:11 -04:00
RsDiscSpace : : setPartialsPath ( path ) ;
2008-10-29 16:58:23 -04:00
#if 0 /*** FIX ME !!!**************/
2008-07-23 18:01:59 -04:00
/* move all existing files! */
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl > : : iterator it ;
2014-10-24 18:07:26 -04:00
for ( it = mDownloads . begin ( ) ; it ! = mDownloads . end ( ) ; + + it )
2008-07-23 18:01:59 -04:00
{
( it - > second ) . mCreator - > changePartialDirectory ( mPartialPath ) ;
}
2008-10-29 16:58:23 -04:00
# endif
2009-06-11 17:41:42 -04:00
IndicateConfigChanged ( ) ;
2008-07-23 18:01:59 -04:00
return true ;
}
2008-08-09 13:03:24 -04:00
2008-07-23 18:01:59 -04:00
return false ;
}
std : : string ftController : : getDownloadDirectory ( )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
return mDownloadPath ;
}
std : : string ftController : : getPartialsDirectory ( )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-10-29 16:58:23 -04:00
return mPartialsPath ;
2008-07-23 18:01:59 -04:00
}
2014-03-17 16:56:06 -04:00
bool ftController : : setDestinationDirectory ( const RsFileHash & hash , const std : : string & dest_dir )
2013-02-27 11:59:16 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
2013-02-27 11:59:16 -05:00
if ( it = = mDownloads . end ( ) )
return false ;
std : : cerr < < " (II) Changing destination of file " < < it - > second - > mDestination < < std : : endl ;
it - > second - > mDestination = dest_dir + ' / ' + it - > second - > mName ;
std : : cerr < < " (II) ...to " < < it - > second - > mDestination < < std : : endl ;
return true ;
}
2014-03-17 16:56:06 -04:00
bool ftController : : setDestinationName ( const RsFileHash & hash , const std : : string & dest_name )
2013-02-27 11:59:16 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
2013-02-27 11:59:16 -05:00
if ( it = = mDownloads . end ( ) )
return false ;
std : : cerr < < " (II) Changing destination of file " < < it - > second - > mDestination < < std : : endl ;
std : : string dest_path ;
RsDirUtil : : removeTopDir ( it - > second - > mDestination , dest_path ) ; /* remove fname */
it - > second - > mDestination = dest_path + ' / ' + dest_name ;
it - > second - > mName = dest_name ;
std : : cerr < < " (II) ...to " < < it - > second - > mDestination < < std : : endl ;
return true ;
}
2014-03-17 16:56:06 -04:00
bool ftController : : FileDetails ( const RsFileHash & hash , FileInfo & info )
2008-07-23 18:01:59 -04:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-11-09 17:17:20 -05:00
bool completed = false ;
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
2008-07-23 18:01:59 -04:00
if ( it = = mDownloads . end ( ) )
{
2008-11-09 17:17:20 -05:00
/* search completed files too */
it = mCompleted . find ( hash ) ;
if ( it = = mCompleted . end ( ) )
{
2009-06-11 17:41:42 -04:00
/* Note: mTransfer & mCreator
2008-11-09 17:17:20 -05:00
* are both NULL
*/
return false ;
}
completed = true ;
2008-07-23 18:01:59 -04:00
}
/* extract details */
2008-11-02 06:38:11 -05:00
info . hash = hash ;
2010-03-06 18:29:47 -05:00
info . fname = it - > second - > mName ;
2012-11-08 14:47:39 -05:00
info . storage_permission_flags . clear ( ) ;
2012-11-01 06:06:12 -04:00
info . transfer_info_flags = it - > second - > mFlags ;
2011-11-18 03:49:53 -05:00
info . priority = SPEED_NORMAL ;
2012-06-01 16:51:14 -04:00
RsDirUtil : : removeTopDir ( it - > second - > mDestination , info . path ) ; /* remove fname */
2010-03-06 18:29:47 -05:00
info . queue_position = it - > second - > mQueuePosition ;
2008-11-02 06:38:11 -05:00
2012-11-08 14:47:39 -05:00
if ( it - > second - > mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING )
info . storage_permission_flags | = DIR_FLAGS_NETWORK_WIDE_OTHERS ; // file being downloaded anonymously are always anonymously available.
2008-11-02 06:38:11 -05:00
/* get list of sources from transferModule */
2014-03-17 16:56:06 -04:00
std : : list < RsPeerId > peerIds ;
std : : list < RsPeerId > : : iterator pit ;
2008-11-02 06:38:11 -05:00
2008-11-09 17:17:20 -05:00
if ( ! completed )
2011-11-18 03:49:53 -05:00
{
2010-03-06 18:29:47 -05:00
it - > second - > mTransfer - > getFileSources ( peerIds ) ;
2011-11-18 03:49:53 -05:00
info . priority = it - > second - > mTransfer - > downloadPriority ( ) ;
2013-12-04 15:26:54 -05:00
info . lastTS = it - > second - > mCreator - > lastRecvTimeStamp ( ) ; // last time the file was actually written
2011-11-18 03:49:53 -05:00
}
2013-11-28 14:43:14 -05:00
else
info . lastTS = 0 ;
2008-11-02 06:38:11 -05:00
2009-02-12 07:47:57 -05:00
double totalRate = 0 ;
uint32_t tfRate = 0 ;
uint32_t state = 0 ;
2008-11-02 06:38:11 -05:00
bool isDownloading = false ;
bool isSuspended = false ;
2014-10-24 18:07:26 -04:00
for ( pit = peerIds . begin ( ) ; pit ! = peerIds . end ( ) ; + + pit )
2008-11-02 06:38:11 -05:00
{
2010-03-06 18:29:47 -05:00
if ( it - > second - > mTransfer - > getPeerState ( * pit , state , tfRate ) )
2008-11-02 06:38:11 -05:00
{
TransferInfo ti ;
switch ( state )
{
case PQIPEER_INIT :
ti . status = FT_STATE_OKAY ;
break ;
case PQIPEER_NOT_ONLINE :
ti . status = FT_STATE_WAITING ;
break ;
case PQIPEER_DOWNLOADING :
isDownloading = true ;
ti . status = FT_STATE_DOWNLOADING ;
break ;
case PQIPEER_IDLE :
ti . status = FT_STATE_OKAY ;
break ;
default :
case PQIPEER_SUSPEND :
isSuspended = true ;
ti . status = FT_STATE_FAILED ;
break ;
}
ti . tfRate = tfRate / 1024.0 ;
ti . peerId = * pit ;
info . peers . push_back ( ti ) ;
totalRate + = tfRate / 1024.0 ;
}
}
2010-03-06 18:29:47 -05:00
if ( ( completed ) | | ( ( it - > second ) - > mCreator - > finished ( ) ) )
2008-11-02 06:38:11 -05:00
{
info . downloadStatus = FT_STATE_COMPLETE ;
}
else if ( isDownloading )
{
info . downloadStatus = FT_STATE_DOWNLOADING ;
}
else if ( isSuspended )
{
info . downloadStatus = FT_STATE_FAILED ;
}
2009-06-11 17:41:42 -04:00
else
2008-11-02 06:38:11 -05:00
{
info . downloadStatus = FT_STATE_WAITING ;
}
2010-03-06 18:29:47 -05:00
if ( it - > second - > mState = = ftFileControl : : QUEUED )
info . downloadStatus = FT_STATE_QUEUED ;
2010-03-15 08:57:08 -04:00
if ( it - > second - > mState = = ftFileControl : : PAUSED )
info . downloadStatus = FT_STATE_PAUSED ;
2010-07-06 01:04:11 -04:00
if ( ( ! completed ) & & it - > second - > mTransfer - > isCheckingHash ( ) )
info . downloadStatus = FT_STATE_CHECKING_HASH ;
2008-11-02 06:38:11 -05:00
info . tfRate = totalRate ;
2010-03-06 18:29:47 -05:00
info . size = ( it - > second ) - > mSize ;
2008-11-09 17:17:20 -05:00
if ( completed )
{
info . transfered = info . size ;
2008-11-30 12:17:28 -05:00
info . avail = info . transfered ;
2008-11-09 17:17:20 -05:00
}
else
{
2010-03-06 18:29:47 -05:00
info . transfered = ( it - > second ) - > mCreator - > getRecvd ( ) ;
2008-11-30 12:17:28 -05:00
info . avail = info . transfered ;
2008-11-09 17:17:20 -05:00
}
2008-07-23 18:01:59 -04:00
return true ;
}
/***************************************************************/
/********************** Controller Access **********************/
/***************************************************************/
/* pqiMonitor callback:
* Used to tell TransferModules new available peers
*/
2014-03-28 23:57:44 -04:00
void ftController : : statusChange ( const std : : list < pqiServicePeer > & plist )
2008-07-23 18:01:59 -04:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2008-11-13 18:03:46 -05:00
uint32_t rate = FT_CNTRL_STANDARD_RATE ;
2008-07-23 18:01:59 -04:00
/* add online to all downloads */
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator it ;
2014-03-28 23:57:44 -04:00
std : : list < pqiServicePeer > : : const_iterator pit ;
2008-07-23 18:01:59 -04:00
2008-11-13 18:03:46 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::statusChange() " ;
std : : cerr < < std : : endl ;
# endif
2014-10-24 18:07:26 -04:00
for ( it = mDownloads . begin ( ) ; it ! = mDownloads . end ( ) ; + + it )
2013-10-15 16:39:13 -04:00
if ( it - > second - > mState = = ftFileControl : : DOWNLOADING )
2008-07-23 18:01:59 -04:00
{
2008-11-13 18:03:46 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::statusChange() Updating Hash: " ;
std : : cerr < < it - > first ;
std : : cerr < < std : : endl ;
# endif
2014-10-24 18:07:26 -04:00
for ( pit = plist . begin ( ) ; pit ! = plist . end ( ) ; + + pit )
2008-07-23 18:01:59 -04:00
{
2008-11-13 18:03:46 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " Peer: " < < pit - > id ;
# endif
2014-03-28 23:57:44 -04:00
if ( pit - > actions & RS_SERVICE_PEER_CONNECTED )
2008-11-13 18:03:46 -05:00
{
# ifdef CONTROL_DEBUG
std : : cerr < < " is Newly Connected! " ;
std : : cerr < < std : : endl ;
# endif
2010-03-06 18:29:47 -05:00
setPeerState ( it - > second - > mTransfer , pit - > id , rate , true ) ;
2008-11-13 18:03:46 -05:00
}
2014-03-28 23:57:44 -04:00
else if ( pit - > actions & RS_SERVICE_PEER_DISCONNECTED )
2008-07-23 18:01:59 -04:00
{
2008-11-13 18:03:46 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " is Just disconnected! " ;
std : : cerr < < std : : endl ;
2009-05-26 17:42:45 -04:00
# endif
2010-03-06 18:29:47 -05:00
setPeerState ( it - > second - > mTransfer , pit - > id , rate , false ) ;
2009-05-26 17:42:45 -04:00
}
2014-03-28 23:57:44 -04:00
else // Added or Removed.
2009-05-26 17:42:45 -04:00
{
# ifdef CONTROL_DEBUG
std : : cerr < < " had something happen to it: " ;
std : : cerr < < pit - > actions ;
std : : cerr < < std : : endl ;
# endif
2010-03-06 18:29:47 -05:00
setPeerState ( it - > second - > mTransfer , pit - > id , rate , false ) ;
2009-05-26 17:42:45 -04:00
}
}
2009-06-11 17:41:42 -04:00
2009-05-26 17:42:45 -04:00
// Now also look at turtle virtual peers.
//
2013-10-21 05:05:51 -04:00
std : : list < pqipeer > vlist ;
2014-03-28 23:57:44 -04:00
std : : list < pqipeer > : : const_iterator vit ;
2013-10-21 05:05:51 -04:00
mTurtle - > getSourceVirtualPeersList ( it - > first , vlist ) ;
2013-10-21 14:09:40 -04:00
# ifdef CONTROL_DEBUG
2013-10-21 05:05:51 -04:00
std : : cerr < < " vlist.size() = " < < vlist . size ( ) < < std : : endl ;
2013-10-21 14:09:40 -04:00
# endif
2013-10-21 05:05:51 -04:00
2014-10-24 18:07:26 -04:00
for ( vit = vlist . begin ( ) ; vit ! = vlist . end ( ) ; + + vit )
2009-05-26 17:42:45 -04:00
{
# ifdef CONTROL_DEBUG
2014-03-28 23:57:44 -04:00
std : : cerr < < " Peer: " < < vit - > id ;
2009-05-26 17:42:45 -04:00
# endif
2014-03-28 23:57:44 -04:00
if ( vit - > actions & RS_PEER_CONNECTED )
2009-05-26 17:42:45 -04:00
{
# ifdef CONTROL_DEBUG
std : : cerr < < " is Newly Connected! " ;
std : : cerr < < std : : endl ;
# endif
2014-03-28 23:57:44 -04:00
setPeerState ( it - > second - > mTransfer , vit - > id , rate , true ) ;
2009-05-26 17:42:45 -04:00
}
2014-03-28 23:57:44 -04:00
else if ( vit - > actions & RS_PEER_DISCONNECTED )
2009-05-26 17:42:45 -04:00
{
# ifdef CONTROL_DEBUG
std : : cerr < < " is Just disconnected! " ;
std : : cerr < < std : : endl ;
2008-11-13 18:03:46 -05:00
# endif
2014-03-28 23:57:44 -04:00
setPeerState ( it - > second - > mTransfer , vit - > id , rate , false ) ;
2008-07-23 18:01:59 -04:00
}
2008-11-13 18:03:46 -05:00
else
2008-07-23 18:01:59 -04:00
{
2008-11-13 18:03:46 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " had something happen to it: " ;
2014-03-28 23:57:44 -04:00
std : : cerr < < vit - > actions ;
2008-11-13 18:03:46 -05:00
std : : cerr < < std : : endl ;
# endif
2014-03-28 23:57:44 -04:00
setPeerState ( it - > second - > mTransfer , vit - > id , rate , false ) ;
2008-07-23 18:01:59 -04:00
}
}
}
2008-08-09 13:03:24 -04:00
}
2008-07-23 18:01:59 -04:00
2011-01-23 09:55:57 -05:00
const std : : string active_downloads_size_ss ( " MAX_ACTIVE_DOWNLOADS " ) ;
2012-01-10 18:07:53 -05:00
const std : : string min_prioritized_downl_ss ( " MIN_PRORITIZED_DOWNLOADS " ) ;
2008-11-15 15:00:29 -05:00
const std : : string download_dir_ss ( " DOWN_DIR " ) ;
const std : : string partial_dir_ss ( " PART_DIR " ) ;
2010-03-21 17:07:12 -04:00
const std : : string default_chunk_strategy_ss ( " DEFAULT_CHUNK_STRATEGY " ) ;
2010-05-21 16:49:48 -04:00
const std : : string free_space_limit_ss ( " FREE_SPACE_LIMIT " ) ;
2008-11-15 15:00:29 -05:00
/* p3Config Interface */
RsSerialiser * ftController : : setupSerialiser ( )
{
RsSerialiser * rss = new RsSerialiser ( ) ;
/* add in the types we need! */
rss - > addSerialType ( new RsFileConfigSerialiser ( ) ) ;
rss - > addSerialType ( new RsGeneralConfigSerialiser ( ) ) ;
return rss ;
}
2010-12-18 14:35:07 -05:00
bool ftController : : saveList ( bool & cleanup , std : : list < RsItem * > & saveData )
2008-11-15 15:00:29 -05:00
{
2010-12-18 14:35:07 -05:00
2008-11-15 15:00:29 -05:00
/* it can delete them! */
cleanup = true ;
/* create a key/value set for most of the parameters */
std : : map < std : : string , std : : string > configMap ;
std : : map < std : : string , std : : string > : : iterator mit ;
2014-03-17 16:56:06 -04:00
std : : list < RsFileHash > : : iterator it ;
2008-11-15 15:00:29 -05:00
/* basic control parameters */
2012-04-17 20:00:59 -04:00
std : : string s ;
rs_sprintf ( s , " %lu " , getMinPrioritizedTransfers ( ) ) ;
configMap [ min_prioritized_downl_ss ] = s ;
rs_sprintf ( s , " %lu " , getQueueSize ( ) ) ;
configMap [ active_downloads_size_ss ] = s ;
2008-11-15 15:00:29 -05:00
configMap [ download_dir_ss ] = getDownloadDirectory ( ) ;
configMap [ partial_dir_ss ] = getPartialsDirectory ( ) ;
2013-03-22 08:14:48 -04:00
switch ( mDefaultChunkStrategy )
{
case FileChunksInfo : : CHUNK_STRATEGY_STREAMING : configMap [ default_chunk_strategy_ss ] = " STREAMING " ;
break ;
case FileChunksInfo : : CHUNK_STRATEGY_RANDOM : configMap [ default_chunk_strategy_ss ] = " RANDOM " ;
break ;
default :
case FileChunksInfo : : CHUNK_STRATEGY_PROGRESSIVE : configMap [ default_chunk_strategy_ss ] = " PROGRESSIVE " ;
break ;
}
2008-11-15 15:00:29 -05:00
2012-04-17 20:00:59 -04:00
rs_sprintf ( s , " %lu " , RsDiscSpace : : freeSpaceLimit ( ) ) ;
configMap [ free_space_limit_ss ] = s ;
2010-05-21 16:49:48 -04:00
2008-11-15 15:00:29 -05:00
RsConfigKeyValueSet * rskv = new RsConfigKeyValueSet ( ) ;
/* Convert to TLV */
2014-10-24 18:07:26 -04:00
for ( mit = configMap . begin ( ) ; mit ! = configMap . end ( ) ; + + mit )
2008-11-15 15:00:29 -05:00
{
RsTlvKeyValue kv ;
kv . key = mit - > first ;
kv . value = mit - > second ;
rskv - > tlvkvs . pairs . push_back ( kv ) ;
}
/* Add KeyValue to saveList */
saveData . push_back ( rskv ) ;
/* get list of Downloads ....
* strip out Caches / ExtraList / Channels ? ? ? ?
* ( anything with a callback ? )
* - most systems will restart missing files .
*/
/* get Details of File Transfers */
2014-03-17 16:56:06 -04:00
std : : list < RsFileHash > hashs ;
2008-11-15 15:00:29 -05:00
FileDownloads ( hashs ) ;
2014-10-24 18:07:26 -04:00
for ( it = hashs . begin ( ) ; it ! = hashs . end ( ) ; + + it )
2008-11-15 15:00:29 -05:00
{
/* stack mutex released each loop */
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator fit = mDownloads . find ( * it ) ;
2008-11-15 15:00:29 -05:00
if ( fit = = mDownloads . end ( ) )
continue ;
2010-10-16 11:21:37 -04:00
/* ignore cache files. As this is small files, better download them again from scratch at restart.*/
2012-02-16 17:04:03 -05:00
// Node: We still save finished transfers. This keeps transfers that are
// in checking mode. Finished or checked transfers will restart and
// immediately terminate/recheck at next startup.
//
// if ((fit->second)->mCreator->finished())
// continue;
2008-11-15 15:00:29 -05:00
/* make RsFileTransfer item for save list */
RsFileTransfer * rft = new RsFileTransfer ( ) ;
/* what data is important? */
2010-03-06 18:29:47 -05:00
rft - > file . name = fit - > second - > mName ;
rft - > file . hash = fit - > second - > mHash ;
rft - > file . filesize = fit - > second - > mSize ;
2012-06-01 16:51:14 -04:00
RsDirUtil : : removeTopDir ( fit - > second - > mDestination , rft - > file . path ) ; /* remove fname */
2012-11-02 09:52:29 -04:00
rft - > flags = fit - > second - > mFlags . toUInt32 ( ) ;
2010-03-06 18:29:47 -05:00
rft - > state = fit - > second - > mState ;
2010-01-11 11:00:42 -05:00
2014-03-17 16:56:06 -04:00
std : : list < RsPeerId > lst ;
fit - > second - > mTransfer - > getFileSources ( lst ) ;
2010-02-13 15:42:49 -05:00
2010-01-11 11:00:42 -05:00
// Remove turtle peers from sources, as they are not supposed to survive a reboot of RS, since they are dynamic sources.
// Otherwize, such sources are unknown from the turtle router, at restart, and never get removed.
//
2014-03-17 16:56:06 -04:00
for ( std : : list < RsPeerId > : : const_iterator it ( lst . begin ( ) ) ; it ! = lst . end ( ) ; + + it )
if ( ! mTurtle - > isTurtlePeer ( * it ) )
2015-04-17 17:36:22 -04:00
rft - > allPeerIds . ids . insert ( * it ) ;
2010-01-11 11:00:42 -05:00
2014-03-17 16:56:06 -04:00
rft - > transferred = fit - > second - > mCreator - > getRecvd ( ) ;
2010-03-06 18:29:47 -05:00
fit - > second - > mCreator - > getAvailabilityMap ( rft - > compressed_chunk_map ) ;
rft - > chunk_strategy = fit - > second - > mCreator - > getChunkStrategy ( ) ;
2008-11-15 15:00:29 -05:00
saveData . push_back ( rft ) ;
}
2012-05-07 10:54:46 -04:00
{
/* Save pending list of downloads */
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
std : : list < ftPendingRequest > : : iterator pit ;
for ( pit = mPendingRequests . begin ( ) ; pit ! = mPendingRequests . end ( ) ; + + pit )
{
/* make RsFileTransfer item for save list */
RsFileTransfer * rft = NULL ;
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , RsFileTransfer * > : : iterator rit = mPendingChunkMaps . find ( pit - > mHash ) ;
2012-05-07 10:54:46 -04:00
if ( rit ! = mPendingChunkMaps . end ( ) ) {
/* use item from the not loaded pending list */
rft = new RsFileTransfer ( * ( rit - > second ) ) ;
} else {
rft = new RsFileTransfer ( ) ;
/* what data is important? */
rft - > file . name = pit - > mName ;
rft - > file . hash = pit - > mHash ;
rft - > file . filesize = pit - > mSize ;
2012-06-01 16:51:14 -04:00
RsDirUtil : : removeTopDir ( pit - > mDest , rft - > file . path ) ; /* remove fname */
2012-11-02 09:52:29 -04:00
rft - > flags = pit - > mFlags . toUInt32 ( ) ;
2013-10-06 08:56:37 -04:00
rft - > state = pit - > mState ;
2014-03-17 16:56:06 -04:00
rft - > allPeerIds . ids . clear ( ) ;
for ( std : : list < RsPeerId > : : const_iterator it ( pit - > mSrcIds . begin ( ) ) ; it ! = pit - > mSrcIds . end ( ) ; + + it )
2015-04-17 17:36:22 -04:00
rft - > allPeerIds . ids . insert ( * it ) ;
2012-05-07 10:54:46 -04:00
}
// Remove turtle peers from sources, as they are not supposed to survive a reboot of RS, since they are dynamic sources.
2014-03-17 16:56:06 -04:00
// Otherwize, such sources are unknown from the turtle router, at restart, and never get removed. We do that in post
// process since the rft object may have been created from mPendingChunkMaps
2012-05-07 10:54:46 -04:00
//
2015-04-17 17:36:22 -04:00
for ( std : : set < RsPeerId > : : iterator sit ( rft - > allPeerIds . ids . begin ( ) ) ; sit ! = rft - > allPeerIds . ids . end ( ) ; )
2014-03-17 16:56:06 -04:00
if ( mTurtle - > isTurtlePeer ( RsPeerId ( * sit ) ) )
{
2015-04-17 17:36:22 -04:00
std : : set < RsPeerId > : : iterator sittmp ( sit ) ;
2014-03-17 16:56:06 -04:00
+ + sittmp ;
rft - > allPeerIds . ids . erase ( sit ) ;
sit = sittmp ;
}
2012-05-07 10:54:46 -04:00
else
+ + sit ;
saveData . push_back ( rft ) ;
}
}
2008-11-15 15:00:29 -05:00
/* list completed! */
2010-12-18 14:35:07 -05:00
return true ;
2008-11-15 15:00:29 -05:00
}
2010-12-18 14:35:07 -05:00
bool ftController : : loadList ( std : : list < RsItem * > & load )
2008-11-15 15:00:29 -05:00
{
std : : list < RsItem * > : : iterator it ;
std : : list < RsTlvKeyValue > : : iterator kit ;
RsConfigKeyValueSet * rskv ;
RsFileTransfer * rsft ;
2009-06-11 17:41:42 -04:00
# ifdef CONTROL_DEBUG
2008-11-15 15:00:29 -05:00
std : : cerr < < " ftController::loadList() Item Count: " < < load . size ( ) ;
std : : cerr < < std : : endl ;
# endif
2014-10-24 18:07:26 -04:00
for ( it = load . begin ( ) ; it ! = load . end ( ) ; + + it )
2008-11-15 15:00:29 -05:00
{
/* switch on type */
if ( NULL ! = ( rskv = dynamic_cast < RsConfigKeyValueSet * > ( * it ) ) )
{
/* make into map */
std : : map < std : : string , std : : string > configMap ;
for ( kit = rskv - > tlvkvs . pairs . begin ( ) ;
2014-10-24 18:07:26 -04:00
kit ! = rskv - > tlvkvs . pairs . end ( ) ; + + kit )
2008-11-15 15:00:29 -05:00
{
configMap [ kit - > key ] = kit - > value ;
}
loadConfigMap ( configMap ) ;
}
else if ( NULL ! = ( rsft = dynamic_cast < RsFileTransfer * > ( * it ) ) )
{
2009-06-11 17:41:42 -04:00
/* This will get stored on a waiting list - until the
2008-11-20 19:10:59 -05:00
* config files are fully loaded
*/
2012-11-08 14:18:45 -05:00
// Compatibility with previous versions.
if ( rsft - > flags & RS_FILE_HINTS_NETWORK_WIDE . toUInt32 ( ) )
{
std : : cerr < < " Ensuring compatibility, replacing RS_FILE_HINTS_NETWORK_WIDE with RS_FILE_REQ_ANONYMOUS_ROUTING " < < std : : endl ;
rsft - > flags & = ~ RS_FILE_HINTS_NETWORK_WIDE . toUInt32 ( ) ;
rsft - > flags | = RS_FILE_REQ_ANONYMOUS_ROUTING . toUInt32 ( ) ;
}
2010-10-15 18:12:29 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::loadList(): requesting " < < rsft - > file . name < < " , " < < rsft - > file . hash < < " , " < < rsft - > file . filesize < < std : : endl ;
# endif
2014-03-17 16:56:06 -04:00
std : : list < RsPeerId > src_lst ;
2015-04-17 17:36:22 -04:00
for ( std : : set < RsPeerId > : : const_iterator it ( rsft - > allPeerIds . ids . begin ( ) ) ; it ! = rsft - > allPeerIds . ids . end ( ) ; + + it )
2014-03-17 16:56:06 -04:00
src_lst . push_back ( * it ) ;
FileRequest ( rsft - > file . name , rsft - > file . hash , rsft - > file . filesize , rsft - > file . path , TransferRequestFlags ( rsft - > flags ) , src_lst , rsft - > state ) ;
2009-12-10 17:55:27 -05:00
{
RsStackMutex mtx ( ctrlMutex ) ;
2014-03-17 16:56:06 -04:00
std : : map < RsFileHash , ftFileControl * > : : iterator fit = mDownloads . find ( rsft - > file . hash ) ;
2008-11-20 19:10:59 -05:00
2010-03-06 18:29:47 -05:00
if ( ( fit = = mDownloads . end ( ) | | ( fit - > second ) - > mCreator = = NULL ) )
2009-12-10 17:55:27 -05:00
{
std : : cerr < < " ftController::loadList(): Error: could not find hash " < < rsft - > file . hash < < " in mDownloads list ! " < < std : : endl ;
std : : cerr < < " Storing the map in a wait list. " < < std : : endl ;
mPendingChunkMaps [ rsft - > file . hash ] = rsft ;
2012-11-08 14:18:45 -05:00
2009-12-10 17:55:27 -05:00
continue ; // i.e. don't delete the item!
}
else
2010-01-11 11:00:42 -05:00
{
2010-03-06 18:29:47 -05:00
( fit - > second ) - > mCreator - > setAvailabilityMap ( rsft - > compressed_chunk_map ) ;
( fit - > second ) - > mCreator - > setChunkStrategy ( ( FileChunksInfo : : ChunkStrategy ) ( rsft - > chunk_strategy ) ) ;
2010-01-11 11:00:42 -05:00
}
2009-12-10 17:55:27 -05:00
}
2008-11-15 15:00:29 -05:00
}
2008-11-20 19:10:59 -05:00
/* cleanup */
delete ( * it ) ;
2008-11-15 15:00:29 -05:00
}
2015-12-30 18:20:09 -05:00
load . clear ( ) ;
2008-11-15 15:00:29 -05:00
return true ;
}
bool ftController : : loadConfigMap ( std : : map < std : : string , std : : string > & configMap )
{
std : : map < std : : string , std : : string > : : iterator mit ;
std : : string str_true ( " true " ) ;
std : : string empty ( " " ) ;
std : : string dir = " notempty " ;
if ( configMap . end ( ) ! = ( mit = configMap . find ( download_dir_ss ) ) )
setDownloadDirectory ( mit - > second ) ;
2011-01-23 09:55:57 -05:00
if ( configMap . end ( ) ! = ( mit = configMap . find ( active_downloads_size_ss ) ) )
{
int n = 5 ;
2012-05-03 09:41:03 -04:00
sscanf ( mit - > second . c_str ( ) , " %d " , & n ) ;
2011-01-23 09:55:57 -05:00
std : : cerr < < " Note: loading active max downloads: " < < n < < std : : endl ;
setQueueSize ( n ) ;
2008-11-15 15:00:29 -05:00
}
2012-01-10 18:07:53 -05:00
if ( configMap . end ( ) ! = ( mit = configMap . find ( min_prioritized_downl_ss ) ) )
{
int n = 3 ;
2012-05-03 09:41:03 -04:00
sscanf ( mit - > second . c_str ( ) , " %d " , & n ) ;
2012-01-10 18:07:53 -05:00
std : : cerr < < " Note: loading min prioritized downloads: " < < n < < std : : endl ;
setMinPrioritizedTransfers ( n ) ;
}
2008-11-15 15:00:29 -05:00
if ( configMap . end ( ) ! = ( mit = configMap . find ( partial_dir_ss ) ) )
{
2009-06-11 17:41:42 -04:00
setPartialsDirectory ( mit - > second ) ;
2008-11-15 15:00:29 -05:00
}
2010-03-21 17:07:12 -04:00
if ( configMap . end ( ) ! = ( mit = configMap . find ( default_chunk_strategy_ss ) ) )
{
if ( mit - > second = = " STREAMING " )
2010-04-30 17:07:21 -04:00
{
2010-03-21 17:07:12 -04:00
setDefaultChunkStrategy ( FileChunksInfo : : CHUNK_STRATEGY_STREAMING ) ;
2010-04-30 17:07:21 -04:00
std : : cerr < < " Note: loading default value for chunk strategy: streaming " < < std : : endl ;
}
2010-03-21 17:07:12 -04:00
else if ( mit - > second = = " RANDOM " )
2010-04-30 17:07:21 -04:00
{
2010-03-21 17:07:12 -04:00
setDefaultChunkStrategy ( FileChunksInfo : : CHUNK_STRATEGY_RANDOM ) ;
2010-04-30 17:07:21 -04:00
std : : cerr < < " Note: loading default value for chunk strategy: random " < < std : : endl ;
}
2013-02-28 15:42:01 -05:00
else if ( mit - > second = = " PROGRESSIVE " )
{
setDefaultChunkStrategy ( FileChunksInfo : : CHUNK_STRATEGY_PROGRESSIVE ) ;
std : : cerr < < " Note: loading default value for chunk strategy: progressive " < < std : : endl ;
}
2010-04-30 17:07:21 -04:00
else
std : : cerr < < " **** ERROR ***: Unknown value for default chunk strategy in keymap. " < < std : : endl ;
2010-03-21 17:07:12 -04:00
}
2010-05-21 16:49:48 -04:00
if ( configMap . end ( ) ! = ( mit = configMap . find ( free_space_limit_ss ) ) )
{
uint32_t size ;
2012-05-03 09:41:03 -04:00
if ( sscanf ( mit - > second . c_str ( ) , " %u " , & size ) = = 1 ) {
std : : cerr < < " have read a size limit of " < < size < < " MB " < < std : : endl ;
2010-05-21 16:49:48 -04:00
2012-05-03 09:41:03 -04:00
RsDiscSpace : : setFreeSpaceLimit ( size ) ;
}
2010-05-21 16:49:48 -04:00
}
2008-11-15 15:00:29 -05:00
return true ;
}
2010-05-21 16:49:48 -04:00
void ftController : : setFreeDiskSpaceLimit ( uint32_t size_in_mb )
{
RsDiscSpace : : setFreeSpaceLimit ( size_in_mb ) ;
IndicateConfigChanged ( ) ;
}
uint32_t ftController : : freeDiskSpaceLimit ( ) const
{
return RsDiscSpace : : freeSpaceLimit ( ) ;
}
2010-03-21 17:07:12 -04:00
FileChunksInfo : : ChunkStrategy ftController : : defaultChunkStrategy ( )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
return mDefaultChunkStrategy ;
}
void ftController : : setDefaultChunkStrategy ( FileChunksInfo : : ChunkStrategy S )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2010-04-30 17:07:21 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " Note: in frController: setting chunk strategy to " < < S < < std : : endl ;
# endif
2010-03-21 17:07:12 -04:00
mDefaultChunkStrategy = S ;
IndicateConfigChanged ( ) ;
}