Tizen 2.1 base
[platform/upstream/glib2.0.git] / gio / fen / fen-helper.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set expandtab ts=4 shiftwidth=4: */
3 /* 
4  * Copyright (c) 2008, 2010 Oracle and/or its affiliates, Inc. All rights
5  * reserved.
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 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
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.
21  *
22  * Authors: Lin Ma <lin.ma@sun.com>
23  */
24
25 #include "config.h"
26 #include <glib.h>
27 #include "fen-helper.h"
28 #include "fen-kernel.h"
29 #ifdef GIO_COMPILATION
30 #include <gio/gfilemonitor.h>
31 #else
32 #include "gam_event.h"
33 #include "gam_server.h"
34 #include "gam_protocol.h"
35 #endif
36
37 #ifdef GIO_COMPILATION
38 #define FH_W if (FALSE) g_debug
39 #else
40 #include "gam_error.h"
41 #define FH_W(...) GAM_DEBUG(DEBUG_INFO, __VA_ARGS__)
42 #endif
43
44 G_LOCK_EXTERN (fen_lock);
45
46 /* misc */
47 static void
48 scan_children_init(node_t *f, gpointer sub)
49 {
50     gboolean emit;
51     gint event;
52
53     FH_W ("%s %s [0x%p]\n", __func__, NODE_NAME(f), f);
54
55 #ifdef GIO_COMPILATION
56     emit = FALSE;
57     event = G_FILE_MONITOR_EVENT_CREATED;
58 #else
59     emit = TRUE;
60     event = GAMIN_EVENT_EXISTS;
61 #endif
62
63     if (!NODE_HAS_FLAG(f, NODE_FLAG_SNAPSHOT_UPDATED)) {
64         /* TODO snapshot should also compare to the sub created timestamp. */
65         /* GIO initially doesn't emit created/existed events. */
66         node_create_children_snapshot(f, event, emit);
67     } else {
68         GHashTableIter iter;
69         gpointer value;
70
71         g_hash_table_iter_init (&iter, f->children);
72         while (g_hash_table_iter_next (&iter, NULL, &value)) {
73             node_t *child = (node_t *)value;
74
75 #ifdef GIO_COMPILATION
76             /* GIO initially doesn't emit created/existed events. */
77             /* g_file_monitor_emit_event(G_FILE_MONITOR(sub), child->gfile, NULL, event); */
78 #else
79             gam_server_emit_one_event(NODE_NAME(child), gam_subscription_is_dir(sub), event, sub, 1);
80 #endif
81         }
82     }
83 }
84
85 /**
86  * fen_add
87  * 
88  * Won't hold a ref, we have a timout callback to clean unused node_t.
89  * If there is no value for a key, add it and return it; else return the old
90  * one.
91  */
92 void
93 fen_add (const gchar *filename, gpointer sub, gboolean is_mondir)
94 {
95         node_t* f;
96
97     g_assert (filename);
98     g_assert (sub);
99
100     G_LOCK (fen_lock);
101         f = node_find(NULL, filename, TRUE);
102     FH_W ("%s 0x%p sub[0x%p] %s\n", __func__, f, sub, filename);
103     g_assert (f);
104
105     /* Update timestamp, the events in global queue will compare itself to this
106      * timestamp to decide if be emitted. TODO, timestamp should be per sub.
107      */
108     if (!NODE_IS_ACTIVE(f)) {
109         g_get_current_time(&f->atv);
110     }
111
112     if (is_mondir) {
113         f->dir_subs = g_list_prepend(f->dir_subs, sub);
114     } else {
115         f->subs = g_list_prepend(f->subs, sub);
116     }
117     
118     if (NODE_HAS_STATE(f, NODE_STATE_ASSOCIATED) ||
119       (node_lstat(f) == 0 && port_add(f) == 0)) {
120 #ifndef GIO_COMPILATION
121         gam_server_emit_one_event (NODE_NAME(f),
122           gam_subscription_is_dir (sub), GAMIN_EVENT_EXISTS, sub, 1);
123 #endif
124         if (is_mondir) {
125             scan_children_init (f, sub);
126         }
127     } else {
128 #ifndef GIO_COMPILATION
129         gam_server_emit_one_event (NODE_NAME(f),
130           gam_subscription_is_dir (sub), GAMIN_EVENT_DELETED, sub, 1);
131 #endif
132         node_adjust_deleted (f);
133     }
134 #ifndef GIO_COMPILATION
135     gam_server_emit_one_event (NODE_NAME(f),
136       gam_subscription_is_dir (sub), GAMIN_EVENT_ENDEXISTS, sub, 1);
137 #endif
138     G_UNLOCK (fen_lock);
139 }
140
141 void
142 fen_remove (const gchar *filename, gpointer sub, gboolean is_mondir)
143 {
144     node_t* f;
145     
146     g_assert (filename);
147     g_assert (sub);
148
149     G_LOCK (fen_lock);
150         f = node_find(NULL, filename, FALSE);
151     FH_W ("%s 0x%p sub[0x%p] %s\n", __func__, f, sub, filename);
152
153     if (f) {
154         if (is_mondir) {
155             f->dir_subs = g_list_remove(f->dir_subs, sub);
156         } else {
157             f->subs = g_list_remove(f->subs, sub);
158         }
159
160         if (!NODE_IS_ACTIVE(f)) {
161             node_try_delete (f);
162         }
163     }
164     G_UNLOCK (fen_lock);
165 }
166
167 /**
168  * fen_init:
169  * 
170  * FEN subsystem initializing.
171  */
172 gboolean
173 fen_init ()
174 {
175     static gboolean initialized = FALSE;
176     static gboolean result = FALSE;
177
178     G_LOCK (fen_lock);
179     if (initialized) {
180         G_UNLOCK (fen_lock);
181         return result;
182     }
183
184     result = node_class_init();
185
186     if (!result) {
187         G_UNLOCK (fen_lock);
188         return result;
189     }
190
191     initialized = TRUE;
192
193     G_UNLOCK (fen_lock);
194     return result;
195 }