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