1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set expandtab ts=4 shiftwidth=4: */
4 * Copyright (C) 2008 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
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 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 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307, USA.
22 * Authors: Lin Ma <lin.ma@sun.com>
28 #include "fen-helper.h"
29 #include "fen-kernel.h"
30 #ifdef GIO_COMPILATION
32 #include "gfilemonitor.h"
34 #include "gam_event.h"
35 #include "gam_server.h"
36 #include "gam_protocol.h"
39 #ifdef GIO_COMPILATION
40 #define FH_W if (fh_debug_enabled) g_warning
41 static gboolean fh_debug_enabled = FALSE;
43 #include "gam_error.h"
44 #define FH_W(...) GAM_DEBUG(DEBUG_INFO, __VA_ARGS__)
47 G_LOCK_EXTERN (fen_lock);
49 static void default_emit_event_cb (fdata *f, int events);
50 static void default_emit_once_event_cb (fdata *f, int events, gpointer sub);
51 static int default_event_converter (int event);
54 scan_children_init (node_t *f, gpointer sub)
58 node_op_t op = {NULL, NULL, _pre_del_cb, NULL};
61 FH_W ("%s %s [0x%p]\n", __func__, NODE_NAME(f), f);
62 pdata = _node_get_data (f);
64 dir = g_dir_open (NODE_NAME(f), 0, &err);
68 while ((basename = g_dir_read_name (dir)))
70 node_t *childf = NULL;
74 childf = _children_find (f, basename);
78 filename = g_build_filename (NODE_NAME(f), basename, NULL);
79 childf = _add_node (f, filename);
83 if ((data = _node_get_data (childf)) == NULL) {
84 data = _fdata_new (childf, FALSE);
87 if (is_monitoring (data)) {
89 } else if (/* !_is_ported (data) && */
90 _port_add (&data->fobj, &data->len, data)) {
91 /* Emit created to all other subs */
92 _fdata_emit_events (data, FN_EVENT_CREATED);
94 /* Emit created to the new sub */
95 #ifdef GIO_COMPILATION
96 /* _fdata_emit_events_once (data, FN_EVENT_CREATED, sub); */
98 gam_server_emit_one_event (NODE_NAME(childf),
99 gam_subscription_is_dir (sub), GAMIN_EVENT_EXISTS, sub, 1);
112 * Won't hold a ref, we have a timout callback to clean unused fdata.
113 * If there is no value for a key, add it and return it; else return the old
117 _fen_add (const gchar *filename, gpointer sub, gboolean is_mondir)
119 node_op_t op = {NULL, _add_missing_cb, _pre_del_cb, (gpointer)filename};
127 f = _find_node_full (filename, &op);
128 FH_W ("[ %s ] f[0x%p] sub[0x%p] %s\n", __func__, f, sub, filename);
130 data = _node_get_data (f);
132 data = _fdata_new (f, is_mondir);
136 data->mon_dir_num ++;
139 /* Change to active */
140 #ifdef GIO_COMPILATION
141 if (_port_add (&data->fobj, &data->len, data) ||
142 g_file_test (FN_NAME(data), G_FILE_TEST_EXISTS)) {
144 scan_children_init (f, sub);
146 _fdata_sub_add (data, sub);
148 _fdata_sub_add (data, sub);
149 _fdata_adjust_deleted (data);
152 if (_port_add (&data->fobj, &data->len, data) ||
153 g_file_test (FN_NAME(data), G_FILE_TEST_EXISTS)) {
154 gam_server_emit_one_event (FN_NAME(data),
155 gam_subscription_is_dir (sub), GAMIN_EVENT_EXISTS, sub, 1);
157 scan_children_init (f, sub);
159 gam_server_emit_one_event (FN_NAME(data),
160 gam_subscription_is_dir (sub), GAMIN_EVENT_ENDEXISTS, sub, 1);
161 _fdata_sub_add (data, sub);
163 _fdata_sub_add (data, sub);
164 gam_server_emit_one_event (FN_NAME(data),
165 gam_subscription_is_dir (sub), GAMIN_EVENT_DELETED, sub, 1);
166 _fdata_adjust_deleted (data);
167 gam_server_emit_one_event (FN_NAME(data),
168 gam_subscription_is_dir (sub), GAMIN_EVENT_ENDEXISTS, sub, 1);
175 _fen_remove (const gchar *filename, gpointer sub, gboolean is_mondir)
177 node_op_t op = {NULL, _add_missing_cb, _pre_del_cb, (gpointer)filename};
185 f = _find_node (filename);
186 FH_W ("[ %s ] f[0x%p] sub[0x%p] %s\n", __func__, f, sub, filename);
189 data = _node_get_data (f);
193 data->mon_dir_num --;
195 _fdata_sub_remove (data, sub);
196 if (FN_IS_PASSIVE(data)) {
197 #ifdef GIO_COMPILATION
198 _pending_remove_node (f, &op);
200 _remove_node (f, &op);
207 fen_init_once_func (gpointer data)
209 FH_W ("%s\n", __func__);
210 if (!_node_class_init ()) {
211 FH_W ("_node_class_init failed.");
214 if (!_fdata_class_init (default_emit_event_cb,
215 default_emit_once_event_cb,
216 default_event_converter)) {
217 FH_W ("_fdata_class_init failed.");
226 #ifdef GIO_COMPILATION
227 static GOnce fen_init_once = G_ONCE_INIT;
228 g_once (&fen_init_once, (GThreadFunc)fen_init_once_func, NULL);
229 return (gboolean)fen_init_once.retval;
231 return fen_init_once_func (NULL);
236 default_emit_once_event_cb (fdata *f, int events, gpointer sub)
238 #ifdef GIO_COMPILATION
240 fen_sub* _sub = (fen_sub*)sub;
241 child = g_file_new_for_path (FN_NAME(f));
242 g_file_monitor_emit_event (G_FILE_MONITOR (_sub->user_data),
243 child, NULL, events);
244 g_object_unref (child);
246 gam_server_emit_one_event (FN_NAME(f),
247 gam_subscription_is_dir (sub), events, sub, 1);
252 default_emit_event_cb (fdata *f, int events)
257 #ifdef GIO_COMPILATION
259 child = g_file_new_for_path (FN_NAME(f));
260 for (i = f->subs; i; i = i->next) {
261 fen_sub* sub = (fen_sub*)i->data;
262 gboolean file_is_dir = sub->is_mondir;
263 if ((events != G_FILE_MONITOR_EVENT_CHANGED &&
264 events != G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) ||
266 g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
267 child, NULL, events);
270 if ((pdata = _get_parent_data (f)) != NULL) {
271 for (i = pdata->subs; i; i = i->next) {
272 fen_sub* sub = (fen_sub*)i->data;
273 gboolean file_is_dir = sub->is_mondir;
274 g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
275 child, NULL, events);
278 g_object_unref (child);
280 for (i = f->subs; i; i = i->next) {
281 gboolean file_is_dir = gam_subscription_is_dir (i->data);
282 if (events != GAMIN_EVENT_CHANGED || !file_is_dir) {
283 gam_server_emit_one_event (FN_NAME(f), file_is_dir, events, i->data, 1);
286 if ((pdata = _get_parent_data (f)) != NULL) {
287 for (i = pdata->subs; i; i = i->next) {
288 gboolean file_is_dir = gam_subscription_is_dir (i->data);
289 gam_server_emit_one_event (FN_NAME(f), file_is_dir, events, i->data, 1);
296 default_event_converter (int event)
298 #ifdef GIO_COMPILATION
300 case FN_EVENT_CREATED:
301 return G_FILE_MONITOR_EVENT_CREATED;
303 case FILE_RENAME_FROM:
304 return G_FILE_MONITOR_EVENT_DELETED;
306 return G_FILE_MONITOR_EVENT_UNMOUNTED;
308 return G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED;
312 return G_FILE_MONITOR_EVENT_CHANGED;
314 /* case FILE_ACCESS: */
315 g_assert_not_reached ();
320 case FN_EVENT_CREATED:
321 return GAMIN_EVENT_CREATED;
323 case FILE_RENAME_FROM:
324 return GAMIN_EVENT_DELETED;
330 return GAMIN_EVENT_CHANGED;
332 /* case FILE_ACCESS: */
333 g_assert_not_reached ();