/* vim:set ts=2 sw=2 sts=2 et: */ /** * \author Marcus Holland-Moritz (github@mhxnet.de) * \copyright Copyright (c) Marcus Holland-Moritz * * This file is part of dwarfs. * * dwarfs is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * dwarfs is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with dwarfs. If not, see . */ #include #include #ifdef _WIN32 #include #else #include #include #endif #include #include #include namespace dwarfs { namespace { uint64_t get_page_size() { #ifdef _WIN32 ::SYSTEM_INFO info; ::GetSystemInfo(&info); return info.dwPageSize; #else return ::sysconf(_SC_PAGESIZE); #endif } #ifndef _WIN32 int posix_advice(advice adv) { switch (adv) { case advice::normal: return MADV_NORMAL; case advice::random: return MADV_RANDOM; case advice::sequential: return MADV_SEQUENTIAL; case advice::willneed: return MADV_WILLNEED; case advice::dontneed: return MADV_DONTNEED; } assert(false); return MADV_NORMAL; } #endif boost::filesystem::path boost_from_std_path(std::filesystem::path const& p) { #ifdef _WIN32 return boost::filesystem::path(p.wstring()); #else return boost::filesystem::path(p.string()); #endif } } // namespace std::error_code mmap::lock(file_off_t offset [[maybe_unused]], size_t size [[maybe_unused]]) { std::error_code ec; auto data = mf_.const_data() + offset; #ifdef _WIN32 if (::VirtualLock(const_cast(data), size) == 0) { ec.assign(::GetLastError(), std::system_category()); } #else if (::mlock(data, size) != 0) { ec.assign(errno, std::generic_category()); } #endif return ec; } std::error_code mmap::advise(advice adv [[maybe_unused]], file_off_t offset [[maybe_unused]], size_t size [[maybe_unused]]) { std::error_code ec; #ifdef _WIN32 //// TODO: this doesn't currently work // if (::VirtualFree(data, size, MEM_DECOMMIT) == 0) { // ec.assign(::GetLastError(), std::system_category()); // } #else auto misalign = offset % page_size_; offset -= misalign; size += misalign; size -= size % page_size_; auto data = const_cast(mf_.const_data() + offset); int native_adv = posix_advice(adv); if (::madvise(data, size, native_adv) != 0) { ec.assign(errno, std::generic_category()); } #endif return ec; } std::error_code mmap::advise(advice adv) { return advise(adv, 0, size()); } std::error_code mmap::release(file_off_t offset, size_t size) { return advise(advice::dontneed, offset, size); } std::error_code mmap::release_until(file_off_t offset) { return release(0, offset); } void const* mmap::addr() const { return mf_.const_data(); } size_t mmap::size() const { return mf_.size(); } std::filesystem::path const& mmap::path() const { return path_; } mmap::mmap(char const* path) : mmap(std::filesystem::path(path)) {} mmap::mmap(std::string const& path) : mmap(std::filesystem::path(path)) {} mmap::mmap(std::filesystem::path const& path) : mf_(boost_from_std_path(path), boost::iostreams::mapped_file::readonly) , page_size_(get_page_size()) , path_{path} { assert(mf_.is_open()); } mmap::mmap(std::string const& path, size_t size) : mmap(std::filesystem::path(path), size) {} mmap::mmap(std::filesystem::path const& path, size_t size) : mf_(boost_from_std_path(path), boost::iostreams::mapped_file::readonly, size) , page_size_(get_page_size()) , path_{path} { assert(mf_.is_open()); } } // namespace dwarfs