mirror of
https://github.com/trapexit/mergerfs.git
synced 2024-11-26 02:09:52 +08:00
Merge pull request #1123 from trapexit/wait
Add option to wait for branches to become new mounts
This commit is contained in:
commit
16e9ba2f19
2
LICENSE
2
LICENSE
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2021, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
% mergerfs(1) mergerfs user manual
|
||||
% Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
% 2023-01-16
|
||||
% 2023-01-24
|
||||
|
||||
# NAME
|
||||
|
||||
|
@ -165,6 +165,9 @@ These options are the same regardless of whether you use them with the `mergerfs
|
|||
* **nfsopenhack=off|git|all**: A workaround for exporting mergerfs
|
||||
over NFS where there are issues with creating files for write while
|
||||
setting the mode to read-only. (default: off)
|
||||
* **branches-mount-timeout=UINT**: Number of seconds to wait at
|
||||
startup for branches to be a mount other than the mountpoint's
|
||||
filesystem. (default: 0)
|
||||
* **follow-symlinks=never|directory|regular|all**: Turns symlinks into
|
||||
what they point to. (default: never)
|
||||
* **link-exdev=passthrough|rel-symlink|abs-base-symlink|abs-pool-symlink**:
|
||||
|
|
|
@ -363,6 +363,17 @@ Branches::Impl::to_paths(StrVec &paths_) const
|
|||
}
|
||||
}
|
||||
|
||||
fs::PathVector
|
||||
Branches::Impl::to_paths() const
|
||||
{
|
||||
fs::PathVector vp;
|
||||
|
||||
for(const auto &branch : *this)
|
||||
vp.emplace_back(branch.path);
|
||||
|
||||
return vp;
|
||||
}
|
||||
|
||||
int
|
||||
Branches::from_string(const std::string &str_)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "branch.hpp"
|
||||
#include "nonstd/optional.hpp"
|
||||
#include "fs_pathvector.hpp"
|
||||
#include "strvec.hpp"
|
||||
#include "tofrom_string.hpp"
|
||||
|
||||
|
@ -49,6 +49,7 @@ public:
|
|||
public:
|
||||
const uint64_t& minfreespace(void) const;
|
||||
void to_paths(StrVec &strvec) const;
|
||||
fs::PathVector to_paths() const;
|
||||
|
||||
public:
|
||||
Impl& operator=(Impl &impl_);
|
||||
|
|
135
src/config.cpp
135
src/config.cpp
|
@ -53,6 +53,7 @@ namespace l
|
|||
readonly(const std::string &s_)
|
||||
{
|
||||
IFERT("async_read");
|
||||
IFERT("branches-mount-timeout");
|
||||
IFERT("cache.symlinks");
|
||||
IFERT("cache.writeback");
|
||||
IFERT("fsname");
|
||||
|
@ -73,6 +74,7 @@ Config::Config()
|
|||
auto_cache(false),
|
||||
minfreespace(MINFREESPACE_DEFAULT),
|
||||
branches(minfreespace),
|
||||
branches_mount_timeout(0),
|
||||
cache_attr(1),
|
||||
cache_entry(1),
|
||||
cache_files(CacheFiles::ENUM::LIBFUSE),
|
||||
|
@ -113,72 +115,73 @@ Config::Config()
|
|||
writeback_cache(false),
|
||||
xattr(XAttr::ENUM::PASSTHROUGH)
|
||||
{
|
||||
_map["async_read"] = &async_read;
|
||||
_map["auto_cache"] = &auto_cache;
|
||||
_map["branches"] = &branches;
|
||||
_map["cache.attr"] = &cache_attr;
|
||||
_map["cache.entry"] = &cache_entry;
|
||||
_map["cache.files"] = &cache_files;
|
||||
_map["cache.negative_entry"] = &cache_negative_entry;
|
||||
_map["cache.readdir"] = &cache_readdir;
|
||||
_map["cache.statfs"] = &cache_statfs;
|
||||
_map["cache.symlinks"] = &cache_symlinks;
|
||||
_map["cache.writeback"] = &writeback_cache;
|
||||
_map["category.action"] = &category.action;
|
||||
_map["category.create"] = &category.create;
|
||||
_map["category.search"] = &category.search;
|
||||
_map["direct_io"] = &direct_io;
|
||||
_map["dropcacheonclose"] = &dropcacheonclose;
|
||||
_map["follow-symlinks"] = &follow_symlinks;
|
||||
_map["fsname"] = &fsname;
|
||||
_map["func.access"] = &func.access;
|
||||
_map["func.chmod"] = &func.chmod;
|
||||
_map["func.chown"] = &func.chown;
|
||||
_map["func.create"] = &func.create;
|
||||
_map["func.getattr"] = &func.getattr;
|
||||
_map["func.getxattr"] = &func.getxattr;
|
||||
_map["func.link"] = &func.link;
|
||||
_map["func.listxattr"] = &func.listxattr;
|
||||
_map["func.mkdir"] = &func.mkdir;
|
||||
_map["func.mknod"] = &func.mknod;
|
||||
_map["func.open"] = &func.open;
|
||||
_map["func.readlink"] = &func.readlink;
|
||||
_map["func.removexattr"] = &func.removexattr;
|
||||
_map["func.rename"] = &func.rename;
|
||||
_map["func.rmdir"] = &func.rmdir;
|
||||
_map["func.setxattr"] = &func.setxattr;
|
||||
_map["func.symlink"] = &func.symlink;
|
||||
_map["func.truncate"] = &func.truncate;
|
||||
_map["func.unlink"] = &func.unlink;
|
||||
_map["func.utimens"] = &func.utimens;
|
||||
_map["fuse_msg_size"] = &fuse_msg_size;
|
||||
_map["ignorepponrename"] = &ignorepponrename;
|
||||
_map["inodecalc"] = &inodecalc;
|
||||
_map["kernel_cache"] = &kernel_cache;
|
||||
_map["link_cow"] = &link_cow;
|
||||
_map["link-exdev"] = &link_exdev;
|
||||
_map["log.metrics"] = &log_metrics;
|
||||
_map["minfreespace"] = &minfreespace;
|
||||
_map["mount"] = &mount;
|
||||
_map["moveonenospc"] = &moveonenospc;
|
||||
_map["nfsopenhack"] = &nfsopenhack;
|
||||
_map["nullrw"] = &nullrw;
|
||||
_map["pid"] = &pid;
|
||||
_map["posix_acl"] = &posix_acl;
|
||||
// _map["readdir"] = &readdir;
|
||||
_map["readdirplus"] = &readdirplus;
|
||||
_map["rename-exdev"] = &rename_exdev;
|
||||
_map["security_capability"] = &security_capability;
|
||||
_map["srcmounts"] = &srcmounts;
|
||||
_map["statfs"] = &statfs;
|
||||
_map["statfs_ignore"] = &statfs_ignore;
|
||||
_map["symlinkify"] = &symlinkify;
|
||||
_map["symlinkify_timeout"] = &symlinkify_timeout;
|
||||
_map["threads"] = &fuse_read_thread_count;
|
||||
_map["read-thread-count"] = &fuse_read_thread_count;
|
||||
_map["process-thread-count"] = &fuse_process_thread_count;
|
||||
_map["version"] = &version;
|
||||
_map["xattr"] = &xattr;
|
||||
_map["async_read"] = &async_read;
|
||||
_map["auto_cache"] = &auto_cache;
|
||||
_map["branches"] = &branches;
|
||||
_map["branches-mount-timeout"] = &branches_mount_timeout;
|
||||
_map["cache.attr"] = &cache_attr;
|
||||
_map["cache.entry"] = &cache_entry;
|
||||
_map["cache.files"] = &cache_files;
|
||||
_map["cache.negative_entry"] = &cache_negative_entry;
|
||||
_map["cache.readdir"] = &cache_readdir;
|
||||
_map["cache.statfs"] = &cache_statfs;
|
||||
_map["cache.symlinks"] = &cache_symlinks;
|
||||
_map["cache.writeback"] = &writeback_cache;
|
||||
_map["category.action"] = &category.action;
|
||||
_map["category.create"] = &category.create;
|
||||
_map["category.search"] = &category.search;
|
||||
_map["direct_io"] = &direct_io;
|
||||
_map["dropcacheonclose"] = &dropcacheonclose;
|
||||
_map["follow-symlinks"] = &follow_symlinks;
|
||||
_map["fsname"] = &fsname;
|
||||
_map["func.access"] = &func.access;
|
||||
_map["func.chmod"] = &func.chmod;
|
||||
_map["func.chown"] = &func.chown;
|
||||
_map["func.create"] = &func.create;
|
||||
_map["func.getattr"] = &func.getattr;
|
||||
_map["func.getxattr"] = &func.getxattr;
|
||||
_map["func.link"] = &func.link;
|
||||
_map["func.listxattr"] = &func.listxattr;
|
||||
_map["func.mkdir"] = &func.mkdir;
|
||||
_map["func.mknod"] = &func.mknod;
|
||||
_map["func.open"] = &func.open;
|
||||
_map["func.readlink"] = &func.readlink;
|
||||
_map["func.removexattr"] = &func.removexattr;
|
||||
_map["func.rename"] = &func.rename;
|
||||
_map["func.rmdir"] = &func.rmdir;
|
||||
_map["func.setxattr"] = &func.setxattr;
|
||||
_map["func.symlink"] = &func.symlink;
|
||||
_map["func.truncate"] = &func.truncate;
|
||||
_map["func.unlink"] = &func.unlink;
|
||||
_map["func.utimens"] = &func.utimens;
|
||||
_map["fuse_msg_size"] = &fuse_msg_size;
|
||||
_map["ignorepponrename"] = &ignorepponrename;
|
||||
_map["inodecalc"] = &inodecalc;
|
||||
_map["kernel_cache"] = &kernel_cache;
|
||||
_map["link_cow"] = &link_cow;
|
||||
_map["link-exdev"] = &link_exdev;
|
||||
_map["log.metrics"] = &log_metrics;
|
||||
_map["minfreespace"] = &minfreespace;
|
||||
_map["mount"] = &mount;
|
||||
_map["moveonenospc"] = &moveonenospc;
|
||||
_map["nfsopenhack"] = &nfsopenhack;
|
||||
_map["nullrw"] = &nullrw;
|
||||
_map["pid"] = &pid;
|
||||
_map["posix_acl"] = &posix_acl;
|
||||
// _map["readdir"] = &readdir;
|
||||
_map["readdirplus"] = &readdirplus;
|
||||
_map["rename-exdev"] = &rename_exdev;
|
||||
_map["security_capability"] = &security_capability;
|
||||
_map["srcmounts"] = &srcmounts;
|
||||
_map["statfs"] = &statfs;
|
||||
_map["statfs_ignore"] = &statfs_ignore;
|
||||
_map["symlinkify"] = &symlinkify;
|
||||
_map["symlinkify_timeout"] = &symlinkify_timeout;
|
||||
_map["threads"] = &fuse_read_thread_count;
|
||||
_map["read-thread-count"] = &fuse_read_thread_count;
|
||||
_map["process-thread-count"] = &fuse_process_thread_count;
|
||||
_map["version"] = &version;
|
||||
_map["xattr"] = &xattr;
|
||||
}
|
||||
|
||||
Config&
|
||||
|
|
|
@ -103,6 +103,7 @@ public:
|
|||
ConfigBOOL auto_cache;
|
||||
ConfigUINT64 minfreespace;
|
||||
Branches branches;
|
||||
ConfigUINT64 branches_mount_timeout;
|
||||
ConfigUINT64 cache_attr;
|
||||
ConfigUINT64 cache_entry;
|
||||
CacheFiles cache_files;
|
||||
|
|
10
src/fs_pathvector.hpp
Normal file
10
src/fs_pathvector.hpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "ghc/filesystem.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace fs
|
||||
{
|
||||
typedef std::vector<ghc::filesystem::path> PathVector;
|
||||
}
|
112
src/fs_wait_for_mount.cpp
Normal file
112
src/fs_wait_for_mount.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
|
||||
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 appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "fs_wait_for_mount.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
||||
constexpr std::chrono::milliseconds SLEEP_DURATION = std::chrono::milliseconds(333);
|
||||
|
||||
|
||||
bool
|
||||
fs::wait_for_mount(const struct stat &src_st_,
|
||||
const ghc::filesystem::path &tgtpath_,
|
||||
const std::chrono::milliseconds &timeout_)
|
||||
{
|
||||
int rv;
|
||||
std::chrono::duration<double> time_diff;
|
||||
std::chrono::time_point<std::chrono::steady_clock> start_time;
|
||||
|
||||
start_time = std::chrono::steady_clock::now();
|
||||
while(true)
|
||||
{
|
||||
struct stat tgt_st;
|
||||
|
||||
rv = fs::stat(tgtpath_,&tgt_st);
|
||||
if(rv == 0)
|
||||
{
|
||||
if(tgt_st.st_dev != src_st_.st_dev)
|
||||
return true;
|
||||
}
|
||||
|
||||
time_diff = (std::chrono::steady_clock::now() - start_time);
|
||||
if(time_diff > timeout_)
|
||||
return false;
|
||||
|
||||
std::this_thread::sleep_for(SLEEP_DURATION);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
_wait_for_mount(const struct stat &src_st_,
|
||||
const fs::PathVector &tgtpaths_,
|
||||
const std::chrono::milliseconds &timeout_,
|
||||
fs::PathVector &failed_paths_)
|
||||
{
|
||||
bool rv;
|
||||
fs::PathVector::const_iterator i;
|
||||
std::chrono::milliseconds timeout;
|
||||
std::chrono::milliseconds diff;
|
||||
std::chrono::time_point<std::chrono::steady_clock> now;
|
||||
std::chrono::time_point<std::chrono::steady_clock> start_time;
|
||||
|
||||
timeout = timeout_;
|
||||
now = start_time = std::chrono::steady_clock::now();
|
||||
for(auto i = tgtpaths_.begin(); i != tgtpaths_.end(); ++i)
|
||||
{
|
||||
diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
|
||||
timeout -= diff;
|
||||
|
||||
rv = fs::wait_for_mount(src_st_,*i,timeout);
|
||||
if(rv == false)
|
||||
failed_paths_.push_back(*i);
|
||||
|
||||
now = std::chrono::steady_clock::now();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fs::wait_for_mount(const struct stat &src_st_,
|
||||
const fs::PathVector &tgtpaths_,
|
||||
const std::chrono::milliseconds &timeout_,
|
||||
fs::PathVector &failed_paths_)
|
||||
{
|
||||
if(tgtpaths_.empty())
|
||||
return;
|
||||
|
||||
_wait_for_mount(src_st_,tgtpaths_,timeout_,failed_paths_);
|
||||
}
|
||||
|
||||
void
|
||||
fs::wait_for_mount(const ghc::filesystem::path &srcpath_,
|
||||
const fs::PathVector &tgtpaths_,
|
||||
const std::chrono::milliseconds &timeout_,
|
||||
fs::PathVector &failed_paths_)
|
||||
{
|
||||
int rv;
|
||||
struct stat src_st;
|
||||
|
||||
rv = fs::stat(srcpath_,&src_st);
|
||||
if(rv == -1)
|
||||
return;
|
||||
|
||||
fs::wait_for_mount(src_st,tgtpaths_,timeout_,failed_paths_);
|
||||
}
|
50
src/fs_wait_for_mount.hpp
Normal file
50
src/fs_wait_for_mount.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
|
||||
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 appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ghc/filesystem.hpp"
|
||||
|
||||
#include "fs_pathvector.hpp"
|
||||
#include "fs_stat.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace fs
|
||||
{
|
||||
typedef std::vector<ghc::filesystem::path> PathVector;
|
||||
|
||||
bool
|
||||
wait_for_mount(const struct stat &st,
|
||||
const ghc::filesystem::path &tgtpath,
|
||||
const std::chrono::milliseconds &timeout);
|
||||
|
||||
void
|
||||
wait_for_mount(const struct stat &st,
|
||||
const fs::PathVector &tgtpaths,
|
||||
const std::chrono::milliseconds &timeout,
|
||||
fs::PathVector &failed_paths);
|
||||
|
||||
void
|
||||
wait_for_mount(const ghc::filesystem::path &srcpath,
|
||||
const fs::PathVector &tgtpaths,
|
||||
const std::chrono::milliseconds &timeout,
|
||||
fs::PathVector &failed_paths);
|
||||
}
|
|
@ -14,6 +14,9 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "fs_wait_for_mount.hpp"
|
||||
#include "syslog.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
#include "mergerfs.hpp"
|
||||
#include "option_parser.hpp"
|
||||
|
@ -147,6 +150,33 @@ namespace l
|
|||
resources::setpriority(prio);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
wait_for_mount(const Config::Read &cfg_)
|
||||
{
|
||||
fs::PathVector paths;
|
||||
fs::PathVector failed;
|
||||
std::chrono::milliseconds timeout;
|
||||
|
||||
paths = cfg_->branches->to_paths();
|
||||
|
||||
syslog_info("Waiting %u seconds for branches to mount",
|
||||
(uint64_t)cfg_->branches_mount_timeout);
|
||||
|
||||
timeout = std::chrono::milliseconds(cfg_->branches_mount_timeout * 1000);
|
||||
fs::wait_for_mount((std::string)cfg_->mount,
|
||||
paths,
|
||||
timeout,
|
||||
failed);
|
||||
for(auto &path : failed)
|
||||
syslog_warning("Branch %s was not mounted within timeout",
|
||||
path.c_str());
|
||||
if(failed.size())
|
||||
syslog_warning("Continuing to mount mergerfs despite %u branches not "
|
||||
"being different from the mountpoint filesystem",
|
||||
failed.size());
|
||||
}
|
||||
|
||||
int
|
||||
main(const int argc_,
|
||||
char **argv_)
|
||||
|
@ -156,6 +186,8 @@ namespace l
|
|||
fuse_args args;
|
||||
fuse_operations ops;
|
||||
|
||||
syslog_open();
|
||||
|
||||
memset(&ops,0,sizeof(fuse_operations));
|
||||
|
||||
args.argc = argc_;
|
||||
|
@ -169,6 +201,9 @@ namespace l
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(cfg->branches_mount_timeout > 0)
|
||||
l::wait_for_mount(cfg);
|
||||
|
||||
l::setup_resources();
|
||||
l::get_fuse_operations(ops,cfg->nullrw);
|
||||
|
||||
|
|
2537
src/nonstd/expected.hpp
Normal file
2537
src/nonstd/expected.hpp
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -44,20 +44,26 @@
|
|||
# define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
|
||||
#endif
|
||||
|
||||
// Control presence of extensions:
|
||||
|
||||
#ifndef optional_CONFIG_NO_EXTENSIONS
|
||||
#define optional_CONFIG_NO_EXTENSIONS 0
|
||||
#endif
|
||||
|
||||
// Control presence of exception handling (try and auto discover):
|
||||
|
||||
#ifndef optional_CONFIG_NO_EXCEPTIONS
|
||||
# if defined(_MSC_VER)
|
||||
# include <cstddef> // for _HAS_EXCEPTIONS
|
||||
# endif
|
||||
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
|
||||
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS))
|
||||
# define optional_CONFIG_NO_EXCEPTIONS 0
|
||||
# else
|
||||
# define optional_CONFIG_NO_EXCEPTIONS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// C++ language version detection (C++20 is speculative):
|
||||
// C++ language version detection (C++23 is speculative):
|
||||
// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
|
||||
|
||||
#ifndef optional_CPLUSPLUS
|
||||
|
@ -73,7 +79,8 @@
|
|||
#define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L )
|
||||
#define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L )
|
||||
#define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L )
|
||||
#define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202000L )
|
||||
#define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202002L )
|
||||
#define optional_CPP23_OR_GREATER ( optional_CPLUSPLUS >= 202300L )
|
||||
|
||||
// C++ language version (represent 98 as 3):
|
||||
|
||||
|
@ -782,7 +789,7 @@ union storage_t
|
|||
|
||||
void construct_value( value_type && v )
|
||||
{
|
||||
::new( value_ptr() ) value_type( std::move( v ) );
|
||||
::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( std::move( v ) );
|
||||
}
|
||||
|
||||
template< class... Args >
|
||||
|
@ -794,13 +801,13 @@ union storage_t
|
|||
template< class... Args >
|
||||
void emplace( Args&&... args )
|
||||
{
|
||||
::new( value_ptr() ) value_type( std::forward<Args>(args)... );
|
||||
::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( std::forward<Args>(args)... );
|
||||
}
|
||||
|
||||
template< class U, class... Args >
|
||||
void emplace( std::initializer_list<U> il, Args&&... args )
|
||||
{
|
||||
::new( value_ptr() ) value_type( il, std::forward<Args>(args)... );
|
||||
::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( il, std::forward<Args>(args)... );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1485,7 +1492,40 @@ public:
|
|||
return has_value() ? contained.value() : static_cast<value_type>( v );
|
||||
}
|
||||
|
||||
#endif // optional_CPP11_OR_GREATER
|
||||
#endif // optional_HAVE( REF_QUALIFIER )
|
||||
|
||||
#if !optional_CONFIG_NO_EXTENSIONS
|
||||
#if optional_HAVE( REF_QUALIFIER )
|
||||
|
||||
template< typename F >
|
||||
optional_constexpr value_type value_or_eval( F f ) const &
|
||||
{
|
||||
return has_value() ? contained.value() : f();
|
||||
}
|
||||
|
||||
template< typename F >
|
||||
optional_constexpr14 value_type value_or_eval( F f ) &&
|
||||
{
|
||||
if ( has_value() )
|
||||
{
|
||||
return std::move( contained.value() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return f();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template< typename F >
|
||||
optional_constexpr value_type value_or_eval( F f ) const
|
||||
{
|
||||
return has_value() ? contained.value() : f();
|
||||
}
|
||||
|
||||
#endif // optional_HAVE( REF_QUALIFIER )
|
||||
#endif // !optional_CONFIG_NO_EXTENSIONS
|
||||
|
||||
// x.x.3.6, modifiers
|
||||
|
||||
|
@ -1530,37 +1570,37 @@ private:
|
|||
// Relational operators
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
|
||||
optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
|
||||
{
|
||||
return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
|
||||
optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
|
||||
optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
|
||||
{
|
||||
return (!y) ? false : (!x) ? true : *x < *y;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
|
||||
optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
|
||||
{
|
||||
return (y < x);
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
|
||||
optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
|
||||
optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
@ -1568,73 +1608,73 @@ inline optional_constexpr bool operator>=( optional<T> const & x, optional<U> co
|
|||
// Comparison with nullopt
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
|
||||
{
|
||||
return (!x);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
|
||||
{
|
||||
return (!x);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
|
||||
{
|
||||
return bool(x);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
|
||||
{
|
||||
return bool(x);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
|
||||
{
|
||||
return bool(x);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
|
||||
{
|
||||
return (!x);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
|
||||
{
|
||||
return bool(x);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
|
||||
optional_nodiscard optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
|
||||
{
|
||||
return (!x);
|
||||
}
|
||||
|
@ -1642,73 +1682,73 @@ inline optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> con
|
|||
// Comparison with T
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator==( optional<T> const & x, U const & v )
|
||||
optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, U const & v )
|
||||
{
|
||||
return bool(x) ? *x == v : false;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator==( U const & v, optional<T> const & x )
|
||||
optional_nodiscard optional_constexpr bool operator==( U const & v, optional<T> const & x )
|
||||
{
|
||||
return bool(x) ? v == *x : false;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator!=( optional<T> const & x, U const & v )
|
||||
optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, U const & v )
|
||||
{
|
||||
return bool(x) ? *x != v : true;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator!=( U const & v, optional<T> const & x )
|
||||
optional_nodiscard optional_constexpr bool operator!=( U const & v, optional<T> const & x )
|
||||
{
|
||||
return bool(x) ? v != *x : true;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator<( optional<T> const & x, U const & v )
|
||||
optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, U const & v )
|
||||
{
|
||||
return bool(x) ? *x < v : true;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator<( U const & v, optional<T> const & x )
|
||||
optional_nodiscard optional_constexpr bool operator<( U const & v, optional<T> const & x )
|
||||
{
|
||||
return bool(x) ? v < *x : false;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator<=( optional<T> const & x, U const & v )
|
||||
optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, U const & v )
|
||||
{
|
||||
return bool(x) ? *x <= v : true;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator<=( U const & v, optional<T> const & x )
|
||||
optional_nodiscard optional_constexpr bool operator<=( U const & v, optional<T> const & x )
|
||||
{
|
||||
return bool(x) ? v <= *x : false;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator>( optional<T> const & x, U const & v )
|
||||
optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, U const & v )
|
||||
{
|
||||
return bool(x) ? *x > v : false;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator>( U const & v, optional<T> const & x )
|
||||
optional_nodiscard optional_constexpr bool operator>( U const & v, optional<T> const & x )
|
||||
{
|
||||
return bool(x) ? v > *x : true;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator>=( optional<T> const & x, U const & v )
|
||||
optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, U const & v )
|
||||
{
|
||||
return bool(x) ? *x >= v : false;
|
||||
}
|
||||
|
||||
template< typename T, typename U >
|
||||
inline optional_constexpr bool operator>=( U const & v, optional<T> const & x )
|
||||
optional_nodiscard optional_constexpr bool operator>=( U const & v, optional<T> const & x )
|
||||
{
|
||||
return bool(x) ? v >= *x : true;
|
||||
}
|
||||
|
|
96
src/syslog.cpp
Normal file
96
src/syslog.cpp
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
|
||||
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 appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
|
||||
static bool g_SYSLOG_ENABLED = false;
|
||||
|
||||
void
|
||||
syslog_open()
|
||||
{
|
||||
const char *ident = "mergerfs";
|
||||
const int option = (LOG_CONS|LOG_PID);
|
||||
const int facility = LOG_USER;
|
||||
|
||||
openlog(ident,option,facility);
|
||||
g_SYSLOG_ENABLED = true;
|
||||
}
|
||||
|
||||
void
|
||||
syslog_close()
|
||||
{
|
||||
closelog();
|
||||
g_SYSLOG_ENABLED = false;
|
||||
}
|
||||
|
||||
void
|
||||
syslog_log(const int priority_,
|
||||
const char *format_,
|
||||
va_list valist_)
|
||||
{
|
||||
if(g_SYSLOG_ENABLED == false)
|
||||
return;
|
||||
|
||||
vsyslog(priority_,format_,valist_);
|
||||
}
|
||||
|
||||
void
|
||||
syslog_log(const int priority_,
|
||||
const char *format_,
|
||||
...)
|
||||
{
|
||||
va_list valist;
|
||||
|
||||
va_start(valist,format_);
|
||||
syslog_log(priority_,format_,valist);
|
||||
va_end(valist);
|
||||
}
|
||||
|
||||
void
|
||||
syslog_info(const char *format_,
|
||||
...)
|
||||
{
|
||||
va_list valist;
|
||||
|
||||
va_start(valist,format_);
|
||||
syslog_log(LOG_INFO,format_,valist);
|
||||
va_end(valist);
|
||||
}
|
||||
|
||||
void
|
||||
syslog_warning(const char *format_,
|
||||
...)
|
||||
{
|
||||
va_list valist;
|
||||
|
||||
va_start(valist,format_);
|
||||
syslog_log(LOG_WARNING,format_,valist);
|
||||
va_end(valist);
|
||||
}
|
||||
|
||||
void
|
||||
syslog_error(const char *format_,
|
||||
...)
|
||||
{
|
||||
va_list valist;
|
||||
|
||||
va_start(valist,format_);
|
||||
syslog_log(LOG_ERR,format_,valist);
|
||||
va_end(valist);
|
||||
}
|
29
src/syslog.hpp
Normal file
29
src/syslog.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
|
||||
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 appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
|
||||
void syslog_open();
|
||||
void syslog_log(const int priority, const char *format, ...);
|
||||
void syslog_info(const char *format, ...);
|
||||
void syslog_warning(const char *format, ...);
|
||||
void syslog_error(const char *format, ...);
|
||||
void syslog_close();
|
Loading…
Reference in New Issue
Block a user