Removed unnecessary file
[platform/upstream/glib.git] / gio / gpollfilemonitor.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
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 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
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include <config.h>
24 #include <string.h>
25
26 #include "gpollfilemonitor.h"
27 #include "gfilemonitor.h"
28
29 #include "gioalias.h"
30
31 static gboolean g_poll_file_monitor_cancel (GFileMonitor* monitor);
32 static void schedule_poll_timeout (GPollFileMonitor* poll_monitor);
33
34 struct _GPollFileMonitor
35 {
36   GFileMonitor parent_instance;
37   GFile *file;
38   GFileInfo *last_info;
39   guint timeout;
40 };
41
42 #define POLL_TIME_SECS 5
43
44 #define g_poll_file_monitor_get_type _g_poll_file_monitor_get_type
45 G_DEFINE_TYPE (GPollFileMonitor, g_poll_file_monitor, G_TYPE_FILE_MONITOR)
46
47 static void
48 g_poll_file_monitor_finalize (GObject* object)
49 {
50   GPollFileMonitor* poll_monitor;
51   
52   poll_monitor = G_POLL_FILE_MONITOR (object);
53
54   g_object_unref (poll_monitor->file);
55
56   if (G_OBJECT_CLASS (g_poll_file_monitor_parent_class)->finalize)
57     (*G_OBJECT_CLASS (g_poll_file_monitor_parent_class)->finalize) (object);
58 }
59
60
61 static void
62 g_poll_file_monitor_class_init (GPollFileMonitorClass* klass)
63 {
64   GObjectClass* gobject_class = G_OBJECT_CLASS (klass);
65   GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass);
66   
67   gobject_class->finalize = g_poll_file_monitor_finalize;
68
69   file_monitor_class->cancel = g_poll_file_monitor_cancel;
70 }
71
72 static void
73 g_poll_file_monitor_init (GPollFileMonitor* poll_monitor)
74 {
75 }
76
77 static int 
78 safe_strcmp (const char *a, const char *b)
79 {
80   if (a == NULL && b == NULL)
81     return 0;
82   if (a == NULL)
83     return -1;
84   if (b == NULL)
85     return 1;
86   
87   return strcmp (a, b);
88 }
89
90 static int
91 calc_event_type (GFileInfo *last,
92                  GFileInfo *new)
93 {
94   if (last == NULL && new == NULL)
95     return -1;
96
97   if (last == NULL && new != NULL)
98     return G_FILE_MONITOR_EVENT_CREATED;
99   
100   if (last != NULL && new == NULL)
101     return G_FILE_MONITOR_EVENT_DELETED;
102
103   if (safe_strcmp (g_file_info_get_etag (last),
104                    g_file_info_get_etag (new)))
105     return G_FILE_MONITOR_EVENT_CHANGED;
106   
107   if (g_file_info_get_size (last) !=
108       g_file_info_get_size (new))
109     return G_FILE_MONITOR_EVENT_CHANGED;
110
111   return -1;
112 }
113
114 static void
115 got_new_info (GObject *source_object,
116               GAsyncResult *res,
117               gpointer user_data)
118 {
119   GPollFileMonitor* poll_monitor = user_data;
120   GFileInfo *info;
121   int event;
122
123   info = g_file_query_info_finish (poll_monitor->file, res, NULL);
124
125   if (!g_file_monitor_is_cancelled (G_FILE_MONITOR (poll_monitor)))
126     {
127       event = calc_event_type (poll_monitor->last_info, info);
128
129       if (event != -1)
130         {
131           g_file_monitor_emit_event (G_FILE_MONITOR (poll_monitor),
132                                      poll_monitor->file,
133                                      NULL, event);
134           /* We're polling so slowly anyway, so always emit the done hint */
135           if (event == G_FILE_MONITOR_EVENT_CHANGED)
136             g_file_monitor_emit_event (G_FILE_MONITOR (poll_monitor),
137                                        poll_monitor->file,
138                                        NULL, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
139         }
140       
141       if (poll_monitor->last_info)
142         {
143           g_object_unref (poll_monitor->last_info);
144           poll_monitor->last_info = NULL;
145         }
146       
147       if (info)
148         poll_monitor->last_info = g_object_ref (info);
149       
150       schedule_poll_timeout (poll_monitor);
151     }
152
153   if (info)
154     g_object_unref (info);
155   
156   g_object_unref (poll_monitor);
157 }
158
159 static gboolean
160 poll_file_timeout (gpointer data)
161 {
162   GPollFileMonitor* poll_monitor = data;
163
164   poll_monitor->timeout = FALSE;
165
166   g_file_query_info_async (poll_monitor->file, G_FILE_ATTRIBUTE_ETAG_VALUE "," G_FILE_ATTRIBUTE_STD_SIZE,
167                          0, 0, NULL, got_new_info, g_object_ref (poll_monitor));
168   
169   return FALSE;
170 }
171
172 static void
173 schedule_poll_timeout (GPollFileMonitor* poll_monitor)
174 {
175   poll_monitor->timeout = g_timeout_add_seconds (POLL_TIME_SECS, poll_file_timeout, poll_monitor);
176  }
177
178 static void
179 got_initial_info (GObject *source_object,
180                   GAsyncResult *res,
181                   gpointer user_data)
182 {
183   GPollFileMonitor* poll_monitor = user_data;
184   GFileInfo *info;
185
186   info = g_file_query_info_finish (poll_monitor->file, res, NULL);
187
188   poll_monitor->last_info = info;
189
190   if (!g_file_monitor_is_cancelled (G_FILE_MONITOR (poll_monitor)))
191     schedule_poll_timeout (poll_monitor);
192   
193   g_object_unref (poll_monitor);
194 }
195
196 /**
197  * g_poll_file_monitor_new:
198  * @file: a #GFile.
199  * 
200  * Polls @file for changes.
201  * 
202  * Returns: a new #GFileMonitor for the given #GFile. 
203  **/
204 GFileMonitor*
205 _g_poll_file_monitor_new (GFile *file)
206 {
207   GPollFileMonitor* poll_monitor;
208   
209   poll_monitor = g_object_new (G_TYPE_POLL_FILE_MONITOR, NULL);
210
211   poll_monitor->file = g_object_ref (file);
212
213   g_file_query_info_async (file, G_FILE_ATTRIBUTE_ETAG_VALUE "," G_FILE_ATTRIBUTE_STD_SIZE,
214                            0, 0, NULL, got_initial_info, g_object_ref (poll_monitor));
215   
216   return G_FILE_MONITOR (poll_monitor);
217 }
218
219 static gboolean
220 g_poll_file_monitor_cancel (GFileMonitor* monitor)
221 {
222   GPollFileMonitor *poll_monitor = G_POLL_FILE_MONITOR (monitor);
223   
224   if (poll_monitor->timeout)
225     {
226       g_source_remove (poll_monitor->timeout);
227       poll_monitor->timeout = 0;
228     }
229   
230   return TRUE;
231 }