2008-09-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Implemented the ability to get timestamp from remote HTTP server 
and
	apply it to local file. To enable this feature, --remote-time 
option
	is added. No usage text has been written yet.
	If several servers returns difference timestamp, then aria2 uses 
latest
	one.
	* src/CopyDiskAdaptor.cc
	* src/CopyDiskAdaptor.h
	* src/DirectDiskAdaptor.cc
	* src/DirectDiskAdaptor.h
	* src/DiskAdaptor.h
	* src/File.cc
	* src/File.h
	* src/HttpHeader.cc
	* src/HttpHeader.h
	* src/HttpResponse.cc
	* src/HttpResponse.h
	* src/HttpResponseCommand.cc
	* src/HttpResponseCommand.h
	* src/MultiDiskAdaptor.cc
	* src/MultiDiskAdaptor.h
	* src/OptionHandlerFactory.cc
	* src/RequestGroup.cc
	* src/RequestGroup.h
	* src/RequestGroupMan.cc
	* src/option_processing.cc
	* src/prefs.cc
	* src/prefs.h
	* test/CopyDiskAdaptorTest.cc
	* test/FileTest.cc
	* test/Makefile.am
	* test/Makefile.in
	* test/MultiDiskAdaptorTest.cc
	* test/TestUtil.cc
pull/1/head
Tatsuhiro Tsujikawa 2008-09-07 14:38:26 +00:00
parent 4e28efd925
commit dbc8f5b737
29 changed files with 352 additions and 13 deletions

View File

@ -1,3 +1,39 @@
2008-09-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Implemented the ability to get timestamp from remote HTTP server and
apply it to local file. To enable this feature, --remote-time option
is added. No usage text has been written yet.
If several servers returns difference timestamp, then aria2 uses latest
one.
* src/CopyDiskAdaptor.cc
* src/CopyDiskAdaptor.h
* src/DirectDiskAdaptor.cc
* src/DirectDiskAdaptor.h
* src/DiskAdaptor.h
* src/File.cc
* src/File.h
* src/HttpHeader.cc
* src/HttpHeader.h
* src/HttpResponse.cc
* src/HttpResponse.h
* src/HttpResponseCommand.cc
* src/HttpResponseCommand.h
* src/MultiDiskAdaptor.cc
* src/MultiDiskAdaptor.h
* src/OptionHandlerFactory.cc
* src/RequestGroup.cc
* src/RequestGroup.h
* src/RequestGroupMan.cc
* src/option_processing.cc
* src/prefs.cc
* src/prefs.h
* test/CopyDiskAdaptorTest.cc
* test/FileTest.cc
* test/Makefile.am
* test/Makefile.in
* test/MultiDiskAdaptorTest.cc
* test/TestUtil.cc
2008-09-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Fixed the bug that DiskWriterEntry is not created when its

View File

@ -37,6 +37,7 @@
#include "Logger.h"
#include "Util.h"
#include "message.h"
#include "File.h"
namespace aria2 {
@ -70,4 +71,20 @@ std::string CopyDiskAdaptor::getFilePath()
return storeDir+"/"+tempFilename;
}
size_t CopyDiskAdaptor::utime(const Time& actime, const Time& modtime)
{
size_t numOK = 0;
std::string topDirPath = storeDir+"/"+topDir;
for(std::deque<SharedHandle<FileEntry> >::const_iterator i =
fileEntries.begin(); i != fileEntries.end(); ++i) {
if((*i)->isExtracted() && (*i)->isRequested()) {
File f(topDirPath+"/"+(*i)->getPath());
if(f.isFile() && f.utime(actime, modtime)) {
++numOK;
}
}
}
return numOK;
}
} // namespace aria2

View File

@ -54,6 +54,8 @@ public:
virtual void onDownloadComplete();
virtual size_t utime(const Time& actime, const Time& modtime);
// tempFilename is relative to storeDir
void setTempFilename(const std::string& tempFilename) {
this->tempFilename = tempFilename;

View File

@ -34,6 +34,7 @@
/* copyright --> */
#include "DirectDiskAdaptor.h"
#include "FileEntry.h"
#include "File.h"
namespace aria2 {
@ -48,4 +49,15 @@ void DirectDiskAdaptor::onDownloadComplete()
openFile();
}
size_t DirectDiskAdaptor::utime(const Time& actime, const Time& modtime)
{
File f(getFilePath());
if(f.isFile() && f.utime(actime, modtime)) {
return 1;
} else {
return 0;
}
}
} // namespace aria2

