(root)/
glib-2.79.0/
gio/
inotify/
inotify-missing.c
       1  /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
       2  
       3  /* inotify-missing.c - GVFS Monitor based on inotify.
       4  
       5     Copyright (C) 2005 John McCutchan
       6  
       7     This library is free software; you can redistribute it and/or
       8     modify it under the terms of the GNU Lesser General Public
       9     License as published by the Free Software Foundation; either
      10     version 2.1 of the License, or (at your option) any later version.
      11  
      12     This library is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15     Lesser General Public License for more details.
      16  
      17     You should have received a copy of the GNU Lesser General Public License
      18     along with this library; if not, see <http://www.gnu.org/licenses/>.
      19  
      20     Authors: 
      21  		 John McCutchan <john@johnmccutchan.com>
      22  */
      23  
      24  #include "config.h"
      25  #include <glib.h>
      26  #include "inotify-missing.h"
      27  #include "inotify-path.h"
      28  #include "glib-private.h"
      29  
      30  #define SCAN_MISSING_TIME 4 /* 1/4 Hz */
      31  
      32  static gboolean im_debug_enabled = FALSE;
      33  #define IM_W if (im_debug_enabled) g_warning
      34  
      35  /* We put inotify_sub's that are missing on this list */
      36  static GList *missing_sub_list = NULL;
      37  static gboolean im_scan_missing (gpointer user_data);
      38  static gboolean scan_missing_running = FALSE;
      39  static void (*missing_cb)(inotify_sub *sub) = NULL;
      40  
      41  G_LOCK_EXTERN (inotify_lock);
      42  
      43  /* inotify_lock must be held before calling */
      44  void
      45  _im_startup (void (*callback)(inotify_sub *sub))
      46  {
      47    static gboolean initialized = FALSE;
      48    
      49    if (!initialized)
      50      {
      51        missing_cb = callback;
      52        initialized = TRUE;
      53      }
      54  }
      55  
      56  /* inotify_lock must be held before calling */
      57  void
      58  _im_add (inotify_sub *sub)
      59  {
      60    if (g_list_find (missing_sub_list, sub))
      61      {
      62        IM_W ("asked to add %s to missing list but it's already on the list!\n", sub->dirname);
      63        return;
      64      }
      65  
      66    IM_W ("adding %s to missing list\n", sub->dirname);
      67    missing_sub_list = g_list_prepend (missing_sub_list, sub);
      68  
      69    /* If the timeout is turned off, we turn it back on */
      70    if (!scan_missing_running)
      71      {
      72        GSource *source;
      73  
      74        scan_missing_running = TRUE;
      75        source = g_timeout_source_new_seconds (SCAN_MISSING_TIME);
      76        g_source_set_callback (source, im_scan_missing, NULL, NULL);
      77        g_source_attach (source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
      78        g_source_unref (source);
      79      }
      80  }
      81  
      82  /* inotify_lock must be held before calling */
      83  void
      84  _im_rm (inotify_sub *sub)
      85  {
      86    GList *link;
      87    
      88    link = g_list_find (missing_sub_list, sub);
      89  
      90    if (!link)
      91      {
      92        IM_W ("asked to remove %s from missing list but it isn't on the list!\n", sub->dirname);
      93        return;
      94      }
      95  
      96    IM_W ("removing %s from missing list\n", sub->dirname);
      97  
      98    missing_sub_list = g_list_remove_link (missing_sub_list, link);
      99    g_list_free_1 (link);
     100  }
     101  
     102  /* Scans the list of missing subscriptions checking if they
     103   * are available yet.
     104   */
     105  static gboolean
     106  im_scan_missing (gpointer user_data)
     107  {
     108    GList *nolonger_missing = NULL;
     109    GList *l;
     110    
     111    G_LOCK (inotify_lock);
     112    
     113    IM_W ("scanning missing list with %d items\n", g_list_length (missing_sub_list));
     114    for (l = missing_sub_list; l; l = l->next)
     115      {
     116        inotify_sub *sub = l->data;
     117        gboolean not_m = FALSE;
     118        
     119        IM_W ("checking %p\n", sub);
     120        g_assert (sub);
     121        g_assert (sub->dirname);
     122        not_m = _ip_start_watching (sub);
     123  
     124        if (not_m)
     125  	{
     126  	  missing_cb (sub);
     127  	  IM_W ("removed %s from missing list\n", sub->dirname);
     128  	  /* We have to build a list of list nodes to remove from the
     129  	   * missing_sub_list. We do the removal outside of this loop.
     130  	   */
     131  	  nolonger_missing = g_list_prepend (nolonger_missing, l);
     132  	} 
     133      }
     134  
     135    for (l = nolonger_missing; l ; l = l->next)
     136      {
     137        GList *llink = l->data;
     138        missing_sub_list = g_list_remove_link (missing_sub_list, llink);
     139        g_list_free_1 (llink);
     140      }
     141  
     142    g_list_free (nolonger_missing);
     143    
     144    /* If the missing list is now empty, we disable the timeout */
     145    if (missing_sub_list == NULL)
     146      {
     147        scan_missing_running = FALSE;
     148        G_UNLOCK (inotify_lock);
     149        return FALSE;
     150      }
     151    else
     152      {
     153        G_UNLOCK (inotify_lock);
     154        return TRUE;
     155      }
     156  }