2007-09-02 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Now *.aria2 contorol file is first saved to *.aria2__temp and if
	it is successful, then renamed to *.aria2.
	This prevents *.aria2 file from being truncated	or corrupted 
when
	file system becomes out of space.
	* src/DefaultBtProgressInfoFile.cc (save)
	* src/SegmentMan.cc (save)
	* test/DefaultBtProgressInfoFileTest.cc (testSave): Implemented.
pull/1/head
Tatsuhiro Tsujikawa 2007-09-01 16:10:30 +00:00
parent 2bea8759c4
commit 57471aac9c
6 changed files with 103 additions and 16 deletions

View File

@ -1,3 +1,13 @@
2007-09-02 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Now *.aria2 contorol file is first saved to *.aria2__temp and if
it is successful, then renamed to *.aria2.
This prevents *.aria2 file from being truncated or corrupted when
file system becomes out of space.
* src/DefaultBtProgressInfoFile.cc (save)
* src/SegmentMan.cc (save)
* test/DefaultBtProgressInfoFileTest.cc (testSave): Implemented.
2007-09-01 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Reduced the fragmentation of bitfield in http/ftp download.

View File

@ -60,7 +60,8 @@ DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {}
void DefaultBtProgressInfoFile::save() {
logger->info(MSG_SAVING_SEGMENT_FILE, filename.c_str());
FILE* file = openFile(filename, "wb");
string filenameTemp = filename+"__temp";
FILE* file = openFile(filenameTemp, "wb");
try {
if(fwrite(btContext->getInfoHash(),
btContext->getInfoHashLength(), 1, file) < 1) {
@ -90,6 +91,11 @@ void DefaultBtProgressInfoFile::save() {
throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
filename.c_str(), strerror(errno));
}
if(rename(filenameTemp.c_str(), filename.c_str()) == -1) {
throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
filename.c_str(), strerror(errno));
}
}
void DefaultBtProgressInfoFile::load() {

View File

@ -99,7 +99,9 @@ void SegmentMan::save() const {
}
string segFilename = getSegmentFilePath();
logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
FILE* segFile = openSegFile(segFilename, "wb");
string segFilenameTemp = segFilename+"__temp";
FILE* segFile = openSegFile(segFilenameTemp, "wb");
try {
if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
throw string("writeError");
@ -140,6 +142,11 @@ void SegmentMan::save() const {
throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
segFilename.c_str(), strerror(errno));
}
if(rename(segFilenameTemp.c_str(), segFilename.c_str()) == -1) {
throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
segFilename.c_str(), strerror(errno));
}
}
FILE* SegmentMan::openSegFile(const string& segFilename, const string& mode) const {

View File

@ -3,6 +3,10 @@
#include "Option.h"
#include "Util.h"
#include "Exception.h"
#include "MockBtContext.h"
#include "MockPeerStorage.h"
#include "MockPieceStorage.h"
#include "prefs.h"
#include <cppunit/extensions/HelperMacros.h>
using namespace std;
@ -31,4 +35,59 @@ public:
CPPUNIT_TEST_SUITE_REGISTRATION(DefaultBtProgressInfoFileTest);
void DefaultBtProgressInfoFileTest::testSave() {
unsigned char infoHash[] = {
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa,
0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
};
Option option;
option.put(PREF_DIR, ".");
MockBtContextHandle btContext = new MockBtContext();
btContext->setInfoHash(infoHash);
btContext->setName("save-temp");
BitfieldMan bitfield(1024, 80*1024);
bitfield.setAllBit();
bitfield.unsetBit(79);
MockPieceStorageHandle pieceStorage = new MockPieceStorage();
pieceStorage->setBitfield(&bitfield);
pieceStorage->setCompletedLength(80896);
MockPeerStorageHandle peerStorage = new MockPeerStorage();
TransferStat stat;
stat.sessionUploadLength = 1024;
peerStorage->setStat(stat);
BtRuntimeHandle btRuntime = new BtRuntime();
DefaultBtProgressInfoFile infoFile(btContext, &option);
infoFile.setPieceStorage(pieceStorage);
infoFile.setPeerStorage(peerStorage);
infoFile.setBtRuntime(btRuntime);
infoFile.save();
// read and validate
ifstream in(string(option.get(PREF_DIR)+"/"+btContext->getName()+".aria2").c_str());
unsigned char infoHashRead[20];
in.read((char*)infoHashRead, sizeof(infoHashRead));
CPPUNIT_ASSERT_EQUAL(string("112233445566778899aabbccddeeff00ffffffff"),
Util::toHex(infoHashRead, sizeof(infoHashRead)));
unsigned char bitfieldRead[10];
in.read((char*)bitfieldRead, sizeof(bitfieldRead));
CPPUNIT_ASSERT_EQUAL(string("fffffffffffffffffffe"),
Util::toHex(bitfieldRead, sizeof(bitfieldRead)));
int64_t allTimeDownloadLengthRead = 0;
in.read((char*)&allTimeDownloadLengthRead, sizeof(allTimeDownloadLengthRead));
CPPUNIT_ASSERT_EQUAL((int64_t)80896, allTimeDownloadLengthRead);
int64_t allTimeUploadLengthRead = 0;
in.read((char*)&allTimeUploadLengthRead, sizeof(allTimeUploadLengthRead));
CPPUNIT_ASSERT_EQUAL((int64_t)1024, allTimeUploadLengthRead);
string temp;
getline(in, temp);
CPPUNIT_ASSERT_EQUAL(string(""), temp);
CPPUNIT_ASSERT(in.eof());
}

View File

@ -1,6 +1,7 @@
TESTS = aria2c
check_PROGRAMS = $(TESTS)
aria2c_SOURCES = AllTest.cc\
DefaultBtProgressInfoFileTest.cc\
RequestGroupTest.cc\
PStringBuildVisitorTest.cc\
ParameterizedStringParserTest.cc\

View File

@ -110,12 +110,13 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
am__EXEEXT_1 = aria2c$(EXEEXT)
am__aria2c_SOURCES_DIST = AllTest.cc RequestGroupTest.cc \
PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \
UtilTest.cc AlphaNumberDecoratorTest.cc \
FileUriListParserTest.cc StreamUriListParserTest.cc \
HttpHeaderProcessorTest.cc CookieBoxTest.cc RequestTest.cc \
CookieParserTest.cc HttpRequestTest.cc CookieBoxFactoryTest.cc \
am__aria2c_SOURCES_DIST = AllTest.cc DefaultBtProgressInfoFileTest.cc \
RequestGroupTest.cc PStringBuildVisitorTest.cc \
ParameterizedStringParserTest.cc UtilTest.cc \
AlphaNumberDecoratorTest.cc FileUriListParserTest.cc \
StreamUriListParserTest.cc HttpHeaderProcessorTest.cc \
CookieBoxTest.cc RequestTest.cc CookieParserTest.cc \
HttpRequestTest.cc CookieBoxFactoryTest.cc \
RequestGroupManTest.cc RequestFactoryTest.cc \
NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \
OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \
@ -195,8 +196,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc RequestGroupTest.cc \
@ENABLE_METALINK_TRUE@am__objects_3 = MetalinkerTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessorTest.$(OBJEXT)
am_aria2c_OBJECTS = AllTest.$(OBJEXT) RequestGroupTest.$(OBJEXT) \
PStringBuildVisitorTest.$(OBJEXT) \
am_aria2c_OBJECTS = AllTest.$(OBJEXT) \
DefaultBtProgressInfoFileTest.$(OBJEXT) \
RequestGroupTest.$(OBJEXT) PStringBuildVisitorTest.$(OBJEXT) \
ParameterizedStringParserTest.$(OBJEXT) UtilTest.$(OBJEXT) \
AlphaNumberDecoratorTest.$(OBJEXT) \
FileUriListParserTest.$(OBJEXT) \
@ -403,12 +405,13 @@ target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
TESTS = aria2c
aria2c_SOURCES = AllTest.cc RequestGroupTest.cc \
PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \
UtilTest.cc AlphaNumberDecoratorTest.cc \
FileUriListParserTest.cc StreamUriListParserTest.cc \
HttpHeaderProcessorTest.cc CookieBoxTest.cc RequestTest.cc \
CookieParserTest.cc HttpRequestTest.cc CookieBoxFactoryTest.cc \
aria2c_SOURCES = AllTest.cc DefaultBtProgressInfoFileTest.cc \
RequestGroupTest.cc PStringBuildVisitorTest.cc \
ParameterizedStringParserTest.cc UtilTest.cc \
AlphaNumberDecoratorTest.cc FileUriListParserTest.cc \
StreamUriListParserTest.cc HttpHeaderProcessorTest.cc \
CookieBoxTest.cc RequestTest.cc CookieParserTest.cc \
HttpRequestTest.cc CookieBoxFactoryTest.cc \
RequestGroupManTest.cc RequestFactoryTest.cc \
NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \
OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \
@ -516,6 +519,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtAnnounceTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtContextTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtMessageDispatcherTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtProgressInfoFileTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtRequestFactoryTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriterTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerListProcessorTest.Po@am__quote@