summaryrefslogtreecommitdiff
path: root/src/lib/eio/eio_monitor_poll.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/eio/eio_monitor_poll.c')
-rw-r--r--src/lib/eio/eio_monitor_poll.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/lib/eio/eio_monitor_poll.c b/src/lib/eio/eio_monitor_poll.c
new file mode 100644
index 0000000..4cd7d1a
--- /dev/null
+++ b/src/lib/eio/eio_monitor_poll.c
@@ -0,0 +1,354 @@
1/* EIO - EFL data type library
2 * Copyright (C) 2011 Enlightenment Developers:
3 * Cedric Bail <cedric.bail@free.fr>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library;
17 * if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "eio_private.h"
21#include "Eio.h"
22
23/*============================================================================*
24 * Local *
25 *============================================================================*/
26
27/**
28 * @cond LOCAL
29 */
30
31typedef struct _Eio_Monitor_Stat Eio_Monitor_Stat;
32
33struct _Eio_Monitor_Stat
34{
35 Eina_Stat buffer;
36 int version;
37};
38
39struct _Eio_Monitor_Backend
40{
41 Eio_Monitor *parent;
42
43 Eina_Stat self;
44 Eina_Hash *children;
45
46 Ecore_Timer *timer;
47 Ecore_Idler *idler;
48 Ecore_Thread *work;
49
50 int version;
51
52 Eina_Bool delete_me : 1;
53 Eina_Bool initialised : 1;
54 Eina_Bool destroyed : 1;
55};
56
57static Eina_Bool _eio_monitor_fallback_timer_cb(void *data);
58
59static void
60_eio_monitor_fallback_heavy_cb(void *data, Ecore_Thread *thread)
61{
62 Eio_Monitor_Backend *backend = data;
63 Eina_Iterator *it;
64 Eina_Stat *est;
65 Eina_File_Direct_Info *info;
66 _eio_stat_t st;
67 /* FIXME : copy ecore_file_monitor_poll here */
68
69 if (!backend->initialised)
70 est = &backend->self;
71 else
72 est = alloca(sizeof (Eina_Stat));
73
74 if (!backend->parent)
75 return ;
76
77 if (_eio_stat(backend->parent->path, &st))
78 {
79 if (backend->initialised && !backend->destroyed)
80 {
81 ecore_thread_main_loop_begin();
82 _eio_monitor_send(backend->parent, backend->parent->path, EIO_MONITOR_SELF_DELETED);
83 ecore_thread_main_loop_end();
84 backend->destroyed = EINA_TRUE;
85 }
86 return ;
87 }
88
89 backend->destroyed = EINA_FALSE;
90
91 est->dev = st.st_dev;
92 est->ino = st.st_ino;
93 est->mode = st.st_mode;
94 est->nlink = st.st_nlink;
95 est->uid = st.st_uid;
96 est->gid = st.st_gid;
97 est->rdev = st.st_rdev;
98 est->size = st.st_size;
99#ifdef _WIN32
100 est->blksize = 0;
101 est->blocks = 0;
102#else
103 est->blksize = st.st_blksize;
104 est->blocks = st.st_blocks;
105#endif
106 est->atime = st.st_atime;
107 est->mtime = st.st_mtime;
108 est->ctime = st.st_ctime;
109#ifdef _STAT_VER_LINUX
110# if (defined __USE_MISC && defined st_mtime)
111 est->atimensec = st.st_atim.tv_nsec;
112 est->mtimensec = st.st_mtim.tv_nsec;
113 est->ctimensec = st.st_ctim.tv_nsec;
114# else
115 est->atimensec = st.st_atimensec;
116 est->mtimensec = st.st_mtimensec;
117 est->ctimensec = st.st_ctimensec;
118# endif
119#else
120 est->atimensec = 0;
121 est->mtimensec = 0;
122 est->ctimensec = 0;
123#endif
124
125 if (memcmp(est, &backend->self, sizeof (Eina_Stat)) != 0)
126 {
127 ecore_thread_main_loop_begin();
128 _eio_monitor_send(backend->parent, backend->parent->path, EIO_MONITOR_SELF_DELETED);
129 ecore_thread_main_loop_end();
130 }
131
132 it = eina_file_direct_ls(backend->parent->path);
133 EINA_ITERATOR_FOREACH(it, info)
134 {
135 Eio_Monitor_Stat *cmp;
136 Eio_Monitor_Stat buffer;
137
138 if (!backend->initialised)
139 cmp = calloc(1, sizeof (Eio_Monitor_Stat));
140 else
141 cmp = &buffer;
142
143 if (eina_file_statat(eina_iterator_container_get(it), info, &cmp->buffer))
144 {
145 if (!backend->initialised) free(cmp);
146 continue ;
147 }
148
149 if (!backend->initialised)
150 {
151 eina_hash_add(backend->children, info->path + info->name_start, cmp);
152 }
153 else
154 {
155 cmp = eina_hash_find(backend->children, info->path + info->name_start);
156 if (!cmp)
157 {
158 /* New file or new directory added */
159 ecore_thread_main_loop_begin();
160 _eio_monitor_send(backend->parent, info->path + info->name_start,
161 info->type != EINA_FILE_DIR ? EIO_MONITOR_FILE_CREATED : EIO_MONITOR_DIRECTORY_CREATED);
162 ecore_thread_main_loop_end();
163
164 cmp = malloc(sizeof (Eio_Monitor_Stat));
165 memcpy(cmp, &buffer, sizeof (Eina_Stat));
166
167 eina_hash_add(backend->children, info->path + info->name_start, cmp);
168 }
169 else if (memcmp(cmp, &buffer, sizeof (Eina_Stat)) != 0)
170 {
171 /* file has been modified */
172 ecore_thread_main_loop_begin();
173 _eio_monitor_send(backend->parent, info->path + info->name_start,
174 info->type != EINA_FILE_DIR ? EIO_MONITOR_FILE_MODIFIED : EIO_MONITOR_DIRECTORY_MODIFIED);
175 ecore_thread_main_loop_end();
176
177 memcpy(cmp, &buffer, sizeof (Eina_Stat));
178 }
179 }
180
181 cmp->version = backend->version;
182 if (ecore_thread_check(thread)) goto out;
183 }
184 out:
185 if (it) eina_iterator_free(it);
186
187 if (backend->initialised && !ecore_thread_check(thread))
188 {
189 Eina_Hash_Tuple *tuple;
190
191 it = eina_hash_iterator_tuple_new(backend->children);
192 ecore_thread_main_loop_begin();
193
194 EINA_ITERATOR_FOREACH(it, tuple)
195 {
196 Eio_Monitor_Stat *cmp = tuple->data;
197
198 if (cmp->version != backend->version)
199 {
200 _eio_monitor_send(backend->parent, tuple->key,
201 eio_file_is_dir(&cmp->buffer) ? EIO_MONITOR_DIRECTORY_DELETED : EIO_MONITOR_FILE_DELETED);
202 eina_hash_del(backend->children, tuple->key, tuple->data);
203 }
204 }
205
206 ecore_thread_main_loop_end();
207 eina_iterator_free(it);
208 }
209
210 backend->version++;
211 backend->initialised = EINA_TRUE;
212}
213
214static void
215_eio_monitor_fallback_end_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
216{
217 Eio_Monitor_Backend *backend = data;
218
219 backend->work = NULL;
220 backend->timer = ecore_timer_add(60.0, _eio_monitor_fallback_timer_cb, backend);
221}
222
223static void
224_eio_monitor_fallback_cancel_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
225{
226 Eio_Monitor_Backend *backend = data;
227
228 backend->work = NULL;
229 if (backend->delete_me)
230 {
231 free(backend);
232 return ;
233 }
234 backend->timer = ecore_timer_add(60.0, _eio_monitor_fallback_timer_cb, backend);
235}
236
237static Eina_Bool
238_eio_monitor_fallback_idler_cb(void *data)
239{
240 Eio_Monitor_Backend *backend = data;
241
242 backend->idler = NULL;
243 backend->work = ecore_thread_run(_eio_monitor_fallback_heavy_cb,
244 _eio_monitor_fallback_end_cb,
245 _eio_monitor_fallback_cancel_cb,
246 backend);
247 return EINA_FALSE;
248}
249
250static Eina_Bool
251_eio_monitor_fallback_timer_cb(void *data)
252{
253 Eio_Monitor_Backend *backend = data;
254
255 backend->timer = NULL;
256 backend->idler = ecore_idler_add(_eio_monitor_fallback_idler_cb, backend);
257
258 return EINA_FALSE;
259}
260
261/**
262 * @endcond
263 */
264
265/*============================================================================*
266 * Global *
267 *============================================================================*/
268
269/**
270 * @cond LOCAL
271 */
272
273#if !defined HAVE_INOTIFY && !defined HAVE_NOTIFY_WIN32
274void eio_monitor_backend_init(void)
275{
276}
277
278void eio_monitor_backend_shutdown(void)
279{
280}
281
282void eio_monitor_backend_add(Eio_Monitor *monitor)
283{
284 eio_monitor_fallback_add(monitor);
285}
286
287void eio_monitor_backend_del(Eio_Monitor *monitor)
288{
289 eio_monitor_fallback_del(monitor);
290}
291#endif
292
293void
294eio_monitor_fallback_init(void)
295{
296}
297
298void
299eio_monitor_fallback_shutdown(void)
300{
301}
302
303void
304eio_monitor_fallback_add(Eio_Monitor *monitor)
305{
306 Eio_Monitor_Backend *backend;
307
308 monitor->backend = NULL;
309
310 backend = calloc(1, sizeof (Eio_Monitor_Backend));
311 if (!backend) return ;
312
313 backend->children = eina_hash_string_superfast_new(free);
314 backend->parent = monitor;
315 monitor->backend = backend;
316 backend->work = ecore_thread_run(_eio_monitor_fallback_heavy_cb,
317 _eio_monitor_fallback_end_cb,
318 _eio_monitor_fallback_cancel_cb,
319 backend);
320}
321
322void
323eio_monitor_fallback_del(Eio_Monitor *monitor)
324{
325 Eio_Monitor_Backend *backend;
326
327 backend = monitor->backend;
328 monitor->backend = NULL;
329
330 if (!backend) return ;
331
332 backend->parent = NULL;
333 if (backend->timer) ecore_timer_del(backend->timer);
334 backend->timer = NULL;
335 if (backend->idler) ecore_idler_del(backend->idler);
336 backend->idler = NULL;
337 if (backend->work)
338 {
339 backend->delete_me = EINA_TRUE;
340 ecore_thread_cancel(backend->work);
341 return ;
342 }
343 eina_hash_free(backend->children);
344 free(backend);
345}
346
347/**
348 * @endcond
349 */
350
351
352/*============================================================================*
353 * API *
354 *============================================================================*/