2008-07-01 22:36:39 -04:00
|
|
|
#include "ftfileprovider.h"
|
2010-01-11 11:00:42 -05:00
|
|
|
#include "ftchunkmap.h"
|
2008-07-01 22:36:39 -04:00
|
|
|
|
2008-08-09 13:03:24 -04:00
|
|
|
#include "util/rsdir.h"
|
2008-11-02 08:53:17 -05:00
|
|
|
#include <stdlib.h>
|
2009-05-11 10:30:53 -04:00
|
|
|
#include <stdio.h>
|
2008-08-09 13:03:24 -04:00
|
|
|
|
2010-05-16 19:26:45 -04:00
|
|
|
#ifdef WINDOWS_SYS
|
|
|
|
#include "util/rswin.h"
|
|
|
|
#endif // WINDOWS_SYS
|
|
|
|
|
|
|
|
|
2010-01-11 11:00:42 -05:00
|
|
|
static const time_t UPLOAD_CHUNK_MAPS_TIME = 30 ; // time to ask for a new chunkmap from uploaders in seconds.
|
|
|
|
|
2008-07-01 22:36:39 -04:00
|
|
|
ftFileProvider::ftFileProvider(std::string path, uint64_t size, std::string
|
2010-06-06 21:47:15 -04:00
|
|
|
hash) : mSize(size), hash(hash), file_name(path), fd(NULL),req_loc(0),transfer_rate(0),total_size(0)
|
2008-10-22 14:12:58 -04:00
|
|
|
{
|
2010-02-15 13:03:27 -05:00
|
|
|
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
2010-01-26 15:40:21 -05:00
|
|
|
clients_chunk_maps.clear();
|
2009-02-08 08:04:32 -05:00
|
|
|
#ifdef DEBUG_FT_FILE_PROVIDER
|
2009-02-06 15:42:01 -05:00
|
|
|
std::cout << "Creating file provider for " << hash << std::endl ;
|
2009-02-08 08:04:32 -05:00
|
|
|
#endif
|
2009-02-04 19:01:51 -05:00
|
|
|
lastTS = time(NULL) ;
|
2009-02-08 08:04:32 -05:00
|
|
|
lastTS_t = lastTS ;
|
2008-07-01 22:36:39 -04:00
|
|
|
}
|
2008-07-02 00:05:58 -04:00
|
|
|
|
2008-07-01 22:36:39 -04:00
|
|
|
ftFileProvider::~ftFileProvider(){
|
2009-02-08 08:04:32 -05:00
|
|
|
#ifdef DEBUG_FT_FILE_PROVIDER
|
2009-02-06 15:42:01 -05:00
|
|
|
std::cout << "Destroying file provider for " << hash << std::endl ;
|
2009-02-08 08:04:32 -05:00
|
|
|
#endif
|
2008-07-01 22:36:39 -04:00
|
|
|
if (fd!=NULL) {
|
|
|
|
fclose(fd);
|
2010-03-28 16:46:45 -04:00
|
|
|
fd = NULL ;
|
2008-07-01 22:36:39 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-04 16:35:39 -05:00
|
|
|
void ftFileProvider::setPeerId(const std::string& id)
|
|
|
|
{
|
|
|
|
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
|
|
|
lastRequestor = id ;
|
|
|
|
}
|
|
|
|
|
2008-10-22 14:12:58 -04:00
|
|
|
bool ftFileProvider::fileOk()
|
|
|
|
{
|
|
|
|
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
|
|
|
return (fd != NULL);
|
|
|
|
}
|
|
|
|
|
2008-08-03 08:45:53 -04:00
|
|
|
std::string ftFileProvider::getHash()
|
|
|
|
{
|
2008-10-22 14:12:58 -04:00
|
|
|
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
2008-08-03 08:45:53 -04:00
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t ftFileProvider::getFileSize()
|
|
|
|
{
|
2008-10-22 14:12:58 -04:00
|
|
|
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
|
|
|
return mSize;
|
2008-08-03 08:45:53 -04:00
|
|
|
}
|
|
|
|
|
2008-08-09 13:03:24 -04:00
|
|
|
bool ftFileProvider::FileDetails(FileInfo &info)
|
|
|
|
{
|
2009-02-04 16:35:39 -05:00
|
|
|
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
2008-08-09 13:03:24 -04:00
|
|
|
info.hash = hash;
|
2008-10-22 14:12:58 -04:00
|
|
|
info.size = mSize;
|
2008-08-09 13:03:24 -04:00
|
|
|
info.path = file_name;
|
|
|
|
info.fname = RsDirUtil::getTopDir(file_name);
|
2009-02-04 16:35:39 -05:00
|
|
|
info.transfered = req_loc ;
|
2009-02-04 19:01:51 -05:00
|
|
|
info.lastTS = lastTS;
|
2009-02-04 16:35:39 -05:00
|
|
|
info.status = FT_STATE_DOWNLOADING ;
|
|
|
|
|
|
|
|
info.peers.clear() ;
|
|
|
|
|
|
|
|
TransferInfo inf ;
|
|
|
|
inf.peerId = lastRequestor ;
|
|
|
|
inf.status = FT_STATE_DOWNLOADING ;
|
2009-02-04 19:01:51 -05:00
|
|
|
|
|
|
|
inf.tfRate = transfer_rate/1024.0 ;
|
|
|
|
info.tfRate = transfer_rate/1024.0 ;
|
2009-02-04 16:35:39 -05:00
|
|
|
info.peers.push_back(inf) ;
|
|
|
|
|
2008-08-09 13:03:24 -04:00
|
|
|
/* Use req_loc / req_size to estimate data rate */
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-11 11:00:42 -05:00
|
|
|
void ftFileProvider::getAvailabilityMap(CompressedChunkMap& cmap)
|
|
|
|
{
|
|
|
|
// We are here because the file we deal with is complete. So we return a plain map.
|
|
|
|
//
|
|
|
|
ChunkMap::buildPlainMap(mSize,cmap) ;
|
|
|
|
}
|
|
|
|
|
2008-08-09 13:03:24 -04:00
|
|
|
|
2008-11-20 17:59:58 -05:00
|
|
|
bool ftFileProvider::getFileData(uint64_t offset, uint32_t &chunk_size, void *data)
|
2008-07-01 22:36:39 -04:00
|
|
|
{
|
2008-10-22 14:12:58 -04:00
|
|
|
/* dodgey checking outside of mutex...
|
|
|
|
* much check again inside FileAttrs().
|
|
|
|
*/
|
|
|
|
if (fd == NULL)
|
|
|
|
if (!initializeFileAttrs())
|
|
|
|
return false;
|
|
|
|
|
2009-02-04 16:35:39 -05:00
|
|
|
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
2008-10-22 14:12:58 -04:00
|
|
|
|
2008-07-02 00:05:58 -04:00
|
|
|
/*
|
|
|
|
* FIXME: Warning of comparison between unsigned and signed int?
|
|
|
|
*/
|
2008-11-13 18:03:46 -05:00
|
|
|
|
|
|
|
uint32_t data_size = chunk_size;
|
|
|
|
uint64_t base_loc = offset;
|
2008-07-01 22:36:39 -04:00
|
|
|
|
2008-10-22 14:12:58 -04:00
|
|
|
if (base_loc + data_size > mSize)
|
2008-07-01 22:36:39 -04:00
|
|
|
{
|
2008-10-22 14:12:58 -04:00
|
|
|
data_size = mSize - base_loc;
|
2008-11-20 17:59:58 -05:00
|
|
|
chunk_size = mSize - base_loc;
|
2008-07-01 22:36:39 -04:00
|
|
|
std::cerr <<"Chunk Size greater than total file size, adjusting chunk size " << data_size << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data_size > 0)
|
2009-07-27 16:31:56 -04:00
|
|
|
{
|
|
|
|
if(data == NULL)
|
|
|
|
{
|
|
|
|
std::cerr << "ftFileProvider: Warning ! Re-allocating data, which probably could not be allocated because of weird chunk size." << std::endl ;
|
|
|
|
if(NULL == (data = malloc(data_size)))
|
|
|
|
{
|
|
|
|
std::cerr << "ftFileProvider: Could not malloc a size of " << data_size << std::endl ;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2008-07-02 00:05:58 -04:00
|
|
|
/*
|
|
|
|
* seek for base_loc
|
|
|
|
*/
|
2009-08-29 14:55:13 -04:00
|
|
|
fseeko64(fd, base_loc, SEEK_SET);
|
2008-07-01 22:36:39 -04:00
|
|
|
|
2008-10-29 16:58:23 -04:00
|
|
|
// Data space allocated by caller.
|
|
|
|
//void *data = malloc(chunk_size);
|
2008-07-02 00:05:58 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* read the data
|
|
|
|
*/
|
|
|
|
|
2008-07-01 22:36:39 -04:00
|
|
|
if (1 != fread(data, data_size, 1, fd))
|
|
|
|
{
|
2010-02-08 09:06:43 -05:00
|
|
|
#ifdef DEBUG_FT_FILE_PROVIDER
|
|
|
|
std::cerr << "ftFileProvider::getFileData() Failed to get data. Data_size=" << data_size << ", base_loc=" << base_loc << " !" << std::endl;
|
|
|
|
#endif
|
2009-08-09 11:55:31 -04:00
|
|
|
//free(data); No!! It's already freed upwards in ftDataMultiplex::locked_handleServerRequest()
|
2008-07-01 22:36:39 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-07-02 00:05:58 -04:00
|
|
|
/*
|
|
|
|
* Update status of ftFileStatus to reflect last usage (for GUI display)
|
2008-07-01 22:36:39 -04:00
|
|
|
* We need to store.
|
|
|
|
* (a) Id,
|
|
|
|
* (b) Offset,
|
|
|
|
* (c) Size,
|
|
|
|
* (d) timestamp
|
|
|
|
*/
|
|
|
|
|
2009-02-08 08:04:32 -05:00
|
|
|
time_t now_t = time(NULL) ;
|
2009-02-06 15:42:01 -05:00
|
|
|
|
|
|
|
long int diff = (long int)now_t - (long int)lastTS_t ; // in bytes/s. Average over multiple samples
|
|
|
|
|
2009-02-08 08:04:32 -05:00
|
|
|
#ifdef DEBUG_FT_FILE_PROVIDER
|
2009-02-06 15:42:01 -05:00
|
|
|
std::cout << "diff = " << diff << std::endl ;
|
2009-02-08 08:04:32 -05:00
|
|
|
#endif
|
2009-02-06 15:42:01 -05:00
|
|
|
|
2009-02-08 08:04:32 -05:00
|
|
|
if(diff > 3)
|
2009-02-06 15:42:01 -05:00
|
|
|
{
|
2009-02-08 08:04:32 -05:00
|
|
|
transfer_rate = total_size / (float)diff ;
|
2009-02-06 15:42:01 -05:00
|
|
|
#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 ;
|
|
|
|
}
|
|
|
|
|
2008-07-01 22:36:39 -04:00
|
|
|
req_loc = offset;
|
2009-02-06 15:42:01 -05:00
|
|
|
lastTS = time(NULL) ;
|
2008-07-01 22:36:39 -04:00
|
|
|
req_size = data_size;
|
2009-02-04 19:01:51 -05:00
|
|
|
total_size += req_size ;
|
2008-07-01 22:36:39 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
std::cerr << "No data to read" << std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-01-11 11:00:42 -05:00
|
|
|
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) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
map_is_too_old = true ;
|
|
|
|
it->second.second = time(NULL) ; // to avoid re-asking before the TTL
|
|
|
|
}
|
|
|
|
else
|
|
|
|
map_is_too_old = false ;
|
|
|
|
|
|
|
|
cmap = it->second.first ;
|
|
|
|
}
|
|
|
|
|
2008-07-01 22:36:39 -04:00
|
|
|
int ftFileProvider::initializeFileAttrs()
|
|
|
|
{
|
2010-03-07 09:42:13 -05:00
|
|
|
#ifdef DEBUG_FT_FILE_PROVIDER
|
|
|
|
std::cerr << "ftFileProvider::initializeFileAttrs() Filename: " << file_name << std::endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/
|
2008-10-22 14:12:58 -04:00
|
|
|
if (fd)
|
|
|
|
return 1;
|
|
|
|
|
2008-07-02 00:05:58 -04:00
|
|
|
/*
|
2010-03-07 09:42:13 -05:00
|
|
|
* check if the file exists
|
|
|
|
*/
|
|
|
|
|
2008-07-01 22:36:39 -04:00
|
|
|
{
|
2010-03-07 09:42:13 -05:00
|
|
|
#ifdef DEBUG_FT_FILE_PROVIDER
|
|
|
|
std::cerr << "ftFileProvider::initializeFileAttrs() trying (r+b) " << std::endl;
|
|
|
|
#endif
|
2008-07-01 22:36:39 -04:00
|
|
|
}
|
|
|
|
|
2008-07-02 00:05:58 -04:00
|
|
|
/*
|
2010-03-07 09:42:13 -05:00
|
|
|
* attempt to open file
|
|
|
|
*/
|
|
|
|
|
2010-05-16 19:26:45 -04:00
|
|
|
#ifdef WINDOWS_SYS
|
|
|
|
std::wstring wfile_name;
|
|
|
|
librs::util::ConvertUtf8ToUtf16(file_name, wfile_name);
|
|
|
|
fd = _wfopen(wfile_name.c_str(), L"r+b");
|
|
|
|
#else
|
2010-03-28 16:46:45 -04:00
|
|
|
fd = fopen64(file_name.c_str(), "r+b");
|
2010-05-16 19:26:45 -04:00
|
|
|
#endif
|
2008-07-01 22:36:39 -04:00
|
|
|
if (!fd)
|
|
|
|
{
|
2008-10-29 16:58:23 -04:00
|
|
|
std::cerr << "ftFileProvider::initializeFileAttrs() Failed to open (r+b): ";
|
|
|
|
std::cerr << file_name << std::endl;
|
2008-07-01 22:36:39 -04:00
|
|
|
|
2008-11-13 18:03:46 -05:00
|
|
|
/* try opening read only */
|
2010-05-16 19:26:45 -04:00
|
|
|
#ifdef WINDOWS_SYS
|
|
|
|
fd = _wfopen(wfile_name.c_str(), L"rb");
|
|
|
|
#else
|
2009-08-29 14:55:13 -04:00
|
|
|
fd = fopen64(file_name.c_str(), "rb");
|
2010-05-16 19:26:45 -04:00
|
|
|
#endif
|
2008-11-13 18:03:46 -05:00
|
|
|
if (!fd)
|
|
|
|
{
|
|
|
|
std::cerr << "ftFileProvider::initializeFileAttrs() Failed to open (rb): ";
|
|
|
|
std::cerr << file_name << std::endl;
|
2010-03-07 09:42:13 -05:00
|
|
|
|
2008-11-13 18:03:46 -05:00
|
|
|
/* try opening read only */
|
|
|
|
return 0;
|
|
|
|
}
|
2008-07-01 22:36:39 -04:00
|
|
|
}
|
|
|
|
|
2008-07-02 00:05:58 -04:00
|
|
|
/*
|
2010-03-07 09:42:13 -05:00
|
|
|
* if it opened, find it's length
|
2008-07-02 00:05:58 -04:00
|
|
|
* move to the end
|
2010-03-07 09:42:13 -05:00
|
|
|
*/
|
2008-07-01 22:36:39 -04:00
|
|
|
|
2010-03-07 09:42:13 -05:00
|
|
|
// 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
|
2008-10-22 14:12:58 -04:00
|
|
|
|
2008-07-01 22:36:39 -04:00
|
|
|
return 1;
|
|
|
|
}
|