Blame gio/inotify/inotify-missing.c

Packit ae235b
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
Packit ae235b
Packit ae235b
/* inotify-missing.c - GVFS Monitor based on inotify.
Packit ae235b
Packit ae235b
   Copyright (C) 2005 John McCutchan
Packit ae235b
Packit ae235b
   This library is free software; you can redistribute it and/or
Packit ae235b
   modify it under the terms of the GNU Lesser General Public
Packit ae235b
   License as published by the Free Software Foundation; either
Packit ae235b
   version 2.1 of the License, or (at your option) any later version.
Packit ae235b
Packit ae235b
   This library is distributed in the hope that it will be useful,
Packit ae235b
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ae235b
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit ae235b
   Lesser General Public License for more details.
Packit ae235b
Packit ae235b
   You should have received a copy of the GNU Lesser General Public License
Packit ae235b
   along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit ae235b
Packit ae235b
   Authors: 
Packit ae235b
		 John McCutchan <john@johnmccutchan.com>
Packit ae235b
*/
Packit ae235b
Packit ae235b
#include "config.h"
Packit ae235b
#include <glib.h>
Packit ae235b
#include "inotify-missing.h"
Packit ae235b
#include "inotify-path.h"
Packit ae235b
#include "glib-private.h"
Packit ae235b
Packit ae235b
#define SCAN_MISSING_TIME 4 /* 1/4 Hz */
Packit ae235b
Packit ae235b
static gboolean im_debug_enabled = FALSE;
Packit ae235b
#define IM_W if (im_debug_enabled) g_warning
Packit ae235b
Packit ae235b
/* We put inotify_sub's that are missing on this list */
Packit ae235b
static GList *missing_sub_list = NULL;
Packit ae235b
static gboolean im_scan_missing (gpointer user_data);
Packit ae235b
static gboolean scan_missing_running = FALSE;
Packit ae235b
static void (*missing_cb)(inotify_sub *sub) = NULL;
Packit ae235b
Packit ae235b
G_LOCK_EXTERN (inotify_lock);
Packit ae235b
Packit ae235b
/* inotify_lock must be held before calling */
Packit ae235b
void
Packit ae235b
_im_startup (void (*callback)(inotify_sub *sub))
Packit ae235b
{
Packit ae235b
  static gboolean initialized = FALSE;
Packit ae235b
  
Packit ae235b
  if (!initialized)
Packit ae235b
    {
Packit ae235b
      missing_cb = callback;
Packit ae235b
      initialized = TRUE;
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/* inotify_lock must be held before calling */
Packit ae235b
void
Packit ae235b
_im_add (inotify_sub *sub)
Packit ae235b
{
Packit ae235b
  if (g_list_find (missing_sub_list, sub))
Packit ae235b
    {
Packit ae235b
      IM_W ("asked to add %s to missing list but it's already on the list!\n", sub->dirname);
Packit ae235b
      return;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  IM_W ("adding %s to missing list\n", sub->dirname);
Packit ae235b
  missing_sub_list = g_list_prepend (missing_sub_list, sub);
Packit ae235b
Packit ae235b
  /* If the timeout is turned off, we turn it back on */
Packit ae235b
  if (!scan_missing_running)
Packit ae235b
    {
Packit ae235b
      GSource *source;
Packit ae235b
Packit ae235b
      scan_missing_running = TRUE;
Packit ae235b
      source = g_timeout_source_new_seconds (SCAN_MISSING_TIME);
Packit ae235b
      g_source_set_callback (source, im_scan_missing, NULL, NULL);
Packit ae235b
      g_source_attach (source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
Packit ae235b
      g_source_unref (source);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/* inotify_lock must be held before calling */
Packit ae235b
void
Packit ae235b
_im_rm (inotify_sub *sub)
Packit ae235b
{
Packit ae235b
  GList *link;
Packit ae235b
  
Packit ae235b
  link = g_list_find (missing_sub_list, sub);
Packit ae235b
Packit ae235b
  if (!link)
Packit ae235b
    {
Packit ae235b
      IM_W ("asked to remove %s from missing list but it isn't on the list!\n", sub->dirname);
Packit ae235b
      return;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  IM_W ("removing %s from missing list\n", sub->dirname);
Packit ae235b
Packit ae235b
  missing_sub_list = g_list_remove_link (missing_sub_list, link);
Packit ae235b
  g_list_free_1 (link);
Packit ae235b
}
Packit ae235b
Packit ae235b
/* Scans the list of missing subscriptions checking if they
Packit ae235b
 * are available yet.
Packit ae235b
 */
Packit ae235b
static gboolean
Packit ae235b
im_scan_missing (gpointer user_data)
Packit ae235b
{
Packit ae235b
  GList *nolonger_missing = NULL;
Packit ae235b
  GList *l;
Packit ae235b
  
Packit ae235b
  G_LOCK (inotify_lock);
Packit ae235b
  
Packit ae235b
  IM_W ("scanning missing list with %d items\n", g_list_length (missing_sub_list));
Packit ae235b
  for (l = missing_sub_list; l; l = l->next)
Packit ae235b
    {
Packit ae235b
      inotify_sub *sub = l->data;
Packit ae235b
      gboolean not_m = FALSE;
Packit ae235b
      
Packit ae235b
      IM_W ("checking %p\n", sub);
Packit ae235b
      g_assert (sub);
Packit ae235b
      g_assert (sub->dirname);
Packit ae235b
      not_m = _ip_start_watching (sub);
Packit ae235b
Packit ae235b
      if (not_m)
Packit ae235b
	{
Packit ae235b
	  missing_cb (sub);
Packit ae235b
	  IM_W ("removed %s from missing list\n", sub->dirname);
Packit ae235b
	  /* We have to build a list of list nodes to remove from the
Packit ae235b
	   * missing_sub_list. We do the removal outside of this loop.
Packit ae235b
	   */
Packit ae235b
	  nolonger_missing = g_list_prepend (nolonger_missing, l);
Packit ae235b
	} 
Packit ae235b
    }
Packit ae235b
Packit ae235b
  for (l = nolonger_missing; l ; l = l->next)
Packit ae235b
    {
Packit ae235b
      GList *llink = l->data;
Packit ae235b
      missing_sub_list = g_list_remove_link (missing_sub_list, llink);
Packit ae235b
      g_list_free_1 (llink);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_list_free (nolonger_missing);
Packit ae235b
  
Packit ae235b
  /* If the missing list is now empty, we disable the timeout */
Packit ae235b
  if (missing_sub_list == NULL)
Packit ae235b
    {
Packit ae235b
      scan_missing_running = FALSE;
Packit ae235b
      G_UNLOCK (inotify_lock);
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      G_UNLOCK (inotify_lock);
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
}