41# ifndef TPL_PAGED_TREE_DURABILITY_H
42# define TPL_PAGED_TREE_DURABILITY_H
54# include <type_traits>
59# if defined(__unix__) || defined(__APPLE__)
63# include <sys/types.h>
92# if defined(__unix__) || defined(__APPLE__)
93 namespace fs = std::filesystem;
94 const fs::path parent = fs::path(path).has_parent_path()
95 ? fs::path(path).parent_path()
100 << kind <<
": cannot open parent directory " << parent.string()
103 const int status =
::fsync(fd);
106 << kind <<
": cannot fsync parent directory " << parent.string();
108 << kind <<
": cannot close parent directory " << parent.string();
117# if defined(__unix__) || defined(__APPLE__)
118 const int fd = ::open(path.c_str(),
O_RDONLY);
120 << kind <<
": cannot open " << path <<
" for fsync";
122 const int status =
::fsync(fd);
125 << kind <<
": cannot fsync " << path;
127 << kind <<
": cannot close " << path;
135 const std::string & path,
138# if defined(__unix__) || defined(__APPLE__)
139 const int status =
::fsync(fd);
141 << kind <<
": cannot fsync " << path;
152 namespace fs = std::filesystem;
154 const bool removed = fs::remove(path,
ec);
156 << kind <<
": cannot remove " << path <<
" (" <<
ec.message() <<
")";
162 const std::string &
dst,
165 namespace fs = std::filesystem;
167 fs::rename(src,
dst,
ec);
169 << kind <<
": cannot rename " << src <<
" to " <<
dst
170 <<
" (" <<
ec.message() <<
")";
175 const std::string &
dst,
178 std::ifstream
in(src, std::ios::binary);
180 << kind <<
": cannot open " << src <<
" for reading";
182 std::ofstream
out(
dst, std::ios::binary | std::ios::trunc);
184 << kind <<
": cannot open " <<
dst <<
" for writing";
186 std::array<char, 8192> buffer = {};
189 in.read(buffer.data(), buffer.size());
190 const auto count =
in.gcount();
196 << kind <<
": cannot read " << src;
200 << kind <<
": cannot flush " <<
dst;
204 << kind <<
": cannot close " <<
dst;
217 const size_t size)
noexcept
219 const auto * ptr =
static_cast<const unsigned char *
>(data);
220 for (
size_t i = 0; i <
size; ++i)
224 crc = (
crc >> 1) ^ (0xEDB88320u &
static_cast<std::uint32_t
>(-
static_cast<int>(
crc & 1u)));
229 template <
typename T>
231 const T & value)
noexcept
233 static_assert(std::is_trivially_copyable_v<T>,
234 "crc32_add requires a trivially copyable value");
245# if defined(__unix__) || defined(__APPLE__)
246 return static_cast<long long>(
::getpid());
254# if defined(__unix__) || defined(__APPLE__)
280# if defined(__unix__) || defined(__APPLE__)
286 static std::mutex mutex;
292 static std::vector<Local_Lock_State> states;
302 const auto it = std::find_if(states.begin(), states.end(),
305 return state.path == path;
308 if (it == states.end())
314 states.push_back(std::move(state));
321 << kind <<
": this process already holds an exclusive lock "
328 << kind <<
": this process already holds the lock " << path;
336 const auto it = std::find_if(states.begin(), states.end(),
339 return state.path == path;
341 if (it == states.end())
346 if (it->shared_count > 0)
350 it->exclusive =
false;
352 if (it->shared_count == 0
and not it->exclusive)
358 std::ifstream
in(path);
370# if defined(__unix__) || defined(__APPLE__)
373 const std::string & path,
376 struct flock lock = {};
386 << kind <<
": cannot acquire advisory lock " << path;
388 << kind <<
": another process already holds the lock " << path;
392 const std::string & path,
398 << kind <<
": cannot truncate pid lock " << path;
400 << kind <<
": cannot seek pid lock " << path;
404 << kind <<
": cannot write pid lock " << path;
434 namespace fs = std::filesystem;
438 (
void) fs::create_directories(fs::path(
path_).parent_path(),
ec);
441# if defined(__unix__) || defined(__APPLE__)
445 << kind <<
": cannot query pid lock " <<
path_ <<
" ("
455 << kind <<
": cannot open pid lock " <<
lock_path;
477 std::ofstream
out(
path_, std::ios::out | std::ios::trunc);
487 << kind <<
": another process already holds the lock " <<
path_;
499# if defined(__unix__) || defined(__APPLE__)
508 std::filesystem::remove(
path_,
ec);
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
#define ah_runtime_error()
Throws std::runtime_error unconditionally.
static std::mutex & registry_mutex()
~Pid_File_Lock() noexcept
Pid_File_Lock(Pid_File_Lock &&)=delete
static void register_path(const std::string &path, const Pid_File_Lock_Mode mode, const char *kind)
Pid_File_Lock(const Pid_File_Lock &)=delete
static bool stale_lock(const std::string &path)
Pid_File_Lock & operator=(const Pid_File_Lock &)=delete
static void unregister_path(const std::string &path, const Pid_File_Lock_Mode mode) noexcept
void acquire(const std::string &path, const char *kind, const Pid_File_Lock_Mode mode=Pid_File_Lock_Mode::Exclusive)
static std::vector< Local_Lock_State > & registry()
std::uint32_t crc32_add_bytes(std::uint32_t crc, const void *data, const size_t size) noexcept
void sync_parent_directory(const std::string &path, const char *kind)
long long current_process_id() noexcept
bool process_is_alive(const long long pid) noexcept
void copy_file_contents(const std::string &src, const std::string &dst, const char *kind)
void remove_file_if_exists(const std::string &path, const char *kind)
std::uint32_t crc32_begin() noexcept
std::uint32_t crc32_add(std::uint32_t crc, const T &value) noexcept
void rename_file_atomic(const std::string &src, const std::string &dst, const char *kind)
void sync_file_descriptor(const int fd, const std::string &path, const char *kind)
std::uint32_t crc32_finish(const std::uint32_t crc) noexcept
void sync_file_by_path(const std::string &path, const char *kind)
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
size_t size(Node *root) noexcept
Paged_File_Open_Mode
Open mode for paged persistent tree files.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
auto mode(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute the mode (most frequent value).
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.