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

Fixed the bug that read-only file with wrong file size will
	cause error because it cannot be truncated to the correct size.
	Now if file size is different than the expected one, re-open
	file in writable mode.
	* src/AbstractSingleDiskAdaptor.cc
	* src/AbstractSingleDiskAdaptor.h
	* src/BtCheckIntegrityEntry.cc
	* src/DiskAdaptor.h
	* src/MultiDiskAdaptor.h
	* src/RequestGroup.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-05-03 11:00:39 +00:00
parent ee229c6f00
commit eeece05063
7 changed files with 47 additions and 8 deletions

View File

@ -1,3 +1,16 @@
2009-05-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that read-only file with wrong file size will cause
error because it cannot be truncated to the correct size. Now if
file size is different than the expected one, re-open file in
writable mode.
* src/AbstractSingleDiskAdaptor.cc
* src/AbstractSingleDiskAdaptor.h
* src/BtCheckIntegrityEntry.cc
* src/DiskAdaptor.h
* src/MultiDiskAdaptor.h
* src/RequestGroup.cc
2009-05-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2009-05-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that with --check-integrity option aria2 reports Fixed the bug that with --check-integrity option aria2 reports

View File

@ -42,7 +42,8 @@
namespace aria2 { namespace aria2 {
AbstractSingleDiskAdaptor::AbstractSingleDiskAdaptor():totalLength(0) {} AbstractSingleDiskAdaptor::AbstractSingleDiskAdaptor():
totalLength(0), _readOnly(false) {}
AbstractSingleDiskAdaptor::~AbstractSingleDiskAdaptor() {} AbstractSingleDiskAdaptor::~AbstractSingleDiskAdaptor() {}
@ -126,11 +127,13 @@ bool AbstractSingleDiskAdaptor::directIOAllowed() const
void AbstractSingleDiskAdaptor::enableReadOnly() void AbstractSingleDiskAdaptor::enableReadOnly()
{ {
diskWriter->enableReadOnly(); diskWriter->enableReadOnly();
_readOnly = true;
} }
void AbstractSingleDiskAdaptor::disableReadOnly() void AbstractSingleDiskAdaptor::disableReadOnly()
{ {
diskWriter->disableReadOnly(); diskWriter->disableReadOnly();
_readOnly = false;
} }
void AbstractSingleDiskAdaptor::cutTrailingGarbage() void AbstractSingleDiskAdaptor::cutTrailingGarbage()

View File

@ -46,6 +46,7 @@ class AbstractSingleDiskAdaptor : public DiskAdaptor {
protected: protected:
SharedHandle<DiskWriter> diskWriter; SharedHandle<DiskWriter> diskWriter;
uint64_t totalLength; uint64_t totalLength;
bool _readOnly;
public: public:
AbstractSingleDiskAdaptor(); AbstractSingleDiskAdaptor();
@ -84,6 +85,8 @@ public:
// Make sure that DiskWriter is set before calling this function. // Make sure that DiskWriter is set before calling this function.
virtual void disableReadOnly(); virtual void disableReadOnly();
virtual bool isReadOnlyEnabled() const { return _readOnly; }
virtual void cutTrailingGarbage(); virtual void cutTrailingGarbage();
virtual std::string getFilePath() = 0; virtual std::string getFilePath() = 0;

View File

@ -51,11 +51,14 @@ BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {}
void BtCheckIntegrityEntry::onDownloadIncomplete(std::deque<Command*>& commands, void BtCheckIntegrityEntry::onDownloadIncomplete(std::deque<Command*>& commands,
DownloadEngine* e) DownloadEngine* e)
{ {
// Now reopen DiskAdaptor with read only disabled. const SharedHandle<DiskAdaptor>& diskAdaptor =
_requestGroup->getPieceStorage()->getDiskAdaptor()->closeFile(); _requestGroup->getPieceStorage()->getDiskAdaptor();
_requestGroup->getPieceStorage()->getDiskAdaptor()->disableReadOnly(); if(diskAdaptor->isReadOnlyEnabled()) {
_requestGroup->getPieceStorage()->getDiskAdaptor()->openFile(); // Now reopen DiskAdaptor with read only disabled.
diskAdaptor->closeFile();
diskAdaptor->disableReadOnly();
diskAdaptor->openFile();
}
SharedHandle<BtFileAllocationEntry> entry SharedHandle<BtFileAllocationEntry> entry
(new BtFileAllocationEntry(_requestGroup)); (new BtFileAllocationEntry(_requestGroup));
proceedFileAllocation(commands, entry, e); proceedFileAllocation(commands, entry, e);

View File

@ -100,6 +100,8 @@ public:
virtual void disableReadOnly() {} virtual void disableReadOnly() {}
virtual bool isReadOnlyEnabled() const { return false; }
// Assumed each file length is stored in fileEntries or DiskAdaptor knows it. // Assumed each file length is stored in fileEntries or DiskAdaptor knows it.
// If each actual file's length is larger than that, truncate file to that // If each actual file's length is larger than that, truncate file to that
// length. // length.

View File

@ -155,6 +155,8 @@ public:
virtual void disableReadOnly(); virtual void disableReadOnly();
virtual bool isReadOnlyEnabled() const { return _readOnly; }
void setPieceLength(size_t pieceLength) { void setPieceLength(size_t pieceLength) {
this->pieceLength = pieceLength; this->pieceLength = pieceLength;
} }

View File

@ -311,7 +311,20 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands,
} }
} }
_progressInfoFile = progressInfoFile; _progressInfoFile = progressInfoFile;
{
uint64_t actualFileSize = _pieceStorage->getDiskAdaptor()->size();
if(actualFileSize != btContext->getTotalLength()) {
// Re-open file in writable mode to allow the program
// truncate the file to the specified length
_logger->debug("File size not match. Re-open file in writable mode."
" Expected:%s Actual:%s",
Util::uitos(btContext->getTotalLength()).c_str(),
Util::uitos(actualFileSize).c_str());
_pieceStorage->getDiskAdaptor()->closeFile();
_pieceStorage->getDiskAdaptor()->disableReadOnly();
_pieceStorage->getDiskAdaptor()->openFile();
}
}
if(!btContext->isPrivate() && _option->getAsBool(PREF_ENABLE_DHT)) { if(!btContext->isPrivate() && _option->getAsBool(PREF_ENABLE_DHT)) {
std::deque<Command*> commands; std::deque<Command*> commands;
DHTSetup().setup(commands, e, _option); DHTSetup().setup(commands, e, _option);
@ -371,7 +384,7 @@ void RequestGroup::processCheckIntegrityEntry(std::deque<Command*>& commands,
if(e->option->getAsBool(PREF_CHECK_INTEGRITY) && if(e->option->getAsBool(PREF_CHECK_INTEGRITY) &&
entry->isValidationReady()) { entry->isValidationReady()) {
entry->initValidator(); entry->initValidator();
entry->cutTrailingGarbage(); entry->cutTrailingGarbage();
e->_checkIntegrityMan->pushEntry(entry); e->_checkIntegrityMan->pushEntry(entry);
} else } else
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST