Send CHANGES_DONE_HINT on file moves if no IN_CLOSE_WRITE is emitted

This patch makes GFileMonitor to emit EVENT_CHANGES_DONE_HINT when
EVENT_CREATED is emitted but the file is not opened for writing.

On file moves across different mounted volumes, inotify will always emit
IN_CREATE and IN_CLOSE_WRITE (plus other events).
This translates into GIO's _EVENT_CREATED and _EVENT_CHANGES_DONE_HINT.

On file moves across the same mounted volumes, inotify will emit
IN_MOVED_FROM/IN_MOVED_TO which will be translated into
_EVENT_DELETED/_EVENT_CREATED GIO's side. No _EVENT_CHANGES_DONE_HINT is
emited afterwards.
Under such circumstances a file indexer does not know when actually the
file is ready to be indexed, either waiting too much or triggering the
indexing twice. On small devices it's not advisable.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=640077
Bug-NB: NB#219982
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: Tomas Bzatek <tbzatek@redhat.com>
This commit is contained in:
Cosimo Alfarano 2011-01-19 19:08:15 +00:00 committed by Simon McVittie
parent 83d0c8a739
commit fd1e9938b3
3 changed files with 35 additions and 1 deletions

View File

@ -190,6 +190,30 @@ ih_event_callback (ik_event_t *event,
g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
child, other, eflags);
/* For paired moves or moves whose mask has been changed from IN_MOVED_TO to
* IN_CREATE, notify also that it's probably the last change to the file,
* emitting CHANGES_DONE_HINT.
* The first (first part of the if's guard below) is the case of a normal
* move within the monitored tree and in the same mounted volume.
* The latter (second part of the guard) is the case of a move within the
* same mounted volume, but from a not monitored directory.
*
* It's not needed in cases like moves across mounted volumes as the IN_CREATE
* will be followed by a IN_MODIFY and IN_CLOSE_WRITE events.
* Also not needed if sub->pair_moves is set as EVENT_MOVED will be emitted
* instead of EVENT_CREATED which implies no further modification will be
* applied to the file
* See: https://bugzilla.gnome.org/show_bug.cgi?id=640077
*/
if ((!sub->pair_moves &&
event->is_second_in_pair && (event->mask & IN_MOVED_TO)) ||
(!ih_event_is_paired_move (event) &&
(event->original_mask & IN_MOVED_TO) && (event->mask & IN_CREATE)))
{
g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
child, NULL, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
}
g_object_unref (child);
if (other)
g_object_unref (other);

View File

@ -516,6 +516,7 @@ ik_pair_events (ik_event_internal_t *event1,
/* Pair the internal structures and the ik_event_t structures */
event1->pair = event2;
event1->event->pair = event2->event;
event2->event->is_second_in_pair = TRUE;
if (g_timeval_lt (&event1->hold_until, &event2->hold_until))
event1->hold_until = event2->hold_until;
@ -634,7 +635,8 @@ ik_process_events (void)
* the event masks */
/* Changeing MOVED_FROM to DELETE and MOVED_TO to create lets us make
* the gaurantee that you will never see a non-matched MOVE event */
event->event->original_mask = event->event->mask;
if (event->event->mask & IN_MOVED_FROM)
{
event->event->mask = IN_DELETE|(event->event->mask & IN_ISDIR);

View File

@ -26,9 +26,17 @@
typedef struct ik_event_s {
gint32 wd;
guint32 mask;
guint32 original_mask;
guint32 cookie;
guint32 len;
char * name;
/* TRUE if this event is the last element of a pair
* (e.g., MOVE_TO in a pair of MOVE_FROM, MOVE_TO events) */
gboolean is_second_in_pair;
/* if event1 and event2 are two paired events
* (e.g., MOVE_FROM and MOVE_TO events related to the same file move),
* then event1->pair == event2 and event2->pair == NULL.
* It will result also in event1->pair->is_second_in_pair == TRUE */
struct ik_event_s *pair;
} ik_event_t;