1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 10:57:35 +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:
sin-ack 2021-05-09 17:09:30 +00:00 committed by Andreas Kling
parent fe5ca6ca27
commit 2159f90e00
12 changed files with 403 additions and 140 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Nick Vella <nick@nxk.io>
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -8,6 +9,7 @@
#include <AK/LexicalPath.h>
#include <AK/QuickSort.h>
#include <Kernel/API/InodeWatcherEvent.h>
#include <LibCore/DirIterator.h>
#include <LibGUI/Icon.h>
#include <LibGUI/Variant.h>
@ -21,12 +23,21 @@ ProjectTemplatesModel::ProjectTemplatesModel()
: m_templates()
, m_mapping()
{
auto watcher_or_error = Core::FileWatcher::watch(ProjectTemplate::templates_path());
auto watcher_or_error = Core::FileWatcher::create();
if (!watcher_or_error.is_error()) {
m_file_watcher = watcher_or_error.release_value();
m_file_watcher->on_change = [&](auto) {
update();
};
auto watch_result = m_file_watcher->add_watch(
ProjectTemplate::templates_path(),
Core::FileWatcherEvent::Type::ChildCreated
| Core::FileWatcherEvent::Type::ChildDeleted);
if (watch_result.is_error()) {
warnln("Unable to watch templates directory, templates will not automatically refresh. Error: {}", watch_result.error());
}
} else {
warnln("Unable to watch templates directory, templates will not automatically refresh. Error: {}", watcher_or_error.error());
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
* Copyright (c) 2020, the SerenityOS developers.
* Copyright (c) 2020-2021, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -24,6 +24,7 @@
#include "TerminalWrapper.h"
#include <AK/LexicalPath.h>
#include <AK/StringBuilder.h>
#include <Kernel/API/InodeWatcherEvent.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/Event.h>
#include <LibCore/EventLoop.h>
@ -131,6 +132,24 @@ HackStudioWidget::HackStudioWidget(const String& path_to_project)
initialize_debugger();
create_toolbar(toolbar_container);
auto maybe_watcher = Core::FileWatcher::create();
if (maybe_watcher.is_error()) {
warnln("Couldn't create a file watcher, deleted files won't be noticed! Error: {}", maybe_watcher.error());
} else {
m_file_watcher = maybe_watcher.release_value();
m_file_watcher->on_change = [this](Core::FileWatcherEvent const& event) {
if (event.type != Core::FileWatcherEvent::Type::Deleted)
return;
if (event.event_path.starts_with(project().root_path())) {
String relative_path = LexicalPath::relative_path(event.event_path, project().root_path());
handle_external_file_deletion(relative_path);
} else {
handle_external_file_deletion(event.event_path);
}
};
}
}
void HackStudioWidget::update_actions()
@ -224,18 +243,12 @@ bool HackStudioWidget::open_file(const String& full_filename)
new_project_file = m_project->get_file(filename);
m_open_files.set(filename, *new_project_file);
m_open_files_vector.append(filename);
auto watcher_or_error = Core::FileWatcher::watch(filename);
if (!watcher_or_error.is_error()) {
auto& watcher = watcher_or_error.value();
watcher->on_change = [this, filename]() {
struct stat st;
if (lstat(filename.characters(), &st) < 0) {
if (errno == ENOENT) {
handle_external_file_deletion(filename);
}
}
};
m_file_watchers.set(filename, watcher_or_error.release_value());
if (!m_file_watcher.is_null()) {
auto watch_result = m_file_watcher->add_watch(filename, Core::FileWatcherEvent::Type::Deleted);
if (watch_result.is_error()) {
warnln("Couldn't watch '{}'", filename);
}
}
m_open_files_view->model()->update();
@ -1030,7 +1043,6 @@ void HackStudioWidget::handle_external_file_deletion(const String& filepath)
}
}
m_file_watchers.remove(filepath);
m_open_files_view->model()->update();
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
* Copyright (c) 2020, the SerenityOS developers.
* Copyright (c) 2020-2021, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -122,7 +122,7 @@ private:
RefPtr<EditorWrapper> m_current_editor_wrapper;
HashMap<String, NonnullRefPtr<ProjectFile>> m_open_files;
HashMap<String, NonnullRefPtr<Core::FileWatcher>> m_file_watchers;
RefPtr<Core::FileWatcher> m_file_watcher;
Vector<String> m_open_files_vector; // NOTE: This contains the keys from m_open_files and m_file_watchers
OwnPtr<Project> m_project;

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -158,7 +159,9 @@ private:
int virt$sched_getparam(pid_t, FlatPtr);
int virt$set_thread_name(pid_t, FlatPtr, size_t);
pid_t virt$setsid();
int virt$watch_file(FlatPtr, size_t);
int virt$create_inode_watcher(unsigned);
int virt$inode_watcher_add_watch(FlatPtr);
int virt$inode_watcher_remove_watch(int, int);
int virt$readlink(FlatPtr);
u32 virt$allocate_tls(FlatPtr, size_t);
int virt$ptsname(int fd, FlatPtr buffer, size_t buffer_size);

View file

@ -222,8 +222,12 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
return virt$set_thread_name(arg1, arg2, arg3);
case SC_setsid:
return virt$setsid();
case SC_watch_file:
return virt$watch_file(arg1, arg2);
case SC_create_inode_watcher:
return virt$create_inode_watcher(arg1);
case SC_inode_watcher_add_watch:
return virt$inode_watcher_add_watch(arg1);
case SC_inode_watcher_remove_watch:
return virt$inode_watcher_remove_watch(arg1, arg2);
case SC_clock_nanosleep:
return virt$clock_nanosleep(arg1);
case SC_readlink:
@ -1386,10 +1390,21 @@ pid_t Emulator::virt$setsid()
return syscall(SC_setsid);
}
int Emulator::virt$watch_file(FlatPtr user_path_addr, size_t path_length)
int Emulator::virt$create_inode_watcher(unsigned flags)
{
auto user_path = mmu().copy_buffer_from_vm(user_path_addr, path_length);
return syscall(SC_watch_file, user_path.data(), user_path.size());
return syscall(SC_create_inode_watcher, flags);
}
int Emulator::virt$inode_watcher_add_watch(FlatPtr params_addr)
{
Syscall::SC_inode_watcher_add_watch_params params;
mmu().copy_from_vm(&params, params_addr, sizeof(params));
return syscall(SC_inode_watcher_add_watch, &params);
}
int Emulator::virt$inode_watcher_remove_watch(int fd, int wd)
{
return syscall(SC_inode_watcher_add_watch, fd, wd);
}
int Emulator::virt$clock_nanosleep(FlatPtr params_addr)