- 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:
csoler 2010-07-27 16:05:21 +00:00
parent 8b3af9143f
commit 81203b3cfd
9 changed files with 220 additions and 245 deletions

View file

@ -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)

View file

@ -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 ;
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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