Browse Source

2007-12-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Rewritten direct I/O support routine
	* src/SingleFileAllocationIterator.cc
	* src/MultiDiskAdaptor.{h, cc}
	* src/ByteArrayDiskWriter.h
	* src/AbstractSingleDiskAdaptor.h
	* src/AbstractDiskWriter.cc
	* src/DefaultPieceStorage.cc
	* src/DiskWriter.h
	* src/BinaryStream.h
	* src/IteratableChunkChecksumValidator.cc
	* src/IteratableChecksumValidator.cc
	* src/CheckIntegrityEntry.cc
	* src/FileAllocationEntry.cc
Tatsuhiro Tsujikawa 18 years ago
parent
commit
2850c16f8a

+ 16 - 0
ChangeLog

@@ -1,3 +1,19 @@
+2007-12-06  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Rewritten direct I/O support routine
+	* src/SingleFileAllocationIterator.cc
+	* src/MultiDiskAdaptor.{h, cc}
+	* src/ByteArrayDiskWriter.h
+	* src/AbstractSingleDiskAdaptor.h
+	* src/AbstractDiskWriter.cc
+	* src/DefaultPieceStorage.cc
+	* src/DiskWriter.h
+	* src/BinaryStream.h
+	* src/IteratableChunkChecksumValidator.cc
+	* src/IteratableChecksumValidator.cc
+	* src/CheckIntegrityEntry.cc
+	* src/FileAllocationEntry.cc
+
 2007-12-06  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Fixed typo

+ 6 - 5
src/AbstractDiskWriter.cc

@@ -47,8 +47,7 @@
 
 AbstractDiskWriter::AbstractDiskWriter():
   fd(-1),
-  logger(LogFactory::getInstance())
-{}
+  logger(LogFactory::getInstance()) {}
 
 AbstractDiskWriter::~AbstractDiskWriter()
 {
@@ -167,9 +166,11 @@ int64_t AbstractDiskWriter::size() const
 void AbstractDiskWriter::enableDirectIO()
 {
 #ifdef ENABLE_DIRECT_IO
-  int32_t flg;
-  while((flg = fcntl(fd, F_GETFL)) == -1 && errno == EINTR);
-  while(fcntl(fd, F_SETFL, flg|O_DIRECT) == -1 && errno == EINTR);
+  if(_directIOAllowed) {
+    int32_t flg;
+    while((flg = fcntl(fd, F_GETFL)) == -1 && errno == EINTR);
+    while(fcntl(fd, F_SETFL, flg|O_DIRECT) == -1 && errno == EINTR);
+  }
 #endif // ENABLE_DIRECT_IO
 }
 

+ 6 - 1
src/AbstractSingleDiskAdaptor.h

@@ -77,7 +77,12 @@ public:
   virtual void enableDirectIO();
 
   virtual void disableDirectIO();
-
+  
+  virtual bool directIOAllowed() const
+  {
+    return diskWriter->directIOAllowed();
+  }
+  
   void setDiskWriter(const DiskWriterHandle diskWriter) {
     this->diskWriter = diskWriter;
   }

+ 6 - 0
src/BinaryStream.h

@@ -47,6 +47,12 @@ public:
   virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
 
   virtual void truncate(int64_t length) = 0;
+
+  virtual void enableDirectIO() = 0;
+
+  virtual void disableDirectIO() = 0;
+  
+  virtual bool directIOAllowed() const = 0;
 };
 
 typedef SharedHandle<BinaryStream> BinaryStreamHandle;

+ 0 - 2
src/BtCheckIntegrityEntry.cc

@@ -66,7 +66,5 @@ Commands BtCheckIntegrityEntry::onDownloadFinished(DownloadEngine* e)
   // are valid, then aira2 goes to seeding mode. Sometimes it is better
   // to exit rather than doing seeding. So, it would be good to toggle this
   // behavior.
-  // TODO If FileAllocationEntry is not going to be used, call
-  // DiskAdaptor::disableDirectIO() manually here.
   return onDownloadIncomplete(e);
 }

+ 5 - 0
src/ByteArrayDiskWriter.h

@@ -70,6 +70,11 @@ public:
 
   virtual void disableDirectIO() {}
 
