nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /*
2 * Copyright © 2015 Canonical Limited
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * Author: Ryan Lortie <desrt@desrt.ca>
18 */
19  
20 #include "config.h"
21  
22 #include <gio/glocalfilemonitor.h>
23 #include <gio/giomodule.h>
24 #include "glib-private.h"
25 #include <glib-unix.h>
26 #include <fam.h>
27  
28 static GMutex fam_lock;
29 static gboolean fam_initialised;
30 static FAMConnection fam_connection;
31 static GSource *fam_source;
32  
33 #define G_TYPE_FAM_FILE_MONITOR (g_fam_file_monitor_get_type ())
34 #define G_FAM_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
35 G_TYPE_FAM_FILE_MONITOR, GFamFileMonitor))
36  
37 typedef GLocalFileMonitorClass GFamFileMonitorClass;
38  
39 typedef struct
40 {
41 GLocalFileMonitor parent_instance;
42  
43 FAMRequest request;
44 } GFamFileMonitor;
45  
46 static GType g_fam_file_monitor_get_type (void);
47 G_DEFINE_DYNAMIC_TYPE (GFamFileMonitor, g_fam_file_monitor, G_TYPE_LOCAL_FILE_MONITOR)
48  
49 static gboolean
50 g_fam_file_monitor_callback (gint fd,
51 GIOCondition condition,
52 gpointer user_data)
53 {
54 gint64 now = g_source_get_time (fam_source);
55  
56 g_mutex_lock (&fam_lock);
57  
58 while (FAMPending (&fam_connection))
59 {
60 const gchar *child;
61 FAMEvent ev;
62  
63 if (FAMNextEvent (&fam_connection, &ev) != 1)
64 {
65 /* The daemon died. We're in a really bad situation now
66 * because we potentially have a bunch of request structures
67 * outstanding which no longer make any sense to anyone.
68 *
69 * The best thing that we can do is do nothing. Notification
70 * won't work anymore for this process.
71 */
72 g_mutex_unlock (&fam_lock);
73  
74 g_warning ("Lost connection to FAM (file monitoring) service. Expect no further file monitor events.");
75  
76 return FALSE;
77 }
78  
79 /* We expect ev.filename to be a relative path for children in a
80 * monitored directory, and an absolute path for a monitored file
81 * or the directory itself.
82 */
83 if (ev.filename[0] != '/')
84 child = ev.filename;
85 else
86 child = NULL;
87  
88 switch (ev.code)
89 {
90 case FAMAcknowledge:
91 g_source_unref (ev.userdata);
92 break;
93  
94 case FAMChanged:
95 g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CHANGED, child, NULL, NULL, now);
96 break;
97  
98 case FAMDeleted:
99 g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_DELETED, child, NULL, NULL, now);
100 break;
101  
102 case FAMCreated:
103 g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CREATED, child, NULL, NULL, now);
104 break;
105  
106 default:
107 /* unknown type */
108 break;
109 }
110 }
111  
112 g_mutex_unlock (&fam_lock);
113  
114 return TRUE;
115 }
116  
117 static gboolean
118 g_fam_file_monitor_is_supported (void)
119 {
120 g_mutex_lock (&fam_lock);
121  
122 if (!fam_initialised)
123 {
124 fam_initialised = FAMOpen2 (&fam_connection, "GLib GIO") == 0;
125  
126 if (fam_initialised)
127 {
128 #ifdef HAVE_FAM_NO_EXISTS
129 /* This is a gamin extension that avoids sending all the
130 * Exists event for dir monitors
131 */
132 FAMNoExists (&fam_connection);
133 #endif
134  
135 fam_source = g_unix_fd_source_new (FAMCONNECTION_GETFD (&fam_connection), G_IO_IN);
136 g_source_set_callback (fam_source, (GSourceFunc) g_fam_file_monitor_callback, NULL, NULL);
137 g_source_attach (fam_source, GLIB_PRIVATE_CALL(g_get_worker_context) ());
138 }
139 }
140  
141 g_mutex_unlock (&fam_lock);
142  
143 g_print ("II %d\n", fam_initialised);
144  
145 return fam_initialised;
146 }
147  
148 static gboolean
149 g_fam_file_monitor_cancel (GFileMonitor *monitor)
150 {
151 GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (monitor);
152  
153 g_mutex_lock (&fam_lock);
154  
155 g_assert (fam_initialised);
156  
157 FAMCancelMonitor (&fam_connection, &gffm->request);
158  
159 g_mutex_unlock (&fam_lock);
160  
161 return TRUE;
162 }
163  
164 static void
165 g_fam_file_monitor_start (GLocalFileMonitor *local_monitor,
166 const gchar *dirname,
167 const gchar *basename,
168 const gchar *filename,
169 GFileMonitorSource *source)
170 {
171 GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (local_monitor);
172  
173 g_mutex_lock (&fam_lock);
174  
175 g_assert (fam_initialised);
176  
177 g_source_ref ((GSource *) source);
178  
179 if (dirname)
180 FAMMonitorDirectory (&fam_connection, dirname, &gffm->request, source);
181 else
182 FAMMonitorFile (&fam_connection, filename, &gffm->request, source);
183  
184 g_mutex_unlock (&fam_lock);
185 }
186  
187 static void
188 g_fam_file_monitor_init (GFamFileMonitor* monitor)
189 {
190 }
191  
192 static void
193 g_fam_file_monitor_class_init (GFamFileMonitorClass *class)
194 {
195 GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (class);
196  
197 class->is_supported = g_fam_file_monitor_is_supported;
198 class->start = g_fam_file_monitor_start;
199 file_monitor_class->cancel = g_fam_file_monitor_cancel;
200 }
201  
202 static void
203 g_fam_file_monitor_class_finalize (GFamFileMonitorClass *class)
204 {
205 }
206  
207 void
208 g_io_module_load (GIOModule *module)
209 {
210 g_type_module_use (G_TYPE_MODULE (module));
211  
212 g_fam_file_monitor_register_type (G_TYPE_MODULE (module));
213  
214 g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
215 G_TYPE_FAM_FILE_MONITOR, "fam", 10);
216  
217 g_io_extension_point_implement (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME,
218 G_TYPE_FAM_FILE_MONITOR, "fam", 10);
219 }
220  
221 void
222 g_io_module_unload (GIOModule *module)
223 {
224 g_assert_not_reached ();
225 }
226  
227 char **
228 g_io_module_query (void)
229 {
230 char *eps[] = {
231 G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
232 G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME,
233 NULL
234 };
235  
236 return g_strdupv (eps);
237 }