mirror of https://github.com/aria2/aria2
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.ccpull/1/head
parent
4e28efd925
commit
dbc8f5b737
36
ChangeLog
36
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
19
src/File.cc
19
src/File.cc
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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@
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue