mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd::fs: Asynchronous writes to local filesystem.
This commit is contained in:
parent
1bb9624bce
commit
4a56c0a1cd
5 changed files with 195 additions and 31 deletions
|
@ -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
73
include/ircd/fs/write.h
Normal 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);
|
||||
}
|
75
ircd/aio.cc
75
ircd/aio.cc
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 &);
|
||||
};
|
||||
|
|
63
ircd/fs.cc
63
ircd/fs.cc
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue