Closed4
Entropia File System Watcher (efsw)メモ
C++で実装されたクロスプラットフォームなフォルダ監視ライブラリefsw
を調査していくスレ
homebrew
には展開されていなかったので、気合いで自前ビルドが必要そう。
C API
とC++ API
が提供されている。
src/test
下のユニットテストをもとに機能を類推。
C API
C++ APIをラップしている。
インスタンス作成
efsw_watcher EFSW_API efsw_create(int generic_mode);
- generic_mode: 引数はbool値でプラットフォーム特化の実装を使用する場合はfalseを渡す
インスタンスの解放
void EFSW_API efsw_release(efsw_watcher watcher);
最後に発生したエラーメッセージの取得
EFSW_API const char* efsw_getlasterror();
エラーメッセージの破棄
EFSW_API void efsw_clearlasterror();
監視対象の追加
efsw_watchid EFSW_API efsw_addwatch(efsw_watcher watcher, const char* directory,
efsw_pfn_fileaction_callback callback_fn, int recursive, void* param);
efsw_watchid EFSW_API efsw_addwatch_withoptions(efsw_watcher watcher, const char* directory,
efsw_pfn_fileaction_callback callback_fn, int recursive, efsw_watcher_option *options,
int options_number, void* param);
後者は前者のオプション付き版。
現状オプションはWindows
用。
- 戻り値はエラーの場合
efsw.hpp
のErrors::Error
列挙体の値、正常系なら識別するための数値 - 監視対象はファイルそのものではなくフォルダのパスを指定する模様
-
efsw_pfn_fileaction_callback
は変更があった際に呼ばれるコールバックだろう -
recursive
は再帰的に監視対象を深掘りするかどうか -
param
は多分、コールバックに渡すコンテキスト情報
監視対象の解除
void EFSW_API efsw_removewatch(efsw_watcher watcher, const char* directory);
void EFSW_API efsw_removewatch_byid(efsw_watcher watcher, efsw_watchid watchid);
- 前者はフォルダパス指定
- 後者は
efsw_addwatch
の戻り値をしてい- 後者の方がO(logN)で圧倒的に速いらしい
監視を開始する
void EFSW_API efsw_watch(efsw_watcher watcher);
監視は別スレッドを起動してそこで行う模様
フラグ設定
void EFSW_API efsw_follow_symlinks(efsw_watcher watcher, int enable);
int EFSW_API efsw_follow_symlinks_isenabled(efsw_watcher watcher);
- シンボリックリンクのリンク先を追跡するかどうか
- 後者はその設定値の取得っぽい
void EFSW_API efsw_allow_outofscopelinks(efsw_watcher watcher, int allow);
int EFSW_API efsw_outofscopelinks_isallowed(efsw_watcher watcher);
- シンボリックリンクがフォルダの場合のその先まで再帰的に追跡するかどうかの指定
- 先に
efsw_follow_symlinks
を有効にしておく必要がある
- 先に
- このフラグを有効化するとくっそ遅くなる危険を孕むことになるので、使う時はよーく考えた上でねって感じ
- 後者は設定値の取得
C++ API
FileWatcher クラス
このライブラリの本体。
監視対象の管理と監視の開始を行う。
C APIとの違いは、コールバック関数の代わりにFileWatchListener
クラスのインスタンスを指定するくらい。
FileWatchListener クラス
監視対象の変更が観測されたときに呼ばれるリスナー(コールバック)
FileWatchListener::handleFileAction
メソッドをオーバーライドする
virtual void handleFileAction( WatchID watchid, const std::string& dir,
const std::string& filename, Action action,
std::string oldFilename = "" ) = 0;
C API
とは異なり、ユーザコンテキストは引数で受け取らない。
メンバフィールドに置いとけってスタンス。
WatcherOption クラス
FileWatcher::addWatch
に渡すオプション
2024/11/01
現在、オプションは以下の2つ
どちらもWindows
向けの設定っぽい
- Options::Option::WinBufferSize
- バッファサイズの規定値は
63*1024
だけど、サイズ不足で稀によく取りこぼすらしい - このオプションは監視対象ごとに指定したサイズで調整する
- ちな、ネットワークドライブでは
Windows
の仕様により動かない模様
- バッファサイズの規定値は
- Options::Option::WinNotifyFilter
-
Windows API
のReadDirectoryChangesW
のdwNotifyFilter
引数に渡す値をビットマスクとして指定する - https://learn.microsoft.com/ja-jp/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
-
プラットフォームごとのファイル監視の方法
EFSW_PLATFORM
マクロ変数の値で判定
Windows
たぶんIOCP使う
- FileWatcherWin32 クラス
-
EFSW_PLATFORM
にEFSW_PLATFORM_WIN32
を指定する
Linux
INotifyを使う
- FileWatcherInotify クラス
-
EFSW_PLATFORM
にEFSW_PLATFORM_INOTIFY
を指定する
BSD系
kqueueを使う
- FileWatcherKqueue クラス
-
EFSW_PLATFORM
にEFSW_PLATFORM_KQUEUE
を指定する
MacOS
DSEventを使う
もしかしたらkqueueも使えるのかも
- FileWatcherFSEvents
-
EFSW_PLATFORM
に@EFSW_PLATFORM_FSEVENTS`を指定する
それ以外
efsw_create
関数や FileWatcher
クラスのコンストラクタにgeneric_mode
を渡した場合
または、プラットフォーム特化実装が使えなかった場合のフォールバック
- FileWatcherGeneric
このスクラップは17日前にクローズされました