2009-03-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Added --index-out option to specify each file path for torrent.
	Here index shown in --show-files option is used to specify which
	file path should be altered. For example, to change the file
	path with index=2, use --index-out=2=aria2.tar.bz2. You can use
	this option multiple times: --index-out=1=aria2.tar.bz2
	--index-out=2=aria2-opt.tar.bz2. The short hand form -O is also
	available. This option can be specified in -i list.	
	* src/DefaultBtContext.cc
	* src/DefaultBtContext.h
	* src/MultiDiskAdaptor.cc
	* src/MultiDiskAdaptor.h
	* src/MultiFileAllocationIterator.cc
	* src/OptionHandlerFactory.cc
	* src/OptionHandlerImpl.h
	* src/Util.cc
	* src/Util.h
	* src/download_helper.cc
	* src/prefs.cc
	* src/prefs.h
	* src/usage_text.h
	* test/DefaultBtContextTest.cc
	* test/MultiDiskAdaptorTest.cc
	* test/MultiFileAllocationIteratorTest.cc
	* test/UtilTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-03-07 03:10:53 +00:00
parent 4aae48c9b2
commit f44554a634
18 changed files with 280 additions and 111 deletions

View File

@ -1,3 +1,30 @@
2009-03-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added --index-out option to specify each file path for torrent.
Here index shown in --show-files option is used to specify which
file path should be altered. For example, to change the file path
with index=2, use --index-out=2=aria2.tar.bz2. You can use this
option multiple times: --index-out=1=aria2.tar.bz2
--index-out=2=aria2-opt.tar.bz2. The short hand form -O is also
available. This option can be specified in -i list.
* src/DefaultBtContext.cc
* src/DefaultBtContext.h
* src/MultiDiskAdaptor.cc
* src/MultiDiskAdaptor.h
* src/MultiFileAllocationIterator.cc
* src/OptionHandlerFactory.cc
* src/OptionHandlerImpl.h
* src/Util.cc
* src/Util.h
* src/download_helper.cc
* src/prefs.cc
* src/prefs.h
* src/usage_text.h
* test/DefaultBtContextTest.cc
* test/MultiDiskAdaptorTest.cc
* test/MultiFileAllocationIteratorTest.cc
* test/UtilTest.cc
2009-03-05 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Use Util::pathJoin()

View File

@ -151,14 +151,20 @@ void DefaultBtContext::extractFileEntries(const bencode::BDE& infoDict,
throw DlAbortEx("Path is empty.");
}
std::vector<std::string> elements(pathList.size());
std::transform(pathList.listBegin(), pathList.listEnd(), elements.begin(),
std::vector<std::string> pathelem(pathList.size());
std::transform(pathList.listBegin(), pathList.listEnd(), pathelem.begin(),
std::mem_fun_ref(&bencode::BDE::s));
std::string path = Util::joinPath(elements.begin(), elements.end());
std::string path = Util::joinPath(pathelem.begin(), pathelem.end());
// Split path with '/' again because each pathList element can
// contain "/" inside.
std::deque<std::string> elements;
Util::slice(elements, path, '/');
elements.push_front(name);
path = Util::joinPath(elements.begin(), elements.end());
std::deque<std::string> uris;
std::transform(urlList.begin(), urlList.end(), std::back_inserter(uris),
std::bind2nd(std::plus<std::string>(), "/"+name+"/"+path));
std::bind2nd(std::plus<std::string>(), "/"+path));
FileEntryHandle fileEntry(new FileEntry(path, fileLengthData.i(),
offset, uris));
fileEntries.push_back(fileEntry);
@ -475,4 +481,15 @@ void DefaultBtContext::setInfoHash(const unsigned char* infoHash)
memcpy(this->infoHash, infoHash, sizeof(this->infoHash));
}
void DefaultBtContext::setFilePathWithIndex
(size_t index, const std::string& path)
{
if(0 < index && index <= fileEntries.size()) {
fileEntries[index-1]->setPath(path);
} else {
throw DlAbortEx(StringFormat("No such file with index=%u",
static_cast<unsigned int>(index)).str());
}
}
} // namespace aria2

View File

@ -182,6 +182,12 @@ private:
void setRandomizer(const SharedHandle<Randomizer>& randomizer);
// Sets file path for spcified index. index starts from 1. The index
// is the same used in BtContext::setFileFilter(). Please note that
// path is not the actual file path. The actual file path is
// getDir()+"/"+path.
void setFilePathWithIndex(size_t index, const std::string& path);
friend std::ostream& operator<<(std::ostream& o, const DefaultBtContext& ctx);
static const std::string DEFAULT_PEER_ID_PREFIX;

View File

@ -58,15 +58,15 @@ DiskWriterEntry::DiskWriterEntry(const SharedHandle<FileEntry>& fileEntry):
DiskWriterEntry::~DiskWriterEntry() {}
std::string DiskWriterEntry::getFilePath(const std::string& topDir) const
std::string DiskWriterEntry::getFilePath(const std::string& storeDir) const
{
return topDir+"/"+fileEntry->getPath();
return storeDir+"/"+fileEntry->getPath();
}
void DiskWriterEntry::initAndOpenFile(const std::string& topDir)
void DiskWriterEntry::initAndOpenFile(const std::string& storeDir)
{
if(!diskWriter.isNull()) {
diskWriter->initAndOpenFile(getFilePath(topDir), fileEntry->getLength());
diskWriter->initAndOpenFile(getFilePath(storeDir), fileEntry->getLength());
if(_directIO) {
diskWriter->enableDirectIO();
}
@ -74,10 +74,10 @@ void DiskWriterEntry::initAndOpenFile(const std::string& topDir)
}
}
void DiskWriterEntry::openFile(const std::string& topDir)
void DiskWriterEntry::openFile(const std::string& storeDir)
{
if(!diskWriter.isNull()) {
diskWriter->openFile(getFilePath(topDir), fileEntry->getLength());
diskWriter->openFile(getFilePath(storeDir), fileEntry->getLength());
if(_directIO) {
diskWriter->enableDirectIO();
}
@ -85,10 +85,10 @@ void DiskWriterEntry::openFile(const std::string& topDir)
}
}
void DiskWriterEntry::openExistingFile(const std::string& topDir)
void DiskWriterEntry::openExistingFile(const std::string& storeDir)
{
if(!diskWriter.isNull()) {
diskWriter->openExistingFile(getFilePath(topDir), fileEntry->getLength());
diskWriter->openExistingFile(getFilePath(storeDir), fileEntry->getLength());
if(_directIO) {
diskWriter->enableDirectIO();
}
@ -109,9 +109,9 @@ void DiskWriterEntry::closeFile()
}
}
bool DiskWriterEntry::fileExists(const std::string& topDir)
bool DiskWriterEntry::fileExists(const std::string& storeDir)
{
return File(getFilePath(topDir)).exists();
return File(getFilePath(storeDir)).exists();
}
uint64_t DiskWriterEntry::size() const
@ -270,9 +270,9 @@ void MultiDiskAdaptor::resetDiskWriterEntries()
diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) {
if((*i)->needsFileAllocation() ||
dwreq.find((*i)->getFileEntry()->getPath()) != dwreq.end() ||
(*i)->fileExists(getTopDirPath())) {
(*i)->fileExists(storeDir)) {
logger->debug("Creating DiskWriter for filename=%s",
(*i)->getFilePath(getTopDirPath()).c_str());
(*i)->getFilePath(storeDir).c_str());
(*i)->setDiskWriter(dwFactory.newDiskWriter());
(*i)->getDiskWriter()->setDirectIOAllowed(_directIOAllowed);
if(_readOnly) {
@ -287,25 +287,25 @@ std::string MultiDiskAdaptor::getTopDirPath() const
return storeDir+"/"+topDir;
}
void MultiDiskAdaptor::mkdir(const std::string& topDirPath) const
void MultiDiskAdaptor::mkdir(const std::string& storeDir) const
{
for(std::deque<SharedHandle<DiskWriterEntry> >::const_iterator i =
diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) {
(*i)->getFileEntry()->setupDir(topDirPath);
(*i)->getFileEntry()->setupDir(storeDir);
}
}
void MultiDiskAdaptor::openIfNot
(const SharedHandle<DiskWriterEntry>& entry,
void (DiskWriterEntry::*open)(const std::string&),
const std::string& topDirPath)
const std::string& storeDir)
{
if(!entry->isOpen()) {
// logger->debug("DiskWriterEntry: Cache MISS. offset=%s",
// Util::itos(entry->getFileEntry()->getOffset()).c_str());
size_t numOpened = _openedDiskWriterEntries.size();
(entry.get()->*open)(topDirPath);
(entry.get()->*open)(storeDir);
if(numOpened >= _maxOpenFiles) {
// Cache is full.
// Choose one DiskWriterEntry randomly and close it.
@ -326,32 +326,29 @@ void MultiDiskAdaptor::openIfNot
void MultiDiskAdaptor::openFile()
{
_cachedTopDirPath = getTopDirPath();
resetDiskWriterEntries();
mkdir(_cachedTopDirPath);
mkdir(storeDir);
// Call DiskWriterEntry::openFile to make sure that zero-length files are
// created.
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
itr != diskWriterEntries.end(); ++itr) {
openIfNot(*itr, &DiskWriterEntry::openFile, _cachedTopDirPath);
openIfNot(*itr, &DiskWriterEntry::openFile, storeDir);
}
}
void MultiDiskAdaptor::initAndOpenFile()
{
_cachedTopDirPath = getTopDirPath();
resetDiskWriterEntries();
mkdir(_cachedTopDirPath);
mkdir(storeDir);
// Call DiskWriterEntry::initAndOpenFile to make files truncated.
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
itr != diskWriterEntries.end(); ++itr) {
openIfNot(*itr, &DiskWriterEntry::initAndOpenFile, _cachedTopDirPath);
openIfNot(*itr, &DiskWriterEntry::initAndOpenFile, storeDir);
}
}
void MultiDiskAdaptor::openExistingFile()
{
_cachedTopDirPath = getTopDirPath();
resetDiskWriterEntries();
// Not need to call openIfNot here.
}
@ -416,12 +413,12 @@ findFirstDiskWriterEntry(const DiskWriterEntries& diskWriterEntries, off_t offse
static void throwOnDiskWriterNotOpened(const SharedHandle<DiskWriterEntry>& e,
off_t offset,
const std::string& topDirPath)
const std::string& storeDir)
{
throw DlAbortEx
(StringFormat("DiskWriter for offset=%s, filename=%s is not opened.",
Util::itos(offset).c_str(),
e->getFilePath(topDirPath).c_str()).str());
e->getFilePath(storeDir).c_str()).str());
}
void MultiDiskAdaptor::writeData(const unsigned char* data, size_t len,
@ -434,10 +431,10 @@ void MultiDiskAdaptor::writeData(const unsigned char* data, size_t len,
for(DiskWriterEntries::const_iterator i = first; i != diskWriterEntries.end(); ++i) {
size_t writeLength = calculateLength(*i, fileOffset, rem);
openIfNot(*i, &DiskWriterEntry::openFile, _cachedTopDirPath);
openIfNot(*i, &DiskWriterEntry::openFile, storeDir);
if(!(*i)->isOpen()) {
throwOnDiskWriterNotOpened(*i, offset+(len-rem), _cachedTopDirPath);
throwOnDiskWriterNotOpened(*i, offset+(len-rem), storeDir);
}
(*i)->getDiskWriter()->writeData(data+(len-rem), writeLength, fileOffset);
@ -459,10 +456,10 @@ ssize_t MultiDiskAdaptor::readData(unsigned char* data, size_t len, off_t offset
for(DiskWriterEntries::const_iterator i = first; i != diskWriterEntries.end(); ++i) {
size_t readLength = calculateLength(*i, fileOffset, rem);
openIfNot(*i, &DiskWriterEntry::openFile, _cachedTopDirPath);
openIfNot(*i, &DiskWriterEntry::openFile, storeDir);
if(!(*i)->isOpen()) {
throwOnDiskWriterNotOpened(*i, offset+(len-rem), _cachedTopDirPath);
throwOnDiskWriterNotOpened(*i, offset+(len-rem), storeDir);
}
totalReadLength +=
@ -478,12 +475,13 @@ ssize_t MultiDiskAdaptor::readData(unsigned char* data, size_t len, off_t offset
bool MultiDiskAdaptor::fileExists()
{
// TODO Use FileEntry::fileExists() here.
// Don't use _cachedTopDirPath because they are initialized after opening files.
// This method could be called before opening files.
std::string topDirPath = getTopDirPath();
for(std::deque<SharedHandle<FileEntry> >::iterator i =
fileEntries.begin(); i != fileEntries.end(); ++i) {
if(File(topDirPath+"/"+(*i)->getPath()).exists()) {
if(File(storeDir+"/"+(*i)->getPath()).exists()) {
return true;
}
}
@ -496,7 +494,7 @@ uint64_t MultiDiskAdaptor::size()
uint64_t size = 0;
for(DiskWriterEntries::const_iterator itr = diskWriterEntries.begin();
itr != diskWriterEntries.end(); ++itr) {
openIfNot(*itr, &DiskWriterEntry::openFile, _cachedTopDirPath);
openIfNot(*itr, &DiskWriterEntry::openFile, storeDir);
size += (*itr)->size();
}
return size;
@ -538,9 +536,9 @@ void MultiDiskAdaptor::cutTrailingGarbage()
for(std::deque<SharedHandle<DiskWriterEntry> >::const_iterator i =
diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) {
uint64_t length = (*i)->getFileEntry()->getLength();
if(File((*i)->getFilePath(_cachedTopDirPath)).size() > length) {
if(File((*i)->getFilePath(storeDir)).size() > length) {
// We need open file before calling DiskWriter::truncate(uint64_t)
openIfNot(*i, &DiskWriterEntry::openFile, _cachedTopDirPath);
openIfNot(*i, &DiskWriterEntry::openFile, storeDir);
(*i)->getDiskWriter()->truncate(length);
}
}
@ -557,7 +555,7 @@ size_t MultiDiskAdaptor::utime(const Time& actime, const Time& modtime)
for(std::deque<SharedHandle<FileEntry> >::const_iterator i =
fileEntries.begin(); i != fileEntries.end(); ++i) {
if((*i)->isRequested()) {
File f(getTopDirPath()+"/"+(*i)->getPath());
File f(storeDir+"/"+(*i)->getPath());
if(f.isFile() && f.utime(actime, modtime)) {
++numOK;
}
@ -572,4 +570,9 @@ MultiDiskAdaptor::getDiskWriterEntries() const
return diskWriterEntries;
}
const std::string& MultiDiskAdaptor::getStoreDir() const
{
return storeDir;
}
} // namespace aria2

View File

@ -55,19 +55,19 @@ public:
~DiskWriterEntry();
std::string getFilePath(const std::string& topDir) const;
std::string getFilePath(const std::string& storeDir) const;
void initAndOpenFile(const std::string& topDir);
void initAndOpenFile(const std::string& storeDir);
void openFile(const std::string& topDir);
void openFile(const std::string& storeDir);
void openExistingFile(const std::string& topDir);
void openExistingFile(const std::string& storeDir);
void closeFile();
bool isOpen() const;
bool fileExists(const std::string& topDir);
bool fileExists(const std::string& storeDir);
uint64_t size() const;
@ -105,8 +105,6 @@ private:
size_t pieceLength;
DiskWriterEntries diskWriterEntries;
std::string _cachedTopDirPath;
std::deque<SharedHandle<DiskWriterEntry> > _openedDiskWriterEntries;
size_t _maxOpenFiles;
@ -117,13 +115,13 @@ private:
void resetDiskWriterEntries();
void mkdir(const std::string& topDirPath) const;
void mkdir(const std::string& storeDir) const;
std::string getTopDirPath() const;
void openIfNot(const SharedHandle<DiskWriterEntry>& entry,
void (DiskWriterEntry::*f)(const std::string&),
const std::string& topDirPath);
const std::string& storeDir);
static const size_t DEFAULT_MAX_OPEN_FILES = 100;
@ -200,6 +198,8 @@ public:
const std::deque<SharedHandle<DiskWriterEntry> >&
getDiskWriterEntries() const;
const std::string& getStoreDir() const;
};
typedef SharedHandle<MultiDiskAdaptor> MultiDiskAdaptorHandle;

View File

@ -59,7 +59,7 @@ void MultiFileAllocationIterator::allocateChunk()
FileEntryHandle fileEntry = entry->getFileEntry();
// Open file before calling DiskWriterEntry::size()
_diskAdaptor->openIfNot(entry, &DiskWriterEntry::openFile,
_diskAdaptor->getTopDirPath());
_diskAdaptor->getStoreDir());
entry->enableDirectIO();
if(entry->needsFileAllocation() && entry->size() < fileEntry->getLength()) {
// Calling private function of MultiDiskAdaptor.

View File

@ -968,6 +968,14 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
op->addTag(TAG_BITTORRENT);
handlers.push_back(op);
}
{
SharedHandle<OptionHandler> op(new IndexOutOptionHandler
(PREF_INDEX_OUT,
TEXT_INDEX_OUT,
'O'));
op->addTag(TAG_BITTORRENT);
handlers.push_back(op);
}
{
SharedHandle<OptionHandler> op(new IntegerRangeOptionHandler
(PREF_LISTEN_PORT,

View File

@ -366,6 +366,32 @@ public:
}
};
class IndexOutOptionHandler : public NameMatchOptionHandler {
private:
public:
IndexOutOptionHandler(const std::string& optName,
const std::string& description,
char shortName = 0):
NameMatchOptionHandler(optName, description, NO_DEFAULT_VALUE,
OptionHandler::REQ_ARG, shortName) {}
virtual ~IndexOutOptionHandler() {}
virtual void parseArg(Option& option, const std::string& optarg)
{
// See optarg is in the fomrat of "INDEX=PATH"
Util::parseIndexPath(optarg);
std::string value = option.get(_optName);
value += optarg+"\n";
option.put(_optName, value);
}
virtual std::string createPossibleValuesString() const
{
return "INDEX=PATH";
}
};
class ParameterOptionHandler : public NameMatchOptionHandler {
private:
std::deque<std::string> _validParamValues;

View File

@ -941,4 +941,26 @@ std::string Util::htmlEscape(const std::string& src)
return dest;
}
std::map<size_t, std::string>::value_type
Util::parseIndexPath(const std::string& line)
{
std::pair<std::string, std::string> p = Util::split(line, "=");
size_t index = parseUInt(p.first);
if(p.second.empty()) {
throw DlAbortEx(StringFormat("Path with index=%u is empty.",
static_cast<unsigned int>(index)).str());
}
return std::map<size_t, std::string>::value_type(index, p.second);
}
std::map<size_t, std::string> Util::createIndexPathMap(std::istream& i)
{
std::map<size_t, std::string> indexPathMap;
std::string line;
while(getline(i, line)) {
indexPathMap.insert(indexPathMap.begin(), parseIndexPath(line));
}
return indexPathMap;
}
} // namespace aria2

View File

@ -44,6 +44,7 @@
#include <deque>
#include <iosfwd>
#include <numeric>
#include <map>
#include "SharedHandle.h"
#include "IntSequence.h"
@ -306,6 +307,13 @@ public:
return std::accumulate(elements.begin()+1, elements.end(), elements[0],
Concat("/"));
}
// Parses INDEX=PATH format string. INDEX must be an unsigned
// integer.
static std::map<size_t, std::string>::value_type
parseIndexPath(const std::string& line);
static std::map<size_t, std::string> createIndexPathMap(std::istream& i);
};
} // namespace aria2

View File

@ -37,6 +37,7 @@
#include <iostream>
#include <fstream>
#include <algorithm>
#include <sstream>
#include "RequestGroup.h"
#include "Option.h"
@ -124,6 +125,13 @@ createBtRequestGroup(const std::string& torrentFilePath,
btContext->setDir(requestOption.get(PREF_DIR));
btContext->setFileFilter
(Util::parseIntRange(requestOption.get(PREF_SELECT_FILE)));
std::istringstream indexOutIn(requestOption.get(PREF_INDEX_OUT));
std::map<size_t, std::string> indexPathMap =
Util::createIndexPathMap(indexOutIn);
for(std::map<size_t, std::string>::const_iterator i = indexPathMap.begin();
i != indexPathMap.end(); ++i) {
btContext->setFilePathWithIndex((*i).first, (*i).second);
}
rg->setDownloadContext(btContext);
btContext->setOwnerRequestGroup(rg.get());
return rg;
@ -295,11 +303,13 @@ static void createRequestGroupForUriList
if(uris.empty()) {
continue;
}
// TODO use OptionParser to validate the value in the options.
// These options can be specified in input list(-i list).
static const std::string REQUEST_OPTIONS[] = {
PREF_DIR,
PREF_OUT,
PREF_SELECT_FILE
PREF_SELECT_FILE,
PREF_INDEX_OUT
};
foreachCopyIfndef(&REQUEST_OPTIONS[0],
&REQUEST_OPTIONS[arrayLength(REQUEST_OPTIONS)],

View File

@ -283,6 +283,8 @@ const std::string PREF_BT_HASH_CHECK_SEED("bt-hash-check-seed");
const std::string PREF_BT_MAX_PEERS("bt-max-peers");
// values: a string (IP address)
const std::string PREF_BT_EXTERNAL_IP("bt-external-ip");
// values: 1*digit '=' a string that your file system recognizes as a file name.
const std::string PREF_INDEX_OUT("index-out");
/**
* Metalink related preferences

View File

@ -287,6 +287,8 @@ extern const std::string PREF_BT_HASH_CHECK_SEED;
extern const std::string PREF_BT_MAX_PEERS;
// values: a string (IP address)
extern const std::string PREF_BT_EXTERNAL_IP;
// values: 1*digit '=' a string that your file system recognizes as a file name.
extern const std::string PREF_INDEX_OUT;
/**
* Metalink related preferences

View File

@ -493,3 +493,9 @@ _(" --http-auth-challenge[=true|false] Send HTTP authorization header only when
" are embedded in URI, authorization header is\n"\
" always sent to the server regardless of this\n"\
" option.")
#define TEXT_INDEX_OUT \
_(" -O, --index-out=INDEX=PATH Set file path for file with index=INDEX. You can\n"\
" find the file index using the --show-files option.\n"\
" PATH is a relative path to the path specified in\n"\
" --dir option. You can use this option multiple\n"\
" times.")

View File

@ -108,11 +108,11 @@ void DefaultBtContextTest::testGetFileEntries() {
std::deque<SharedHandle<FileEntry> >::iterator itr = fileEntries.begin();
SharedHandle<FileEntry> fileEntry1 = *itr;
CPPUNIT_ASSERT_EQUAL(std::string("aria2/src/aria2c"),
CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2/src/aria2c"),
fileEntry1->getPath());
itr++;
SharedHandle<FileEntry> fileEntry2 = *itr;
CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.2.2.tar.bz2"),
CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2-0.2.2.tar.bz2"),
fileEntry2->getPath());
}
@ -289,7 +289,7 @@ void DefaultBtContextTest::testGetFileEntries_multiFileUrlList() {
std::deque<SharedHandle<FileEntry> >::iterator itr = fileEntries.begin();
SharedHandle<FileEntry> fileEntry1 = *itr;
CPPUNIT_ASSERT_EQUAL(std::string("aria2/src/aria2c"),
CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2/src/aria2c"),
fileEntry1->getPath());
std::deque<std::string> uris1 = fileEntry1->getAssociatedUris();
CPPUNIT_ASSERT_EQUAL((size_t)2, uris1.size());
@ -300,7 +300,7 @@ void DefaultBtContextTest::testGetFileEntries_multiFileUrlList() {
itr++;
SharedHandle<FileEntry> fileEntry2 = *itr;
CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.2.2.tar.bz2"),
CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2-0.2.2.tar.bz2"),
fileEntry2->getPath());
std::deque<std::string> uris2 = fileEntry2->getAssociatedUris();
CPPUNIT_ASSERT_EQUAL((size_t)2, uris2.size());

View File

@ -434,9 +434,7 @@ void MultiDiskAdaptorTest::testSize()
void MultiDiskAdaptorTest::testUtime()
{
std::string storeDir = "/tmp";
std::string topDir = "aria2_MultiDiskAdaptorTest_testUtime";
std::string prefix = storeDir+"/"+topDir;
std::string storeDir = "/tmp/aria2_MultiDiskAdaptorTest_testUtime";
SharedHandle<FileEntry> entries[] = {
SharedHandle<FileEntry>(new FileEntry("requested", 0, 0)),
SharedHandle<FileEntry>(new FileEntry("notFound", 0, 0)),
@ -444,10 +442,10 @@ void MultiDiskAdaptorTest::testUtime()
SharedHandle<FileEntry>(new FileEntry("anotherRequested", 0, 0)),
};
createFile(prefix+"/"+entries[0]->getPath(), entries[0]->getLength());
File(prefix+"/"+entries[1]->getPath()).remove();
createFile(prefix+"/"+entries[2]->getPath(), entries[2]->getLength());
createFile(prefix+"/"+entries[3]->getPath(), entries[3]->getLength());
createFile(storeDir+"/"+entries[0]->getPath(), entries[0]->getLength());
File(storeDir+"/"+entries[1]->getPath()).remove();
createFile(storeDir+"/"+entries[2]->getPath(), entries[2]->getLength());
createFile(storeDir+"/"+entries[3]->getPath(), entries[3]->getLength());
entries[2]->setRequested(false);
@ -455,7 +453,6 @@ void MultiDiskAdaptorTest::testUtime()
(&entries[0], &entries[arrayLength(entries)]);
MultiDiskAdaptor adaptor;
adaptor.setStoreDir(storeDir);
adaptor.setTopDir(topDir);
adaptor.setFileEntries(fileEntries);
time_t atime = (time_t) 100000;
@ -464,14 +461,14 @@ void MultiDiskAdaptorTest::testUtime()
CPPUNIT_ASSERT_EQUAL((size_t)2, adaptor.utime(Time(atime), Time(mtime)));
CPPUNIT_ASSERT_EQUAL((time_t)mtime,
File(prefix+"/"+entries[0]->getPath())
File(storeDir+"/"+entries[0]->getPath())
.getModifiedTime().getTime());
CPPUNIT_ASSERT_EQUAL((time_t)mtime,
File(prefix+"/"+entries[3]->getPath())
File(storeDir+"/"+entries[3]->getPath())
.getModifiedTime().getTime());
CPPUNIT_ASSERT((time_t)mtime != File(prefix+"/"+entries[2]->getPath())
CPPUNIT_ASSERT((time_t)mtime != File(storeDir+"/"+entries[2]->getPath())
.getModifiedTime().getTime());
}

View File

@ -1,4 +1,10 @@
#include "MultiFileAllocationIterator.h"
#include <algorithm>
#include <iostream>
#include <cppunit/extensions/HelperMacros.h>
#include "File.h"
#include "MultiDiskAdaptor.h"
#include "FileEntry.h"
@ -6,9 +12,6 @@
#include "array_fun.h"
#include "TestUtil.h"
#include "DiskWriter.h"
#include <algorithm>
#include <iostream>
#include <cppunit/extensions/HelperMacros.h>
namespace aria2 {
@ -53,20 +56,17 @@ void MultiFileAllocationIteratorTest::testMakeDiskWriterEntries()
fs[8]->setRequested(false); // file9
fs[9]->setRequested(false); // fileA
std::string topDir = "top";
std::string storeDir = "/tmp/aria2_MultiFileAllocationIteratorTest"
"_testMakeDiskWriterEntries";
std::string prefix = storeDir+"/"+topDir;
// create empty file4
createFile(prefix+std::string("/file4"), 0);
createFile(storeDir+std::string("/file4"), 0);
SharedHandle<MultiDiskAdaptor> diskAdaptor(new MultiDiskAdaptor());
diskAdaptor->setFileEntries
(std::deque<SharedHandle<FileEntry> >(&fs[0], &fs[arrayLength(fs)]));
diskAdaptor->setPieceLength(1024);
diskAdaptor->setStoreDir(storeDir);
diskAdaptor->setTopDir(topDir);
diskAdaptor->openFile();
SharedHandle<MultiFileAllocationIterator> itr
@ -78,67 +78,67 @@ void MultiFileAllocationIteratorTest::testMakeDiskWriterEntries()
CPPUNIT_ASSERT_EQUAL((size_t)11, entries.size());
// file1
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file1"),
entries[0]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file1"),
entries[0]->getFilePath(storeDir));
CPPUNIT_ASSERT(entries[0]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
// file2
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file2"),
entries[1]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file2"),
entries[1]->getFilePath(storeDir));
CPPUNIT_ASSERT(entries[1]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
// file3
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file3"),
entries[2]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file3"),
entries[2]->getFilePath(storeDir));
CPPUNIT_ASSERT(entries[2]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
// file4, diskWriter is not null, because file exists.
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file4"),
entries[3]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file4"),
entries[3]->getFilePath(storeDir));
CPPUNIT_ASSERT(!entries[3]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
// file5
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file5"),
entries[4]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file5"),
entries[4]->getFilePath(storeDir));
CPPUNIT_ASSERT(!entries[4]->needsFileAllocation());
CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull());
// file6
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file6"),
entries[5]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file6"),
entries[5]->getFilePath(storeDir));
CPPUNIT_ASSERT(entries[5]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
// file7
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file7"),
entries[6]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file7"),
entries[6]->getFilePath(storeDir));
CPPUNIT_ASSERT(entries[6]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[6]->getDiskWriter().isNull());
// file8
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file8"),
entries[7]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file8"),
entries[7]->getFilePath(storeDir));
CPPUNIT_ASSERT(entries[7]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[7]->getDiskWriter().isNull());
// file9
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file9"),
entries[8]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file9"),
entries[8]->getFilePath(storeDir));
CPPUNIT_ASSERT(!entries[8]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[8]->getDiskWriter().isNull());
// fileA
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/fileA"),
entries[9]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/fileA"),
entries[9]->getFilePath(storeDir));
CPPUNIT_ASSERT(!entries[9]->needsFileAllocation());
CPPUNIT_ASSERT(entries[9]->getDiskWriter().isNull());
// fileB
CPPUNIT_ASSERT_EQUAL(prefix+std::string("/fileB"),
entries[10]->getFilePath(prefix));
CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/fileB"),
entries[10]->getFilePath(storeDir));
CPPUNIT_ASSERT(entries[10]->needsFileAllocation());
CPPUNIT_ASSERT(!entries[10]->getDiskWriter().isNull());
}
void MultiFileAllocationIteratorTest::testAllocate()
{
std::string dir = "/tmp";
std::string topDir = "aria2_MultiFileAllocationIteratorTest_testAllocate";
std::string prefix = dir+"/"+topDir;
std::string storeDir =
"/tmp/aria2_MultiFileAllocationIteratorTest_testAllocate";
std::string fname1 = "file1";
std::string fname2 = "file2";
std::string fname3 = "file3";
@ -154,8 +154,7 @@ void MultiFileAllocationIteratorTest::testAllocate()
try {
SharedHandle<MultiDiskAdaptor> diskAdaptor(new MultiDiskAdaptor());
diskAdaptor->setStoreDir(dir);
diskAdaptor->setTopDir(topDir);
diskAdaptor->setStoreDir(storeDir);
diskAdaptor->setPieceLength(1);
int64_t offset = 0;
@ -199,12 +198,12 @@ void MultiFileAllocationIteratorTest::testAllocate()
diskAdaptor->setFileEntries(fs);
File(prefix+"/"+fname1).remove();
File(prefix+"/"+fname2).remove();
File(prefix+"/"+fname3).remove();
File(prefix+"/"+fname4).remove();
File(prefix+"/"+fname5).remove();
File(prefix+"/"+fname6).remove();
File(storeDir+"/"+fname1).remove();
File(storeDir+"/"+fname2).remove();
File(storeDir+"/"+fname3).remove();
File(storeDir+"/"+fname4).remove();
File(storeDir+"/"+fname5).remove();
File(storeDir+"/"+fname6).remove();
// we have to open file first.
diskAdaptor->initAndOpenFile();
@ -214,13 +213,13 @@ void MultiFileAllocationIteratorTest::testAllocate()
while(!itr->finished()) {
itr->allocateChunk();
}
CPPUNIT_ASSERT_EQUAL((uint64_t)length1, File(prefix+"/"+fname1).size());
CPPUNIT_ASSERT_EQUAL((uint64_t)length2, File(prefix+"/"+fname2).size());
CPPUNIT_ASSERT_EQUAL((uint64_t)length3, File(prefix+"/"+fname3).size());
CPPUNIT_ASSERT(!File(prefix+"/"+fname4).isFile());
CPPUNIT_ASSERT_EQUAL((uint64_t)length1, File(storeDir+"/"+fname1).size());
CPPUNIT_ASSERT_EQUAL((uint64_t)length2, File(storeDir+"/"+fname2).size());
CPPUNIT_ASSERT_EQUAL((uint64_t)length3, File(storeDir+"/"+fname3).size());
CPPUNIT_ASSERT(!File(storeDir+"/"+fname4).isFile());
CPPUNIT_ASSERT_EQUAL((uint64_t)length5, File(prefix+"/"+fname5).size());
CPPUNIT_ASSERT(!File(prefix+"/"+fname6).isFile());
CPPUNIT_ASSERT_EQUAL((uint64_t)length5, File(storeDir+"/"+fname5).size());
CPPUNIT_ASSERT(!File(storeDir+"/"+fname6).isFile());
} catch(Exception& e) {
CPPUNIT_FAIL(e.stackTrace());

View File

@ -54,6 +54,8 @@ class UtilTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testUrlencode);
CPPUNIT_TEST(testHtmlEscape);
CPPUNIT_TEST(testJoinPath);
CPPUNIT_TEST(testParseIndexPath);
CPPUNIT_TEST(testCreateIndexPathMap);
CPPUNIT_TEST_SUITE_END();
private:
@ -97,6 +99,8 @@ public:
void testUrlencode();
void testHtmlEscape();
void testJoinPath();
void testParseIndexPath();
void testCreateIndexPathMap();
};
@ -778,4 +782,36 @@ void UtilTest::testJoinPath()
&parentdot[arrayLength(parentdot)]));
}
void UtilTest::testParseIndexPath()
{
std::map<size_t, std::string>::value_type p = Util::parseIndexPath("1=foo");
CPPUNIT_ASSERT_EQUAL((size_t)1, p.first);
CPPUNIT_ASSERT_EQUAL(std::string("foo"), p.second);
try {
Util::parseIndexPath("1X=foo");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
// success
}
try {
Util::parseIndexPath("1=");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
// success
}
}
void UtilTest::testCreateIndexPathMap()
{
std::stringstream in
("1=/tmp/myfile\n"
"100=/myhome/mypicture.png\n");
std::map<size_t, std::string> m = Util::createIndexPathMap(in);
CPPUNIT_ASSERT_EQUAL((size_t)2, m.size());
CPPUNIT_ASSERT(m.find(1) != m.end());
CPPUNIT_ASSERT_EQUAL(std::string("/tmp/myfile"), m[1]);
CPPUNIT_ASSERT(m.find(100) != m.end());
CPPUNIT_ASSERT_EQUAL(std::string("/myhome/mypicture.png"), m[100]);
}
} // namespace aria2