diff options
author | elfmz <fenix1905@tut.by> | 2022-10-27 00:19:22 +0300 |
---|---|---|
committer | elfmz <fenix1905@tut.by> | 2022-10-27 10:08:18 +0300 |
commit | ecefbdfc83366ac6d119e8356901ecfeb70afa7c (patch) | |
tree | 82f7a7c64f16f8878a0a7bb2c0e158c3a243f4a0 | |
parent | 6cc79cf88da56351d39b4bf4154385adde4f1d19 (diff) |
add BSD and MAC support into MountInfo
-rw-r--r-- | far2l/src/farwinapi.cpp | 2 | ||||
-rw-r--r-- | far2l/src/findfile.cpp | 2 | ||||
-rw-r--r-- | far2l/src/mix/MountInfo.cpp | 142 | ||||
-rw-r--r-- | far2l/src/mix/MountInfo.h | 12 | ||||
-rw-r--r-- | utils/include/Threaded.h | 4 | ||||
-rw-r--r-- | utils/src/Threaded.cpp | 15 |
6 files changed, 152 insertions, 25 deletions
diff --git a/far2l/src/farwinapi.cpp b/far2l/src/farwinapi.cpp index 64e9d254..0afad4d4 100644 --- a/far2l/src/farwinapi.cpp +++ b/far2l/src/farwinapi.cpp @@ -514,7 +514,7 @@ BOOL apiGetVolumeInformation( } if (pFileSystemName) { - *pFileSystemName = MountInfo().GetFileSystem(path); + *pFileSystemName = MountInfo(false).GetFileSystem(path); } return TRUE; diff --git a/far2l/src/findfile.cpp b/far2l/src/findfile.cpp index f4655733..d27f3939 100644 --- a/far2l/src/findfile.cpp +++ b/far2l/src/findfile.cpp @@ -2803,7 +2803,7 @@ public: { SudoClientRegion scr; DWORD msec = GetProcessUptimeMSec(); - pMountInfo.reset(new MountInfo); + pMountInfo.reset(new MountInfo(false)); if (PluginMode) { DoPreparePluginList(hDlg); diff --git a/far2l/src/mix/MountInfo.cpp b/far2l/src/mix/MountInfo.cpp index 96368b45..a655ccfb 100644 --- a/far2l/src/mix/MountInfo.cpp +++ b/far2l/src/mix/MountInfo.cpp @@ -7,15 +7,23 @@ #include <sys/statvfs.h> #include <fcntl.h> #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__CYGWIN__) -# include <errno.h> +# if defined(__APPLE__) || defined(__FreeBSD__) +# include <sys/param.h> +# include <sys/ucred.h> +# endif # include <sys/mount.h> #else # include <sys/statfs.h> # include <linux/fs.h> #endif +#include <errno.h> #include <fstream> +#include <chrono> +#include <mutex> +#include <condition_variable> #include "MountInfo.h" #include <ScopeHelpers.h> +#include <Threaded.h> #include <os_call.hpp> static struct FSMagic { @@ -97,9 +105,67 @@ static struct FSMagic { ///////////////////////////////////////////////////////////////////////////////////////////// -MountInfo::MountInfo() +struct Mountpoint +{ + std::string path; + std::string filesystem; + bool multi_thread_friendly; + unsigned long long total, used; +}; + +struct Mountpoints : std::vector<Mountpoint> +{ + struct Pending + { + std::mutex mtx; + std::condition_variable cond; + int cnt{0}; + } pending; +}; + +class ThreadedStatFS : Threaded +{ + std::shared_ptr<Mountpoints> _mps; + size_t _mpi; + + void *ThreadProc() + { + struct statfs fs{}; + int r = statfs((*_mps)[_mpi].path.c_str(), &fs); + if (r == 0) { + (*_mps)[_mpi].total = fs.f_bsize * fs.f_blocks; + (*_mps)[_mpi].used = (fs.f_bsize - fs.f_bfree) * fs.f_blocks; + } + return nullptr; + } + +public: + ThreadedStatFS(std::shared_ptr<Mountpoints> &mps, size_t mpi) + : _mps(mps), _mpi(mpi) + { + } + + virtual ~ThreadedStatFS() + { + std::unique_lock<std::mutex> lock(_mps->pending.mtx); + _mps->pending.cnt--; + if (_mps->pending.cnt == 0) { + _mps->pending.cond.notify_all(); + } + + } + + void Start() + { + if (!StartThread(true)) { + fprintf(stderr, "ThreadedStatFS: can't start thread\n"); + delete this; + } + } +}; + +MountInfo::MountInfo(bool query_space) { -#ifdef __linux__ // force-enable multi-threaded disk access: echo e > ~/.config/far2l/mtfs // force-disable multi-threaded disk access: echo d > ~/.config/far2l/mtfs FDScope fd(open(InMyConfig("mtfs").c_str(), O_RDONLY)); @@ -109,7 +175,9 @@ MountInfo::MountInfo() } fprintf(stderr, "%s: _mtfs='%c'\n", __FUNCTION__, _mtfs); } + _mountpoints = std::make_shared<Mountpoints>(); +#ifdef __linux__ std::ifstream is("/proc/mounts"); if (is.is_open()) { std::string line, sys_path; @@ -142,18 +210,70 @@ MountInfo::MountInfo() if (parts.size() == 1) { parts.emplace_back(); } - _mountpoints.emplace_back(Mountpoint{parts[1], parts[2], multi_thread_friendly}); - fprintf(stderr, "%s: mtf=%d fs='%s' for '%s' at '%s'\n", __FUNCTION__, - multi_thread_friendly, parts[2].c_str(), parts[0].c_str(), parts[1].c_str()); + _mountpoints->emplace_back(Mountpoint{ + parts[1], + parts[2], + multi_thread_friendly, + 0, + 0 + }); } } } - if (_mountpoints.empty()) { - fprintf(stderr, "%s: failed to parse /proc/mounts\n", __FUNCTION__); + +#elif defined(__APPLE__) || defined(__FreeBSD__) + + int r = getfsstat(nullptr, 0, MNT_NOWAIT); + if (r > 0) { + std::vector<struct statfs> buf(r * 2 + 2); + r = getfsstat(buf.data(), buf.size(), MNT_NOWAIT); + if (r > 0) { + buf.resize(r); + for (const auto &fs : buf) { + _mountpoints->emplace_back(Mountpoint{ + fs.f_mntonname, + fs.f_fstypename, + true, + fs.f_bsize * fs.f_blocks, + (fs.f_bsize - fs.f_bfree) * fs.f_blocks + }); + } + } } #endif - // TODO: BSD, MacOS + if (_mountpoints->empty()) { + fprintf(stderr, "%s: no mountpoints found\n", __FUNCTION__); + + } else if (query_space) { + for (size_t i = 0; i < _mountpoints->size(); ++i) { + try { + (new ThreadedStatFS(_mountpoints, i))->Start(); + std::unique_lock<std::mutex> lock(_mountpoints->pending.mtx); + _mountpoints->pending.cnt++; + } catch (std::exception &e) { + fprintf(stderr, "%s: %s\n", __FUNCTION__, e.what()); + } + } + for (DWORD ms = 0; ms < 1000;) { + std::chrono::milliseconds ms_before = std::chrono::duration_cast< std::chrono::milliseconds > + (std::chrono::steady_clock::now().time_since_epoch()); + { + std::unique_lock<std::mutex> lock(_mountpoints->pending.mtx); + _mountpoints->pending.cond.wait_for(lock, std::chrono::milliseconds(1000 - ms)); + if (_mountpoints->pending.cnt == 0) { + break; + } + } + ms+= (std::chrono::duration_cast< std::chrono::milliseconds > + (std::chrono::steady_clock::now().time_since_epoch()) - ms_before).count(); + } + } + + for (const auto &it : *_mountpoints) { + fprintf(stderr, "%s: mtf=%d spc=[%llu/%llu] fs='%s' at '%s'\n", __FUNCTION__, + it.multi_thread_friendly, it.used, it.total, it.filesystem.c_str(), it.path.c_str()); + } } @@ -161,7 +281,7 @@ std::string MountInfo::GetFileSystem(const std::string &path) const { std::string out; size_t longest_match = 0; - for (const auto &it : _mountpoints) { + for (const auto &it : *_mountpoints) { if (it.path.size() > longest_match && StrStartsFrom(path, it.path.c_str())) { longest_match = it.path.size(); out = it.filesystem; @@ -199,7 +319,7 @@ bool MountInfo::IsMultiThreadFriendly(const std::string &path) const bool out = true; size_t longest_match = 0; - for (const auto &it : _mountpoints) { + for (const auto &it : *_mountpoints) { if (it.path.size() > longest_match && StrStartsFrom(path, it.path.c_str())) { longest_match = it.path.size(); out = it.multi_thread_friendly; diff --git a/far2l/src/mix/MountInfo.h b/far2l/src/mix/MountInfo.h index 4c630697..65781245 100644 --- a/far2l/src/mix/MountInfo.h +++ b/far2l/src/mix/MountInfo.h @@ -1,6 +1,9 @@ #pragma once #include <string> #include <vector> +#include <memory> + +struct Mountpoints; /* This class detects if path points to device that is best to be * accessed in multi-thread parallel manner, like SSD drives. @@ -8,16 +11,11 @@ */ class MountInfo { - struct Mountpoint { - std::string path; - std::string filesystem; - bool multi_thread_friendly; - }; - struct Mountpoints : std::vector<Mountpoint> {} _mountpoints; + std::shared_ptr<Mountpoints> _mountpoints; char _mtfs = 0; public: - MountInfo(); + MountInfo(bool query_space); std::string GetFileSystem(const std::string &path) const; diff --git a/utils/include/Threaded.h b/utils/include/Threaded.h index 80590ff2..93caccfb 100644 --- a/utils/include/Threaded.h +++ b/utils/include/Threaded.h @@ -7,6 +7,7 @@ class Threaded { std::condition_variable _trd_cond; std::mutex _trd_mtx; + bool _self_destruct = false; pthread_t _trd = 0; void *_trd_result = nullptr; @@ -19,7 +20,8 @@ protected: virtual void *ThreadProc() = 0; - bool StartThread(); + void Detach(); + bool StartThread(bool self_destruct = false); bool WaitThread(unsigned int msec = (unsigned int)-1); void *GetThreadResult(); }; diff --git a/utils/src/Threaded.cpp b/utils/src/Threaded.cpp index ee393a29..7e404f1d 100644 --- a/utils/src/Threaded.cpp +++ b/utils/src/Threaded.cpp @@ -21,14 +21,20 @@ void *Threaded::sThreadProc(void *p) Threaded *it = (Threaded *)p; void *result = it->ThreadProc(); - std::lock_guard<std::mutex> lock(it->_trd_mtx); - it->_trd_exited = true; - it->_trd_cond.notify_all(); + { + std::lock_guard<std::mutex> lock(it->_trd_mtx); + it->_trd_exited = true; + it->_trd_cond.notify_all(); + } + + if (it->_self_destruct) { + delete it; + } return result; } -bool Threaded::StartThread() +bool Threaded::StartThread(bool self_destruct) { std::lock_guard<std::mutex> lock(_trd_mtx); if (!_trd_joined) { @@ -41,6 +47,7 @@ bool Threaded::StartThread() } _trd_joined = _trd_exited = false; + _self_destruct = self_destruct; if (pthread_create(&_trd, NULL, &sThreadProc, this) != 0) { _trd_joined = _trd_exited = true; _trd = 0; |