Skip to content

Commit

Permalink
Making ReadBuffer a proper class, simplifying
Browse files Browse the repository at this point in the history
  • Loading branch information
mikekazakov committed Jul 2, 2024
1 parent a4e24bc commit 727bde5
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 54 deletions.
26 changes: 13 additions & 13 deletions Source/VFS/source/NetFTP/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace nc::vfs::ftp {

File::File(const char *_relative_path, std::shared_ptr<FTPHost> _host)
: VFSFile(_relative_path, _host), m_ReadBuf(std::make_unique<ReadBuffer>())
: VFSFile(_relative_path, _host)
{
Log::Trace(SPDLOC, "File::File({}, {}) called", _relative_path, static_cast<void *>(_host.get()));
}
Expand Down Expand Up @@ -48,7 +48,7 @@ int File::Close()
m_FilePos = 0;
m_FileSize = 0;
m_Mode = Mode::Closed;
m_ReadBuf->clear();
m_ReadBuf.Clear();
m_BufFileOffset = 0;
m_CURL.reset();
m_URLRequest.clear();
Expand Down Expand Up @@ -128,27 +128,27 @@ ssize_t File::ReadChunk(void *_read_to, uint64_t _read_size, uint64_t _file_offs
// TODO: mutex lock
bool error = false;

if( (m_ReadBuf->size < _read_size + _file_offset - m_BufFileOffset || _file_offset < m_BufFileOffset ||
_file_offset > m_BufFileOffset + m_ReadBuf->size) &&
(m_ReadBuf->size < m_FileSize) ) {
if( (m_ReadBuf.Size() < _read_size + _file_offset - m_BufFileOffset || _file_offset < m_BufFileOffset ||
_file_offset > m_BufFileOffset + m_ReadBuf.Size()) &&
(m_ReadBuf.Size() < m_FileSize) ) {
// can't satisfy request from memory buffer, need to perform I/O

// check for dead connection
// check for big offset changes so we need to restart connection
bool has_range = false;
if( _file_offset < m_BufFileOffset || _file_offset > m_BufFileOffset + m_ReadBuf->size ||
if( _file_offset < m_BufFileOffset || _file_offset > m_BufFileOffset + m_ReadBuf.Size() ||
m_CURL->RunningHandles() == 0 ) { // (re)connect

// create a brand new ftp request (possibly reusing exiting network connection)
m_ReadBuf->clear();
m_ReadBuf.Clear();
m_BufFileOffset = _file_offset;

if( m_CURL->IsAttached() )
m_CURL->Detach();

m_CURL->EasySetOpt(CURLOPT_URL, m_URLRequest.c_str());
m_CURL->EasySetOpt(CURLOPT_WRITEFUNCTION, ReadBuffer::write_here_function);
m_CURL->EasySetOpt(CURLOPT_WRITEDATA, m_ReadBuf.get());
m_CURL->EasySetOpt(CURLOPT_WRITEFUNCTION, ReadBuffer::Write);
m_CURL->EasySetOpt(CURLOPT_WRITEDATA, &m_ReadBuf);
m_CURL->EasySetOpt(CURLOPT_UPLOAD, 0l);
m_CURL->EasySetOpt(CURLOPT_INFILESIZE, -1l);
m_CURL->EasySetOpt(CURLOPT_READFUNCTION, nullptr);
Expand Down Expand Up @@ -186,7 +186,7 @@ ssize_t File::ReadChunk(void *_read_to, uint64_t _read_size, uint64_t _file_offs
if( _cancel_checker && _cancel_checker() ) {
return VFSError::Cancelled;
}
} while( still_running && (m_ReadBuf->size < _read_size + _file_offset - m_BufFileOffset) );
} while( still_running && (m_ReadBuf.Size() < _read_size + _file_offset - m_BufFileOffset) );

// check for error codes here
if( still_running == 0 ) {
Expand All @@ -205,12 +205,12 @@ ssize_t File::ReadChunk(void *_read_to, uint64_t _read_size, uint64_t _file_offs
return VFSError::FromErrno(EIO);

assert(m_BufFileOffset >= _file_offset);
size_t to_copy = m_ReadBuf->size + m_BufFileOffset - _file_offset;
size_t to_copy = m_ReadBuf.Size() + m_BufFileOffset - _file_offset;
size_t size = _read_size > to_copy ? to_copy : _read_size;

if( _read_to != nullptr ) {
memcpy(_read_to, m_ReadBuf->buf + _file_offset - m_BufFileOffset, size);
m_ReadBuf->discard(_file_offset - m_BufFileOffset + size);
memcpy(_read_to, static_cast<const uint8_t*>(m_ReadBuf.Data()) + _file_offset - m_BufFileOffset, size);
m_ReadBuf.Discard(_file_offset - m_BufFileOffset + size);
m_BufFileOffset = _file_offset + size;
}

Expand Down
2 changes: 1 addition & 1 deletion Source/VFS/source/NetFTP/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class File final : public VFSFile
void FinishReading();

std::unique_ptr<CURLInstance> m_CURL;
std::unique_ptr<ReadBuffer> m_ReadBuf;
ReadBuffer m_ReadBuf;
uint64_t m_BufFileOffset = 0;
WriteBuffer m_WriteBuf;
Mode m_Mode = Mode::Closed;
Expand Down
32 changes: 32 additions & 0 deletions Source/VFS/source/NetFTP/Internals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,38 @@ void CURLInstance::EasyClearProgFunc()
prog_func = nil;
}

size_t ReadBuffer::Size() const noexcept
{
return m_Buf.size();
}

const void *ReadBuffer::Data() const noexcept
{
return m_Buf.data();
}

void ReadBuffer::Clear()
{
m_Buf.clear();
}

size_t ReadBuffer::Write(const void *buffer, size_t _size, size_t _nmemb, void *userp)
{
ReadBuffer *buf = static_cast<ReadBuffer *>(userp);
const size_t bytes = _size * _nmemb;

buf->m_Buf.insert(
buf->m_Buf.end(), static_cast<const std::byte *>(buffer), static_cast<const std::byte *>(buffer) + bytes);

return bytes;
}

void ReadBuffer::Discard(size_t _sz)
{
assert(_sz <= m_Buf.size());
m_Buf.erase(m_Buf.begin(), std::next(m_Buf.begin(), _sz));
}

void WriteBuffer::Write(const void *_mem, size_t _size)
{
Log::Trace(SPDLOC, "WriteBuffer::Write({}, {}) called", _mem, _size);
Expand Down
56 changes: 18 additions & 38 deletions Source/VFS/source/NetFTP/Internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,47 +52,27 @@ struct CURLInstance {
static int ProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
};

struct ReadBuffer {
ReadBuffer() { grow(default_capacity); }
~ReadBuffer() { free(buf); }
ReadBuffer(const ReadBuffer &) = delete;
ReadBuffer(const ReadBuffer &&) = delete;
void operator=(const ReadBuffer &) = delete;

void clear() { size = 0; }

void add(const void *_mem, size_t _size)
{
if( capacity < size + _size )
grow(size + static_cast<uint32_t>(_size));

memcpy(buf + size, _mem, _size);
size += _size;
}

void grow(uint32_t _new_size)
{
buf = static_cast<uint8_t *>(realloc(buf, capacity = static_cast<uint32_t>(_new_size)));
}
// ...
class ReadBuffer {
public:

// Returns the amount of data stored in the buffer
size_t Size() const noexcept;

// ...
const void *Data() const noexcept;

static size_t write_here_function(void *buffer, size_t size, size_t nmemb, void *userp)
{
ReadBuffer *buf = static_cast<ReadBuffer *>(userp);
buf->add(buffer, size * nmemb);
return size * nmemb;
}
// ...
void Clear();

// ...
static size_t Write(const void *_src, size_t _size, size_t _nmemb, void *_this);

void discard(size_t _sz)
{
assert(_sz <= size);
memmove(buf, buf + _sz, size - _sz);
size = size - static_cast<uint32_t>(_sz);
}
// ...
void Discard(size_t _sz);

uint8_t *buf = 0;
static const uint32_t default_capacity = 32768;
uint32_t size = 0;
uint32_t capacity = 0;
private:
std::vector<std::byte> m_Buf;
};

// WriteBuffer provides an intermediatery storage where a File can write into and CURL can read from afterwards
Expand Down
4 changes: 2 additions & 2 deletions Source/VFS/source/NetFTP/InternalsForward.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2014-2017 Michael Kazakov. Subject to GNU General Public License version 3.
// Copyright (C) 2014-2024 Michael Kazakov. Subject to GNU General Public License version 3.
#pragma once

namespace nc::vfs {
Expand All @@ -9,7 +9,7 @@ namespace ftp {
struct CURLInstance;
struct Entry;
struct Directory;
struct ReadBuffer;
class ReadBuffer;
class WriteBuffer;
class Cache;
class File;
Expand Down

0 comments on commit 727bde5

Please sign in to comment.