tracker-0.16.2/src/libtracker-miner/tracker-task-pool.c

No issues found

  1 /*
  2  * Copyright (C) 2011, Nokia <ivan.frade@nokia.com>
  3  *
  4  * This library is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2.1 of the License, or (at your option) any later version.
  8  *
  9  * This 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  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with this library; if not, write to the
 16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 17  * Boston, MA  02110-1301, USA.
 18  *
 19  * Author: Carlos Garnacho <carlos@lanedo.com>
 20  */
 21 
 22 #include "config.h"
 23 
 24 #include "tracker-task-pool.h"
 25 
 26 enum {
 27 	PROP_0,
 28 	PROP_LIMIT,
 29 	PROP_LIMIT_REACHED
 30 };
 31 
 32 G_DEFINE_TYPE (TrackerTaskPool, tracker_task_pool, G_TYPE_OBJECT)
 33 
 34 typedef struct _TrackerTaskPoolPrivate TrackerTaskPoolPrivate;
 35 
 36 struct _TrackerTaskPoolPrivate
 37 {
 38 	GHashTable *tasks;
 39 	guint limit;
 40 };
 41 
 42 struct _TrackerTask
 43 {
 44 	GFile *file;
 45 	gpointer data;
 46 	GDestroyNotify destroy_notify;
 47 	gint ref_count;
 48 };
 49 
 50 static void
 51 tracker_task_pool_finalize (GObject *object)
 52 {
 53 	TrackerTaskPoolPrivate *priv;
 54 
 55 	priv = TRACKER_TASK_POOL (object)->priv;
 56 	g_hash_table_destroy (priv->tasks);
 57 
 58 	G_OBJECT_CLASS (tracker_task_pool_parent_class)->finalize (object);
 59 }
 60 
 61 static void
 62 tracker_task_pool_set_property (GObject      *object,
 63                                 guint         param_id,
 64                                 const GValue *value,
 65                                 GParamSpec   *pspec)
 66 {
 67 	TrackerTaskPool *pool = TRACKER_TASK_POOL (object);
 68 
 69 
 70 	switch (param_id) {
 71 	case PROP_LIMIT:
 72 		tracker_task_pool_set_limit (pool,
 73 		                             g_value_get_uint (value));
 74 		break;
 75 	default:
 76 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 77 	}
 78 }
 79 
 80 static void
 81 tracker_task_pool_get_property (GObject    *object,
 82                                 guint       param_id,
 83                                 GValue     *value,
 84                                 GParamSpec *pspec)
 85 {
 86 	TrackerTaskPool *pool = TRACKER_TASK_POOL (object);
 87 
 88 	switch (param_id) {
 89 	case PROP_LIMIT:
 90 		g_value_set_uint (value,
 91 		                  tracker_task_pool_get_limit (pool));
 92 		break;
 93 	case PROP_LIMIT_REACHED:
 94 		g_value_set_boolean (value,
 95 		                     tracker_task_pool_limit_reached (pool));
 96 		break;
 97 	default:
 98 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 99 	}
100 }
101 
102 static void
103 tracker_task_pool_class_init (TrackerTaskPoolClass *klass)
104 {
105 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
106 
107 	object_class->finalize = tracker_task_pool_finalize;
108 	object_class->set_property = tracker_task_pool_set_property;
109 	object_class->get_property = tracker_task_pool_get_property;
110 
111 	g_object_class_install_property (object_class,
112 	                                 PROP_LIMIT,
113 	                                 g_param_spec_uint ("limit",
114 	                                                    "Limit",
115 	                                                    "Task limit",
116 	                                                    1, G_MAXUINT, 1,
117 	                                                    G_PARAM_READWRITE));
118 	g_object_class_install_property (object_class,
119 	                                 PROP_LIMIT_REACHED,
120 	                                 g_param_spec_boolean ("limit-reached",
121 	                                                       "Limit reached",
122 	                                                       "Task limit reached",
123 	                                                       FALSE,
124 	                                                       G_PARAM_READABLE));
125 
126 	g_type_class_add_private (klass, sizeof (TrackerTaskPoolPrivate));
127 }
128 
129 static gboolean
130 file_equal (GFile *file1,
131             GFile *file2)
132 {
133 	if (file1 == file2) {
134 		return TRUE;
135 	} else {
136 		return g_file_equal (file1, file2);
137 	}
138 }
139 
140 static void
141 tracker_task_pool_init (TrackerTaskPool *pool)
142 {
143 	TrackerTaskPoolPrivate *priv;
144 
145 	priv = pool->priv = G_TYPE_INSTANCE_GET_PRIVATE (pool,
146 	                                                 TRACKER_TYPE_TASK_POOL,
147 	                                                 TrackerTaskPoolPrivate);
148 	priv->tasks = g_hash_table_new_full (g_file_hash,
149 	                                     (GEqualFunc) file_equal, NULL,
150 	                                     (GDestroyNotify) tracker_task_unref);
151 	priv->limit = 0;
152 }
153 
154 TrackerTaskPool *
155 tracker_task_pool_new (guint limit)
156 {
157 	return g_object_new (TRACKER_TYPE_TASK_POOL,
158 	                     "limit", limit,
159 	                     NULL);
160 }
161 
162 void
163 tracker_task_pool_set_limit (TrackerTaskPool *pool,
164                              guint            limit)
165 {
166 	TrackerTaskPoolPrivate *priv;
167 	gboolean old_limit_reached;
168 
169 	g_return_if_fail (TRACKER_IS_TASK_POOL (pool));
170 
171 	old_limit_reached = tracker_task_pool_limit_reached (pool);
172 
173 	priv = pool->priv;
174 	priv->limit = limit;
175 
176 	if (old_limit_reached !=
177 	    tracker_task_pool_limit_reached (pool)) {
178 		g_object_notify (G_OBJECT (pool), "limit-reached");
179 	}
180 }
181 
182 guint
183 tracker_task_pool_get_limit (TrackerTaskPool *pool)
184 {
185 	TrackerTaskPoolPrivate *priv;
186 
187 	g_return_val_if_fail (TRACKER_IS_TASK_POOL (pool), 0);
188 
189 	priv = pool->priv;
190 	return priv->limit;
191 }
192 
193 guint
194 tracker_task_pool_get_size (TrackerTaskPool *pool)
195 {
196 	TrackerTaskPoolPrivate *priv;
197 
198 	g_return_val_if_fail (TRACKER_IS_TASK_POOL (pool), 0);
199 
200 	priv = pool->priv;
201 	return g_hash_table_size (priv->tasks);
202 }
203 
204 gboolean
205 tracker_task_pool_limit_reached (TrackerTaskPool *pool)
206 {
207 	TrackerTaskPoolPrivate *priv;
208 
209 	g_return_val_if_fail (TRACKER_IS_TASK_POOL (pool), FALSE);
210 
211 	priv = pool->priv;
212 	return (g_hash_table_size (priv->tasks) >= priv->limit);
213 }
214 
215 void
216 tracker_task_pool_add (TrackerTaskPool *pool,
217                        TrackerTask     *task)
218 {
219 	TrackerTaskPoolPrivate *priv;
220 
221 	g_return_if_fail (TRACKER_IS_TASK_POOL (pool));
222 
223 	priv = pool->priv;
224 
225 	g_hash_table_insert (priv->tasks,
226 	                     tracker_task_get_file (task),
227 	                     tracker_task_ref (task));
228 
229 	if (g_hash_table_size (priv->tasks) == priv->limit) {
230 		g_object_notify (G_OBJECT (pool), "limit-reached");
231 	}
232 }
233 
234 gboolean
235 tracker_task_pool_remove (TrackerTaskPool *pool,
236                           TrackerTask     *task)
237 {
238 	TrackerTaskPoolPrivate *priv;
239 
240 	g_return_val_if_fail (TRACKER_IS_TASK_POOL (pool), FALSE);
241 
242 	priv = pool->priv;
243 
244 	if (g_hash_table_remove (priv->tasks,
245 	                         tracker_task_get_file (task))) {
246 		if (g_hash_table_size (priv->tasks) == priv->limit - 1) {
247 			/* We've gone below the threshold again */
248 			g_object_notify (G_OBJECT (pool), "limit-reached");
249 		}
250 
251 		return TRUE;
252 	}
253 
254 	return FALSE;
255 }
256 
257 void
258 tracker_task_pool_foreach (TrackerTaskPool *pool,
259                            GFunc            func,
260                            gpointer         user_data)
261 {
262 	TrackerTaskPoolPrivate *priv;
263 	GHashTableIter iter;
264 	TrackerTask *task;
265 
266 	g_return_if_fail (TRACKER_IS_TASK_POOL (pool));
267 	g_return_if_fail (func != NULL);
268 
269 	priv = pool->priv;
270 	g_hash_table_iter_init (&iter, priv->tasks);
271 
272 	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &task)) {
273 		(func) (task, user_data);
274 	}
275 }
276 
277 TrackerTask *
278 tracker_task_pool_find (TrackerTaskPool *pool,
279                         GFile           *file)
280 {
281 	TrackerTaskPoolPrivate *priv;
282 
283 	g_return_val_if_fail (TRACKER_IS_TASK_POOL (pool), NULL);
284 	g_return_val_if_fail (G_IS_FILE (file), NULL);
285 
286 	priv = pool->priv;
287 	return g_hash_table_lookup (priv->tasks, file);
288 }
289 
290 /* Task */
291 TrackerTask *
292 tracker_task_new (GFile          *file,
293                   gpointer        data,
294                   GDestroyNotify  destroy_notify)
295 {
296 	TrackerTask *task;
297 
298 	task = g_slice_new0 (TrackerTask);
299 	task->file = g_object_ref (file);
300 	task->destroy_notify = destroy_notify;
301 	task->data = data;
302 	task->ref_count = 1;
303 
304 	return task;
305 }
306 
307 TrackerTask *
308 tracker_task_ref (TrackerTask *task)
309 {
310 	g_return_val_if_fail (task != NULL, NULL);
311 
312 	g_atomic_int_inc (&task->ref_count);
313 
314 	return task;
315 }
316 void
317 tracker_task_unref (TrackerTask *task)
318 {
319 	g_return_if_fail (task != NULL);
320 
321 	if (g_atomic_int_dec_and_test (&task->ref_count)) {
322 		g_object_unref (task->file);
323 
324 		if (task->data &&
325 		    task->destroy_notify) {
326 			(task->destroy_notify) (task->data);
327 		}
328 
329 		g_slice_free (TrackerTask, task);
330 	}
331 }
332 
333 GFile *
334 tracker_task_get_file (TrackerTask *task)
335 {
336 	g_return_val_if_fail (task != NULL, NULL);
337 
338 	return task->file;
339 }
340 
341 gpointer
342 tracker_task_get_data (TrackerTask *task)
343 {
344 	g_return_val_if_fail (task != NULL, NULL);
345 
346 	return task->data;
347 }