using namespace std;
+/* Should be a multiple of the common page size (4096) */
+static constexpr unsigned long long APT_BUFFER_SIZE = 64 * 1024;
+
// RunScripts - Run a set of scripts from a configuration subtree /*{{{*/
// ---------------------------------------------------------------------
/* */
return false;
// Buffered copy between fds
- constexpr size_t BufSize = 64000;
+ constexpr size_t BufSize = APT_BUFFER_SIZE;
std::unique_ptr<unsigned char[]> Buf(new unsigned char[BufSize]);
unsigned long long ToRead = 0;
do {
reset(4096);
}
~simple_buffer() {
- delete buffer;
+ delete[] buffer;
}
const char *get() const { return buffer + bufferstart; }
}
ssize_t write(const void *from, unsigned long long requested_size) APT_MUSTCHECK
{
- if (buffersize_max - size() < requested_size)
- requested_size = buffersize_max - size();
- memcpy(buffer + bufferend, from, requested_size);
+ if (free() < requested_size)
+ requested_size = free();
+ memcpy(getend(), from, requested_size);
bufferend += requested_size;
if (bufferstart == bufferend)
bufferstart = bufferend = 0;
{
buffer.reset();
unsigned long long actualread = 0;
- if (filefd->Read(buffer.get(), buffer.buffersize_max, &actualread) == false)
+ if (filefd->Read(buffer.getend(), buffer.free(), &actualread) == false)
return nullptr;
buffer.bufferend = actualread;
if (buffer.size() == 0)
return filefd->FileFdError("Seek on file %s because it couldn't be reopened", filefd->FileName.c_str());
buffer.reset();
+ set_seekpos(0);
if (To != 0)
return filefd->Skip(To);
if (written < 0 && errno == EINTR)
continue;
if (written < 0)
- return false;
+ return wrapped->InternalWriteError();
writebuffer.bufferstart += written;
}
}
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);
+ // Optimisation: If the buffer is empty and we have more to write than
+ // would fit in the buffer (or equal number of bytes), write directly.
+ if (writebuffer.empty() == true && Size >= writebuffer.free())
+ return wrapped->InternalWrite(From, Size);
- written += buffered;
+ // Write as much into the buffer as possible and then flush if needed
+ auto written = writebuffer.write(From, Size);
- if (writebuffer.full() && InternalFlush() == false)
- return -1;
- }
+ if (writebuffer.full() && InternalFlush() == false)
+ return -1;
return written;
}
};
/*}}}*/
class APT_HIDDEN Lz4FileFdPrivate: public FileFdPrivate { /*{{{*/
- static constexpr unsigned long long BLK_SIZE = 64 * 1024;
static constexpr unsigned long long LZ4_HEADER_SIZE = 19;
static constexpr unsigned long long LZ4_FOOTER_SIZE = 4;
#ifdef HAVE_LZ4
FileFd backend;
simple_buffer lz4_buffer;
// Count of bytes that the decompressor expects to read next, or buffer size.
- size_t next_to_load = BLK_SIZE;
+ size_t next_to_load = APT_BUFFER_SIZE;
public:
virtual bool InternalOpen(int const iFd, unsigned int const Mode) override
{
if ((Mode & FileFd::WriteOnly) == FileFd::WriteOnly) {
res = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION);
- lz4_buffer.reset(LZ4F_compressBound(BLK_SIZE, nullptr)
+ lz4_buffer.reset(LZ4F_compressBound(APT_BUFFER_SIZE, nullptr)
+ LZ4_HEADER_SIZE + LZ4_FOOTER_SIZE);
} else {
res = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
- lz4_buffer.reset(64 * 1024);
+ lz4_buffer.reset(APT_BUFFER_SIZE);
}
filefd->Flags |= FileFd::Compressed;
}
virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
{
- unsigned long long const towrite = std::min(BLK_SIZE, Size);
+ unsigned long long const towrite = std::min(APT_BUFFER_SIZE, Size);
res = LZ4F_compressUpdate(cctx,
lz4_buffer.buffer, lz4_buffer.buffersize_max,
{
/* Reset variables */
res = 0;
- next_to_load = BLK_SIZE;
+ next_to_load = APT_BUFFER_SIZE;
if (cctx != nullptr)
{
}
virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
{
+ ssize_t Res;
lzma->stream.next_in = (uint8_t *)From;
lzma->stream.avail_in = Size;
lzma->stream.next_out = lzma->buffer;
size_t const n = sizeof(lzma->buffer)/sizeof(lzma->buffer[0]) - lzma->stream.avail_out;
size_t const m = (n == 0) ? 0 : fwrite(lzma->buffer, 1, n, lzma->file);
if (m != n)
- return -1;
+ {
+ Res = -1;
+ errno = 0;
+ }
else
- return Size - lzma->stream.avail_in;
+ {
+ Res = Size - lzma->stream.avail_in;
+ if (Res == 0)
+ {
+ // lzma run was okay, but produced no output…
+ Res = -1;
+ errno = EINTR;
+ }
+ }
+ return Res;
}
virtual bool InternalWriteError() override
{
while (Res > 0 && Size > 0)
{
Res = d->InternalWrite(From, Size);
- if (Res < 0 && errno == EINTR)
- continue;
+
if (Res < 0)
+ {
+ if (errno == EINTR)
+ {
+ // trick the while-loop into running again
+ Res = 1;
+ errno = 0;
+ continue;
+ }
return d->InternalWriteError();
+ }
From = (char const *)From + Res;
Size -= Res;