summaryrefslogtreecommitdiff
path: root/gio/kqueue/kqueue-missing.c
diff options
context:
space:
mode:
Diffstat (limited to 'gio/kqueue/kqueue-missing.c')
-rw-r--r--gio/kqueue/kqueue-missing.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/gio/kqueue/kqueue-missing.c b/gio/kqueue/kqueue-missing.c
new file mode 100644
index 000000000..797f22728
--- /dev/null
+++ b/gio/kqueue/kqueue-missing.c
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*******************************************************************************/
+
+#include <glib.h>
+
+#include "kqueue-helper.h"
+#include "kqueue-sub.h"
+#include "kqueue-missing.h"
+
+
+#define SCAN_MISSING_TIME 4 /* 1/4 Hz */
+
+static gboolean km_scan_missing (gpointer user_data);
+
+static gboolean km_debug_enabled = FALSE;
+#define KM_W if (km_debug_enabled) g_warning
+
+static GSList *missing_subs_list = NULL;
+G_GNUC_INTERNAL G_LOCK_DEFINE (missing_lock);
+
+static volatile gboolean scan_missing_running = FALSE;
+static on_create_cb file_appeared_callback;
+
+
+/**
+ * _km_init:
+ * @cb: a callback function. It will be called when a watched file
+ * will appear.
+ *
+ * Initialize the kqueue-missing module (optional).
+ **/
+void
+_km_init (on_create_cb cb)
+{
+ file_appeared_callback = cb;
+}
+
+
+/**
+ * _km_add_missing:
+ * @sub: a #kqueue_sub
+ *
+ * Adds a subscription to the missing files list.
+ **/
+void
+_km_add_missing (kqueue_sub *sub)
+{
+ G_LOCK (missing_lock);
+ if (g_slist_find (missing_subs_list, sub))
+ {
+ KM_W ("asked to add %s to missing list but it's already on the list!\n", sub->filename);
+ return;
+ }
+
+ KM_W ("adding %s to missing list\n", sub->filename);
+ missing_subs_list = g_slist_prepend (missing_subs_list, sub);
+ G_UNLOCK (missing_lock);
+
+ if (!scan_missing_running)
+ {
+ scan_missing_running = TRUE;
+ g_timeout_add_seconds (SCAN_MISSING_TIME, km_scan_missing, NULL);
+ }
+}
+
+
+/**
+ * km_scan_missing:
+ * @user_data: unused
+ *
+ * The core missing files watching routine.
+ *
+ * Traverses through a list of missing files, tries to start watching each with
+ * kqueue, removes the appropriate entry and invokes a user callback if the file
+ * has appeared.
+ *
+ * Returns: %FALSE if no missing files left, %TRUE otherwise.
+ **/
+static gboolean
+km_scan_missing (gpointer user_data)
+{
+ GSList *head;
+ GSList *not_missing = NULL;
+ gboolean retval = FALSE;
+
+ G_LOCK (missing_lock);
+
+ if (missing_subs_list)
+ KM_W ("we have a job");
+
+ for (head = missing_subs_list; head; head = head->next)
+ {
+ kqueue_sub *sub = (kqueue_sub *) head->data;
+ g_assert (sub != NULL);
+ g_assert (sub->filename != NULL);
+
+ if (_kh_start_watching (sub))
+ {
+ KM_W ("file %s now exists, starting watching", sub->filename);
+ if (file_appeared_callback)
+ file_appeared_callback (sub);
+ not_missing = g_slist_prepend (not_missing, head);
+ }
+ }
+
+ for (head = not_missing; head; head = head->next)
+ {
+ GSList *link = (GSList *) head->data;
+ missing_subs_list = g_slist_remove_link (missing_subs_list, link);
+ }
+ g_slist_free (not_missing);
+
+ if (missing_subs_list == NULL)
+ {
+ scan_missing_running = FALSE;
+ retval = FALSE;
+ }
+ else
+ retval = TRUE;
+
+ G_UNLOCK (missing_lock);
+ return retval;
+}
+
+
+/**
+ * _km_remove:
+ * @sub: a #kqueue_sub
+ *
+ * Removes a subscription from a list of missing files.
+ **/
+void
+_km_remove (kqueue_sub *sub)
+{
+ G_LOCK (missing_lock);
+ missing_subs_list = g_slist_remove (missing_subs_list, sub);
+ G_UNLOCK (missing_lock);
+}