View File

@ -47,6 +47,8 @@ public:
virtual std::string getFilePath();
virtual void onDownloadComplete();
virtual size_t utime(const Time& actime, const Time& modtime);
};
typedef SharedHandle<DirectDiskAdaptor> DirectDiskAdaptorHandle;

View File

@ -36,6 +36,7 @@
#define _D_DISK_ADAPTOR_H_
#include "BinaryStream.h"
#include "TimeA2.h"
#include <string>
#include <deque>
@ -103,6 +104,10 @@ public:
// Call one of openFile/openExistingFile/initAndOpenFile before calling this
// function.
virtual void cutTrailingGarbage() = 0;
// Returns the number of files, the actime and modtime of which are
// successfully changed.
virtual size_t utime(const Time& actime, const Time& modtime) = 0;
};
typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;

View File

@ -38,6 +38,8 @@
#include <cstring>
#include <stdlib.h>
#include <deque>
#include <sys/types.h>
#include <utime.h>
namespace aria2 {
@ -178,4 +180,21 @@ bool File::renameTo(const std::string& dest)
}
}
bool File::utime(const Time& actime, const Time& modtime) const
{
struct utimbuf ub;
ub.actime = actime.getTime();
ub.modtime = modtime.getTime();
return ::utime(name.c_str(), &ub) == 0;
}
Time File::getModifiedTime()
{
a2_struct_stat fstat;
if(fillStat(fstat) < 0) {
return 0;
}
return Time(fstat.st_mtime);
}
} // namespace aria2

View File

@ -37,6 +37,7 @@
#include "common.h"
#include "a2io.h"
#include "TimeA2.h"
#include <string>
namespace aria2 {
@ -102,6 +103,10 @@ public:
static bool isDir(const std::string& filename);
bool renameTo(const std::string& dest);
bool utime(const Time& actime, const Time& modtime) const;
Time getModifiedTime();
};
} // namespace aria2

View File

@ -68,6 +68,8 @@ const std::string HttpHeader::CONTENT_LENGTH("Content-Length");
const std::string HttpHeader::CONTENT_RANGE("Content-Range");
const std::string HttpHeader::LAST_MODIFIED("Last-Modified");
const std::string HttpHeader::HTTP_1_1("HTTP/1.1");
const std::string HttpHeader::S200("200");

View File

@ -110,6 +110,8 @@ public:
static const std::string CONTENT_RANGE;
static const std::string LAST_MODIFIED;
static const std::string HTTP_1_1;
static const std::string S200;

View File

@ -249,4 +249,9 @@ time_t HttpResponse::getRetryAfter() const
return httpHeader->getFirstAsUInt(HttpHeader::RETRY_AFTER);
}
Time HttpResponse::getLastModifiedTime() const
{
return Time::parseHTTPDate(httpHeader->getFirst(HttpHeader::LAST_MODIFIED));
}
} // namespace aria2

View File

@ -37,7 +37,7 @@
#include "common.h"
#include "SharedHandle.h"
#include "a2time.h"
#include "TimeA2.h"
#include <stdint.h>
namespace aria2 {
@ -115,6 +115,8 @@ public:
bool hasRetryAfter() const;
time_t getRetryAfter() const;
Time getLastModifiedTime() const;
};
typedef SharedHandle<HttpResponse> HttpResponseHandle;

View File

