mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-17 05:22:31 -04:00
- modified ftFileProvider so as to keep multiple client peers per instance
- updated TransfersDialog to display this info correctly git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3316 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
8b3af9143f
commit
81203b3cfd
9 changed files with 220 additions and 245 deletions
|
@ -684,10 +684,8 @@ bool ftDataMultiplex::locked_handleServerRequest(ftFileProvider *provider,
|
|||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if (provider->getFileData(offset, chunksize, data))
|
||||
if (provider->getFileData(peerId,offset, chunksize, data))
|
||||
{
|
||||
// setup info
|
||||
provider->setPeerId(peerId) ;
|
||||
/* send data out */
|
||||
sendData(peerId, hash, size, offset, chunksize, data);
|
||||
return true;
|
||||
|
@ -738,26 +736,26 @@ void ftDataMultiplex::deleteUnusedServers()
|
|||
|
||||
//scan the uploads list in ftdatamultiplex and delete the items which time out
|
||||
time_t now = time(NULL);
|
||||
|
||||
|
||||
for(std::map<std::string, ftFileProvider *>::iterator sit(mServers.begin());sit != mServers.end();)
|
||||
if ((now - sit->second->lastTS) > 10)
|
||||
{
|
||||
if(sit->second->purgeOldPeers(now,10))
|
||||
{
|
||||
#ifdef SERVER_DEBUG
|
||||
std::cout << "info.lastTS = " << info.lastTS << ", now=" << now << std::endl ;
|
||||
std::cout << "info.lastTS = " << info.lastTS << ", now=" << now << std::endl ;
|
||||
#endif
|
||||
// We don't delete servers that are clients at the same time !
|
||||
if(dynamic_cast<ftFileCreator*>(sit->second) == NULL)
|
||||
delete sit->second;
|
||||
// We don't delete servers that are clients at the same time !
|
||||
if(dynamic_cast<ftFileCreator*>(sit->second) == NULL)
|
||||
delete sit->second;
|
||||
|
||||
std::map<std::string, ftFileProvider *>::iterator tmp(sit);
|
||||
++tmp ;
|
||||
std::map<std::string, ftFileProvider *>::iterator tmp(sit);
|
||||
++tmp ;
|
||||
|
||||
mServers.erase(sit);
|
||||
mServers.erase(sit);
|
||||
|
||||
sit = tmp ;
|
||||
}
|
||||
else
|
||||
++sit ;
|
||||
sit = tmp ;
|
||||
}
|
||||
else
|
||||
++sit ;
|
||||
}
|
||||
|
||||
bool ftDataMultiplex::handleSearchRequest(const std::string& peerId, const std::string& hash)
|
||||
|
|
|
@ -38,7 +38,7 @@ ftFileCreator::ftFileCreator(std::string path, uint64_t size, std::string hash)
|
|||
_last_recv_time_t = time(NULL) ;
|
||||
}
|
||||
|
||||
bool ftFileCreator::getFileData(uint64_t offset, uint32_t &chunk_size, void *data)
|
||||
bool ftFileCreator::getFileData(const std::string& peer_id,uint64_t offset, uint32_t &chunk_size, void *data)
|
||||
{
|
||||
// Only send the data if we actually have it.
|
||||
//
|
||||
|
@ -50,7 +50,7 @@ bool ftFileCreator::getFileData(uint64_t offset, uint32_t &chunk_size, void *dat
|
|||
}
|
||||
|
||||
if(have_it)
|
||||
return ftFileProvider::getFileData(offset, chunk_size, data);
|
||||
return ftFileProvider::getFileData(peer_id,offset, chunk_size, data);
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class ftFileCreator: public ftFileProvider
|
|||
~ftFileCreator();
|
||||
|
||||
/* overloaded from FileProvider */
|
||||
virtual bool getFileData(uint64_t offset, uint32_t &chunk_size, void *data);
|
||||
virtual bool getFileData(const std::string& peer_id,uint64_t offset, uint32_t &chunk_size, void *data);
|
||||
bool finished() ;
|
||||
uint64_t getRecvd();
|
||||
|
||||
|
|
|
@ -10,18 +10,16 @@
|
|||
#endif // WINDOWS_SYS
|
||||
|
||||
|
||||
static const time_t UPLOAD_CHUNK_MAPS_TIME = 30 ; // time to ask for a new chunkmap from uploaders in seconds.
|
||||
static const time_t UPLOAD_CHUNK_MAPS_TIME = 20 ; // time to ask for a new chunkmap from uploaders in seconds.
|
||||
|
||||
ftFileProvider::ftFileProvider(std::string path, uint64_t size, std::string
|
||||
hash) : mSize(size), hash(hash), file_name(path), fd(NULL),req_loc(0),transfer_rate(0),total_size(0)
|
||||
ftFileProvider::ftFileProvider(std::string path, uint64_t size, std::string hash)
|
||||
: mSize(size), hash(hash), file_name(path), fd(NULL)
|
||||
{
|
||||
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
||||
clients_chunk_maps.clear();
|
||||
|
||||
#ifdef DEBUG_FT_FILE_PROVIDER
|
||||
std::cout << "Creating file provider for " << hash << std::endl ;
|
||||
#endif
|
||||
lastTS = time(NULL) ;
|
||||
lastTS_t = lastTS ;
|
||||
}
|
||||
|
||||
ftFileProvider::~ftFileProvider(){
|
||||
|
@ -34,15 +32,9 @@ ftFileProvider::~ftFileProvider(){
|
|||
}
|
||||
}
|
||||
|
||||
void ftFileProvider::setPeerId(const std::string& id)
|
||||
{
|
||||
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
||||
lastRequestor = id ;
|
||||
}
|
||||
|
||||
bool ftFileProvider::fileOk()
|
||||
{
|
||||
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
||||
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
||||
return (fd != NULL);
|
||||
}
|
||||
|
||||
|
@ -65,25 +57,54 @@ bool ftFileProvider::FileDetails(FileInfo &info)
|
|||
info.size = mSize;
|
||||
info.path = file_name;
|
||||
info.fname = RsDirUtil::getTopDir(file_name);
|
||||
info.transfered = req_loc ;
|
||||
info.lastTS = lastTS;
|
||||
|
||||
info.transfered = 0 ; // unused
|
||||
info.lastTS = 0;
|
||||
info.status = FT_STATE_DOWNLOADING ;
|
||||
|
||||
info.peers.clear() ;
|
||||
float total_transfer_rate = 0.0f ;
|
||||
|
||||
TransferInfo inf ;
|
||||
inf.peerId = lastRequestor ;
|
||||
inf.status = FT_STATE_DOWNLOADING ;
|
||||
for(std::map<std::string,PeerUploadInfo>::const_iterator it(uploading_peers.begin());it!=uploading_peers.end();++it)
|
||||
{
|
||||
TransferInfo inf ;
|
||||
inf.peerId = it->first ;
|
||||
inf.status = FT_STATE_DOWNLOADING ;
|
||||
inf.name = info.fname ;
|
||||
inf.transfered = it->second.req_loc ;
|
||||
|
||||
inf.tfRate = transfer_rate/1024.0 ;
|
||||
info.tfRate = transfer_rate/1024.0 ;
|
||||
info.peers.push_back(inf) ;
|
||||
inf.tfRate = it->second.transfer_rate/1024.0 ;
|
||||
total_transfer_rate += it->second.transfer_rate ;
|
||||
info.lastTS = std::max(info.lastTS,it->second.lastTS);
|
||||
|
||||
info.peers.push_back(inf) ;
|
||||
}
|
||||
info.tfRate = total_transfer_rate/1024.0 ;
|
||||
|
||||
/* Use req_loc / req_size to estimate data rate */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftFileProvider::purgeOldPeers(time_t now,uint32_t max_duration)
|
||||
{
|
||||
bool ret = true ;
|
||||
for(std::map<std::string,PeerUploadInfo>::iterator it(uploading_peers.begin());it!=uploading_peers.end();)
|
||||
if( (*it).second.lastTS+max_duration < (uint32_t)now)
|
||||
{
|
||||
std::map<std::string,PeerUploadInfo>::iterator tmp = it ;
|
||||
++tmp ;
|
||||
uploading_peers.erase(it) ;
|
||||
it=tmp ;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = false ;
|
||||
++it ;
|
||||
}
|
||||
return ret ;
|
||||
}
|
||||
|
||||
void ftFileProvider::getAvailabilityMap(CompressedChunkMap& cmap)
|
||||
{
|
||||
// We are here because the file we deal with is complete. So we return a plain map.
|
||||
|
@ -92,7 +113,7 @@ void ftFileProvider::getAvailabilityMap(CompressedChunkMap& cmap)
|
|||
}
|
||||
|
||||
|
||||
bool ftFileProvider::getFileData(uint64_t offset, uint32_t &chunk_size, void *data)
|
||||
bool ftFileProvider::getFileData(const std::string& peer_id,uint64_t offset, uint32_t &chunk_size, void *data)
|
||||
{
|
||||
/* dodgey checking outside of mutex...
|
||||
* much check again inside FileAttrs().
|
||||
|
@ -158,67 +179,69 @@ bool ftFileProvider::getFileData(uint64_t offset, uint32_t &chunk_size, void *da
|
|||
* (d) timestamp
|
||||
*/
|
||||
|
||||
time_t now_t = time(NULL) ;
|
||||
|
||||
long int diff = (long int)now_t - (long int)lastTS_t ; // in bytes/s. Average over multiple samples
|
||||
|
||||
#ifdef DEBUG_FT_FILE_PROVIDER
|
||||
std::cout << "diff = " << diff << std::endl ;
|
||||
#endif
|
||||
|
||||
if(diff > 3)
|
||||
{
|
||||
transfer_rate = total_size / (float)diff ;
|
||||
#ifdef DEBUG_FT_FILE_PROVIDER
|
||||
std::cout << "updated TR = " << transfer_rate << ", total_size=" << total_size << std::endl ;
|
||||
#endif
|
||||
lastTS_t = now_t ;
|
||||
total_size = 0 ;
|
||||
}
|
||||
|
||||
req_loc = offset;
|
||||
lastTS = time(NULL) ;
|
||||
req_size = data_size;
|
||||
total_size += req_size ;
|
||||
// This creates the peer info, and updates it.
|
||||
//
|
||||
time_t now = time(NULL) ;
|
||||
uploading_peers[peer_id].updateStatus(offset,data_size,now) ;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
std::cerr << "No data to read" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ftFileProvider::PeerUploadInfo::updateStatus(uint64_t offset,uint32_t data_size,time_t now)
|
||||
{
|
||||
lastTS = now ;
|
||||
long int diff = (long int)now - (long int)lastTS_t ; // in bytes/s. Average over multiple samples
|
||||
|
||||
#ifdef DEBUG_FT_FILE_PROVIDER
|
||||
std::cout << "diff = " << diff << std::endl ;
|
||||
#endif
|
||||
|
||||
if(diff > 3)
|
||||
{
|
||||
transfer_rate = total_size / (float)diff ;
|
||||
#ifdef DEBUG_FT_FILE_PROVIDER
|
||||
std::cout << "updated TR = " << transfer_rate << ", total_size=" << total_size << std::endl ;
|
||||
#endif
|
||||
lastTS_t = now ;
|
||||
total_size = 0 ;
|
||||
}
|
||||
|
||||
req_loc = offset;
|
||||
req_size = data_size;
|
||||
total_size += req_size ;
|
||||
}
|
||||
|
||||
void ftFileProvider::setClientMap(const std::string& peer_id,const CompressedChunkMap& cmap)
|
||||
{
|
||||
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::pair<CompressedChunkMap,time_t>& map_info(clients_chunk_maps[peer_id]) ;
|
||||
|
||||
map_info.first = cmap ;
|
||||
map_info.second = time(NULL) ;
|
||||
// Create by default.
|
||||
uploading_peers[peer_id].client_chunk_map = cmap ;
|
||||
uploading_peers[peer_id].client_chunk_map_stamp = time(NULL) ;
|
||||
}
|
||||
|
||||
void ftFileProvider::getClientMap(const std::string& peer_id,CompressedChunkMap& cmap,bool& map_is_too_old)
|
||||
{
|
||||
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<std::string,std::pair<CompressedChunkMap,time_t> >::iterator it(clients_chunk_maps.find(peer_id)) ;
|
||||
|
||||
if(it == clients_chunk_maps.end())
|
||||
{
|
||||
clients_chunk_maps[peer_id] = std::pair<CompressedChunkMap,time_t>(CompressedChunkMap(),0) ;
|
||||
it = clients_chunk_maps.find(peer_id) ;
|
||||
}
|
||||
|
||||
if(time(NULL) - it->second.second > UPLOAD_CHUNK_MAPS_TIME)
|
||||
PeerUploadInfo& pui(uploading_peers[peer_id]) ;
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
if(now - pui.client_chunk_map_stamp > UPLOAD_CHUNK_MAPS_TIME)
|
||||
{
|
||||
map_is_too_old = true ;
|
||||
it->second.second = time(NULL) ; // to avoid re-asking before the TTL
|
||||
pui.client_chunk_map_stamp = now ; // to avoid re-asking before the TTL
|
||||
}
|
||||
else
|
||||
map_is_too_old = false ;
|
||||
|
||||
cmap = it->second.first ;
|
||||
cmap = pui.client_chunk_map;
|
||||
}
|
||||
|
||||
int ftFileProvider::initializeFileAttrs()
|
||||
|
@ -273,23 +296,6 @@ int ftFileProvider::initializeFileAttrs()
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if it opened, find it's length
|
||||
* move to the end
|
||||
*/
|
||||
|
||||
// if (0 != fseeko64(fd, 0L, SEEK_END))
|
||||
// {
|
||||
// std::cerr << "ftFileProvider::initializeFileAttrs() Seek Failed" << std::endl;
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// uint64_t recvdsize = ftello64(fd);
|
||||
//
|
||||
//#ifdef DEBUG_FT_FILE_PROVIDER
|
||||
// std::cerr << "ftFileProvider::initializeFileAttrs() File Expected Size: " << mSize << " RecvdSize: " << recvdsize << std::endl;
|
||||
//#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,14 +41,12 @@ class ftFileProvider
|
|||
ftFileProvider(std::string path, uint64_t size, std::string hash);
|
||||
virtual ~ftFileProvider();
|
||||
|
||||
virtual bool getFileData(uint64_t offset, uint32_t &chunk_size, void *data);
|
||||
virtual bool getFileData(const std::string& peer_id,uint64_t offset, uint32_t &chunk_size, void *data);
|
||||
virtual bool FileDetails(FileInfo &info);
|
||||
std::string getHash();
|
||||
uint64_t getFileSize();
|
||||
bool fileOk();
|
||||
|
||||
void setPeerId(const std::string& id) ;
|
||||
|
||||
// Provides a client for the map of chunks actually present in the file. If the provider is also
|
||||
// a file creator, because the file is actually being downloaded, then the map may be partially complete.
|
||||
// Otherwize, a plain map is returned.
|
||||
|
@ -65,7 +63,9 @@ class ftFileProvider
|
|||
void getClientMap(const std::string& peer_id,CompressedChunkMap& cmap,bool& map_is_too_old) ;
|
||||
void setClientMap(const std::string& peer_id,const CompressedChunkMap& cmap) ;
|
||||
|
||||
time_t lastTS; // used for checking if it's alive
|
||||
// Removes inactive peers from the client list. Returns true if all peers have been removed.
|
||||
//
|
||||
bool purgeOldPeers(time_t now,uint32_t max_duration) ;
|
||||
protected:
|
||||
virtual int initializeFileAttrs(); /* does for both */
|
||||
|
||||
|
@ -78,17 +78,31 @@ class ftFileProvider
|
|||
* Structure to gather statistics FIXME: lastRequestor - figure out a
|
||||
* way to get last requestor (peerID)
|
||||
*/
|
||||
std::string lastRequestor;
|
||||
uint64_t req_loc;
|
||||
uint32_t req_size;
|
||||
time_t lastTS_t; // used for estimating transfer rate.
|
||||
class PeerUploadInfo
|
||||
{
|
||||
public:
|
||||
PeerUploadInfo()
|
||||
: req_loc(0),req_size(1), lastTS_t(0), transfer_rate(0), total_size(0), client_chunk_map_stamp(0) {}
|
||||
|
||||
// these two are used for speed estimation
|
||||
float transfer_rate ;
|
||||
uint32_t total_size ;
|
||||
void updateStatus(uint64_t offset,uint32_t data_size,time_t now) ;
|
||||
|
||||
// Info about what the downloading peer already has
|
||||
std::map<std::string,std::pair<CompressedChunkMap,time_t> > clients_chunk_maps ;
|
||||
uint64_t req_loc;
|
||||
uint32_t req_size;
|
||||
time_t lastTS_t; // used for estimating transfer rate.
|
||||
time_t lastTS; // last update time (for purging)
|
||||
|
||||
// these two are used for speed estimation
|
||||
float transfer_rate ;
|
||||
uint32_t total_size ;
|
||||
|
||||
// Info about what the downloading peer already has
|
||||
CompressedChunkMap client_chunk_map ;
|
||||
time_t client_chunk_map_stamp ;
|
||||
};
|
||||
|
||||
// Contains statistics (speed, peer name, etc.) of all uploading peers for that file.
|
||||
//
|
||||
std::map<std::string,PeerUploadInfo> uploading_peers ;
|
||||
|
||||
/*
|
||||
* Mutex Required for stuff below
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue