vfs: add Append_file class

This reverts commit cf904e0a5d and
introduces the Append_file class instead.

genodelabs/genode#4352
This commit is contained in:
Johannes Schlatow 2022-08-29 11:38:36 +02:00 committed by Norman Feske
parent 06f24a73d2
commit bc57e9e647
7 changed files with 112 additions and 57 deletions

View File

@ -23,12 +23,12 @@ void Writer::start_iteration(Directory &root,
_file_path = Directory::join(path, info.thread_name());
try {
_dst_file.construct(root, _file_path, true);
_dst_file.construct(root, _file_path);
/* initialise packet header */
_packet_buffer.init_header(info);
}
catch (New_file::Create_failed) {
catch (Append_file::Create_failed) {
error("Could not create file."); }
}

View File

@ -27,7 +27,7 @@ namespace Ctf {
using namespace Trace_recorder;
using Genode::Directory;
using Genode::New_file;
using Genode::Append_file;
using Buffer = Write_buffer<32*1024>;
@ -39,9 +39,9 @@ namespace Ctf {
class Ctf::Writer : public Trace_recorder::Writer_base
{
private:
Buffer &_packet_buffer;
Constructible<New_file> _dst_file { };
Directory::Path _file_path { };
Buffer &_packet_buffer;
Constructible<Append_file> _dst_file { };
Directory::Path _file_path { };
public:
Writer(Genode::Registry<Writer_base> &registry, Buffer &packet_buffer)

View File

@ -64,12 +64,12 @@ class Ctf::Write_buffer
});
}
void write_to_file(Genode::New_file &dst, Genode::Directory::Path const &path)
void write_to_file(Genode::Append_file &dst, Genode::Directory::Path const &path)
{
if (_header().empty())
return;
if (dst.append(_buffer, _header().total_length_bytes()) != New_file::Append_result::OK)
if (dst.append(_buffer, _header().total_length_bytes()) != Append_file::Append_result::OK)
error("Write error for ", path);
_header().reset();

View File

@ -35,14 +35,14 @@ void Writer::start_iteration(Directory &root,
/* append to file */
try {
_dst_file.construct(root, _file_path, true);
_dst_file.construct(root, _file_path);
_interface_registry.clear();
_buffer.clear();
_buffer.append<Section_header_block>();
_empty_section = true;
}
catch (New_file::Create_failed) {
catch (Append_file::Create_failed) {
error("Could not create file."); }
}

View File

@ -27,7 +27,7 @@ namespace Pcapng {
using namespace Trace_recorder;
using Genode::Directory;
using Genode::New_file;
using Genode::Append_file;
using Buffer = Write_buffer<32*1024>;
@ -42,7 +42,7 @@ class Pcapng::Writer : public Trace_recorder::Writer_base
Interface_registry &_interface_registry;
Buffer &_buffer;
Timestamp_calibrator const &_ts_calibrator;
Constructible<New_file> _dst_file { };
Constructible<Append_file> _dst_file { };
Directory::Path _file_path { };
bool _empty_section { false };

View File

@ -62,12 +62,12 @@ class Pcapng::Write_buffer
return Append_ok();
}
void write_to_file(Genode::New_file &dst, Directory::Path const &path)
void write_to_file(Genode::Append_file &dst, Directory::Path const &path)
{
if (_total_length == 0)
return;
if (dst.append(_buffer, _total_length) != New_file::Append_result::OK)
if (dst.append(_buffer, _total_length) != Append_file::Append_result::OK)
error("Write error for ", path);
clear();

View File

@ -27,6 +27,8 @@ namespace Genode {
struct File;
class Readonly_file;
class File_content;
class Writeable_file;
class Append_file;
class New_file;
class Watcher;
template <typename>
@ -124,6 +126,8 @@ struct Genode::Directory : Noncopyable, Interface
friend class Readonly_file;
friend class Root_directory;
friend class Watcher;
friend class Writeable_file;
friend class Append_file;
friend class New_file;
/*
@ -668,24 +672,21 @@ class Genode::File_content
/**
* Utility for writing data to a file via the Genode VFS library
* Base class of `New_file` and `Append_file` providing open for write, sync,
* and append functionality.
*/
class Genode::New_file : Noncopyable
class Genode::Writeable_file : Noncopyable
{
public:
struct Create_failed : Exception { };
private:
enum class Append_result { OK, WRITE_ERROR };
Entrypoint &_ep;
Allocator &_alloc;
Vfs::File_system &_fs;
Vfs::Vfs_handle &_handle;
protected:
Vfs::Vfs_handle &_init_handle(Directory &dir,
Directory::Path const &rel_path,
bool append)
static Vfs::Vfs_handle &_init_handle(Directory &dir,
Directory::Path const &rel_path)
{
/* create compound directory */
{
@ -703,43 +704,24 @@ class Genode::New_file : Noncopyable
Vfs::Vfs_handle *handle_ptr = nullptr;
Vfs::Directory_service::Open_result const res =
_fs.open(path.string(), mode, &handle_ptr, _alloc);
dir._fs.open(path.string(), mode, &handle_ptr, dir._alloc);
if (res != Vfs::Directory_service::OPEN_OK || (handle_ptr == nullptr)) {
error("failed to create file '", path, "', res=", (int)res);
error("failed to create/open file '", path, "' for writing, res=", (int)res);
throw Create_failed();
}
Vfs::Directory_service::Stat stat { };
if (!append)
handle_ptr->fs().ftruncate(handle_ptr, 0);
else if (handle_ptr->ds().stat(path.string(), stat) == Vfs::Directory_service::STAT_OK)
handle_ptr->seek(stat.size);
return *handle_ptr;
}
public:
/**
* Constructor
*
* \throw Create_failed
*/
New_file(Directory &dir, Directory::Path const &path, bool append = false)
:
_ep(dir._ep), _alloc(dir._alloc), _fs(dir._fs),
_handle(_init_handle(dir, path, append))
{ }
~New_file()
static void _sync(Vfs::Vfs_handle &handle, Entrypoint &ep)
{
while (_handle.fs().queue_sync(&_handle) == false)
_ep.wait_and_dispatch_one_io_signal();
while (handle.fs().queue_sync(&handle) == false)
ep.wait_and_dispatch_one_io_signal();
for (bool sync_done = false; !sync_done; ) {
switch (_handle.fs().complete_sync(&_handle)) {
switch (handle.fs().complete_sync(&handle)) {
case Vfs::File_io_service::SYNC_QUEUED:
break;
@ -755,14 +737,12 @@ class Genode::New_file : Noncopyable
}
if (!sync_done)
_ep.wait_and_dispatch_one_io_signal();
ep.wait_and_dispatch_one_io_signal();
}
_handle.ds().close(&_handle);
}
enum class Append_result { OK, WRITE_ERROR };
Append_result append(char const *src, size_t size)
static Append_result _append(Vfs::Vfs_handle &handle, Entrypoint &ep,
char const *src, size_t size)
{
bool write_error = false;
@ -777,7 +757,7 @@ class Genode::New_file : Noncopyable
using Write_result = Vfs::File_io_service::Write_result;
switch (_handle.fs().write(&_handle, src, remaining_bytes,
switch (handle.fs().write(&handle, src, remaining_bytes,
out_count)) {
case Write_result::WRITE_ERR_AGAIN:
@ -795,7 +775,7 @@ class Genode::New_file : Noncopyable
out_count = min((Vfs::file_size)remaining_bytes, out_count);
remaining_bytes -= (size_t)out_count;
src += out_count;
_handle.advance_seek(out_count);
handle.advance_seek(out_count);
break;
};
}
@ -803,7 +783,7 @@ class Genode::New_file : Noncopyable
stalled = true; }
if (stalled)
_ep.wait_and_dispatch_one_io_signal();
ep.wait_and_dispatch_one_io_signal();
}
return write_error ? Append_result::WRITE_ERROR
: Append_result::OK;
@ -811,6 +791,81 @@ class Genode::New_file : Noncopyable
};
/**
* Utility for appending data to an existing file via the Genode VFS library
*/
class Genode::Append_file : public Writeable_file
{
private:
Entrypoint &_ep;
Vfs::Vfs_handle &_handle;
public:
/**
* Constructor
*
* \throw Create_failed
*/
Append_file(Directory &dir, Directory::Path const &path)
:
_ep(dir._ep),
_handle(_init_handle(dir, path))
{
Vfs::Directory_service::Stat stat { };
if (_handle.ds().stat(path.string(), stat) == Vfs::Directory_service::STAT_OK)
_handle.seek(stat.size);
}
~Append_file()
{
_sync(_handle, _ep);
_handle.ds().close(&_handle);
}
Append_result append(char const *src, size_t size) {
return _append(_handle, _ep, src, size); }
};
/**
* Utility for writing data to a new file via the Genode VFS library
*/
class Genode::New_file : public Writeable_file
{
private:
Entrypoint &_ep;
Vfs::Vfs_handle &_handle;
public:
using Writeable_file::Append_result;
using Writeable_file::Create_failed;
/**
* Constructor
*
* \throw Create_failed
*/
New_file(Directory &dir, Directory::Path const &path)
:
_ep(dir._ep),
_handle(_init_handle(dir, path))
{ _handle.fs().ftruncate(&_handle, 0); }
~New_file()
{
_sync(_handle, _ep);
_handle.ds().close(&_handle);
}
Append_result append(char const *src, size_t size) {
return _append(_handle, _ep, src, size); }
};
class Genode::Watcher
{
private: