mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:17:34 +00:00
Userland+LibCore: Update FileWatcher + its users for InodeWatcher 2.0
With the new InodeWatcher API, the old style of creating a watcher per inode will no longer work. Therefore the FileWatcher API has been updated to support multiple watches, and its users have also been refactored to the new style. At the moment, all operations done on a (Blocking)FileWatcher return Result objects, however, this may be changed in the future if it becomes too obnoxious. :^) Co-authored-by: Gunnar Beutner <gunnar@beutner.name>
This commit is contained in:
parent
fe5ca6ca27
commit
2159f90e00
12 changed files with 403 additions and 140 deletions
|
@ -7,54 +7,118 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/EnumBits.h>
|
||||
#include <AK/Function.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/Result.h>
|
||||
#include <AK/String.h>
|
||||
#include <Kernel/API/InodeWatcherEvent.h>
|
||||
#include <Kernel/API/InodeWatcherFlags.h>
|
||||
#include <LibCore/Notifier.h>
|
||||
|
||||
namespace Core {
|
||||
|
||||
struct FileWatcherEvent {
|
||||
enum class Type {
|
||||
Modified,
|
||||
ChildAdded,
|
||||
ChildRemoved,
|
||||
Invalid = 0,
|
||||
MetadataModified = 1 << 0,
|
||||
ContentModified = 1 << 1,
|
||||
Deleted = 1 << 2,
|
||||
ChildCreated = 1 << 3,
|
||||
ChildDeleted = 1 << 4,
|
||||
};
|
||||
Type type;
|
||||
String child_path;
|
||||
String event_path;
|
||||
};
|
||||
|
||||
class BlockingFileWatcher {
|
||||
AK_ENUM_BITWISE_OPERATORS(FileWatcherEvent::Type);
|
||||
|
||||
class FileWatcherBase {
|
||||
public:
|
||||
virtual ~FileWatcherBase() { }
|
||||
|
||||
Result<bool, String> add_watch(String path, FileWatcherEvent::Type event_mask);
|
||||
Result<bool, String> remove_watch(String path);
|
||||
bool is_watching(String const& path) const { return m_path_to_wd.find(path) != m_path_to_wd.end(); }
|
||||
|
||||
protected:
|
||||
FileWatcherBase(int watcher_fd)
|
||||
: m_watcher_fd(watcher_fd)
|
||||
{
|
||||
}
|
||||
|
||||
int m_watcher_fd { -1 };
|
||||
HashMap<String, unsigned> m_path_to_wd;
|
||||
HashMap<unsigned, String> m_wd_to_path;
|
||||
};
|
||||
|
||||
class BlockingFileWatcher final : public FileWatcherBase {
|
||||
AK_MAKE_NONCOPYABLE(BlockingFileWatcher);
|
||||
|
||||
public:
|
||||
explicit BlockingFileWatcher(const String& path);
|
||||
explicit BlockingFileWatcher(InodeWatcherFlags = InodeWatcherFlags::None);
|
||||
~BlockingFileWatcher();
|
||||
|
||||
Optional<FileWatcherEvent> wait_for_event();
|
||||
|
||||
private:
|
||||
String m_path;
|
||||
int m_watcher_fd { -1 };
|
||||
};
|
||||
|
||||
class FileWatcher : public RefCounted<FileWatcher> {
|
||||
class FileWatcher final : public FileWatcherBase
|
||||
, public RefCounted<FileWatcher> {
|
||||
AK_MAKE_NONCOPYABLE(FileWatcher);
|
||||
|
||||
public:
|
||||
static Result<NonnullRefPtr<FileWatcher>, String> watch(const String& path);
|
||||
static Result<NonnullRefPtr<FileWatcher>, String> create(InodeWatcherFlags = InodeWatcherFlags::None);
|
||||
~FileWatcher();
|
||||
|
||||
Function<void(FileWatcherEvent)> on_change;
|
||||
Function<void(FileWatcherEvent const&)> on_change;
|
||||
|
||||
private:
|
||||
FileWatcher(NonnullRefPtr<Notifier>, const String& path);
|
||||
FileWatcher(int watcher_fd, NonnullRefPtr<Notifier>);
|
||||
|
||||
NonnullRefPtr<Notifier> m_notifier;
|
||||
String m_path;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace AK {
|
||||
|
||||
template<>
|
||||
struct Formatter<Core::FileWatcherEvent> : Formatter<FormatString> {
|
||||
void format(FormatBuilder& builder, const Core::FileWatcherEvent& value)
|
||||
{
|
||||
Formatter<FormatString>::format(builder, "FileWatcherEvent(\"{}\", {})", value.event_path, value.type);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Formatter<Core::FileWatcherEvent::Type> : Formatter<FormatString> {
|
||||
void format(FormatBuilder& builder, const Core::FileWatcherEvent::Type& value)
|
||||
{
|
||||
char const* type;
|
||||
switch (value) {
|
||||
case Core::FileWatcherEvent::Type::ChildCreated:
|
||||
type = "ChildCreated";
|
||||
break;
|
||||
case Core::FileWatcherEvent::Type::ChildDeleted:
|
||||
type = "ChildDeleted";
|
||||
break;
|
||||
case Core::FileWatcherEvent::Type::Deleted:
|
||||
type = "Deleted";
|
||||
break;
|
||||
case Core::FileWatcherEvent::Type::ContentModified:
|
||||
type = "ContentModified";
|
||||
break;
|
||||
case Core::FileWatcherEvent::Type::MetadataModified:
|
||||
type = "MetadataModified";
|
||||
break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
builder.put_string(type);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue