RetroShare/libretroshare/src/tests/ft/ftfilemappertest.cc
csoler 3c2a5e8f42 Added a filemapper class to store downloaded files sequentially on the HD. The mapper automatically
re-organises (e.g. defragments) data such that
- when the DL is finished, the file is in the correct order (no need to re-order it)
- during the DL, only the n*_chunk_size first bytes of the partial file are written, where n is the total number of downloaded chunks.
- the total amount of copy operations does not exceed the total size of the file. In practice, it's much lower.

That suppresses the lag when downloading large files due to writing isolated chunks in the middle of the file.

Next:
- integration into ftFileCreator
- load/save in ft_transfers
- retrocompatibility with existing transfers.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4658 b45a01b8-16f6-495d-af2f-9b41ad6348cc
2011-11-01 14:20:51 +00:00

92 lines
2.4 KiB
C++

#include "ft/ftfilemapper.h"
#include "ft/ftchunkmap.h"
#include "retroshare/rstypes.h"
#include <util/utest.h>
#include <util/rsdir.h>
#include <stdlib.h>
#include <iostream>
#include <stdint.h>
INITTEST();
int main()
{
/* Use ftfilemapper to create a file with chunks downloaded on a random direction. */
static const std::string tmpdir = "." ;
static const std::string input_file = tmpdir+"/"+"input.bin" ;
static const std::string output_file = tmpdir+"/"+"output.bin" ;
static const uint64_t size = 1024*1024*12+234;//4357283 ; // some size. Not an integer number of chunks
static const uint32_t chunk_size = 1024*1024 ; // 1MB
pid_t pid = getpid() ;
srand48(pid) ;
srand(pid) ;
std::cerr << "Inited random number generator with seed " << pid << std::endl;
// 0 - create a random file in memory, of size SIZE
void *membuf = malloc(size) ;
CHECK(membuf != NULL) ;
for(int i=0;i<size;++i)
((char*)membuf)[i] = lrand48() & 0xff ;
// also write it to disk
FILE *f = fopen(input_file.c_str(),"w") ;
CHECK(f != NULL) ;
CHECK(fwrite(membuf,size,1,f) == 1) ;
fclose(f) ;
// 1 - allocate a chunkmap for this file
//
ChunkMap chunk_map(size,true) ;
chunk_map.setStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ;
ftFileMapper fmapper(size,chunk_size);
// Get the chunks one by one
//
FILE *fout = fopen(output_file.c_str(),"w+") ;
CHECK(fout != NULL) ;
ftChunk chunk ;
bool source_map_needed ;
while(chunk_map.getDataChunk("virtual peer",1024*200+(lrand48()%1024),chunk,source_map_needed))
{
//std::cerr << "Got chunk " << chunk.offset << " + " << chunk.size << " from chunkmap." << std::endl;
CHECK(fmapper.storeData( (unsigned char *)membuf+chunk.offset,chunk.size,chunk.offset,fout) ) ;
chunk_map.dataReceived(chunk.id) ;
fmapper.print() ;
delete chunk.ref_cnt ;
}
fclose(fout) ;
// Check the sha1 of both source and destination.
//
std::string sha1_1,sha1_2 ;
uint64_t size_1,size_2 ;
RsDirUtil::getFileHash( input_file,sha1_1,size_1) ;
RsDirUtil::getFileHash(output_file,sha1_2,size_2) ;
std::cerr << "Computed hash of file\t " << input_file << "\t :\t" << sha1_1 << ", size=" << size_1 << std::endl;
std::cerr << "Computed hash of file\t " <<output_file << "\t :\t" << sha1_2 << ", size=" << size_2 << std::endl;
CHECK(size_1 == size_2) ;
CHECK(sha1_1 == sha1_2) ;
FINALREPORT("RsTlvItem Stack Tests");
return TESTRESULT();
}