0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-26 00:32:35 +01:00

ircd::fs: Asynchronous writes to local filesystem.

This commit is contained in:
Jason Volk 2018-02-05 23:28:33 -08:00
parent 1bb9624bce
commit 4a56c0a1cd
5 changed files with 195 additions and 31 deletions

View file

@ -84,16 +84,11 @@ namespace ircd::fs
void chdir(const std::string &path);
bool mkdir(const std::string &path);
// This suite of IO functions may yield your context.
bool write(const std::string &name, const const_buffer &buf);
bool append(const std::string &name, const const_buffer &buf);
bool overwrite(const std::string &name, const const_buffer &buf);
bool overwrite(const string_view &name, const const_buffer &buf);
extern aio *aioctx;
}
#include "read.h"
#include "write.h"
struct ircd::fs::init
{

73
include/ircd/fs/write.h Normal file
View file

@ -0,0 +1,73 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_FS_WRITE_H
namespace ircd::fs
{
struct write_opts extern const write_opts_default;
// Yields ircd::ctx for write from buffer; returns view of written portion
string_view write(const string_view &path, const const_buffer &, const write_opts & = write_opts_default);
// Yields ircd::ctx to overwrite (trunc) file from buffer; returns view of written portion
string_view overwrite(const string_view &path, const const_buffer &, const write_opts & = write_opts_default);
// Yields ircd::ctx to append to file from buffer; returns view of written portion
string_view append(const string_view &path, const const_buffer &, const write_opts & = write_opts_default);
}
/// Options for a write operation
struct ircd::fs::write_opts
{
write_opts() = default;
write_opts(const off_t &);
/// Overwrite (trunc) the file
bool overwrite {false};
/// Append to the file (offset is ignored)
bool append {false};
/// Create the file if necessary (default)
bool create {true};
/// Offset in the file to start the write from.
off_t offset {0};
/// Request priority (this option may be improved, avoid for now)
int16_t priority {0};
};
inline
ircd::fs::write_opts::write_opts(const off_t &offset)
:offset{offset}
{}
inline ircd::string_view
ircd::fs::overwrite(const string_view &path,
const const_buffer &buf,
const write_opts &opts_)
{
auto opts(opts_);
opts.overwrite = true;
return write(path, buf, opts);
}
inline ircd::string_view
ircd::fs::append(const string_view &path,
const const_buffer &buf,
const write_opts &opts_)
{
auto opts(opts_);
opts.append = true;
return write(path, buf, opts);
}

View file

@ -319,3 +319,78 @@ ircd::fs::read__aio(const string_view &path,
return view;
}
///////////////////////////////////////////////////////////////////////////////
//
// fs/write.h
//
//
// request::write
//
ircd::fs::aio::request::write::write(const int &fd,
const const_buffer &buf,
const write_opts &opts)
:request{fd}
{
aio_reqprio = opts.priority;
aio_lio_opcode = IOCB_CMD_PWRITE;
aio_buf = uintptr_t(buffer::data(buf));
aio_nbytes = buffer::size(buf);
aio_offset = opts.offset;
}
//
// ircd::fs interface
//
ircd::string_view
ircd::fs::write__aio(const string_view &path,
const const_buffer &buf,
const write_opts &opts)
{
// Path to open(2) must be null terminated;
static thread_local char pathstr[2048];
strlcpy(pathstr, path, sizeof(pathstr));
uint flags{0};
flags |= O_WRONLY;
flags |= O_CLOEXEC;
flags |= opts.create? O_CREAT : 0;
flags |= opts.append? O_APPEND : 0;
flags |= opts.overwrite? O_TRUNC : 0;
const mode_t mask
{
opts.create? S_IRUSR | S_IWUSR : 0U
};
const auto fd
{
syscall(::open, pathstr, flags, mask)
};
const unwind cfd{[&fd]
{
syscall(::close, fd);
}};
aio::request::write request
{
int(fd), buf, opts
};
const size_t bytes
{
request()
};
const string_view view
{
data(buf), bytes
};
return view;
}

View file

@ -70,6 +70,7 @@ struct ircd::fs::aio::request
namespace ircd::fs
{
string_view write__aio(const string_view &path, const const_buffer &, const write_opts &);
string_view read__aio(const string_view &path, const mutable_buffer &, const read_opts &);
std::string read__aio(const string_view &path, const read_opts &);
}
@ -80,3 +81,10 @@ struct ircd::fs::aio::request::read
{
read(const int &fd, const mutable_buffer &, const read_opts &);
};
/// Write request control block
struct ircd::fs::aio::request::write
:request
{
write(const int &fd, const const_buffer &, const write_opts &);
};

View file

@ -147,39 +147,52 @@ ircd::fs::read__std(const string_view &path,
// fs/write.h
//
bool
ircd::fs::write(const std::string &path,
const const_buffer &buf)
namespace ircd::fs
{
if(fs::exists(path))
return false;
return overwrite(path, buf);
string_view write__std(const string_view &path, const const_buffer &, const write_opts &);
}
bool
ircd::fs::overwrite(const string_view &path,
const const_buffer &buf)
ircd::fs::write_opts
const ircd::fs::write_opts_default
{};
ircd::string_view
ircd::fs::write(const string_view &path,
const const_buffer &buf,
const write_opts &opts)
{
return overwrite(std::string{path}, buf);
#ifdef IRCD_USE_AIO
if(likely(aioctx))
return write__aio(path, buf, opts);
#endif
return write__std(path, buf, opts);
}
bool
ircd::fs::overwrite(const std::string &path,
const const_buffer &buf)
ircd::string_view
ircd::fs::write__std(const string_view &path,
const const_buffer &buf,
const write_opts &opts)
{
std::ofstream file{path, std::ios::trunc};
const auto open_mode
{
opts.append?
std::ios::app:
opts.overwrite?
std::ios::trunc:
std::ios::out
};
std::ofstream file
{
std::string{path}, open_mode
};
file.seekp(opts.offset, file.beg);
file.write(data(buf), size(buf));
return true;
}
bool
ircd::fs::append(const std::string &path,
const const_buffer &buf)
{
std::ofstream file{path, std::ios::app};
file.write(data(buf), size(buf));
return true;
return buf;
}
void