+  virtual bool directIOAllowed() const
+  {
+    return false;
+  }
+
   void setString(const string& s)
   {
     buf.str(s);

+ 2 - 15
src/CheckIntegrityEntry.cc

@@ -36,27 +36,14 @@
 #include "Command.h"
 #include "RequestGroup.h"
 #include "IteratableValidator.h"
-#include "prefs.h"
-#include "PieceStorage.h"
-#include "DownloadContext.h"
-#include "DiskAdaptor.h"
-#include "Option.h"
 
 CheckIntegrityEntry::CheckIntegrityEntry(RequestGroup* requestGroup,
 					 Command* nextCommand):
   RequestGroupEntry(requestGroup, nextCommand),
   _validator(0)
-{
-  if(_requestGroup->getOption()->getAsBool(PREF_ENABLE_DIRECT_IO) &&
-     _requestGroup->getDownloadContext()->getFileEntries().size() == 1) {
-    _requestGroup->getPieceStorage()->getDiskAdaptor()->enableDirectIO();
-  }
-}
+{}
 
-CheckIntegrityEntry::~CheckIntegrityEntry()
-{
-  // TODO DiskAdaptor::disableIO() will be called from ~FileAllocationEntry
-}
+CheckIntegrityEntry::~CheckIntegrityEntry() {}
 
 void CheckIntegrityEntry::validateChunk()
 {

+ 3 - 0
src/DefaultPieceStorage.cc

@@ -434,6 +434,7 @@ void DefaultPieceStorage::initStorage()
   if(downloadContext->getFileMode() == DownloadContext::SINGLE) {
     logger->debug("Instantiating DirectDiskAdaptor");
     DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
+    writer->setDirectIOAllowed(option->getAsBool(PREF_ENABLE_DIRECT_IO));
     DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
     directDiskAdaptor->setDiskWriter(writer);
     directDiskAdaptor->setTotalLength(downloadContext->getTotalLength());
@@ -443,12 +444,14 @@ void DefaultPieceStorage::initStorage()
     if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
       logger->debug("Instantiating MultiDiskAdaptor");
       MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor();
+      multiDiskAdaptor->setDirectIOAllowed(option->getAsBool(PREF_ENABLE_DIRECT_IO));
       multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength());
       multiDiskAdaptor->setTopDir(downloadContext->getName());
       this->diskAdaptor = multiDiskAdaptor;
     } else {
       logger->debug("Instantiating CopyDiskAdaptor");
       DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
+      writer->setDirectIOAllowed(option->getAsBool(PREF_ENABLE_DIRECT_IO));
       CopyDiskAdaptorHandle copyDiskAdaptor = new CopyDiskAdaptor();
       copyDiskAdaptor->setDiskWriter(writer);
       copyDiskAdaptor->setTempFilename(downloadContext->getName()+".a2tmp");

+ 2 - 2
src/DiskAdaptor.h

@@ -90,9 +90,9 @@ public:
 
   virtual FileAllocationIteratorHandle fileAllocationIterator() = 0;
 
-  virtual void enableDirectIO() {};
+  virtual void enableDirectIO() {}
 
-  virtual void disableDirectIO() {};
+  virtual void disableDirectIO() {}
 };
 
 typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;

+ 15 - 0
src/DiskWriter.h

@@ -42,7 +42,12 @@
  *
  */
 class DiskWriter:public BinaryStream {
+protected:
+  bool _directIOAllowed;
+
 public:
+  DiskWriter():_directIOAllowed(false) {}
+
   virtual ~DiskWriter() {}
   /**
    * Creates a file output stream to write to the file with the specified name.
@@ -75,6 +80,16 @@ public:
   virtual void enableDirectIO() = 0;
 
   virtual void disableDirectIO() = 0;
+
+  virtual bool directIOAllowed() const
+  {
+    return _directIOAllowed;
+  }
+
+  void setDirectIOAllowed(bool f)
+  {
+    _directIOAllowed = f;
+  }
 };
 
 typedef SharedHandle<DiskWriter> DiskWriterHandle;

+ 2 - 12
src/FileAllocationEntry.cc

@@ -38,24 +38,14 @@
 #include "RequestGroup.h"
 #include "PieceStorage.h"
 #include "DiskAdaptor.h"
-#include "prefs.h"
-#include "Option.h"
 
 FileAllocationEntry::FileAllocationEntry(RequestGroup* requestGroup, Command* nextCommand):
   RequestGroupEntry(requestGroup, nextCommand),
   _fileAllocationIterator(requestGroup->getPieceStorage()->getDiskAdaptor()->fileAllocationIterator())
-{
-  if(_requestGroup->getOption()->getAsBool(PREF_ENABLE_DIRECT_IO)) {
-    _requestGroup->getPieceStorage()->getDiskAdaptor()->enableDirectIO();
-  }
-}
+{}
 
 FileAllocationEntry:: ~FileAllocationEntry()
-{
-  if(_requestGroup->getOption()->getAsBool(PREF_ENABLE_DIRECT_IO)) {
-    _requestGroup->getPieceStorage()->getDiskAdaptor()->disableDirectIO();
-  }
-}
+{}
 
 int64_t FileAllocationEntry::getCurrentLength()
 {

+ 7 - 1
src/IteratableChecksumValidator.cc

@@ -82,7 +82,12 @@ void IteratableChecksumValidator::validateChunk()
 
 bool IteratableChecksumValidator::finished() const
 {
-  return _currentOffset >= _dctx->getTotalLength();
+  if(_currentOffset >= _dctx->getTotalLength()) {
+    _pieceStorage->getDiskAdaptor()->disableDirectIO();
+    return true;
+  } else {
+    return false;
+  }
 }
 
 int64_t IteratableChecksumValidator::getTotalLength() const
@@ -97,6 +102,7 @@ void IteratableChecksumValidator::init()
 #else
   _buffer = new unsigned char[BUFSIZE];
 #endif // HAVE_POSIX_MEMALIGN
+  _pieceStorage->getDiskAdaptor()->enableDirectIO();
   _currentOffset = 0;
   _ctx = new MessageDigestContext();
   _ctx->trySetAlgo(_dctx->getChecksumHashAlgo());

+ 9 - 1
src/IteratableChunkChecksumValidator.cc

@@ -116,6 +116,9 @@ void IteratableChunkChecksumValidator::init()
 #else
   _buffer = new unsigned char[BUFSIZE];
 #endif // HAVE_POSIX_MEMALIGN
+  if(_dctx->getFileEntries().size() == 1) {
+    _pieceStorage->getDiskAdaptor()->enableDirectIO();
+  }
   _ctx = new MessageDigestContext();
   _ctx->trySetAlgo(_dctx->getPieceHashAlgo());
   _ctx->digestInit();
@@ -157,7 +160,12 @@ string IteratableChunkChecksumValidator::digest(int64_t offset, int32_t length)
 
 bool IteratableChunkChecksumValidator::finished() const
 {
-  return _currentIndex >= (uint32_t)_dctx->getNumPieces();
+  if(_currentIndex >= (uint32_t)_dctx->getNumPieces()) {
+    _pieceStorage->getDiskAdaptor()->disableDirectIO();
+    return true;
+  } else {
+    return false;
+  }
 }
 
 int64_t IteratableChunkChecksumValidator::getCurrentOffset() const

+ 1 - 0
src/MultiDiskAdaptor.cc

@@ -51,6 +51,7 @@ void MultiDiskAdaptor::resetDiskWriterEntries()
     } else {
       entry->setDiskWriter(new DefaultDiskWriter());
     }
+    entry->getDiskWriter()->setDirectIOAllowed(_directIOAllowed);
     diskWriterEntries.push_back(entry);
   }
 }

+ 12 - 0
src/MultiDiskAdaptor.h

@@ -116,6 +116,8 @@ private:
   int32_t pieceLength;
   DiskWriterEntries diskWriterEntries;
 
+  bool _directIOAllowed;
+
   void resetDiskWriterEntries();
 
   void mkdir() const;
@@ -178,6 +180,16 @@ public:
   int32_t getPieceLength() const {
     return pieceLength;
   }
+
+  virtual bool directIOAllowed() const
+  {
+    return _directIOAllowed;
+  }
+
+  void setDirectIOAllowed(bool b)
+  {
+    _directIOAllowed = b;
+  }
 };
 
 typedef SharedHandle<MultiDiskAdaptor> MultiDiskAdaptorHandle;

+ 6 - 1
src/SingleFileAllocationIterator.cc

@@ -40,11 +40,16 @@
 #define BUFSIZE (256*1024)
 
 SingleFileAllocationIterator::SingleFileAllocationIterator(BinaryStream* stream, int64_t offset, int64_t totalLength):_stream(stream), _offset(offset), _totalLength(totalLength), _buffer(0)
-{}
+{
+  if(_offset%512 == 0) {
+    _stream->enableDirectIO();
+  }
+}
 
 SingleFileAllocationIterator::~SingleFileAllocationIterator()
 {
   delete [] _buffer;
+  _stream->disableDirectIO();
 }
 
 void SingleFileAllocationIterator::init()