@ -120,6 +120,9 @@ bool HttpResponseCommand::executeInternal()
(StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
_requestGroup->getFilePath().c_str()).str());
}
// update last modified time
updateLastModifiedTime(httpResponse->getLastModifiedTime());
if(totalLength == 0 || httpResponse->isTransferEncodingSpecified() ||
shouldInflateContentEncoding(httpResponse)) {
// we ignore content-length when transfer-encoding is set
@ -131,11 +134,21 @@ bool HttpResponseCommand::executeInternal()
} else {
// validate totalsize
_requestGroup->validateTotalLength(httpResponse->getEntityLength());
// update last modified time
updateLastModifiedTime(httpResponse->getLastModifiedTime());
e->commands.push_back(createHttpDownloadCommand(httpResponse));
return true;
}
}
void HttpResponseCommand::updateLastModifiedTime(const Time& lastModified)
{
if(e->option->getAsBool(PREF_REMOTE_TIME)) {
_requestGroup->updateLastModifiedTime(lastModified);
}
}
static bool fileIsGzipped(const SharedHandle<HttpResponse>& httpResponse)
{
std::string filename =

View File

@ -37,6 +37,7 @@
#include "AbstractCommand.h"
#include "Decoder.h"
#include "TimeA2.h"
namespace aria2 {
@ -59,6 +60,8 @@ private:
= SharedHandle<Decoder>(),
const SharedHandle<Decoder>& contentEncodingDecoder
= SharedHandle<Decoder>());
void updateLastModifiedTime(const Time& lastModified);
protected:
bool executeInternal();

View File

@ -480,4 +480,19 @@ void MultiDiskAdaptor::setMaxOpenFiles(size_t maxOpenFiles)
_maxOpenFiles = maxOpenFiles;
}
size_t MultiDiskAdaptor::utime(const Time& actime, const Time& modtime)
{
size_t numOK = 0;
for(std::deque<SharedHandle<FileEntry> >::const_iterator i =
fileEntries.begin(); i != fileEntries.end(); ++i) {
if((*i)->isRequested()) {
File f(getTopDirPath()+"/"+(*i)->getPath());
if(f.isFile() && f.utime(actime, modtime)) {
++numOK;
}
}
}
return numOK;
}
} // namespace aria2

View File

@ -189,6 +189,8 @@ public:
virtual void cutTrailingGarbage();
void setMaxOpenFiles(size_t maxOpenFiles);
virtual size_t utime(const Time& actime, const Time& modtime);
};
typedef SharedHandle<MultiDiskAdaptor> MultiDiskAdaptorHandle;

View File

@ -154,6 +154,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
0, INT32_MAX)));
handlers.push_back(SH(new DefaultOptionHandler(PREF_SERVER_STAT_IF)));
handlers.push_back(SH(new DefaultOptionHandler(PREF_SERVER_STAT_OF)));
handlers.push_back(SH(new BooleanOptionHandler(PREF_REMOTE_TIME)));
return handlers;
}

View File

@ -123,6 +123,7 @@ RequestGroup::RequestGroup(const Option* option,
_forceHaltRequested(false),
_singleHostMultiConnectionEnabled(true),
_uriSelector(new InOrderURISelector()),
_lastModifiedTime(-1),
_option(option),
_logger(LogFactory::getInstance())
{
@ -1025,4 +1026,21 @@ void RequestGroup::setURISelector(const SharedHandle<URISelector>& uriSelector)
_uriSelector = uriSelector;
}
void RequestGroup::applyLastModifiedTimeToLocalFiles()
{
if(!_pieceStorage.isNull() && _lastModifiedTime.good()) {
time_t t = _lastModifiedTime.getTime();
_logger->info("Applying Last-Modified time: %s", ctime(&t));
size_t n =
_pieceStorage->getDiskAdaptor()->utime(Time(), _lastModifiedTime);
_logger->info("Last-Modified attrs of %zu files were updated.", n);
}
}
void RequestGroup::updateLastModifiedTime(const Time& time)
{
if(time.good() && _lastModifiedTime < time) {
_lastModifiedTime = time;
}
}
} // namespace aria2

View File

@ -38,6 +38,7 @@
#include "common.h"
#include "SharedHandle.h"
#include "TransferStat.h"
#include "TimeA2.h"
#include <string>
#include <deque>
@ -115,6 +116,8 @@ private:
SharedHandle<URISelector> _uriSelector;
Time _lastModifiedTime;
const Option* _option;
Logger* _logger;
@ -361,6 +364,10 @@ public:
static const std::string ACCEPT_METALINK;
void setURISelector(const SharedHandle<URISelector>& uriSelector);
void applyLastModifiedTimeToLocalFiles();
void updateLastModifiedTime(const Time& time);
};
typedef SharedHandle<RequestGroup> RequestGroupHandle;

View File

@ -153,8 +153,9 @@ public:
{
if(group->getNumCommand() == 0) {
try {
group->closeFile();
group->closeFile();
if(group->downloadFinished()) {
group->applyLastModifiedTimeToLocalFiles();
group->reportDownloadFinished();
if(group->allDownloadFinished()) {
group->getProgressInfoFile()->removeFile();

View File

@ -158,6 +158,7 @@ Option* createDefaultOption()
op->put(PREF_LOG_LEVEL, V_DEBUG);
op->put(PREF_URI_SELECTOR, V_INORDER);
op->put(PREF_SERVER_STAT_TIMEOUT, "86400");// 1day
op->put(PREF_REMOTE_TIME, V_FALSE);
return op;
}
@ -239,6 +240,7 @@ Option* option_processing(int argc, char* const argv[])
{ PREF_SERVER_STAT_IF.c_str(), required_argument, &lopt, 221 },
{ PREF_SERVER_STAT_OF.c_str(), required_argument, &lopt, 222 },
{ PREF_SERVER_STAT_TIMEOUT.c_str(), required_argument, &lopt, 223 },
{ PREF_REMOTE_TIME.c_str(), optional_argument, 0, 'R' },
#if defined ENABLE_BITTORRENT || defined ENABLE_METALINK
{ PREF_SHOW_FILES.c_str(), no_argument, NULL, 'S' },
{ PREF_SELECT_FILE.c_str(), required_argument, &lopt, 21 },
@ -280,7 +282,9 @@ Option* option_processing(int argc, char* const argv[])
{ "help", optional_argument, NULL, 'h' },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "Dd:o:l:s:pt:m:vh::ST:M:C:a:cU:ni:j:Z::P::q::", longOpts, &optIndex);
c = getopt_long(argc, argv,
"Dd:o:l:s:pt:m:vh::ST:M:C:a:cU:ni:j:Z::P::q::R::",
longOpts, &optIndex);
if(c == -1) {
break;
}
@ -547,6 +551,9 @@ Option* option_processing(int argc, char* const argv[])
case 'q':
cmdstream << PREF_QUIET << "=" << toBoolArg(optarg) << "\n";
break;
case 'R':
cmdstream << PREF_REMOTE_TIME << "=" << toBoolArg(optarg) << "\n";
break;
case 'v':
showVersion();
exit(EXIT_SUCCESS);

View File

@ -145,6 +145,8 @@ const std::string PREF_SERVER_STAT_TIMEOUT("server-stat-timeout");
const std::string PREF_SERVER_STAT_IF("server-stat-if");
// value: string that your file system recognizes as a file name.
const std::string PREF_SERVER_STAT_OF("server-stat-of");
// value: true | false
const std::string PREF_REMOTE_TIME("remote-time");
/**
* FTP related preferences

View File

@ -149,6 +149,8 @@ extern const std::string PREF_SERVER_STAT_TIMEOUT;
extern const std::string PREF_SERVER_STAT_IF;
// value: string that your file system recognizes as a file name.
extern const std::string PREF_SERVER_STAT_OF;
// value: true | false
extern const std::string PREF_REMOTE_TIME;
/**
* FTP related preferences

View File

@ -0,0 +1,81 @@
#include "CopyDiskAdaptor.h"
#include "FileEntry.h"
#include "Exception.h"
#include "a2io.h"
#include "array_fun.h"
#include "TestUtil.h"
#include <string>
#include <cerrno>
#include <cstring>
#include <cppunit/extensions/HelperMacros.h>
namespace aria2 {
class CopyDiskAdaptorTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(CopyDiskAdaptorTest);
CPPUNIT_TEST(testUtime);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {}
void testUtime();
};
CPPUNIT_TEST_SUITE_REGISTRATION( CopyDiskAdaptorTest );
void CopyDiskAdaptorTest::testUtime()
{
std::string storeDir = "/tmp";
std::string topDir = "aria2_CopyDiskAdaptorTest_testUtime";
std::string prefix = storeDir+"/"+topDir;
SharedHandle<FileEntry> entries[] = {
SharedHandle<FileEntry>(new FileEntry("requested", 10, 0)),
SharedHandle<FileEntry>(new FileEntry("notFound", 10, 10)),
SharedHandle<FileEntry>(new FileEntry("notRequested", 10, 20)),
SharedHandle<FileEntry>(new FileEntry("notExtracted", 10, 30)),
SharedHandle<FileEntry>(new FileEntry("anotherRequested", 10, 40)),
};
std::deque<SharedHandle<FileEntry> > fileEntries
(&entries[0], &entries[arrayLength(entries)]);
CopyDiskAdaptor adaptor;
adaptor.setStoreDir(storeDir);
adaptor.setTopDir(topDir);
adaptor.setFileEntries(fileEntries);
entries[0]->setExtracted(true);
entries[1]->setExtracted(true);
entries[2]->setExtracted(true);
entries[4]->setExtracted(true);
entries[2]->setRequested(false);
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(prefix+"/"+entries[4]->getPath(), entries[4]->getLength());
CPPUNIT_ASSERT_EQUAL((size_t)2, adaptor.utime(Time(1000), Time(2000)));
CPPUNIT_ASSERT_EQUAL((time_t)2000,
File(prefix+"/"+entries[0]->getPath())
.getModifiedTime().getTime());
CPPUNIT_ASSERT_EQUAL((time_t)2000,
File(prefix+"/"+entries[4]->getPath())
.getModifiedTime().getTime());
CPPUNIT_ASSERT((time_t)2000 != File(prefix+"/"+entries[1]->getPath())
.getModifiedTime().getTime());
CPPUNIT_ASSERT((time_t)2000 != File(prefix+"/"+entries[2]->getPath())
.getModifiedTime().getTime());
CPPUNIT_ASSERT((time_t)2000 != File(prefix+"/"+entries[3]->getPath())
.getModifiedTime().getTime());
}
} // namespace aria2

View File

@ -1,4 +1,5 @@
#include "File.h"
#include "TestUtil.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@ -20,6 +21,7 @@ class FileTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testGetDirname);
CPPUNIT_TEST(testGetBasename);
CPPUNIT_TEST(testRenameTo);
CPPUNIT_TEST(testUtime);
CPPUNIT_TEST_SUITE_END();
private:
@ -36,6 +38,7 @@ public:
void testGetDirname();
void testGetBasename();
void testRenameTo();
void testUtime();
};
@ -208,4 +211,20 @@ void FileTest::testRenameTo()
CPPUNIT_ASSERT(f.renameTo(fname));
}
void FileTest::testUtime()
{
File f("/tmp/FileTest_testUTime");
createFile(f.getPath(), 0);
CPPUNIT_ASSERT(f.utime(Time(1000), Time(2000)));
struct stat buf;
CPPUNIT_ASSERT(0 == stat(f.getPath().c_str(), &buf));
CPPUNIT_ASSERT_EQUAL((time_t)1000, buf.st_atime);
CPPUNIT_ASSERT_EQUAL((time_t)2000, f.getModifiedTime().getTime());
File notFound("/tmp/FileTest_testUTime_notFound");
notFound.remove();
CPPUNIT_ASSERT(!notFound.utime(Time(1000), Time(2000)));
}
} // namespace aria2

View File

@ -61,7 +61,8 @@ aria2c_SOURCES = AllTest.cc\
DirectDiskAdaptorTest.cc\
CookieTest.cc\
CookieStorageTest.cc\
TimeTest.cc
TimeTest.cc\
CopyDiskAdaptorTest.cc
if HAVE_LIBZ
aria2c_SOURCES += GZipDecoderTest.cc

View File

@ -194,8 +194,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
ServerStatURISelectorTest.cc InOrderURISelectorTest.cc \
ServerStatTest.cc NsCookieParserTest.cc \
DirectDiskAdaptorTest.cc CookieTest.cc CookieStorageTest.cc \
TimeTest.cc GZipDecoderTest.cc Sqlite3MozCookieParserTest.cc \
MessageDigestHelperTest.cc \
TimeTest.cc CopyDiskAdaptorTest.cc GZipDecoderTest.cc \
Sqlite3MozCookieParserTest.cc MessageDigestHelperTest.cc \
IteratableChunkChecksumValidatorTest.cc \
IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
BtBitfieldMessageTest.cc BtCancelMessageTest.cc \
@ -366,8 +366,9 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \
InOrderURISelectorTest.$(OBJEXT) ServerStatTest.$(OBJEXT) \
NsCookieParserTest.$(OBJEXT) DirectDiskAdaptorTest.$(OBJEXT) \
CookieTest.$(OBJEXT) CookieStorageTest.$(OBJEXT) \
TimeTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
$(am__objects_3) $(am__objects_4) $(am__objects_5)
TimeTest.$(OBJEXT) CopyDiskAdaptorTest.$(OBJEXT) \
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
$(am__objects_4) $(am__objects_5)
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
am__DEPENDENCIES_1 =
aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1)
@ -589,8 +590,9 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \
ServerStatURISelectorTest.cc InOrderURISelectorTest.cc \
ServerStatTest.cc NsCookieParserTest.cc \
DirectDiskAdaptorTest.cc CookieTest.cc CookieStorageTest.cc \
TimeTest.cc $(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_4) $(am__append_5)
TimeTest.cc CopyDiskAdaptorTest.cc $(am__append_1) \
$(am__append_2) $(am__append_3) $(am__append_4) \
$(am__append_5)
#aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
@ -712,6 +714,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieParserTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieStorageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CopyDiskAdaptorTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DHKeyExchangeTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DHTAnnouncePeerMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DHTAnnouncePeerReplyMessageTest.Po@am__quote@

View File

@ -18,6 +18,7 @@ class MultiDiskAdaptorTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testReadData);
CPPUNIT_TEST(testCutTrailingGarbage);
CPPUNIT_TEST(testSize);
CPPUNIT_TEST(testUtime);
CPPUNIT_TEST_SUITE_END();
private:
SharedHandle<MultiDiskAdaptor> adaptor;
@ -33,6 +34,7 @@ public:
void testReadData();
void testCutTrailingGarbage();
void testSize();
void testUtime();
};
@ -181,8 +183,7 @@ void MultiDiskAdaptorTest::testSize()
SharedHandle<FileEntry>(new FileEntry(prefix+"2", 1, 1))
};
for(size_t i = 0; i < arrayLength(entries); ++i) {
createFile(topDirPath+"/"+entries[i]->getPath(),
entries[i]->getLength());
createFile(topDirPath+"/"+entries[i]->getPath(), entries[i]->getLength());
}
std::deque<SharedHandle<FileEntry> > fileEntries
(&entries[0], &entries[arrayLength(entries)]);
@ -199,4 +200,44 @@ void MultiDiskAdaptorTest::testSize()
CPPUNIT_ASSERT_EQUAL((uint64_t)2, adaptor.size());
}
void MultiDiskAdaptorTest::testUtime()
{
std::string storeDir = "/tmp";
std::string topDir = "aria2_MultiDiskAdaptorTest_testUtime";
std::string prefix = storeDir+"/"+topDir;
SharedHandle<FileEntry> entries[] = {
SharedHandle<FileEntry>(new FileEntry("requested", 0, 0)),
SharedHandle<FileEntry>(new FileEntry("notFound", 0, 0)),
SharedHandle<FileEntry>(new FileEntry("notRequested", 0, 0)),
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());
entries[2]->setRequested(false);
std::deque<SharedHandle<FileEntry> > fileEntries
(&entries[0], &entries[arrayLength(entries)]);
MultiDiskAdaptor adaptor;
adaptor.setStoreDir(storeDir);
adaptor.setTopDir(topDir);
adaptor.setFileEntries(fileEntries);
CPPUNIT_ASSERT_EQUAL((size_t)2, adaptor.utime(Time(1000), Time(2000)));
CPPUNIT_ASSERT_EQUAL((time_t)2000,
File(prefix+"/"+entries[0]->getPath())
.getModifiedTime().getTime());
CPPUNIT_ASSERT_EQUAL((time_t)2000,
File(prefix+"/"+entries[3]->getPath())
.getModifiedTime().getTime());
CPPUNIT_ASSERT((time_t)2000 != File(prefix+"/"+entries[2]->getPath())
.getModifiedTime().getTime());
}
} // namespace aria2

View File

@ -1,15 +1,29 @@
#include "TestUtil.h"
#include "a2io.h"
#include "File.h"
#include "StringFormat.h"
#include "FatalException.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cerrno>
#include <cstring>
namespace aria2 {
void createFile(const std::string& path, size_t length)
{
File(File(path).getDirname()).mkdirs();
int fd = creat(path.c_str(), OPEN_MODE);
ftruncate(fd, length);
if(fd == -1) {
throw FatalException(StringFormat("Could not create file=%s. cause:%s",
path.c_str(), strerror(errno)).str());
}
if(-1 == ftruncate(fd, length)) {
throw FatalException(StringFormat("ftruncate failed. cause:%s",
strerror(errno)).str());
}
close(fd);
}
};