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
# include "util/rswin.h"
# 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"
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
2008-08-09 13:03:24 -04:00
# include "pqi/p3connmgr.h"
2009-03-19 08:49:11 -04:00
# include "pqi/pqinotify.h"
2008-07-23 18:01:59 -04:00
2008-11-15 15:00:29 -05:00
# include "serialiser/rsconfigitems.h"
2009-05-11 10:30:53 -04:00
# include <stdio.h>
2010-05-21 16:49:48 -04:00
# include <sstream>
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
* * * * */
2010-10-16 11:21:37 -04:00
# define CONTROL_DEBUG 1
2008-08-09 13:03:24 -04:00
2010-03-06 18:29:47 -05:00
static const uint32_t SAVE_TRANSFERS_DELAY = 61 ; // save transfer progress every 61 seconds.
static const uint32_t INACTIVE_CHUNKS_CHECK_DELAY = 60 ; // time after which an inactive chunk is released
static const uint32_t MAX_TIME_INACTIVE_REQUEUED = 60 ; // time after which an inactive ftFileControl is bt-queued
2009-12-10 17:55:27 -05:00
2010-09-15 15:48:13 -04:00
static const uint32_t FT_FILECONTROL_QUEUE_ADD_END = 0 ;
static const uint32_t FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE = 1 ;
2008-08-17 11:23:11 -04:00
ftFileControl : : ftFileControl ( )
2009-06-11 17:41:42 -04:00
: mTransfer ( NULL ) , mCreator ( NULL ) ,
2010-03-06 18:29:47 -05:00
mState ( DOWNLOADING ) , mSize ( 0 ) , mFlags ( 0 ) ,
2010-01-26 18:25:00 -05:00
mPriority ( SPEED_NORMAL )
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 ,
uint64_t size , std : : string hash , uint32_t 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 ) ,
2010-10-16 11:21:37 -04:00
mSize ( size ) , mFlags ( flags ) ,
2010-01-26 18:25:00 -05:00
mPriority ( SPEED_NORMAL ) // default priority to normal
2008-08-17 11:23:11 -04:00
{
return ;
}
2008-08-09 13:03:24 -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 ) ,
mFtActive ( false ) ,
mShareDownloadDir ( true )
2008-07-23 18:01:59 -04:00
{
2010-03-06 18:29:47 -05:00
_max_active_downloads = 5 ; // default queue size
2008-08-09 13:03:24 -04:00
/* TODO */
2008-07-23 18:01:59 -04:00
}
2009-05-26 17:42:45 -04:00
void ftController : : setTurtleRouter ( p3turtle * pt )
{
mTurtle = pt ;
}
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 ) ;
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 ;
2010-03-06 18:29:47 -05:00
info . flags = it - > second - > mFlags ;
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 ********/
2010-03-06 18:29:47 -05:00
std : : map < std : : string , ftFileControl * > : : iterator it ;
std : : map < std : : string , ftFileControl * > currentDownloads = * ( & mDownloads ) ;
2009-05-26 17:42:45 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController: Adding source " < < peer_id < < " to current download hash= " < < hash ;
# endif
for ( it = currentDownloads . begin ( ) ; it ! = currentDownloads . end ( ) ; it + + )
if ( it - > first = = hash )
{
2010-03-06 18:29:47 -05:00
it - > second - > mTransfer - > addFileSource ( peer_id ) ;
2009-05-26 17:42:45 -04:00
// setPeerState(it->second.mTransfer, peer_id, rate, mConnMgr->isOnline(peer_id));
# ifdef CONTROL_DEBUG
std : : cerr < < " ... added. " < < std : : endl ;
# endif
return ;
}
# 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 ********/
2010-03-06 18:29:47 -05:00
std : : map < std : : string , ftFileControl * > : : iterator it ;
std : : map < std : : string , ftFileControl * > currentDownloads = * ( & mDownloads ) ;
2009-06-03 14:47:14 -04:00
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController: Adding source " < < peer_id < < " to current download hash= " < < hash ;
# endif
for ( it = currentDownloads . begin ( ) ; it ! = currentDownloads . end ( ) ; it + + )
if ( it - > first = = hash )
{
2010-03-06 18:29:47 -05:00
it - > second - > mTransfer - > removeFileSource ( peer_id ) ;
2010-03-07 09:42:13 -05:00
it - > second - > mCreator - > removeFileSource ( peer_id ) ;
2009-05-26 17:42:45 -04:00
2009-06-03 14:47:14 -04:00
// setPeerState(it->second.mTransfer, peer_id, rate, mConnMgr->isOnline(peer_id));
# ifdef CONTROL_DEBUG
std : : cerr < < " ... added. " < < std : : endl ;
# endif
return ;
}
# 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 ;
2010-05-29 11:14:25 -04:00
while ( m_bRun )
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 ) ;
2010-01-11 11:00:42 -05:00
if ( ( int ) now - ( int ) last_save_time > ( int ) SAVE_TRANSFERS_DELAY )
2009-12-10 17:55:27 -05:00
{
2010-01-26 15:40:21 -05:00
cleanCacheDownloads ( ) ;
2009-12-10 17:55:27 -05:00
IndicateConfigChanged ( ) ;
last_save_time = now ;
}
2010-01-21 07:31:00 -05:00
if ( ( int ) now - ( int ) last_clean_time > ( int ) INACTIVE_CHUNKS_CHECK_DELAY )
{
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-01-26 15:40:21 -05:00
RsStackMutex stack2 ( doneMutex ) ;
2008-10-29 16:58:23 -04:00
2010-01-26 15:40:21 -05:00
for ( std : : list < std : : string > : : iterator it ( mDone . begin ( ) ) ; it ! = mDone . end ( ) ; it + + )
completeFile ( * it ) ;
mDone . clear ( ) ;
}
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
}
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
std : : vector < std : : vector < ftTransferModule * > > priority_tab ( 3 , std : : vector < ftTransferModule * > ( ) ) ;
2010-01-26 15:40:21 -05:00
2010-03-06 18:29:47 -05:00
// 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 )
2010-03-06 18:29:47 -05:00
priority_tab [ it - > second - > mPriority ] . push_back ( it - > second - > mTransfer ) ;
2010-01-26 15:40:21 -05:00
// 2 - tick arrays with a probability proportional to priority
// 2.1 - decide based on probability, which category of files we handle.
2010-03-06 18:29:47 -05:00
# ifdef CONTROL_DEBUG
2010-01-26 15:40:21 -05:00
std : : cerr < < " Priority tabs: " ;
2010-03-06 18:29:47 -05:00
std : : cerr < < " Low ( " < < priority_tab [ SPEED_LOW ] . size ( ) < < " ) " ;
std : : cerr < < " Normal ( " < < priority_tab [ SPEED_NORMAL ] . size ( ) < < " ) " ;
std : : cerr < < " High ( " < < priority_tab [ SPEED_HIGH ] . size ( ) < < " ) " ;
2010-01-26 15:40:21 -05:00
std : : cerr < < std : : endl ;
2010-03-06 18:29:47 -05:00
# endif
2010-01-26 15:40:21 -05:00
/* tick the transferModules */
// start anywhere in the chosen list of transfers, so that not to favor any special transfer
//
for ( int chosen = 2 ; chosen > = 0 ; - - chosen )
2010-03-06 18:29:47 -05:00
if ( ! priority_tab [ chosen ] . empty ( ) )
2010-01-26 15:40:21 -05:00
{
2010-03-06 18:29:47 -05:00
int start = rand ( ) % priority_tab [ chosen ] . size ( ) ;
2010-01-26 15:40:21 -05:00
2010-03-06 18:29:47 -05:00
for ( int i = 0 ; i < ( int ) priority_tab [ chosen ] . size ( ) ; + + i )
priority_tab [ chosen ] [ ( i + start ) % ( int ) priority_tab [ chosen ] . size ( ) ] - > 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 ( ) )
{
2010-03-06 18:29:47 -05:00
p = it - > second - > mPriority ;
2010-01-26 15:40:21 -05:00
return true ;
}
else
return false ;
}
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 ( ) )
2010-03-06 18:29:47 -05:00
it - > second - > mPriority = p ;
2010-01-26 15:40:21 -05:00
}
void ftController : : cleanCacheDownloads ( )
{
std : : vector < std : : string > toCancel ;
{
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 )
if ( ( it - > second ) - > mFlags & RS_FILE_HINTS_CACHE ) //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
{
# 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
2010-03-06 18:29:47 -05:00
if ( ( time ( NULL ) - ( it - > second ) - > mCreateTime ) > TIMOUT_CACHE_FILE_TRANSFER )
2010-01-26 15:40:21 -05:00
{
2009-05-06 16:48:32 -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
// - set the queue priority to 1+largest in the queue.
// 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
& & it - > second - > mState ! = ftFileControl : : PAUSED
2010-03-21 17:07:12 -04:00
& & 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
2010-03-06 18:29:47 -05:00
locked_bottomQueue ( it - > second - > mQueuePosition ) ;
# 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
}
}
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 )
{
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.
//
uint32_t pos = 0 ;
while ( pos < _queue . size ( ) & & ( _queue [ pos ] - > mFlags & RS_FILE_HINTS_CACHE ) > 0 )
+ + 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
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
if ( _queue [ pos ] - > mFlags & RS_FILE_HINTS_NETWORK_WIDE )
mTurtle - > monitorFileTunnels ( _queue [ pos ] - > mName , _queue [ pos ] - > mHash , _queue [ pos ] - > mSize ) ;
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
if ( _queue [ pos ] - > mFlags & RS_FILE_HINTS_NETWORK_WIDE )
mTurtle - > stopMonitoringFileTunnels ( _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 )
{
2009-03-23 10:45:51 -04:00
FILE * in = fopen ( source . c_str ( ) , " rb " ) ;
2009-03-19 08:49:11 -04:00
if ( in = = NULL )
{
getPqiNotify ( ) - > AddSysMessage ( 0 , RS_SYS_WARNING , " File copy error " , " Error while copying file " + dest + " \n Cannot open input file " + source ) ;
return false ;
}
2009-03-23 10:45:51 -04:00
FILE * out = 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 ) ;
2010-05-09 09:52:05 -04:00
return true ;
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-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 ;
uint32_t flags = 0 ;
2010-10-16 11:21:37 -04:00
uint32_t extraflags = 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
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 ;
//hash = fc->mHash;
size = fc - > mSize ;
state = fc - > mState ;
period = 30 * 24 * 3600 ; /* 30 days */
2010-10-16 11:21:37 -04:00
extraflags = 0 ;
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
2009-02-12 07:47:57 -05:00
mDataplex - > removeTransferModule ( hash_to_suppress ) ;
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 */
if ( ! ( fc - > mFlags & RS_FILE_HINTS_CACHE ) ) /* clean up completed cache files automatically */
mCompleted [ fc - > mHash ] = fc ;
else
delete fc ;
2009-02-12 07:47:57 -05:00
mDownloads . erase ( it ) ;
2009-06-14 15:34:22 -04:00
2010-10-16 11:21:37 -04:00
if ( flags & RS_FILE_HINTS_NETWORK_WIDE )
2010-01-22 18:23:37 -05:00
mTurtle - > stopMonitoringFileTunnels ( 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
if ( flags & ( RS_FILE_HINTS_CACHE | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_MEDIA ) )
2008-10-29 16:58:23 -04:00
{
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, callbackflags: " < < ( flags & ( RS_FILE_HINTS_CACHE | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_MEDIA ) ) ;
2008-11-04 18:12:53 -05:00
std : : cerr < < std : : endl ;
# endif
2010-10-16 11:21:37 -04:00
if ( flags & RS_FILE_HINTS_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 ) ;
}
}
if ( flags & RS_FILE_HINTS_EXTRA )
{
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
2010-10-16 11:21:37 -04:00
if ( flags & RS_FILE_HINTS_MEDIA )
{
2008-11-04 18:12:53 -05:00
# 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
2008-11-15 15:00:29 -05:00
IndicateConfigChanged ( ) ; /* completed transfer -> save */
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
}
/***************************************************************/
/********************** Controller Access **********************/
/***************************************************************/
2008-11-18 20:12:21 -05:00
const uint32_t FT_CNTRL_STANDARD_RATE = 1024 * 1024 ;
const uint32_t FT_CNTRL_SLOW_RATE = 10 * 1024 ;
2008-11-04 18:12:53 -05:00
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
2008-11-20 19:10:59 -05:00
FileRequest ( req . mName , req . mHash , req . mSize , req . mDest , req . mFlags , req . mSrcIds ) ;
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 ) ) ;
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
2010-05-29 09:17:09 -04:00
if ( mSearch - > search ( hash , RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE | 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 ,
uint64_t size , const std : : string & dest , uint32_t flags ,
const std : : list < std : : string > & _srcIds )
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.
2010-05-16 19:26:45 -04:00
# ifdef WINDOWS_SYS
std : : wstring destinationW ;
librs : : util : : ConvertUtf8ToUtf16 ( destination , destinationW ) ;
FILE * f = _wfopen ( destinationW . c_str ( ) , L " w " ) ;
# else
2010-03-06 18:29:47 -05:00
FILE * f = fopen ( destination . c_str ( ) , " w " ) ;
2010-05-16 19:26:45 -04:00
# endif
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 */
ftPendingRequest req ( fname , hash , size , dest , flags , srcIds ) ;
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-13 18:03:46 -05:00
std : : string ownId = mConnMgr - > getOwnId ( ) ;
2008-11-09 17:17:20 -05:00
uint32_t rate = 0 ;
if ( flags & RS_FILE_HINTS_BACKGROUND )
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 ) ;
setPeerState ( dit - > second - > mTransfer , * it , rate , mConnMgr - > 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
2010-10-16 11:21:37 -04:00
if ( ! ( flags & RS_FILE_HINTS_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
//
if ( ( ! ( flags & RS_FILE_HINTS_NETWORK_WIDE ) ) & & 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
2008-10-29 16:58:23 -04:00
2010-01-11 17:38:18 -05:00
if ( srcIds . end ( ) = = std : : find ( srcIds . begin ( ) , srcIds . end ( ) , 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
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
}
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-01-11 17:38:18 -05:00
// We check that flags are consistent. In particular, for know
// we can't send chunkmaps through normal traffic, so availability must be assumed whenever the traffic is not
// a turtle traffic:
if ( flags & RS_FILE_HINTS_NETWORK_WIDE )
mTurtle - > monitorFileTunnels ( fname , hash , size ) ;
2010-03-06 18:29:47 -05:00
ftFileCreator * fc = new ftFileCreator ( savepath , size , hash ) ;
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
2008-11-13 18:03:46 -05:00
setPeerState ( tm , * it , rate , mConnMgr - > 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 ********/
2010-09-15 15:48:13 -04:00
locked_addToQueue ( ftfc , ( flags & RS_FILE_HINTS_CACHE ) ? FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE : 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
{
if ( id = = mConnMgr - > getOwnId ( ) )
{
# 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
{
2010-01-11 17:38:18 -05:00
rsTurtle - > stopMonitoringFileTunnels ( hash ) ;
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-03-15 08:57:08 -04:00
//#ifdef CONTROL_DEBUG
2008-09-08 04:44:37 -04:00
std : : cerr < < " ftController::FileControl( " < < hash < < " , " ;
std : : cerr < < flags < < " ) " < < std : : endl ;
2010-03-15 08:57:08 -04:00
//#endif
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->mState = ftFileControl::CHECKING_HASH ;
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 ;
}
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-03-06 18:29:47 -05:00
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
for ( std : : map < std : : string , ftFileControl * > : : iterator it ( mCompleted . begin ( ) ) ; it ! = mCompleted . end ( ) ; + + it )
delete it - > second ;
2010-02-19 15:36:47 -05:00
mCompleted . clear ( ) ;
2010-03-06 18:29:47 -05:00
2010-02-19 15:36:47 -05:00
IndicateConfigChanged ( ) ;
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 ********/
mDownloadPath = path ;
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 ) ;
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
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
}
bool ftController : : FileDetails ( std : : string hash , FileInfo & info )
{
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 ;
info . flags = it - > second - > mFlags ;
info . path = RsDirUtil : : removeTopDir ( it - > second - > mDestination ) ; /* remove fname */
info . priority = it - > second - > mPriority ;
info . queue_position = it - > second - > mQueuePosition ;
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 )
2010-03-06 18:29:47 -05:00
it - > second - > mTransfer - > getFileSources ( peerIds ) ;
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 ;
2009-05-26 17:42:45 -04:00
std : : list < pqipeer > vlist ;
mTurtle - > getVirtualPeersList ( vlist ) ;
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 + + )
{
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.
//
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
}
2010-01-26 15:40:21 -05:00
FileRequest ( hash , hash , size , path , RS_FILE_HINTS_CACHE | RS_FILE_HINTS_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 )
{
# ifdef CONTROL_DEBUG
std : : cerr < < " ftController::CancelCacheFile( " < < id < < " , " ;
std : : cerr < < path < < " , " < < hash < < " , " < < size < < " ) " ;
std : : cerr < < std : : endl ;
# endif
2008-10-29 16:58:23 -04:00
return true ;
2008-08-17 11:23:11 -04:00
}
2008-11-15 15:00:29 -05:00
const std : : string download_dir_ss ( " DOWN_DIR " ) ;
const std : : string partial_dir_ss ( " PART_DIR " ) ;
2009-07-12 09:22:31 -04:00
const std : : string share_dwl_dir ( " SHARE_DWL_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 ;
}
std : : list < RsItem * > ftController : : saveList ( bool & cleanup )
{
std : : list < RsItem * > saveData ;
/* 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 */
configMap [ download_dir_ss ] = getDownloadDirectory ( ) ;
configMap [ partial_dir_ss ] = getPartialsDirectory ( ) ;
2009-07-12 09:22:31 -04:00
configMap [ share_dwl_dir ] = mShareDownloadDir ? " YES " : " NO " ;
2010-03-21 17:07:12 -04:00
configMap [ default_chunk_strategy_ss ] = ( mDefaultChunkStrategy = = FileChunksInfo : : CHUNK_STRATEGY_STREAMING ) ? " STREAMING " : " RANDOM " ;
2008-11-15 15:00:29 -05:00
2010-05-21 16:49:48 -04:00
std : : ostringstream s ;
s < < RsDiscSpace : : freeSpaceLimit ( ) ;
configMap [ free_space_limit_ss ] = s . str ( ) ;
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.*/
if ( fit - > second - > mFlags & RS_FILE_HINTS_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
2010-03-06 18:29:47 -05:00
if ( ( fit - > second ) - > mCreator - > finished ( ) )
2008-11-15 15:00:29 -05:00
continue ;
/* 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 ;
rft - > file . path = RsDirUtil : : removeTopDir ( fit - > second - > mDestination ) ; /* remove fname */
rft - > flags = fit - > second - > mFlags ;
rft - > state = fit - > second - > mState ;
fit - > second - > mTransfer - > getFileSources ( rft - > allPeerIds . ids ) ;
2010-01-11 11:00:42 -05:00
2010-02-13 15:42:49 -05:00
// just avoid uninitialised memory reads
rft - > in = 0 ;
rft - > cPeerId = " " ;
2010-03-06 18:29:47 -05:00
rft - > transferred = fit - > second - > mCreator - > getRecvd ( ) ;
2010-02-13 15:42:49 -05:00
rft - > crate = 0 ;
rft - > lrate = 0 ;
rft - > trate = 0 ;
rft - > ltransfer = 0 ;
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 ) ;
}
/* list completed! */
return saveData ;
}
bool ftController : : loadList ( std : : list < RsItem * > load )
{
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
*/
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
2010-01-22 18:23:37 -05:00
FileRequest ( rsft - > file . name , rsft - > file . hash , rsft - > file . filesize , rsft - > file . path , rsft - > flags , rsft - > allPeerIds . ids ) ;
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 ;
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 ) ;
}
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
}
2009-07-12 09:22:31 -04:00
if ( configMap . end ( ) ! = ( mit = configMap . find ( share_dwl_dir ) ) )
{
if ( mit - > second = = " YES " )
{
setShareDownloadDirectory ( true ) ;
}
else if ( mit - > second = = " NO " )
{
setShareDownloadDirectory ( false ) ;
}
}
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 ;
}
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 ) ) )
{
std : : istringstream in ( mit - > second ) ;
uint32_t size ;
in > > size ;
std : : cerr < < " have read a size limit of " < < size < < " MB " < < std : : endl ;
RsDiscSpace : : setFreeSpaceLimit ( size ) ;
}
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 ( ) ;
}
2009-07-12 09:22:31 -04:00
void ftController : : setShareDownloadDirectory ( bool value )
{
2010-03-21 17:07:12 -04:00
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2009-07-12 09:22:31 -04:00
mShareDownloadDir = value ;
2010-03-21 17:07:12 -04:00
IndicateConfigChanged ( ) ;
2009-07-12 09:22:31 -04:00
}
bool ftController : : getShareDownloadDirectory ( )
{
2010-03-21 17:07:12 -04:00
RsStackMutex stack ( ctrlMutex ) ; /******* LOCKED ********/
2009-07-12 09:22:31 -04:00
return mShareDownloadDir ;
}
2010-03-21 17:07:12 -04:00