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"
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"
2008-07-23 18:01:59 -04:00
2011-07-09 14:39:34 -04:00
# include "pqi/p3linkmgr.h"
2009-03-19 08:49:11 -04:00
# include "pqi/pqinotify.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
2012-02-17 05:03:38 -05:00
static const int32_t SAVE_TRANSFERS_DELAY = 61 ; // save transfer progress every 61 seconds.
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
static const int32_t TIMOUT_CACHE_FILE_TRANSFER = 800 ; // time after which cache transfer gets cancelled if inactive.
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 ;
static const int32_t FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE = 1 ;
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 ) ,
2011-11-16 15:30:20 -05:00
mState ( DOWNLOADING ) , mSize ( 0 ) , mFlags ( 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 ,
2012-11-02 09:52:29 -04:00
uint64_t size , std : : string 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 ) ,
2011-11-16 15:30:20 -05:00
mSize ( size ) , mFlags ( flags )
2008-08-17 11:23:11 -04:00
{
return ;
}
2011-08-12 09:42:30 -04:00
ftController : : ftController ( CacheStrapper * cs , ftDataMultiplex * dm , std : : string /*configDir*/ )
2010-01-11 11:00:42 -05:00
: CacheTransfer ( cs ) , p3Config ( CONFIG_TYPE_FT_CONTROL ) ,
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 ) ,
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 */
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
2010-01-11 11:00:42 -05:00
bool ftController : : getFileDownloadChunksDetails ( const std : : string & hash , FileChunksInfo & info )
2009-11-18 18:02:37 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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
}
2009-05-26 17:42:45 -04:00
void ftController : : addFileSource ( const std : : string & hash , const std : : string & peer_id )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2013-10-15 16:39:13 -04:00
std : : map < std : : string , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
2009-05-26 17:42:45 -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 - > addFileSource ( peer_id ) ;
setPeerState ( it - > second - > mTransfer , peer_id , FT_CNTRL_STANDARD_RATE , mLinkMgr - > isOnline ( 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
}
2009-06-03 14:47:14 -04:00
void ftController : : removeFileSource ( const std : : string & hash , const std : : string & peer_id )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2013-10-15 16:39:13 -04:00
std : : map < std : : string , 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
}
2008-08-09 13:03:24 -04:00
void ftController : : run ( )
2008-07-23 18:01:59 -04:00
{
2008-08-17 11:23:11 -04:00
2009-05-06 16:48:32 -04:00
/* check the queues */
2010-03-06 18:29:47 -05:00
uint32_t cnt = 0 ;
2011-03-03 18:30:08 -05:00
while ( isRunning ( ) )
2008-08-17 11:23:11 -04:00
{
2008-08-25 16:03:39 -04:00
# ifdef WIN32
Sleep ( 1000 ) ;
# else
2008-08-21 17:30:59 -04:00
sleep ( 1 ) ;
2008-08-25 16:03:39 -04:00
# endif
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
{
2010-01-26 15:40:21 -05:00
cleanCacheDownloads ( ) ;
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 ********/
2010-03-06 18:29:47 -05:00
for ( std : : map < std : : string , ftFileControl * > : : iterator it ( mDownloads . begin ( ) ) ; it ! = mDownloads . end ( ) ; + + it )
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
{
2010-11-22 16:15:21 -05:00
std : : list < std : : string > 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 ( ) ;
}
for ( std : : list < std : : string > : : 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
}
2008-12-07 09:53:57 -05:00
2010-01-26 15:40:21 -05:00
}
2012-11-19 17:45:37 -05:00
void ftController : : searchForDirectSources ( )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
for ( std : : map < std : : string , ftFileControl * > : : iterator it ( mDownloads . begin ( ) ) ; it ! = mDownloads . end ( ) ; it + + )
if ( it - > second - > mState ! = ftFileControl : : QUEUED & & it - > second - > mState ! = ftFileControl : : PAUSED )
if ( ! ( it - > second - > mFlags & RS_FILE_REQ_CACHE ) )
2012-11-20 16:42:21 -05: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-19 17:45:37 -05: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 + + )
2013-06-05 08:57:11 -04:00
if ( rsPeers - > servicePermissionFlags_sslid ( pit - > peerId ) & RS_SERVICE_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 , mLinkMgr - > isOnline ( pit - > peerId ) ) ;
2012-11-20 16:42:21 -05:00
}
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.
//
for ( std : : map < std : : string , 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
}
2010-01-26 18:25:00 -05:00
bool ftController : : getPriority ( const std : : string & hash , DwlSpeed & p )
2010-01-26 15:40:21 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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
2010-01-26 18:25:00 -05:00
void ftController : : setPriority ( const std : : string & hash , DwlSpeed p )
2010-01-26 15:40:21 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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
}
void ftController : : cleanCacheDownloads ( )
{
std : : vector < std : : string > toCancel ;
2011-04-17 12:22:03 -04:00
time_t now = time ( NULL ) ;
2010-01-26 15:40:21 -05:00
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2009-01-24 10:22:08 -05:00
2010-03-06 18:29:47 -05:00
for ( std : : map < std : : string , ftFileControl * > : : iterator it ( mDownloads . begin ( ) ) ; it ! = mDownloads . end ( ) ; + + it )
2012-11-02 09:52:29 -04:00
if ( ( ( it - > second ) - > mFlags & RS_FILE_REQ_CACHE ) & & it - > second - > mState ! = ftFileControl : : DOWNLOADING )
2011-04-17 12:22:03 -04:00
// check if a cache file is downloaded, if the case, timeout the transfer after TIMOUT_CACHE_FILE_TRANSFER
2009-05-26 17:42:45 -04:00
{
2011-06-25 08:41:37 -04:00
# ifdef CONTROL_DEBUG
2010-03-06 18:29:47 -05:00
std : : cerr < < " ftController::run() cache transfer found. age of this tranfer is : " < < ( int ) ( time ( NULL ) - ( it - > second ) - > mCreateTime ) ;
2009-05-26 17:42:45 -04:00
std : : cerr < < std : : endl ;
# endif
2011-06-25 07:49:38 -04:00
if ( now > ( it - > second ) - > mCreator - > creationTimeStamp ( ) + TIMOUT_CACHE_FILE_TRANSFER )
2010-01-26 15:40:21 -05:00
{
2011-06-25 08:41:37 -04:00
# ifdef CONTROL_DEBUG
2010-03-06 18:29:47 -05:00
std : : cerr < < " ftController::run() cache transfer to old. Cancelling transfer. Hash : " < < ( it - > second ) - > mHash < < " , time= " < < ( it - > second ) - > mCreateTime < < " , now = " < < time ( NULL ) ;
2009-05-26 17:42:45 -04:00
std : : cerr < < std : : endl ;
2009-05-06 16:48:32 -04:00
# endif
2010-03-06 18:29:47 -05:00
toCancel . push_back ( ( it - > second ) - > mHash ) ;
2009-05-06 16:48:32 -04:00
}
}
2008-08-17 11:23:11 -04:00
}
2008-10-29 16:58:23 -04:00
2010-01-26 15:40:21 -05:00
for ( uint32_t i = 0 ; i < toCancel . size ( ) ; + + i )
FileCancel ( toCancel [ i ] ) ;
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
2010-03-21 17:07:12 -04:00
for ( std : : map < std : : string , 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
| | now > it - > second - > mCreator - > lastRecvTimeStamp ( ) + ( 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
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 - > lastRecvTimeStamp ( ) < < std : : endl ;
# 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
2010-03-21 17:07:12 -04:00
it - > second - > mCreator - > resetRecvTimeStamp ( ) ; // very important!
+ + 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 )
2012-11-02 09:52:29 -04:00
if ( _queue [ p ] - > mFlags & RS_FILE_REQ_CACHE ) // cache file. add to potential move list
2012-01-10 18:07:53 -05:00
to_move_before . push_back ( p ) ;
else
+ + 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 ;
2012-11-02 09:52:29 -04:00
if ( ! ( _queue [ p ] - > mFlags & RS_FILE_REQ_CACHE ) ) // non cache file. add to potential move list
2012-01-10 18:07:53 -05:00
to_move_after . push_back ( p ) ;
}
}
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 ;
case FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE :
{
// We add the transfer just before the first non cache transfer.
2012-02-12 15:00:22 -05:00
// This is costly, so only use this in case we really need it.
2010-09-15 15:48:13 -04:00
//
uint32_t pos = 0 ;
2012-11-02 09:52:29 -04:00
while ( pos < _queue . size ( ) & & ( pos < _min_prioritized_transfers | | ( _queue [ pos ] - > mFlags & RS_FILE_REQ_CACHE ) > 0 ) )
2010-09-15 15:48:13 -04:00
+ + pos ;
_queue . push_back ( NULL ) ;
2010-10-07 17:31:42 -04:00
for ( int i = int ( _queue . size ( ) ) - 1 ; i > ( int ) pos ; - - i )
2010-09-15 15:48:13 -04:00
{
_queue [ i ] = _queue [ i - 1 ] ;
locked_checkQueueElement ( i ) ;
}
_queue [ pos ] = ftfc ;
locked_checkQueueElement ( pos ) ;
}
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 ;
}
void ftController : : moveInQueue ( const std : : string & hash , QueueMove mv )
{
RsStackMutex mtx ( ctrlMutex ) ;
std : : map < std : : string , ftFileControl * > : : iterator it ( mDownloads . find ( hash ) ) ;
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 )
_queue [ pos ] - > mCreator - > resetRecvTimeStamp ( ) ;
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 )
2013-04-06 05:21:01 -04:00
mTurtle - > monitorTunnels ( _queue [ pos ] - > mHash , mFtServer ) ;
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
}
2008-10-29 16:58:23 -04:00
bool ftController : : FlagFileComplete ( std : : string 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
{
getPqiNotify ( ) - > AddSysMessage ( 0 , RS_SYS_WARNING , " File erase error " , " Error while removing hash file " + dest + " \n Read-only file system ? " ) ;
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 )
{
2011-07-06 15:08:30 -04:00
//getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "File copy error", "Error while copying file " + dest + "\nCannot open input file "+source);
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 )
{
getPqiNotify ( ) - > 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.
void * buffer = malloc ( BUFF_SIZE ) ;
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 )
{
getPqiNotify ( ) - > 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
2008-10-29 16:58:23 -04:00
bool ftController : : completeFile ( std : : string hash )
{
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 ;
2008-11-09 17:17:20 -05: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
2010-03-06 18:29:47 -05:00
std : : map < std : : string , ftFileControl * > : : iterator it ( mDownloads . find ( hash ) ) ;
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!
2009-06-11 17:41:42 -04:00
std : : string 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 */
2012-11-02 09:52:29 -04:00
if ( ! ( fc - > mFlags & RS_FILE_REQ_CACHE ) ) /* clean up completed cache files automatically */
2010-11-24 19:20:25 -05:00
{
2010-03-06 18:29:47 -05:00
mCompleted [ fc - > mHash ] = fc ;
2010-11-24 19:20:25 -05:00
completeCount = mCompleted . size ( ) ;
} else
2010-03-06 18:29:47 -05:00
delete fc ;
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
2012-11-02 09:52:29 -04:00
if ( flags & ( RS_FILE_REQ_CACHE | RS_FILE_REQ_EXTRA ) ) // | RS_FILE_HINTS_MEDIA))
2008-10-29 16:58:23 -04:00
{
2008-11-04 18:12:53 -05:00
# ifdef CONTROL_DEBUG
2013-03-11 16:46:18 -04:00
std : : cerr < < " ftController::completeFile() doing Callback, callbackflags: " < < ( flags & ( RS_FILE_REQ_CACHE | RS_FILE_REQ_EXTRA ) ) ; //| RS_FILE_HINTS_MEDIA)) ;
2008-11-04 18:12:53 -05:00
std : : cerr < < std : : endl ;
# endif
2012-11-02 09:52:29 -04:00
if ( flags & RS_FILE_REQ_CACHE )
2008-10-29 16:58:23 -04:00
{
2010-10-16 11:21:37 -04:00
/* callback */
if ( state = = ftFileControl : : COMPLETED )
{
2008-11-04 18:12:53 -05:00
# ifdef CONTROL_DEBUG
2010-10-16 11:21:37 -04:00
std : : cerr < < " ftController::completeFile() doing Callback : Success " ;
std : : cerr < < std : : endl ;
2008-11-04 18:12:53 -05:00
# endif
2009-06-11 17:41:42 -04:00
2010-10-16 11:21:37 -04:00
CompletedCache ( hash ) ;
}
else
{
2008-11-04 18:12:53 -05:00
# ifdef CONTROL_DEBUG
2010-10-16 11:21:37 -04:00
std : : cerr < < " ftController::completeFile() Cache Callback : Failed " ;
std : : cerr < < std : : endl ;
2008-11-04 18:12:53 -05:00
# endif
2010-10-16 11:21:37 -04:00
FailedCache ( hash ) ;
}
}
2012-11-02 09:52:29 -04:00
if ( flags & RS_FILE_REQ_EXTRA )
2010-10-16 11:21:37 -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-11-09 17:17:20 -05:00
2012-11-02 09:52:29 -04:00
// if(flags & RS_FILE_HINTS_MEDIA)
// {
//#ifdef CONTROL_DEBUG
// std::cerr << "ftController::completeFile() NULL MEDIA callback";
// std::cerr << std::endl;
//#endif
// }
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 */
2012-11-02 09:52:29 -04:00
if ( ( flags & RS_FILE_REQ_CACHE ) = = 0 ) {
2010-11-24 19:20:25 -05:00
pqiNotify * notify = getPqiNotify ( ) ;
if ( notify ) {
notify - > AddPopupMessage ( RS_POPUP_DOWNLOAD , hash , name , " " ) ;
}
rsicontrol - > getNotify ( ) . notifyDownloadComplete ( hash ) ;
rsicontrol - > getNotify ( ) . notifyDownloadCompleteCount ( completeCount ) ;
2013-02-27 05:03:54 -05: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 ********/
std : : map < std : : string , RsFileTransfer * > : : iterator it ( mPendingChunkMaps . find ( req . mHash ) ) ;
if ( it ! = mPendingChunkMaps . end ( ) )
{
RsFileTransfer * rsft = it - > second ;
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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
}
2010-10-05 16:39:14 -04:00
bool ftController : : alreadyHaveFile ( const std : : string & 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
2010-07-21 19:14:10 -04:00
bool ftController : : FileRequest ( const std : : string & fname , const std : : string & hash ,
2012-11-02 09:52:29 -04:00
uint64_t size , const std : : string & dest , TransferRequestFlags flags ,
2013-10-06 08:56:37 -04:00
const std : : list < std : : string > & _srcIds , uint16_t state )
2008-07-23 18:01:59 -04:00
{
2010-07-21 19:14:10 -04:00
std : : list < std : : string > srcIds ( _srcIds ) ;
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
}
2010-07-21 19:14:10 -04:00
std : : list < std : : string > : : const_iterator it ;
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 < < " ,< " ;
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
2010-07-21 19:14:10 -04:00
std : : map < std : : string , 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
2010-01-16 10:42:26 -05:00
for ( it = srcIds . begin ( ) ; it ! = srcIds . end ( ) ; it + + )
2008-11-09 17:17:20 -05:00
{
2010-01-16 10:42:26 -05:00
uint32_t i , j ;
2010-03-06 18:29:47 -05:00
if ( ( dit - > second ) - > mTransfer - > getPeerState ( * it , i , j ) )
2010-01-16 10:42:26 -05:00
{
2008-11-09 17:17:20 -05:00
# ifdef CONTROL_DEBUG
2010-01-16 10:42:26 -05:00
std : : cerr < < " ftController::FileRequest() Peer Existing " ;
std : : cerr < < std : : endl ;
2008-11-09 17:17:20 -05:00
# endif
2010-01-16 10:42:26 -05:00
continue ; /* already added peer */
}
2008-11-09 17:17:20 -05:00
# ifdef CONTROL_DEBUG
2010-01-16 10:42:26 -05:00
std : : cerr < < " ftController::FileRequest() Adding Peer: " < < * it ;
std : : cerr < < std : : endl ;
2008-11-09 17:17:20 -05:00
# endif
2010-03-06 18:29:47 -05:00
( dit - > second ) - > mTransfer - > addFileSource ( * it ) ;
2011-07-09 14:39:34 -04:00
setPeerState ( dit - > second - > mTransfer , * it , rate , mLinkMgr - > isOnline ( * it ) ) ;
2008-11-15 15:00:29 -05:00
2010-01-16 10:42:26 -05:00
IndicateConfigChanged ( ) ; /* new peer for transfer -> save */
}
2008-11-09 17:17:20 -05:00
2010-01-16 10:42:26 -05:00
if ( srcIds . size ( ) = = 0 )
{
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
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 */
2008-11-02 06:38:11 -05: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
2013-06-06 16:52:24 -04:00
if ( ( srcIds . end ( ) = = std : : find ( srcIds . begin ( ) , srcIds . end ( ) , pit - > peerId ) ) & & ( RS_SERVICE_PERM_DIRECT_DL & rsPeers - > servicePermissionFlags_sslid ( 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
2010-01-16 10:42:26 -05:00
savepath = mPartialsPath + " / " + hash ;
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 )
2013-04-06 05:21:01 -04:00
mTurtle - > monitorTunnels ( hash , mFtServer ) ;
2010-01-11 17:38:18 -05:00
2012-11-02 09:52:29 -04:00
bool assume_availability = flags & RS_FILE_REQ_CACHE ; // assume availability for cache files
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 */
for ( it = srcIds . begin ( ) ; it ! = srcIds . end ( ) ; it + + )
{
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
2011-07-09 14:39:34 -04:00
setPeerState ( tm , * it , rate , mLinkMgr - > isOnline ( * 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
}
2010-01-26 15:40:21 -05:00
bool ftController : : setPeerState ( ftTransferModule * tm , std : : string id , uint32_t maxrate , bool online )
2008-11-13 18:03:46 -05:00
{
2011-07-09 14:39:34 -04:00
if ( id = = mLinkMgr - > 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 ;
}
2009-12-08 17:29:52 -05:00
bool ftController : : setChunkStrategy ( const std : : string & hash , FileChunksInfo : : ChunkStrategy s )
{
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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
2010-07-21 19:14:10 -04:00
bool ftController : : FileCancel ( const std : : string & 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 ) ;
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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
}
2010-07-09 17:04:29 -04:00
bool ftController : : FileControl ( const std : : string & 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*/
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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 ********/
for ( std : : map < std : : string , ftFileControl * > : : iterator it ( mCompleted . begin ( ) ) ; it ! = mCompleted . end ( ) ; + + it )
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
2010-11-24 19:20:25 -05:00
rsicontrol - > getNotify ( ) . 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 */
bool ftController : : FileDownloads ( std : : list < std : : string > & hashs )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2010-03-06 18:29:47 -05:00
std : : map < std : : string , ftFileControl * > : : iterator it ;
2008-07-23 18:01:59 -04:00
for ( it = mDownloads . begin ( ) ; it ! = mDownloads . end ( ) ; it + + )
{
2010-03-06 18:29:47 -05:00
hashs . push_back ( it - > second - > mHash ) ;
2008-07-23 18:01:59 -04:00
}
2008-11-09 17:17:20 -05:00
for ( it = mCompleted . begin ( ) ; it ! = mCompleted . end ( ) ; it + + )
{
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
return true ;
}
/* 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 ) ;
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! */
std : : map < std : : string , ftFileControl > : : iterator it ;
for ( it = mDownloads . begin ( ) ; it ! = mDownloads . end ( ) ; it + + )
{
( 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
}
2013-02-27 11:59:16 -05:00
bool ftController : : setDestinationDirectory ( const std : : string & hash , const std : : string & dest_dir )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
std : : map < std : : string , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
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 ;
}
bool ftController : : setDestinationName ( const std : : string & hash , const std : : string & dest_name )
{
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
std : : map < std : : string , ftFileControl * > : : iterator it = mDownloads . find ( hash ) ;
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 ;
}
2010-10-27 16:01:31 -04:00
bool ftController : : FileDetails ( const std : : string & 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 ;
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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 */
std : : list < std : : string > peerIds ;
std : : list < std : : string > : : iterator pit ;
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 ( ) ;
}
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 ;
for ( pit = peerIds . begin ( ) ; pit ! = peerIds . end ( ) ; pit + + )
{
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
*/
void ftController : : statusChange ( const std : : list < pqipeer > & plist )
{
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 */
2010-03-06 18:29:47 -05:00
std : : map < std : : string , ftFileControl * > : : iterator it ;
2008-07-23 18:01:59 -04:00
std : : list < pqipeer > : : const_iterator pit ;
2008-11-13 18:03:46 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::statusChange() " ;
std : : cerr < < std : : endl ;
# endif
2008-07-23 18:01:59 -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
2008-07-23 18:01:59 -04:00
for ( pit = plist . begin ( ) ; pit ! = plist . end ( ) ; pit + + )
{
2008-11-13 18:03:46 -05:00
# ifdef CONTROL_DEBUG
std : : cerr < < " Peer: " < < pit - > id ;
# endif
if ( pit - > actions & RS_PEER_CONNECTED )
{
# 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
}
else if ( pit - > actions & RS_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
}
else
{
# 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 ;
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
2009-05-26 17:42:45 -04:00
for ( pit = vlist . begin ( ) ; pit ! = vlist . end ( ) ; pit + + )
{
# ifdef CONTROL_DEBUG
std : : cerr < < " Peer: " < < pit - > id ;
# endif
if ( pit - > actions & RS_PEER_CONNECTED )
{
# 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 ) ;
2009-05-26 17:42:45 -04:00
}
else if ( pit - > actions & RS_PEER_DISCONNECTED )
{
# ifdef CONTROL_DEBUG
std : : cerr < < " is Just disconnected! " ;
std : : cerr < < std : : endl ;
2008-11-13 18:03:46 -05:00
# endif
2010-03-06 18:29:47 -05:00
setPeerState ( it - > second - > mTransfer , pit - > 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: " ;
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 ) ;
2008-07-23 18:01:59 -04:00
}
}
}
2008-08-09 13:03:24 -04:00
}
2008-07-23 18:01:59 -04:00
2008-08-17 11:23:11 -04:00
/* Cache Interface */
bool ftController : : RequestCacheFile ( RsPeerId id , std : : string path , std : : string hash , uint64_t size )
{
# ifdef CONTROL_DEBUG
2010-05-09 09:52:05 -04:00
std : : cerr < < " ftController::RequestCacheFile( " < < id < < " , " ;
std : : cerr < < path < < " , " < < hash < < " , " < < size < < " ) " ;
std : : cerr < < std : : endl ;
2008-08-17 11:23:11 -04:00
# endif
/* Request File */
std : : list < std : : string > ids ;
ids . push_back ( id ) ;
2010-05-09 09:52:05 -04:00
FileInfo info ;
if ( mSearch - > search ( hash , RS_FILE_HINTS_CACHE , info ) )
{
# ifdef CONTROL_DEBUG
std : : cerr < < " I already have this file: " < < std : : endl ;
std : : cerr < < " path: " < < info . path < < std : : endl ;
std : : cerr < < " fname: " < < info . fname < < std : : endl ;
std : : cerr < < " hash: " < < info . hash < < std : : endl ;
std : : cerr < < " Copying it !! " < < std : : endl ;
# endif
2010-09-14 17:24:51 -04:00
if ( info . size > 0 & & copyFile ( info . path , path + " / " + hash ) )
2010-05-09 09:52:05 -04:00
{
CompletedCache ( hash ) ;
return true ;
}
2010-09-15 15:53:58 -04:00
else
return false ;
2010-05-09 09:52:05 -04:00
}
2012-11-02 09:52:29 -04:00
FileRequest ( hash , hash , size , path , RS_FILE_REQ_CACHE | RS_FILE_REQ_NO_SEARCH , ids ) ;
2008-10-29 16:58:23 -04:00
return true ;
2008-08-17 11:23:11 -04:00
}
bool ftController : : CancelCacheFile ( RsPeerId id , std : : string path , std : : string hash , uint64_t size )
{
std : : cerr < < " ftController::CancelCacheFile( " < < id < < " , " ;
std : : cerr < < path < < " , " < < hash < < " , " < < size < < " ) " ;
std : : cerr < < std : : endl ;
2011-06-24 11:10:52 -04:00
# ifdef CONTROL_DEBUG
2008-08-17 11:23:11 -04:00
# endif
2011-06-24 11:10:52 -04:00
return FileCancel ( hash ) ;
2008-08-17 11:23:11 -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 ;
std : : list < std : : string > : : iterator it ;
/* 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 */
for ( mit = configMap . begin ( ) ; mit ! = configMap . end ( ) ; mit + + )
{
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 */
std : : list < std : : string > hashs ;
FileDownloads ( hashs ) ;
for ( it = hashs . begin ( ) ; it ! = hashs . end ( ) ; it + + )
{
/* stack mutex released each loop */
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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-11-02 09:52:29 -04:00
if ( fit - > second - > mFlags & RS_FILE_REQ_CACHE )
2010-10-15 18:12:29 -04:00
{
# ifdef CONTROL_DEBUG
std : : cerr < < " ftcontroller::saveList(): Not saving (callback) file entry " < < fit - > second - > mName < < " , " < < fit - > second - > mHash < < " , " < < fit - > second - > mSize < < std : : endl ;
# endif
2008-11-15 15:00:29 -05:00
continue ;
2010-10-15 18:12:29 -04:00
}
2008-11-15 15:00:29 -05:00
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 ;
fit - > second - > mTransfer - > getFileSources ( rft - > allPeerIds . ids ) ;
2010-01-11 11:00:42 -05:00
2010-03-06 18:29:47 -05:00
rft - > transferred = fit - > second - > mCreator - > getRecvd ( ) ;
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.
//
for ( std : : list < std : : string > : : iterator sit ( rft - > allPeerIds . ids . begin ( ) ) ; sit ! = rft - > allPeerIds . ids . end ( ) ; )
if ( mTurtle - > isTurtlePeer ( * sit ) )
{
std : : list < std : : string > : : iterator sittmp ( sit ) ;
+ + sittmp ;
rft - > allPeerIds . ids . erase ( sit ) ;
sit = sittmp ;
}
else
+ + sit ;
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 ;
std : : map < std : : string , RsFileTransfer * > : : iterator rit = mPendingChunkMaps . find ( pit - > mHash ) ;
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 ;
2012-05-07 10:54:46 -04:00
rft - > allPeerIds . ids = pit - > mSrcIds ;
}
// 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.
//
for ( std : : list < std : : string > : : iterator sit ( rft - > allPeerIds . ids . begin ( ) ) ; sit ! = rft - > allPeerIds . ids . end ( ) ; )
if ( mTurtle - > isTurtlePeer ( * sit ) )
{
std : : list < std : : string > : : iterator sittmp ( sit ) ;
sit = rft - > allPeerIds . ids . erase ( sit ) ;
}
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
for ( it = load . begin ( ) ; it ! = load . end ( ) ; it + + )
{
/* 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 ( ) ;
kit ! = rskv - > tlvkvs . pairs . end ( ) ; kit + + )
{
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
2013-10-06 08:56:37 -04:00
FileRequest ( rsft - > file . name , rsft - > file . hash , rsft - > file . filesize , rsft - > file . path , TransferRequestFlags ( rsft - > flags ) , rsft - > allPeerIds . ids , rsft - > state ) ;
2009-12-10 17:55:27 -05:00
{
RsStackMutex mtx ( ctrlMutex ) ;
2010-03-06 18:29:47 -05:00
std : : map < std : : string , 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
}
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 ( ) ;
}