Files
bsdports/devel/libglib/files/patch-gio_kqueue_kqueue-helper.c
2019-12-26 07:26:06 +00:00

410 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--- gio/kqueue/kqueue-helper.c.orig 2018-01-08 21:00:49.000000000 +0100
+++ gio/kqueue/kqueue-helper.c 2018-04-09 22:46:58.181986000 +0200
@@ -34,84 +34,7 @@
#include <errno.h>
#include <pthread.h>
#include "kqueue-helper.h"
-#include "kqueue-utils.h"
-#include "kqueue-thread.h"
-#include "kqueue-missing.h"
-#include "kqueue-exclusions.h"
-static gboolean kh_debug_enabled = FALSE;
-#define KH_W if (kh_debug_enabled) g_warning
-
-static GHashTable *subs_hash_table = NULL;
-G_LOCK_DEFINE_STATIC (hash_lock);
-
-static int kqueue_descriptor = -1;
-static int kqueue_socket_pair[] = {-1, -1};
-static pthread_t kqueue_thread;
-
-
-void _kh_file_appeared_cb (kqueue_sub *sub);
-
-/**
- * accessor function for kqueue_descriptor
- **/
-int
-get_kqueue_descriptor()
-{
- return kqueue_descriptor;
-}
-
-/**
- * convert_kqueue_events_to_gio:
- * @flags: a set of kqueue filter flags
- * @done: a pointer to #gboolean indicating that the
- * conversion has been done (out)
- *
- * Translates kqueue filter flags into GIO event flags.
- *
- * Returns: a #GFileMonitorEvent
- **/
-static GFileMonitorEvent
-convert_kqueue_events_to_gio (uint32_t flags, gboolean *done)
-{
- g_assert (done != NULL);
- *done = FALSE;
-
- /* TODO: The following notifications should be emulated, if possible:
- * - G_FILE_MONITOR_EVENT_PRE_UNMOUNT
- */
- if (flags & NOTE_DELETE)
- {
- *done = TRUE;
- return G_FILE_MONITOR_EVENT_DELETED;
- }
- if (flags & NOTE_ATTRIB)
- {
- *done = TRUE;
- return G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED;
- }
- if (flags & (NOTE_WRITE | NOTE_EXTEND))
- {
- *done = TRUE;
- return G_FILE_MONITOR_EVENT_CHANGED;
- }
- if (flags & NOTE_RENAME)
- {
- /* Since theres apparently no way to get the new name of the file out of
- * kqueue(), all we can do is say that this one has been deleted. */
- *done = TRUE;
- return G_FILE_MONITOR_EVENT_DELETED;
- }
- if (flags & NOTE_REVOKE)
- {
- *done = TRUE;
- return G_FILE_MONITOR_EVENT_UNMOUNTED;
- }
-
- /* done is FALSE */
- return 0;
-}
-
typedef struct {
kqueue_sub *sub;
GFileMonitorSource *source;
@@ -238,318 +161,21 @@ static const traverse_cbs cbs = {
void
-_kh_dir_diff (kqueue_sub *sub, GFileMonitorSource *source)
+_kh_dir_diff (kqueue_sub *sub)
{
dep_list *was;
handle_ctx ctx;
- g_assert (sub != NULL);
- g_assert (source != NULL);
-
memset (&ctx, 0, sizeof (handle_ctx));
ctx.sub = sub;
- ctx.source = source;
+ ctx.source = sub->source;
was = sub->deps;
sub->deps = dl_listing (sub->filename);
-
+
dl_calculate (was, sub->deps, &cbs, &ctx);
dl_free (was);
}
-/**
- * process_kqueue_notifications:
- * @gioc: unused.
- * @cond: unused.
- * @data: unused.
- *
- * Processes notifications, coming from the kqueue thread.
- *
- * Reads notifications from the command file descriptor, emits the
- * "changed" event on the appropriate monitor.
- *
- * A typical GIO Channel callback function.
- *
- * Returns: %TRUE
- **/
-static gboolean
-process_kqueue_notifications (GIOChannel *gioc,
- GIOCondition cond,
- gpointer data)
-{
- struct kqueue_notification n;
- kqueue_sub *sub = NULL;
- GFileMonitorSource *source = NULL;
- GFileMonitorEvent mask = 0;
-
- g_assert (kqueue_socket_pair[0] != -1);
- if (!_ku_read (kqueue_socket_pair[0], &n, sizeof (struct kqueue_notification)))
- {
- KH_W ("Failed to read a kqueue notification, error %d", errno);
- return TRUE;
- }
-
- G_LOCK (hash_lock);
- sub = (kqueue_sub *) g_hash_table_lookup (subs_hash_table, GINT_TO_POINTER (n.fd));
- G_UNLOCK (hash_lock);
-
- if (sub == NULL)
- {
- KH_W ("Got a notification for a deleted or non-existing subscription %d",
- n.fd);
- return TRUE;
- }
-
- source = sub->user_data;
- g_assert (source != NULL);
-
- if (n.flags & (NOTE_DELETE | NOTE_REVOKE))
- {
- if (sub->deps)
- {
- dl_free (sub->deps);
- sub->deps = NULL;
- }
- _km_add_missing (sub);
-
- if (!(n.flags & NOTE_REVOKE))
- {
- /* Note that NOTE_REVOKE is issued by the kqueue thread
- * on EV_ERROR kevent. In this case, a file descriptor is
- * already closed from the kqueue thread, no need to close
- * it manually */
- _kh_cancel_sub (sub);
- }
- }
-
- if (sub->is_dir && n.flags & (NOTE_WRITE | NOTE_EXTEND))
- {
- _kh_dir_diff (sub, source);
- n.flags &= ~(NOTE_WRITE | NOTE_EXTEND);
- }
-
- if (n.flags)
- {
- gboolean done = FALSE;
- mask = convert_kqueue_events_to_gio (n.flags, &done);
- if (done == TRUE)
- g_file_monitor_source_handle_event (source, mask, NULL, NULL, NULL, g_get_monotonic_time ());
- }
-
- return TRUE;
-}
-
-
-/*
- * _kh_startup_impl:
- * @unused: unused
- *
- * Kqueue backend startup code. Should be called only once.
- *
- * Returns: %TRUE on success, %FALSE otherwise.
- **/
-static gpointer
-_kh_startup_impl (gpointer unused)
-{
- GIOChannel *channel = NULL;
- gboolean result = FALSE;
-
- kqueue_descriptor = kqueue ();
- result = (kqueue_descriptor != -1);
- if (!result)
- {
- KH_W ("Failed to initialize kqueue\n!");
- return GINT_TO_POINTER (FALSE);
- }
-
- result = socketpair (AF_UNIX, SOCK_STREAM, 0, kqueue_socket_pair);
- if (result != 0)
- {
- KH_W ("Failed to create socket pair\n!");
- return GINT_TO_POINTER (FALSE) ;
- }
-
- result = pthread_create (&kqueue_thread,
- NULL,
- _kqueue_thread_func,
- &kqueue_socket_pair[1]);
- if (result != 0)
- {
- KH_W ("Failed to run kqueue thread\n!");
- return GINT_TO_POINTER (FALSE);
- }
-
- _km_init (_kh_file_appeared_cb);
-
- channel = g_io_channel_unix_new (kqueue_socket_pair[0]);
- g_io_add_watch (channel, G_IO_IN, process_kqueue_notifications, NULL);
-
- subs_hash_table = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- KH_W ("started gio kqueue backend\n");
- return GINT_TO_POINTER (TRUE);
-}
-
-
-/*
- * _kh_startup:
- * Kqueue backend initialization.
- *
- * Returns: %TRUE on success, %FALSE otherwise.
- **/
-gboolean
-_kh_startup (void)
-{
- static GOnce init_once = G_ONCE_INIT;
- g_once (&init_once, _kh_startup_impl, NULL);
- return GPOINTER_TO_INT (init_once.retval);
-}
-
-
-/**
- * _kh_start_watching:
- * @sub: a #kqueue_sub
- *
- * Starts watching on a subscription.
- *
- * Returns: %TRUE on success, %FALSE otherwise.
- **/
-gboolean
-_kh_start_watching (kqueue_sub *sub)
-{
- g_assert (kqueue_socket_pair[0] != -1);
- g_assert (sub != NULL);
- g_assert (sub->filename != NULL);
-
- /* kqueue requires a file descriptor to monitor. Sad but true */
-#if defined (O_EVTONLY)
- sub->fd = open (sub->filename, O_EVTONLY);
-#else
- sub->fd = open (sub->filename, O_RDONLY);
-#endif
-
- if (sub->fd == -1)
- {
- KH_W ("failed to open file %s (error %d)", sub->filename, errno);
- return FALSE;
- }
-
- _ku_file_information (sub->fd, &sub->is_dir, NULL);
- if (sub->is_dir)
- {
- /* I know, it is very bad to make such decisions in this way and here.
- * We already do have an user_data at the #kqueue_sub, and it may point to
- * GKqueueFileMonitor or GKqueueDirectoryMonitor. For a directory case,
- * we need to scan in contents for the further diffs. Ideally this process
- * should be delegated to the GKqueueDirectoryMonitor, but for now I will
- * do it in a dirty way right here. */
- if (sub->deps)
- dl_free (sub->deps);
-
- sub->deps = dl_listing (sub->filename);
- }
-
- G_LOCK (hash_lock);
- g_hash_table_insert (subs_hash_table, GINT_TO_POINTER (sub->fd), sub);
- G_UNLOCK (hash_lock);
-
- _kqueue_thread_push_fd (sub->fd);
-
- /* Bump the kqueue thread. It will pick up a new sub entry to monitor */
- if (!_ku_write (kqueue_socket_pair[0], "A", 1))
- KH_W ("Failed to bump the kqueue thread (add fd, error %d)", errno);
- return TRUE;
-}
-
-
-/**
- * _kh_add_sub:
- * @sub: a #kqueue_sub
- *
- * Adds a subscription for monitoring.
- *
- * This funciton tries to start watching a subscription with
- * _kh_start_watching(). On failure, i.e. when a file does not exist yet,
- * the subscription will be added to a list of missing files to continue
- * watching when the file will appear.
- *
- * Returns: %TRUE
- **/
-gboolean
-_kh_add_sub (kqueue_sub *sub)
-{
- g_assert (sub != NULL);
-
- if (!_kh_start_watching (sub))
- _km_add_missing (sub);
-
- return TRUE;
-}
-
-
-/**
- * _kh_cancel_sub:
- * @sub a #kqueue_sub
- *
- * Stops monitoring on a subscription.
- *
- * Returns: %TRUE
- **/
-gboolean
-_kh_cancel_sub (kqueue_sub *sub)
-{
- gboolean removed = FALSE;
- g_assert (kqueue_socket_pair[0] != -1);
- g_assert (sub != NULL);
-
- _km_remove (sub);
-
- G_LOCK (hash_lock);
- removed = g_hash_table_remove (subs_hash_table, GINT_TO_POINTER (sub->fd));
- G_UNLOCK (hash_lock);
-
- if (removed)
- {
- /* fd will be closed in the kqueue thread */
- _kqueue_thread_remove_fd (sub->fd);
-
- /* Bump the kqueue thread. It will pick up a new sub entry to remove*/
- if (!_ku_write (kqueue_socket_pair[0], "R", 1))
- KH_W ("Failed to bump the kqueue thread (remove fd, error %d)", errno);
- }
-
- return TRUE;
-}
-
-
-/**
- * _kh_file_appeared_cb:
- * @sub: a #kqueue_sub
- *
- * A callback function for kqueue-missing subsystem.
- *
- * Signals that a missing file has finally appeared in the filesystem.
- * Emits %G_FILE_MONITOR_EVENT_CREATED.
- **/
-void
-_kh_file_appeared_cb (kqueue_sub *sub)
-{
- GFile* child;
-
- g_assert (sub != NULL);
- g_assert (sub->filename);
-
- if (!g_file_test (sub->filename, G_FILE_TEST_EXISTS))
- return;
-
- child = g_file_new_for_path (sub->filename);
-
- g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
- child,
- NULL,
- G_FILE_MONITOR_EVENT_CREATED);
-
- g_object_unref (child);
-}