1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
3 /* inotify-missing.c - GVFS Monitor based on inotify.
5 Copyright (C) 2005 John McCutchan
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
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 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with this library; if not, see <http://www.gnu.org/licenses/>.
21 John McCutchan <john@johnmccutchan.com>
26 #include "inotify-missing.h"
27 #include "inotify-path.h"
28 #include "glib-private.h"
30 #define SCAN_MISSING_TIME 4 /* 1/4 Hz */
32 static gboolean im_debug_enabled
= FALSE
;
33 #define IM_W if (im_debug_enabled) g_warning
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
;
41 G_LOCK_EXTERN (inotify_lock
);
43 /* inotify_lock must be held before calling */
45 _im_startup (void (*callback
)(inotify_sub
*sub
))
47 static gboolean initialized
= FALSE
;
51 missing_cb
= callback
;
56 /* inotify_lock must be held before calling */
58 _im_add (inotify_sub
*sub
)
60 if (g_list_find (missing_sub_list
, sub
))
62 IM_W ("asked to add %s to missing list but it's already on the list!\n", sub
->dirname
);
66 IM_W ("adding %s to missing list\n", sub
->dirname
);
67 missing_sub_list
= g_list_prepend (missing_sub_list
, sub
);
69 /* If the timeout is turned off, we turn it back on */
70 if (!scan_missing_running
)
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
);
82 /* inotify_lock must be held before calling */
84 _im_rm (inotify_sub
*sub
)
88 link
= g_list_find (missing_sub_list
, sub
);
92 IM_W ("asked to remove %s from missing list but it isn't on the list!\n", sub
->dirname
);
96 IM_W ("removing %s from missing list\n", sub
->dirname
);
98 missing_sub_list
= g_list_remove_link (missing_sub_list
, link
);
102 /* Scans the list of missing subscriptions checking if they
106 im_scan_missing (gpointer user_data
)
108 GList
*nolonger_missing
= NULL
;
111 G_LOCK (inotify_lock
);
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
)
116 inotify_sub
*sub
= l
->data
;
117 gboolean not_m
= FALSE
;
119 IM_W ("checking %p\n", sub
);
121 g_assert (sub
->dirname
);
122 not_m
= _ip_start_watching (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.
131 nolonger_missing
= g_list_prepend (nolonger_missing
, l
);
135 for (l
= nolonger_missing
; l
; l
= l
->next
)
137 GList
*llink
= l
->data
;
138 missing_sub_list
= g_list_remove_link (missing_sub_list
, llink
);
139 g_list_free_1 (llink
);
142 g_list_free (nolonger_missing
);
144 /* If the missing list is now empty, we disable the timeout */
145 if (missing_sub_list
== NULL
)
147 scan_missing_running
= FALSE
;
148 G_UNLOCK (inotify_lock
);
153 G_UNLOCK (inotify_lock
);