]> git.saurik.com Git - apt.git/commitdiff
FileFd: Add a buffered writing mode
authorJulian Andres Klode <jak@debian.org>
Sun, 27 Dec 2015 13:29:01 +0000 (14:29 +0100)
committerJulian Andres Klode <jak@debian.org>
Sun, 27 Dec 2015 15:23:32 +0000 (16:23 +0100)
This is somewhat experimental right now, and might not work
for everyone, so it is on an opt-in basis.

apt-pkg/contrib/fileutl.cc
apt-pkg/contrib/fileutl.h

index ecc8c83fd3b7a4ae5af660205bdf66fb280712b8..71dfc83a21045161c5a765ae1a50535b75ab89a5 100644 (file)
@@ -955,6 +955,7 @@ struct APT_HIDDEN simple_buffer {                                                   /*{{{*/
                                                                        /*}}}*/
 
 class APT_HIDDEN FileFdPrivate {                                                       /*{{{*/
+   friend class BufferedWriteFileFdPrivate;
 protected:
    FileFd * const filefd;
    simple_buffer buffer;
@@ -1149,6 +1150,154 @@ public:
    virtual ~FileFdPrivate() {}
 };
                                                                        /*}}}*/
+class APT_HIDDEN BufferedWriteFileFdPrivate : public FileFdPrivate {                                                   /*{{{*/
+protected:
+   FileFdPrivate *wrapped;
+   simple_buffer writebuffer;
+
+public:
+
+   explicit BufferedWriteFileFdPrivate(FileFdPrivate *Priv) :
+      FileFdPrivate(Priv->filefd), wrapped(Priv) {};
+
+   virtual APT::Configuration::Compressor get_compressor() const override
+   {
+      return wrapped->get_compressor();
+   }
+   virtual void set_compressor(APT::Configuration::Compressor const &compressor)  override
+   {
+      return wrapped->set_compressor(compressor);
+   }
+   virtual unsigned int get_openmode() const  override
+   {
+      return wrapped->get_openmode();
+   }
+   virtual void set_openmode(unsigned int openmode)  override
+   {
+      return wrapped->set_openmode(openmode);
+   }
+   virtual bool get_is_pipe() const  override
+   {
+      return wrapped->get_is_pipe();
+   }
+   virtual void set_is_pipe(bool is_pipe) override
+   {
+      FileFdPrivate::set_is_pipe(is_pipe);
+      wrapped->set_is_pipe(is_pipe);
+   }
+   virtual unsigned long long get_seekpos() const override
+   {
+      return wrapped->get_seekpos();
+   }
+   virtual void set_seekpos(unsigned long long seekpos) override
+   {
+      return wrapped->set_seekpos(seekpos);
+   }
+   virtual bool InternalOpen(int const iFd, unsigned int const Mode) override
+   {
+      if (InternalFlush() == false)
+        return false;
+      return wrapped->InternalOpen(iFd, Mode);
+   }
+   virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) override
+   {
+      if (InternalFlush() == false)
+        return -1;
+      return wrapped->InternalUnbufferedRead(To, Size);
+
+   }
+   virtual bool InternalReadError() override
+   {
+      return wrapped->InternalReadError();
+   }
+   virtual char * InternalReadLine(char * To, unsigned long long Size) override
+   {
+      if (InternalFlush() == false)
+        return nullptr;
+      return wrapped->InternalReadLine(To, Size);
+   }
+   virtual bool InternalFlush() override
+   {
+      size_t written = 0;
+      char *data = writebuffer.get();
+      auto size = writebuffer.size();
+
+      while (written <= size) {
+        auto written_this_time = wrapped->InternalWrite(data + written, size - written);
+        if (written_this_time < 0)
+           return false;
+        if (written_this_time == 0)
+           break;
+
+        written += written_this_time;
+      }
+
+      writebuffer.reset();
+      return true;
+   }
+   virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
+   {
+      size_t written = 0;
+
+      while (written < Size) {
+        auto buffered = writebuffer.write(static_cast<char const*>(From) + written, Size - written);
+
+        written += buffered;
+
+        if (writebuffer.full() && InternalFlush() == false)
+              return -1;
+      }
+
+      return written;
+   }
+   virtual bool InternalWriteError()
+   {
+      return wrapped->InternalWriteError();
+   }
+   virtual bool InternalSeek(unsigned long long const To)
+   {
+      if (InternalFlush() == false)
+        return false;
+      return wrapped->InternalSeek(To);
+   }
+   virtual bool InternalSkip(unsigned long long Over)
+   {
+      if (InternalFlush() == false)
+        return false;
+      return wrapped->InternalSkip(Over);
+   }
+   virtual bool InternalTruncate(unsigned long long const Size)
+   {
+      if (InternalFlush() == false)
+        return false;
+      return wrapped->InternalTruncate(Size);
+   }
+   virtual unsigned long long InternalTell()
+   {
+      if (InternalFlush() == false)
+        return -1;
+      return wrapped->InternalTell();
+   }
+   virtual unsigned long long InternalSize()
+   {
+      if (InternalFlush() == false)
+        return -1;
+      return wrapped->InternalSize();
+   }
+   virtual bool InternalClose(std::string const &FileName)
+   {
+      return wrapped->InternalClose(FileName);
+   }
+   virtual bool InternalAlwaysAutoClose() const
+   {
+      return wrapped->InternalAlwaysAutoClose();
+   }
+   virtual ~BufferedWriteFileFdPrivate()
+   {
+      delete wrapped;
+   }
+};
+                                                                       /*}}}*/
 class APT_HIDDEN GzipFileFdPrivate: public FileFdPrivate {                             /*{{{*/
 #ifdef HAVE_ZLIB
 public:
@@ -1985,6 +2134,9 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
       else
         d = new PipedFileFdPrivate(this);
 
+      if (Mode & BufferedWrite)
+        d = new BufferedWriteFileFdPrivate(d);
+
       d->set_openmode(Mode);
       d->set_compressor(compressor);
       if ((Flags & AutoClose) != AutoClose && d->InternalAlwaysAutoClose())
index 8cfb2e989eb97f15cfd80d57888f040d7c6ec412..8619047a0aa5406a26b86f2572e41d8e3564031b 100644 (file)
@@ -66,6 +66,7 @@ class FileFd
        Exclusive = (1 << 3),
        Atomic = Exclusive | (1 << 4),
        Empty = (1 << 5),
+       BufferedWrite = (1 << 6),
 
        WriteEmpty = ReadWrite | Create | Empty,
        WriteExists = ReadWrite,