Преглед на файлове

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
Tatsuhiro Tsujikawa преди 16 години
родител
ревизия
eeece05063
променени са 7 файла, в които са добавени 47 реда и са изтрити 8 реда
  1. 13 0
      ChangeLog
  2. 4 1
      src/AbstractSingleDiskAdaptor.cc
  3. 3 0
      src/AbstractSingleDiskAdaptor.h
  4. 8 5
      src/BtCheckIntegrityEntry.cc
  5. 2 0
      src/DiskAdaptor.h
  6. 2 0
      src/MultiDiskAdaptor.h
  7. 15 2
      src/RequestGroup.cc

+ 13 - 0
ChangeLog

@@ -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>
 
 	Fixed the bug that with --check-integrity option aria2 reports

+ 4 - 1
src/AbstractSingleDiskAdaptor.cc

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

+ 3 - 0
src/AbstractSingleDiskAdaptor.h

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

+ 8 - 5
src/BtCheckIntegrityEntry.cc

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

+ 2 - 0
src/DiskAdaptor.h

@@ -100,6 +100,8 @@ public:
 
   virtual void disableReadOnly() {}
 
+  virtual bool isReadOnlyEnabled() const { return false; }
+
   // 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
   // length.

+ 2 - 0
src/MultiDiskAdaptor.h

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

+ 15 - 2
src/RequestGroup.cc

@@ -311,7 +311,20 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands,
 	}
       }
       _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)) {
 	std::deque<Command*> commands;
 	DHTSetup().setup(commands, e, _option);
@@ -371,7 +384,7 @@ void RequestGroup::processCheckIntegrityEntry(std::deque<Command*>& commands,
   if(e->option->getAsBool(PREF_CHECK_INTEGRITY) &&
      entry->isValidationReady()) {
     entry->initValidator();
-    entry->cutTrailingGarbage();    
+    entry->cutTrailingGarbage();
     e->_checkIntegrityMan->pushEntry(entry);
   } else
 #endif // ENABLE_MESSAGE_DIGEST