81294fa49c6e424e02d8c31d3934d3bfce25a671
[platform/upstream/glib.git] / gio / inotify / inotify-kernel.c
1 /*
2    Copyright (C) 2005 John McCutchan
3
4    The Gnome Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    The Gnome 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    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with the Gnome Library; see the file COPYING.LIB.  If not,
16    see <http://www.gnu.org/licenses/>.
17
18    Authors:.
19                 John McCutchan <john@johnmccutchan.com>
20 */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <sys/ioctl.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <glib.h>
30 #include "inotify-kernel.h"
31 #include <sys/inotify.h>
32
33 #include "glib-private.h"
34
35 /* Timings for pairing MOVED_TO / MOVED_FROM events */
36 #define PROCESS_EVENTS_TIME 1000 /* 1000 milliseconds (1 hz) */
37 #define DEFAULT_HOLD_UNTIL_TIME 0 /* 0 millisecond */
38 #define MOVE_HOLD_UNTIL_TIME 500 /* 500 microseconds or 0.5 milliseconds */
39
40 static int inotify_instance_fd = -1;
41 static GQueue *events_to_process = NULL;
42 static GQueue *event_queue = NULL;
43 static GHashTable * cookie_hash = NULL;
44 static GIOChannel *inotify_read_ioc;
45 static GPollFD ik_poll_fd;
46 static gboolean ik_poll_fd_enabled = TRUE;
47 static void (*user_cb)(ik_event_t *event);
48
49 static gboolean ik_read_callback (gpointer user_data);
50 static gboolean ik_process_eq_callback (gpointer user_data);
51
52 static guint32 ik_move_matches = 0;
53 static guint32 ik_move_misses = 0;
54
55 static gboolean process_eq_running = FALSE;
56
57 /* We use the lock from inotify-helper.c
58  *
59  * There are two places that we take this lock
60  *
61  * 1) In ik_read_callback
62  *
63  * 2) ik_process_eq_callback.
64  *
65  *
66  * The rest of locking is taken care of in inotify-helper.c
67  */
68 G_LOCK_EXTERN (inotify_lock);
69
70 typedef struct ik_event_internal {
71   ik_event_t *event;
72   gboolean seen;
73   gboolean sent;
74   GTimeVal hold_until;
75   struct ik_event_internal *pair;
76 } ik_event_internal_t;
77
78 /* In order to perform non-sleeping inotify event chunking we need
79  * a custom GSource
80  */
81 static gboolean
82 ik_source_prepare (GSource *source,
83                    gint    *timeout)
84 {
85   return FALSE;
86 }
87
88 static gboolean
89 ik_source_timeout (gpointer data)
90 {
91   GSource *source = (GSource *)data;
92   
93   /* Re-active the PollFD */
94   g_source_add_poll (source, &ik_poll_fd);
95   g_source_unref (source);
96   ik_poll_fd_enabled = TRUE;
97   
98   return FALSE;
99 }
100
101 #define MAX_PENDING_COUNT 2
102 #define PENDING_THRESHOLD(qsize) ((qsize) >> 1)
103 #define PENDING_MARGINAL_COST(p) ((unsigned int)(1 << (p)))
104 #define MAX_QUEUED_EVENTS 2048
105 #define AVERAGE_EVENT_SIZE sizeof (struct inotify_event) + 16
106 #define TIMEOUT_MILLISECONDS 10
107
108 static gboolean
109 ik_source_check (GSource *source)
110 {
111   static int prev_pending = 0, pending_count = 0;
112   
113   /* We already disabled the PollFD or
114    * nothing to be read from inotify */
115   if (!ik_poll_fd_enabled || !(ik_poll_fd.revents & G_IO_IN))
116     return FALSE;
117
118   if (pending_count < MAX_PENDING_COUNT)
119     {
120       GSource *timeout_source;
121       unsigned int pending;
122       
123       if (ioctl (inotify_instance_fd, FIONREAD, &pending) == -1)
124         goto do_read;
125       
126       pending /= AVERAGE_EVENT_SIZE;
127       
128       /* Don't wait if the number of pending events is too close
129        * to the maximum queue size.
130        */
131       if (pending > PENDING_THRESHOLD (MAX_QUEUED_EVENTS))
132         goto do_read;
133       
134       /* With each successive iteration, the minimum rate for
135        * further sleep doubles. 
136        */
137       if (pending-prev_pending < PENDING_MARGINAL_COST (pending_count))
138         goto do_read;
139       
140       prev_pending = pending;
141       pending_count++;
142       
143       /* We are going to wait to read the events: */
144       
145       /* Remove the PollFD from the source */
146       g_source_remove_poll (source, &ik_poll_fd);
147       /* To avoid threading issues we need to flag that we've done that */
148       ik_poll_fd_enabled = FALSE;
149       /* Set a timeout to re-add the PollFD to the source */
150       g_source_ref (source);
151
152       timeout_source = g_timeout_source_new (TIMEOUT_MILLISECONDS);
153       g_source_set_callback (timeout_source, ik_source_timeout, source, NULL);
154       g_source_attach (timeout_source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
155       g_source_unref (timeout_source);
156
157       return FALSE;
158     }
159
160 do_read:
161   /* We are ready to read events from inotify */
162
163   prev_pending = 0;
164   pending_count = 0;
165   
166   return TRUE;
167 }
168
169 static gboolean
170 ik_source_dispatch (GSource     *source,
171                     GSourceFunc  callback,
172                     gpointer     user_data)
173 {
174   if (callback)
175     return callback (user_data);
176   return TRUE;
177 }
178
179 static GSourceFuncs ik_source_funcs =
180 {
181   ik_source_prepare,
182   ik_source_check,
183   ik_source_dispatch,
184   NULL
185 };
186
187 gboolean _ik_startup (void (*cb)(ik_event_t *event))
188 {
189   static gboolean initialized = FALSE;
190   GSource *source;
191   
192   user_cb = cb;
193   /* Ignore multi-calls */
194   if (initialized) 
195     return inotify_instance_fd >= 0;
196
197   initialized = TRUE;
198
199 #ifdef HAVE_INOTIFY_INIT1
200   inotify_instance_fd = inotify_init1 (IN_CLOEXEC);
201 #else
202   inotify_instance_fd = -1;
203 #endif
204   if (inotify_instance_fd < 0)
205     inotify_instance_fd = inotify_init ();
206
207   if (inotify_instance_fd < 0)
208     return FALSE;
209
210   inotify_read_ioc = g_io_channel_unix_new (inotify_instance_fd);
211   ik_poll_fd.fd = inotify_instance_fd;
212   ik_poll_fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
213   g_io_channel_set_encoding (inotify_read_ioc, NULL, NULL);
214   g_io_channel_set_flags (inotify_read_ioc, G_IO_FLAG_NONBLOCK, NULL);
215
216   source = g_source_new (&ik_source_funcs, sizeof (GSource));
217   g_source_set_name (source, "GIO Inotify");
218   g_source_add_poll (source, &ik_poll_fd);
219   g_source_set_callback (source, ik_read_callback, NULL, NULL);
220   g_source_attach (source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
221   g_source_unref (source);
222
223   cookie_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
224   event_queue = g_queue_new ();
225   events_to_process = g_queue_new ();
226   
227   return TRUE;
228 }
229
230 static ik_event_internal_t *
231 ik_event_internal_new (ik_event_t *event)
232 {
233   ik_event_internal_t *internal_event = g_new0 (ik_event_internal_t, 1);
234   GTimeVal tv;
235   
236   g_assert (event);
237   
238   g_get_current_time (&tv);
239   g_time_val_add (&tv, DEFAULT_HOLD_UNTIL_TIME);
240   internal_event->event = event;
241   internal_event->hold_until = tv;
242   
243   return internal_event;
244 }
245
246 static ik_event_t *
247 ik_event_new (char *buffer)
248 {
249   struct inotify_event *kevent = (struct inotify_event *)buffer;
250   ik_event_t *event = g_new0 (ik_event_t, 1);
251   
252   g_assert (buffer);
253   
254   event->wd = kevent->wd;
255   event->mask = kevent->mask;
256   event->cookie = kevent->cookie;
257   event->len = kevent->len;
258   if (event->len)
259     event->name = g_strdup (kevent->name);
260   else
261     event->name = g_strdup ("");
262   
263   return event;
264 }
265
266 void
267 _ik_event_free (ik_event_t *event)
268 {
269   if (event->pair)
270     _ik_event_free (event->pair);
271   g_free (event->name);
272   g_free (event);
273 }
274
275 gint32
276 _ik_watch (const char *path, 
277            guint32     mask, 
278            int        *err)
279 {
280   gint32 wd = -1;
281   
282   g_assert (path != NULL);
283   g_assert (inotify_instance_fd >= 0);
284   
285   wd = inotify_add_watch (inotify_instance_fd, path, mask);
286   
287   if (wd < 0)
288     {
289       int e = errno;
290       /* FIXME: debug msg failed to add watch */
291       if (err)
292         *err = e;
293       return wd;
294     }
295   
296   g_assert (wd >= 0);
297   return wd;
298 }
299
300 int
301 _ik_ignore (const char *path, 
302             gint32      wd)
303 {
304   g_assert (wd >= 0);
305   g_assert (inotify_instance_fd >= 0);
306   
307   if (inotify_rm_watch (inotify_instance_fd, wd) < 0)
308     {
309       /* int e = errno; */
310       /* failed to rm watch */
311       return -1;
312     }
313   
314   return 0;
315 }
316
317 static void
318 ik_read_events (gsize  *buffer_size_out, 
319                 gchar **buffer_out)
320 {
321   static gchar *buffer = NULL;
322   static gsize buffer_size;
323   
324   /* Initialize the buffer on our first call */
325   if (buffer == NULL)
326     {
327       buffer_size = AVERAGE_EVENT_SIZE;
328       buffer_size *= MAX_QUEUED_EVENTS;
329       buffer = g_malloc (buffer_size);
330     }
331
332   *buffer_size_out = 0;
333   *buffer_out = NULL;
334   
335   memset (buffer, 0, buffer_size);
336
337   if (g_io_channel_read_chars (inotify_read_ioc, (char *)buffer, buffer_size, buffer_size_out, NULL) != G_IO_STATUS_NORMAL) {
338     /* error reading */
339   }
340   *buffer_out = buffer;
341 }
342
343 static gboolean
344 ik_read_callback (gpointer user_data)
345 {
346   gchar *buffer;
347   gsize buffer_size, buffer_i, events;
348   
349   G_LOCK (inotify_lock);
350   ik_read_events (&buffer_size, &buffer);
351   
352   buffer_i = 0;
353   events = 0;
354   while (buffer_i < buffer_size)
355     {
356       struct inotify_event *event;
357       gsize event_size;
358       event = (struct inotify_event *)&buffer[buffer_i];
359       event_size = sizeof(struct inotify_event) + event->len;
360       g_queue_push_tail (events_to_process, ik_event_internal_new (ik_event_new (&buffer[buffer_i])));
361       buffer_i += event_size;
362       events++;
363     }
364   
365   /* If the event process callback is off, turn it back on */
366   if (!process_eq_running && events)
367     {
368       GSource *timeout_source;
369
370       process_eq_running = TRUE;
371       timeout_source = g_timeout_source_new (PROCESS_EVENTS_TIME);
372       g_source_set_callback (timeout_source, ik_process_eq_callback, NULL, NULL);
373       g_source_attach (timeout_source, GLIB_PRIVATE_CALL (g_get_worker_context ()));
374       g_source_unref (timeout_source);
375     }
376   
377   G_UNLOCK (inotify_lock);
378   
379   return TRUE;
380 }
381
382 static gboolean
383 g_timeval_lt (GTimeVal *val1,
384               GTimeVal *val2)
385 {
386   if (val1->tv_sec < val2->tv_sec)
387     return TRUE;
388
389   if (val1->tv_sec > val2->tv_sec)
390     return FALSE;
391
392   /* val1->tv_sec == val2->tv_sec */
393   if (val1->tv_usec < val2->tv_usec)
394     return TRUE;
395
396   return FALSE;
397 }
398
399 static gboolean
400 g_timeval_le (GTimeVal *val1,
401               GTimeVal *val2)
402 {
403   if (val1->tv_sec < val2->tv_sec)
404     return TRUE;
405
406   if (val1->tv_sec > val2->tv_sec)
407     return FALSE;
408
409   /* val1->tv_sec == val2->tv_sec */
410   if (val1->tv_usec <= val2->tv_usec)
411     return TRUE;
412
413   return FALSE;
414 }
415
416 static void
417 ik_pair_events (ik_event_internal_t *event1, 
418                 ik_event_internal_t *event2)
419 {
420   g_assert (event1 && event2);
421   /* We should only be pairing events that have the same cookie */
422   g_assert (event1->event->cookie == event2->event->cookie);
423   /* We shouldn't pair an event that already is paired */
424   g_assert (event1->pair == NULL && event2->pair == NULL);
425
426   /* Pair the internal structures and the ik_event_t structures */
427   event1->pair = event2;
428   event1->event->pair = event2->event;
429   event2->event->is_second_in_pair = TRUE;
430
431   if (g_timeval_lt (&event1->hold_until, &event2->hold_until))
432     event1->hold_until = event2->hold_until;
433
434   event2->hold_until = event1->hold_until;
435 }
436
437 static void
438 ik_event_add_microseconds (ik_event_internal_t *event, 
439                            glong                ms)
440 {
441   g_assert (event);
442   g_time_val_add (&event->hold_until, ms);
443 }
444
445 static gboolean
446 ik_event_ready (ik_event_internal_t *event)
447 {
448   GTimeVal tv;
449   g_assert (event);
450   
451   g_get_current_time (&tv);
452   
453   /* An event is ready if,
454    *
455    * it has no cookie -- there is nothing to be gained by holding it
456    * or, it is already paired -- we don't need to hold it anymore
457    * or, we have held it long enough
458    */
459   return
460     event->event->cookie == 0 ||
461     event->pair != NULL ||
462     g_timeval_le (&event->hold_until, &tv);
463 }
464
465 static void
466 ik_pair_moves (gpointer data, 
467                gpointer user_data)
468 {
469   ik_event_internal_t *event = (ik_event_internal_t *)data;
470   
471   if (event->seen == TRUE || event->sent == TRUE)
472     return;
473   
474   if (event->event->cookie != 0)
475     {
476       /* When we get a MOVED_FROM event we delay sending the event by
477        * MOVE_HOLD_UNTIL_TIME microseconds. We need to do this because a
478        * MOVED_TO pair _might_ be coming in the near future */
479       if (event->event->mask & IN_MOVED_FROM)
480         {
481           g_hash_table_insert (cookie_hash, GINT_TO_POINTER (event->event->cookie), event);
482           /* because we don't deliver move events there is no point in waiting for the match right now. */
483           ik_event_add_microseconds (event, MOVE_HOLD_UNTIL_TIME);
484         }
485       else if (event->event->mask & IN_MOVED_TO)
486         {
487           /* We need to check if we are waiting for this MOVED_TO events cookie to pair it with
488            * a MOVED_FROM */
489           ik_event_internal_t *match = NULL;
490           match = g_hash_table_lookup (cookie_hash, GINT_TO_POINTER (event->event->cookie));
491           if (match)
492             {
493               g_hash_table_remove (cookie_hash, GINT_TO_POINTER (event->event->cookie));
494               ik_pair_events (match, event);
495             }
496         }
497     }
498   event->seen = TRUE;
499 }
500
501 static void
502 ik_process_events (void)
503 {
504   g_queue_foreach (events_to_process, ik_pair_moves, NULL);
505
506   while (!g_queue_is_empty (events_to_process))
507     {
508       ik_event_internal_t *event = g_queue_peek_head (events_to_process);
509       
510       /* This must have been sent as part of a MOVED_TO/MOVED_FROM */
511       if (event->sent)
512         {
513           /* Pop event */
514           g_queue_pop_head (events_to_process);
515           /* Free the internal event structure */
516           g_free (event);
517           continue;
518         }
519       
520       /* The event isn't ready yet */
521       if (!ik_event_ready (event))
522         break;
523       
524       /* Pop it */
525       event = g_queue_pop_head (events_to_process);
526       
527       /* Check if this is a MOVED_FROM that is also sitting in the cookie_hash */
528       if (event->event->cookie && event->pair == NULL &&
529           g_hash_table_lookup (cookie_hash, GINT_TO_POINTER (event->event->cookie)))
530         g_hash_table_remove (cookie_hash, GINT_TO_POINTER (event->event->cookie));
531       
532       if (event->pair)
533         {
534           /* We send out paired MOVED_FROM/MOVED_TO events in the same event buffer */
535           /* g_assert (event->event->mask == IN_MOVED_FROM && event->pair->event->mask == IN_MOVED_TO); */
536           /* Copy the paired data */
537           event->pair->sent = TRUE;
538           event->sent = TRUE;
539           ik_move_matches++;
540         }
541       else if (event->event->cookie)
542         {
543           /* If we couldn't pair a MOVED_FROM and MOVED_TO together, we change
544            * the event masks */
545           /* Changeing MOVED_FROM to DELETE and MOVED_TO to create lets us make
546            * the gaurantee that you will never see a non-matched MOVE event */
547           event->event->original_mask = event->event->mask;
548
549           if (event->event->mask & IN_MOVED_FROM)
550             {
551               event->event->mask = IN_DELETE|(event->event->mask & IN_ISDIR);
552               ik_move_misses++; /* not super accurate, if we aren't watching the destination it still counts as a miss */
553             }
554           if (event->event->mask & IN_MOVED_TO)
555             event->event->mask = IN_CREATE|(event->event->mask & IN_ISDIR);
556         }
557       
558       /* Push the ik_event_t onto the event queue */
559       g_queue_push_tail (event_queue, event->event);
560       /* Free the internal event structure */
561       g_free (event);
562     }
563 }
564
565 static gboolean
566 ik_process_eq_callback (gpointer user_data)
567 {
568   gboolean res;
569   
570   /* Try and move as many events to the event queue */
571   G_LOCK (inotify_lock);
572   ik_process_events ();
573   
574   while (!g_queue_is_empty (event_queue))
575     {
576       ik_event_t *event = g_queue_pop_head (event_queue);
577       
578       user_cb (event);
579     }
580
581   res = TRUE;
582   
583   if (g_queue_get_length (events_to_process) == 0)
584     {
585       process_eq_running = FALSE;
586       res = FALSE;
587     }
588   
589   G_UNLOCK (inotify_lock);
590   
591   return res;
592 }