No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | tracker-miner-manager.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * Copyright (C) 2009, 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
20 #include "config.h"
21
22 #include <gio/gio.h>
23
24 #include <libtracker-common/tracker-dbus.h>
25 #include <libtracker-common/tracker-type-utils.h>
26
27 #include "tracker-crawler.h"
28 #include "tracker-miner-object.h"
29 #include "tracker-miner-manager.h"
30 #include "tracker-marshal.h"
31 #include "tracker-miner-dbus.h"
32
33 /**
34 * SECTION:tracker-miner-manager
35 * @short_description: External control and monitoring of miners
36 * @include: libtracker-miner/tracker-miner.h
37 *
38 * #TrackerMinerManager keeps track of available miners, their current
39 * progress/status, and also allows basic external control on them, such
40 * as pausing or resuming data processing.
41 **/
42
43 #define TRACKER_MINER_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_MANAGER, TrackerMinerManagerPrivate))
44
45 #define DESKTOP_ENTRY_GROUP "Desktop Entry"
46 #define DBUS_NAME_KEY "DBusName"
47 #define DBUS_PATH_KEY "DBusPath"
48 #define DISPLAY_NAME_KEY "Name"
49 #define DESCRIPTION_KEY "Comment"
50
51 typedef struct TrackerMinerManagerPrivate TrackerMinerManagerPrivate;
52 typedef struct MinerData MinerData;
53
54 struct MinerData {
55 gchar *dbus_name;
56 gchar *dbus_path;
57 gchar *display_name;
58 gchar *description;
59
60 GDBusConnection *connection;
61 guint progress_signal;
62 guint paused_signal;
63 guint resumed_signal;
64 guint watch_name_id;
65 GObject *manager; /* weak */
66 };
67
68 struct TrackerMinerManagerPrivate {
69 GDBusConnection *connection;
70 GList *miners;
71 GHashTable *miner_proxies;
72
73 /* Property values */
74 gboolean auto_start;
75 };
76
77 static void miner_manager_initable_iface_init (GInitableIface *iface);
78 static void miner_manager_set_property (GObject *object,
79 guint param_id,
80 const GValue *value,
81 GParamSpec *pspec);
82 static void miner_manager_get_property (GObject *object,
83 guint param_id,
84 GValue *value,
85 GParamSpec *pspec);
86 static void miner_manager_finalize (GObject *object);
87 static void initialize_miners_data (TrackerMinerManager *manager);
88
89 G_DEFINE_TYPE_WITH_CODE (TrackerMinerManager, tracker_miner_manager, G_TYPE_OBJECT,
90 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
91 miner_manager_initable_iface_init));
92
93 enum {
94 PROP_0,
95 PROP_AUTO_START
96 };
97
98 enum {
99 MINER_PROGRESS,
100 MINER_PAUSED,
101 MINER_RESUMED,
102 MINER_ACTIVATED,
103 MINER_DEACTIVATED,
104 LAST_SIGNAL
105 };
106
107 static guint signals [LAST_SIGNAL] = { 0 };
108
109 static void
110 tracker_miner_manager_class_init (TrackerMinerManagerClass *klass)
111 {
112 GObjectClass *object_class = G_OBJECT_CLASS (klass);
113
114 object_class->set_property = miner_manager_set_property;
115 object_class->get_property = miner_manager_get_property;
116 object_class->finalize = miner_manager_finalize;
117
118 g_object_class_install_property (object_class,
119 PROP_AUTO_START,
120 g_param_spec_boolean ("auto-start",
121 "Auto Start",
122 "If set, auto starts miners when querying their status",
123 TRUE,
124 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
125
126 /**
127 * TrackerMinerManager::miner-progress:
128 * @manager: the #TrackerMinerManager
129 * @miner: miner reference
130 * @status: miner status
131 * @progress: miner progress, from 0 to 1
132 * @remaining_time: remaining processing time
133 *
134 * The ::miner-progress signal is meant to report status/progress changes
135 * in any tracked miner.
136 *
137 * Since: 0.12
138 **/
139 signals [MINER_PROGRESS] =
140 g_signal_new ("miner-progress",
141 G_OBJECT_CLASS_TYPE (object_class),
142 G_SIGNAL_RUN_LAST,
143 G_STRUCT_OFFSET (TrackerMinerManagerClass, miner_progress),
144 NULL, NULL,
145 tracker_marshal_VOID__STRING_STRING_DOUBLE_INT,
146 G_TYPE_NONE, 4,
147 G_TYPE_STRING,
148 G_TYPE_STRING,
149 G_TYPE_DOUBLE,
150 G_TYPE_INT);
151 /**
152 * TrackerMinerManager::miner-paused:
153 * @manager: the #TrackerMinerManager
154 * @miner: miner reference
155 *
156 * The ::miner-paused signal will be emitted whenever a miner
157 * (referenced by @miner) is paused.
158 *
159 * Since: 0.8
160 **/
161 signals [MINER_PAUSED] =
162 g_signal_new ("miner-paused",
163 G_OBJECT_CLASS_TYPE (object_class),
164 G_SIGNAL_RUN_LAST,
165 G_STRUCT_OFFSET (TrackerMinerManagerClass, miner_paused),
166 NULL, NULL,
167 g_cclosure_marshal_VOID__STRING,
168 G_TYPE_NONE, 1,
169 G_TYPE_STRING);
170 /**
171 * TrackerMinerManager::miner-resumed:
172 * @manager: the #TrackerMinerManager
173 * @miner: miner reference
174 *
175 * The ::miner-resumed signal will be emitted whenever a miner
176 * (referenced by @miner) is resumed.
177 *
178 * Since: 0.8
179 **/
180 signals [MINER_RESUMED] =
181 g_signal_new ("miner-resumed",
182 G_OBJECT_CLASS_TYPE (object_class),
183 G_SIGNAL_RUN_LAST,
184 G_STRUCT_OFFSET (TrackerMinerManagerClass, miner_resumed),
185 NULL, NULL,
186 g_cclosure_marshal_VOID__STRING,
187 G_TYPE_NONE, 1,
188 G_TYPE_STRING);
189 /**
190 * TrackerMinerManager::miner-activated:
191 * @manager: the #TrackerMinerManager
192 * @miner: miner reference
193 *
194 * The ::miner-activated signal will be emitted whenever a miner
195 * (referenced by @miner) is activated (technically, this means
196 * the miner has appeared in the session bus).
197 *
198 * Since: 0.8
199 **/
200 signals [MINER_ACTIVATED] =
201 g_signal_new ("miner-activated",
202 G_OBJECT_CLASS_TYPE (object_class),
203 G_SIGNAL_RUN_LAST,
204 G_STRUCT_OFFSET (TrackerMinerManagerClass, miner_activated),
205 NULL, NULL,
206 g_cclosure_marshal_VOID__STRING,
207 G_TYPE_NONE, 1,
208 G_TYPE_STRING);
209 /**
210 * TrackerMinerManager::miner-deactivated:
211 * @manager: the #TrackerMinerManager
212 * @miner: miner reference
213 *
214 * The ::miner-deactivated signal will be emitted whenever a miner
215 * (referenced by @miner) is deactivated (technically, this means
216 * the miner has disappeared from the session bus).
217 *
218 * Since: 0.8
219 **/
220 signals [MINER_DEACTIVATED] =
221 g_signal_new ("miner-deactivated",
222 G_OBJECT_CLASS_TYPE (object_class),
223 G_SIGNAL_RUN_LAST,
224 G_STRUCT_OFFSET (TrackerMinerManagerClass, miner_deactivated),
225 NULL, NULL,
226 g_cclosure_marshal_VOID__STRING,
227 G_TYPE_NONE, 1,
228 G_TYPE_STRING);
229
230 g_type_class_add_private (object_class, sizeof (TrackerMinerManagerPrivate));
231 }
232
233 static void
234 miner_manager_set_property (GObject *object,
235 guint prop_id,
236 const GValue *value,
237 GParamSpec *pspec)
238 {
239 TrackerMinerManager *manager;
240 TrackerMinerManagerPrivate *priv;
241
242 manager = TRACKER_MINER_MANAGER (object);
243 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
244
245 switch (prop_id) {
246 case PROP_AUTO_START:
247 priv->auto_start = g_value_get_boolean (value);
248 break;
249 default:
250 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
251 break;
252 }
253 }
254
255 static void
256 miner_manager_get_property (GObject *object,
257 guint prop_id,
258 GValue *value,
259 GParamSpec *pspec)
260 {
261 TrackerMinerManager *manager;
262 TrackerMinerManagerPrivate *priv;
263
264 manager = TRACKER_MINER_MANAGER (object);
265 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
266
267 switch (prop_id) {
268 case PROP_AUTO_START:
269 g_value_set_boolean (value, priv->auto_start);
270 break;
271 default:
272 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
273 break;
274 }
275 }
276
277 static GDBusProxy *
278 find_miner_proxy (TrackerMinerManager *manager,
279 const gchar *name,
280 gboolean try_suffix)
281 {
282 TrackerMinerManagerPrivate *priv;
283 GHashTableIter iter;
284 gpointer key, value;
285
286 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
287 g_hash_table_iter_init (&iter, priv->miner_proxies);
288
289 while (g_hash_table_iter_next (&iter, &key, &value)) {
290 if (g_strcmp0 (name, (gchar *) value) == 0) {
291 return key;
292 }
293
294 if (try_suffix) {
295 if (g_str_has_suffix (value, name)) {
296 return key;
297 }
298 }
299 }
300
301 return NULL;
302 }
303
304 static void
305 miner_appears (GDBusConnection *connection,
306 const gchar *name,
307 const gchar *name_owner,
308 gpointer user_data)
309 {
310 MinerData *data = user_data;
311 if (data->manager) {
312 g_signal_emit (data->manager, signals[MINER_ACTIVATED], 0, data->dbus_name);
313 }
314 }
315
316 static void
317 miner_disappears (GDBusConnection *connection,
318 const gchar *name,
319 gpointer user_data)
320 {
321 MinerData *data = user_data;
322 if (data->manager) {
323 g_signal_emit (data->manager, signals[MINER_DEACTIVATED], 0, data->dbus_name);
324 }
325 }
326
327 static void
328 miner_progress_changed (GDBusConnection *connection,
329 const gchar *sender_name,
330 const gchar *object_path,
331 const gchar *interface_name,
332 const gchar *signal_name,
333 GVariant *parameters,
334 gpointer user_data)
335 {
336 MinerData *data = user_data;
337 const gchar *status = NULL;
338 gdouble progress = 0;
339 gint remaining_time = -1;
340
341 g_variant_get (parameters, "(&sdi)", &status, &progress, &remaining_time);
342 if (data->manager) {
343 g_signal_emit (data->manager, signals[MINER_PROGRESS], 0, data->dbus_name, status, progress, remaining_time);
344 }
345 }
346
347 static void
348 miner_paused (GDBusConnection *connection,
349 const gchar *sender_name,
350 const gchar *object_path,
351 const gchar *interface_name,
352 const gchar *signal_name,
353 GVariant *parameters,
354 gpointer user_data)
355 {
356 MinerData *data = user_data;
357 if (data->manager) {
358 g_signal_emit (data->manager, signals[MINER_PAUSED], 0, data->dbus_name);
359 }
360 }
361
362 static void
363 miner_resumed (GDBusConnection *connection,
364 const gchar *sender_name,
365 const gchar *object_path,
366 const gchar *interface_name,
367 const gchar *signal_name,
368 GVariant *parameters,
369 gpointer user_data)
370 {
371 MinerData *data = user_data;
372 if (data->manager) {
373 g_signal_emit (data->manager, signals[MINER_RESUMED], 0, data->dbus_name);
374 }
375 }
376
377 static void
378 data_manager_weak_notify (gpointer user_data, GObject *old_object)
379 {
380 MinerData *data = user_data;
381 data->manager = NULL;
382 }
383
384 static void
385 tracker_miner_manager_init (TrackerMinerManager *manager)
386 {
387 TrackerMinerManagerPrivate *priv;
388
389 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
390
391 priv->miner_proxies = g_hash_table_new_full (NULL, NULL,
392 (GDestroyNotify) g_object_unref,
393 (GDestroyNotify) g_free);
394 }
395
396 static gboolean
397 miner_manager_initable_init (GInitable *initable,
398 GCancellable *cancellable,
399 GError **error)
400 {
401 TrackerMinerManager *manager;
402 GError *inner_error = NULL;
403 TrackerMinerManagerPrivate *priv;
404 GList *m;
405
406 manager = TRACKER_MINER_MANAGER (initable);
407 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
408
409 priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &inner_error);
410 if (!priv->connection) {
411 g_propagate_error (error, inner_error);
412 return FALSE;
413 }
414
415 initialize_miners_data (manager);
416
417 for (m = priv->miners; m; m = m->next) {
418 GDBusProxy *proxy;
419 MinerData *data;
420
421 data = m->data;
422 data->connection = g_object_ref (priv->connection);
423 data->manager = G_OBJECT (manager);
424 g_object_weak_ref (data->manager, data_manager_weak_notify, data);
425
426 proxy = g_dbus_proxy_new_sync (priv->connection,
427 (priv->auto_start ?
428 G_DBUS_PROXY_FLAGS_NONE :
429 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START),
430 NULL,
431 data->dbus_name,
432 data->dbus_path,
433 TRACKER_MINER_DBUS_INTERFACE,
434 NULL,
435 &inner_error);
436 /* This error shouldn't be considered fatal */
437 if (inner_error) {
438 g_critical ("Could not create proxy on the D-Bus session bus, %s",
439 inner_error ? inner_error->message : "no error given.");
440 g_clear_error (&inner_error);
441 continue;
442 }
443
444 data->progress_signal = g_dbus_connection_signal_subscribe (priv->connection,
445 data->dbus_name,
446 TRACKER_MINER_DBUS_INTERFACE,
447 "Progress",
448 data->dbus_path,
449 NULL,
450 G_DBUS_SIGNAL_FLAGS_NONE,
451 miner_progress_changed,
452 data,
453 NULL);
454
455 data->paused_signal = g_dbus_connection_signal_subscribe (priv->connection,
456 data->dbus_name,
457 TRACKER_MINER_DBUS_INTERFACE,
458 "Paused",
459 data->dbus_path,
460 NULL,
461 G_DBUS_SIGNAL_FLAGS_NONE,
462 miner_paused,
463 data,
464 NULL);
465
466
467 data->resumed_signal = g_dbus_connection_signal_subscribe (priv->connection,
468 data->dbus_name,
469 TRACKER_MINER_DBUS_INTERFACE,
470 "Resumed",
471 data->dbus_path,
472 NULL,
473 G_DBUS_SIGNAL_FLAGS_NONE,
474 miner_resumed,
475 data,
476 NULL);
477
478 g_hash_table_insert (priv->miner_proxies, proxy, g_strdup (data->dbus_name));
479
480 data->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
481 data->dbus_name,
482 G_BUS_NAME_WATCHER_FLAGS_NONE,
483 miner_appears,
484 miner_disappears,
485 data,
486 NULL);
487
488 }
489
490 return TRUE;
491 }
492
493 static void
494 miner_manager_initable_iface_init (GInitableIface *iface)
495 {
496 iface->init = miner_manager_initable_init;
497 }
498
499
500 static void
501 miner_data_free (MinerData *data)
502 {
503 if (data->watch_name_id != 0) {
504 g_bus_unwatch_name (data->watch_name_id);
505 }
506
507 if (data->progress_signal) {
508 g_dbus_connection_signal_unsubscribe (data->connection,
509 data->progress_signal);
510 }
511
512 if (data->paused_signal) {
513 g_dbus_connection_signal_unsubscribe (data->connection,
514 data->paused_signal);
515 }
516
517 if (data->resumed_signal) {
518 g_dbus_connection_signal_unsubscribe (data->connection,
519 data->resumed_signal);
520 }
521
522 if (data->connection) {
523 g_object_unref (data->connection);
524 }
525
526 if (data->manager) {
527 g_object_weak_unref (data->manager, data_manager_weak_notify, data);
528 }
529
530 g_free (data->dbus_path);
531 g_free (data->display_name);
532 g_slice_free (MinerData, data);
533 }
534
535 static void
536 miner_manager_finalize (GObject *object)
537 {
538 TrackerMinerManagerPrivate *priv;
539
540 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (object);
541
542 if (priv->connection) {
543 g_object_unref (priv->connection);
544 }
545
546 g_list_foreach (priv->miners, (GFunc) miner_data_free, NULL);
547 g_list_free (priv->miners);
548 g_hash_table_unref (priv->miner_proxies);
549
550 G_OBJECT_CLASS (tracker_miner_manager_parent_class)->finalize (object);
551 }
552
553 /**
554 * tracker_miner_manager_new:
555 *
556 * Creates a new #TrackerMinerManager instance.
557 *
558 * Note: Auto-starting miners when querying status will be enabled.
559 *
560 * Returns: a #TrackerMinerManager or #NULL if an error happened.
561 *
562 * Since: 0.8
563 **/
564 TrackerMinerManager *
565 tracker_miner_manager_new (void)
566 {
567 GError *inner_error = NULL;
568 TrackerMinerManager *manager;
569
570 manager = g_initable_new (TRACKER_TYPE_MINER_MANAGER,
571 NULL,
572 &inner_error,
573 NULL);
574 if (!manager) {
575 g_critical ("Couldn't create new TrackerMinerManager: '%s'",
576 inner_error ? inner_error->message : "unknown error");
577 g_clear_error (&inner_error);
578 }
579
580 return manager;
581 }
582
583 /**
584 * tracker_miner_manager_new_full:
585 * @auto_start: Flag to disable auto-starting the miners when querying status
586 * @error: a #GError to report errors.
587 *
588 * Creates a new #TrackerMinerManager.
589 *
590 * Returns: a #TrackerMinerManager. On error, #NULL is returned and @error is set
591 * accordingly.
592 *
593 * Since: 0.10.5
594 **/
595 TrackerMinerManager *
596 tracker_miner_manager_new_full (gboolean auto_start,
597 GError **error)
598 {
599 GError *inner_error = NULL;
600 TrackerMinerManager *manager;
601
602 manager = g_initable_new (TRACKER_TYPE_MINER_MANAGER,
603 NULL,
604 &inner_error,
605 "auto-start", auto_start,
606 NULL);
607 if (inner_error)
608 g_propagate_error (error, inner_error);
609
610 return manager;
611 }
612
613 /**
614 * tracker_miner_manager_get_running:
615 * @manager: a #trackerMinerManager
616 *
617 * Returns a list of references for all active miners. Active miners
618 * are miners which are running within a process.
619 *
620 * Returns: (transfer full) (element-type utf8): a #GSList which must
621 * be freed with g_slist_free() and all contained data with g_free().
622 * Otherwise %NULL is returned if there are no miners.
623 *
624 * Since: 0.8
625 **/
626 GSList *
627 tracker_miner_manager_get_running (TrackerMinerManager *manager)
628 {
629 TrackerMinerManagerPrivate *priv;
630 GSList *list = NULL;
631 GError *error = NULL;
632 GVariant *v;
633 GVariantIter *iter;
634 const gchar *str = NULL;
635
636 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), NULL);
637
638 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
639
640 if (!priv->connection) {
641 return NULL;
642 }
643
644 v = g_dbus_connection_call_sync (priv->connection,
645 "org.freedesktop.DBus",
646 "/org/freedesktop/DBus",
647 "org.freedesktop.DBus",
648 "ListNames",
649 NULL,
650 G_VARIANT_TYPE ("(as)"),
651 G_DBUS_CALL_FLAGS_NONE,
652 -1,
653 NULL,
654 &error);
655
656 if (error) {
657 g_critical ("Could not get a list of names registered on the session bus, %s",
658 error ? error->message : "no error given");
659 g_clear_error (&error);
660 return NULL;
661 }
662
663 g_variant_get (v, "(as)", &iter);
664 while (g_variant_iter_loop (iter, "&s", &str)) {
665 if (!g_str_has_prefix (str, TRACKER_MINER_DBUS_NAME_PREFIX)) {
666 continue;
667 }
668
669 /* Special case miner-fs which has
670 * additional D-Bus interface.
671 */
672 if (strcmp (str, "org.freedesktop.Tracker1.Miner.Files.Index") == 0) {
673 continue;
674 }
675
676 list = g_slist_prepend (list, g_strdup (str));
677 }
678
679 g_variant_iter_free (iter);
680 g_variant_unref (v);
681
682 list = g_slist_reverse (list);
683
684 return list;
685 }
686
687 static gboolean
688 crawler_check_file_cb (TrackerCrawler *crawler,
689 GFile *file,
690 gpointer user_data)
691 {
692 TrackerMinerManager *manager;
693 TrackerMinerManagerPrivate *priv;
694 GKeyFile *key_file;
695 gchar *path, *dbus_path, *dbus_name, *display_name, *description;
696 GError *error = NULL;
697 MinerData *data;
698
699 manager = user_data;
700 path = g_file_get_path (file);
701 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
702
703 if (!g_str_has_suffix (path, ".desktop")) {
704 return FALSE;
705 }
706
707 key_file = g_key_file_new ();
708 g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
709
710 if (error) {
711 g_warning ("Error parsing miner .desktop file: %s", error->message);
712 g_error_free (error);
713 g_key_file_free (key_file);
714
715 return FALSE;
716 }
717
718 dbus_path = g_key_file_get_string (key_file, DESKTOP_ENTRY_GROUP, DBUS_PATH_KEY, NULL);
719 dbus_name = g_key_file_get_string (key_file, DESKTOP_ENTRY_GROUP, DBUS_NAME_KEY, NULL);
720 display_name = g_key_file_get_locale_string (key_file, DESKTOP_ENTRY_GROUP, DISPLAY_NAME_KEY, NULL, NULL);
721
722 if (!dbus_path || !dbus_name || !display_name) {
723 g_warning ("Essential data (DBusPath, DBusName or Name) are missing in miner .desktop file");
724 g_key_file_free (key_file);
725 g_free (dbus_path);
726 g_free (display_name);
727 g_free (dbus_name);
728
729 return FALSE;
730 }
731
732 description = g_key_file_get_locale_string (key_file, DESKTOP_ENTRY_GROUP, DESCRIPTION_KEY, NULL, NULL);
733
734 data = g_slice_new0 (MinerData);
735 data->dbus_path = dbus_path;
736 data->dbus_name = dbus_name;
737 data->display_name = display_name;
738 data->description = description;
739
740 priv->miners = g_list_prepend (priv->miners, data);
741
742 g_key_file_free (key_file);
743 g_free (path);
744
745 return TRUE;
746 }
747
748 static void
749 crawler_finished_cb (TrackerCrawler *crawler,
750 gboolean was_interrupted,
751 gpointer user_data)
752 {
753 g_main_loop_quit (user_data);
754 }
755
756 static void
757 initialize_miners_data (TrackerMinerManager *manager)
758 {
759 GMainLoop *main_loop;
760 GFile *file;
761 TrackerCrawler *crawler;
762 const gchar *miners_dir;
763
764 crawler = tracker_crawler_new ();
765 main_loop = g_main_loop_new (NULL, FALSE);
766
767 g_signal_connect (crawler, "check-file",
768 G_CALLBACK (crawler_check_file_cb),
769 manager);
770 g_signal_connect (crawler, "finished",
771 G_CALLBACK (crawler_finished_cb),
772 main_loop);
773
774 /* Go through service files */
775 miners_dir = g_getenv ("TRACKER_MINERS_DIR");
776 if (G_LIKELY (miners_dir == NULL)) {
777 miners_dir = TRACKER_MINERS_DIR;
778 } else {
779 g_message ("Crawling miners in '%s' (set in env)", miners_dir);
780 }
781
782 file = g_file_new_for_path (miners_dir);
783 tracker_crawler_start (crawler, file, TRUE);
784 g_object_unref (file);
785
786 g_main_loop_run (main_loop);
787
788 g_main_loop_unref (main_loop);
789 g_object_unref (crawler);
790 }
791
792 /**
793 * tracker_miner_manager_get_available:
794 * @manager: a #TrackerMinerManager
795 *
796 * Returns a list of references for all available miners. Available
797 * miners are miners which may or may not be running in a process at
798 * the current time.
799 *
800 * Returns: (transfer full) (element-type utf8): a #GSList which must
801 * be freed with g_slist_free() and all contained data with g_free().
802 * Otherwise %NULL is returned if there are no miners.
803 *
804 * Since: 0.8
805 **/
806 GSList *
807 tracker_miner_manager_get_available (TrackerMinerManager *manager)
808 {
809 TrackerMinerManagerPrivate *priv;
810 GSList *list = NULL;
811 GList *m;
812
813 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
814
815 for (m = priv->miners; m; m = m->next) {
816 MinerData *data = m->data;
817
818 list = g_slist_prepend (list, g_strdup (data->dbus_name));
819 }
820
821 return g_slist_reverse (list);
822 }
823
824 /**
825 * tracker_miner_manager_pause:
826 * @manager: a #TrackerMinerManager.
827 * @miner: miner reference
828 * @reason: reason to pause
829 * @cookie: (out) (allow-none): return location for the pause cookie ID
830 *
831 * Asks @miner to pause. a miner could be paused by
832 * several reasons, and its activity won't be resumed
833 * until all pause requests have been resumed.
834 *
835 * Returns: %TRUE if the miner was paused successfully, otherwise
836 * %FALSE.
837 *
838 * Since: 0.8
839 **/
840 gboolean
841 tracker_miner_manager_pause (TrackerMinerManager *manager,
842 const gchar *miner,
843 const gchar *reason,
844 guint32 *cookie)
845 {
846 GDBusProxy *proxy;
847 const gchar *app_name;
848 GError *error = NULL;
849 GVariant *v;
850
851 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
852 g_return_val_if_fail (miner != NULL, FALSE);
853 g_return_val_if_fail (reason != NULL, FALSE);
854
855 proxy = find_miner_proxy (manager, miner, TRUE);
856
857 if (!proxy) {
858 g_critical ("No D-Bus proxy found for miner '%s'", miner);
859 return FALSE;
860 }
861
862 /* Find a reasonable app name */
863 app_name = g_get_application_name ();
864
865 if (!app_name) {
866 app_name = g_get_prgname ();
867 }
868
869 if (!app_name) {
870 app_name = "TrackerMinerManager client";
871 }
872
873 v = g_dbus_proxy_call_sync (proxy,
874 "Pause",
875 g_variant_new ("(ss)", app_name, reason),
876 G_DBUS_CALL_FLAGS_NONE,
877 -1,
878 NULL,
879 &error);
880
881 if (error) {
882 g_critical ("Could not pause miner '%s': %s", miner, error->message);
883 g_error_free (error);
884 return FALSE;
885 }
886
887 if (cookie) {
888 g_variant_get (v, "(i)", cookie);
889 }
890
891 g_variant_unref (v);
892
893 return TRUE;
894 }
895
896 /**
897 * tracker_miner_manager_pause_for_process:
898 * @manager: a #TrackerMinerManager.
899 * @miner: miner reference
900 * @reason: reason to pause
901 * @cookie: (out) (allow-none): return location for the pause cookie ID
902 *
903 * This function operates exactly the same way as
904 * tracker_miner_manager_pause() with the exception that if the calling
905 * process dies, the pause is resumed. This API is useful for cases
906 * where the calling process has a risk of crashing without resuming
907 * the pause.
908 *
909 * NOTE: If you call g_object_unref() on the @manager before you
910 * intend to resume the pause and it finalizes, it will automatically
911 * resume.
912 *
913 * Returns: %TRUE if the miner was paused successfully, otherwise
914 * %FALSE.
915 *
916 * Since: 0.10.15
917 **/
918 gboolean
919 tracker_miner_manager_pause_for_process (TrackerMinerManager *manager,
920 const gchar *miner,
921 const gchar *reason,
922 guint32 *cookie)
923 {
924 GDBusProxy *proxy;
925 const gchar *app_name;
926 GError *error = NULL;
927 GVariant *v;
928
929 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
930 g_return_val_if_fail (miner != NULL, FALSE);
931 g_return_val_if_fail (reason != NULL, FALSE);
932
933 proxy = find_miner_proxy (manager, miner, TRUE);
934
935 if (!proxy) {
936 g_critical ("No D-Bus proxy found for miner '%s'", miner);
937 return FALSE;
938 }
939
940 /* Find a reasonable app name */
941 app_name = g_get_application_name ();
942
943 if (!app_name) {
944 app_name = g_get_prgname ();
945 }
946
947 if (!app_name) {
948 app_name = "TrackerMinerManager client";
949 }
950
951 v = g_dbus_proxy_call_sync (proxy,
952 "PauseForProcess",
953 g_variant_new ("(ss)", app_name, reason),
954 G_DBUS_CALL_FLAGS_NONE,
955 -1,
956 NULL,
957 &error);
958
959 if (error) {
960 g_critical ("Could not pause miner '%s': %s", miner, error->message);
961 g_error_free (error);
962 return FALSE;
963 }
964
965 if (cookie) {
966 g_variant_get (v, "(i)", cookie);
967 }
968
969 g_variant_unref (v);
970
971 return TRUE;
972 }
973
974 /**
975 * tracker_miner_manager_resume:
976 * @manager: a #TrackerMinerManager
977 * @miner: miner reference
978 * @cookie: pause cookie
979 *
980 * Tells @miner to resume activity. The miner won't actually resume
981 * operations until all pause requests have been resumed.
982 *
983 * Returns: %TRUE if the miner was successfully resumed, otherwise
984 * %FALSE.
985 *
986 * Since: 0.8
987 **/
988 gboolean
989 tracker_miner_manager_resume (TrackerMinerManager *manager,
990 const gchar *miner,
991 guint32 cookie)
992 {
993 GDBusProxy *proxy;
994 GError *error = NULL;
995 GVariant *v;
996
997 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
998 g_return_val_if_fail (miner != NULL, FALSE);
999 proxy = find_miner_proxy (manager, miner, TRUE);
1000
1001 if (!proxy) {
1002 g_critical ("No D-Bus proxy found for miner '%s'", miner);
1003 return FALSE;
1004 }
1005
1006 v = g_dbus_proxy_call_sync (proxy,
1007 "Resume",
1008 g_variant_new ("(i)", (gint) cookie),
1009 G_DBUS_CALL_FLAGS_NONE,
1010 -1,
1011 NULL,
1012 &error);
1013
1014 if (error) {
1015 g_critical ("Could not resume miner '%s': %s", miner, error->message);
1016 g_error_free (error);
1017 return FALSE;
1018 }
1019
1020 g_variant_unref (v);
1021
1022 return TRUE;
1023 }
1024
1025 /**
1026 * tracker_miner_manager_is_active:
1027 * @manager: a #TrackerMinerManager
1028 * @miner: miner reference
1029 *
1030 * Returns the miner's current activity.
1031 *
1032 * Returns: %TRUE if the @miner is active, otherwise %FALSE.
1033 *
1034 * Since: 0.8
1035 **/
1036 gboolean
1037 tracker_miner_manager_is_active (TrackerMinerManager *manager,
1038 const gchar *miner)
1039 {
1040 TrackerMinerManagerPrivate *priv;
1041 GError *error = NULL;
1042 gboolean active = FALSE;
1043 GVariant *v;
1044
1045 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
1046 g_return_val_if_fail (miner != NULL, FALSE);
1047
1048 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
1049
1050 v = g_dbus_connection_call_sync (priv->connection,
1051 "org.freedesktop.DBus",
1052 "/org/freedesktop/DBus",
1053 "org.freedesktop.DBus",
1054 "NameHasOwner",
1055 g_variant_new ("(s)", miner),
1056 (GVariantType *) "(b)",
1057 G_DBUS_CALL_FLAGS_NONE,
1058 -1,
1059 NULL,
1060 &error);
1061
1062 if (error) {
1063 g_critical ("Could not check whether miner '%s' is currently active: %s",
1064 miner, error ? error->message : "no error given");
1065 g_error_free (error);
1066 return FALSE;
1067 }
1068
1069 g_variant_get (v, "(b)", &active);
1070 g_variant_unref (v);
1071
1072 return active;
1073 }
1074
1075 /**
1076 * tracker_miner_manager_get_status:
1077 * @manager: a #TrackerMinerManager
1078 * @miner: miner reference
1079 * @status: (out) (allow-none): return location for status
1080 * @progress: (out) (allow-none): return location for progress
1081 * @remaining_time: (out) (allow-none): return location for remaining time
1082 *
1083 * Returns the current status, progress and remaining time for @miner.
1084 * @remaining_time will be 0 if not possible to compute it yet,
1085 * and less than zero if it is not applicable.
1086 *
1087 * Returns: %TRUE if the status could be retrieved successfully,
1088 * otherwise %FALSE
1089 *
1090 * Since: 0.12
1091 **/
1092 gboolean
1093 tracker_miner_manager_get_status (TrackerMinerManager *manager,
1094 const gchar *miner,
1095 gchar **status,
1096 gdouble *progress,
1097 gint *remaining_time)
1098 {
1099 GDBusProxy *proxy;
1100
1101 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
1102 g_return_val_if_fail (miner != NULL, FALSE);
1103 /* At least one of them should be asked */
1104 g_return_val_if_fail (status != NULL ||
1105 progress != NULL ||
1106 remaining_time != NULL, FALSE);
1107
1108 proxy = find_miner_proxy (manager, miner, TRUE);
1109
1110 if (!proxy) {
1111 g_critical ("No D-Bus proxy found for miner '%s'", miner);
1112 return FALSE;
1113 }
1114
1115 if (progress) {
1116 GError *error = NULL;
1117 GVariant *v;
1118
1119 v = g_dbus_proxy_call_sync (proxy,
1120 "GetProgress",
1121 NULL,
1122 G_DBUS_CALL_FLAGS_NONE,
1123 -1,
1124 NULL,
1125 &error);
1126 if (error) {
1127 /* We handle this error as a special case, some
1128 * plugins don't have .service files.
1129 */
1130 if (error->code != G_DBUS_ERROR_SERVICE_UNKNOWN) {
1131 g_critical ("Could not get miner progress for '%s': %s", miner,
1132 error->message);
1133 }
1134
1135 g_error_free (error);
1136
1137 return FALSE;
1138 }
1139
1140 g_variant_get (v, "(d)", progress);
1141 g_variant_unref (v);
1142 }
1143
1144 if (status) {
1145 GError *error = NULL;
1146 GVariant *v;
1147
1148 v = g_dbus_proxy_call_sync (proxy,
1149 "GetStatus",
1150 NULL,
1151 G_DBUS_CALL_FLAGS_NONE,
1152 -1,
1153 NULL,
1154 &error);
1155 if (error) {
1156 g_critical ("Could not get miner status for '%s': %s", miner,
1157 error->message);
1158 g_error_free (error);
1159 return FALSE;
1160 }
1161
1162 g_variant_get (v, "(s)", status);
1163 g_variant_unref (v);
1164 }
1165
1166 if (remaining_time) {
1167 GError *error = NULL;
1168 GVariant *v;
1169
1170 v = g_dbus_proxy_call_sync (proxy,
1171 "GetRemainingTime",
1172 NULL,
1173 G_DBUS_CALL_FLAGS_NONE,
1174 -1,
1175 NULL,
1176 &error);
1177 if (error) {
1178 g_critical ("Could not get miner remaining processing "
1179 "time for '%s': %s", miner,
1180 error->message);
1181 g_error_free (error);
1182 return FALSE;
1183 }
1184
1185 g_variant_get (v, "(i)", remaining_time);
1186 g_variant_unref (v);
1187 }
1188
1189 return TRUE;
1190 }
1191
1192 /**
1193 * tracker_miner_manager_is_paused:
1194 * @manager: a #TrackerMinerManager
1195 * @miner: miner reference
1196 * @applications: (out callee-allocates) (allow-none) (transfer full):
1197 * return location for application names.
1198 * @reasons: (out callee-allocates) (allow-none) (transfer full):
1199 * return location for pause reasons.
1200 *
1201 * This function either returns %FALSE if the miner is not paused,
1202 * or returns %TRUE and fills in @applications and @reasons with
1203 * the pause reasons and the applications that asked for it. Both
1204 * arrays will have the same lengh, and will be sorted so the
1205 * application/pause reason pairs have the same index.
1206 *
1207 * Returns: %TRUE if @miner is paused, otherwise %FALSE.
1208 *
1209 * Since: 0.8
1210 **/
1211 gboolean
1212 tracker_miner_manager_is_paused (TrackerMinerManager *manager,
1213 const gchar *miner,
1214 GStrv *applications,
1215 GStrv *reasons)
1216 {
1217 GDBusProxy *proxy;
1218 GStrv apps, r;
1219 GError *error = NULL;
1220 gboolean paused;
1221 GVariant *v;
1222
1223 if (applications) {
1224 *applications = NULL;
1225 }
1226
1227 if (reasons) {
1228 *reasons = NULL;
1229 }
1230
1231 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), TRUE);
1232 g_return_val_if_fail (miner != NULL, TRUE);
1233
1234 proxy = find_miner_proxy (manager, miner, TRUE);
1235
1236 if (!proxy) {
1237 g_critical ("No D-Bus proxy found for miner '%s'", miner);
1238 return FALSE;
1239 }
1240
1241 v = g_dbus_proxy_call_sync (proxy,
1242 "GetPauseDetails",
1243 NULL,
1244 G_DBUS_CALL_FLAGS_NONE,
1245 -1,
1246 NULL,
1247 &error);
1248
1249 if (error) {
1250 g_critical ("Could not get pause details for miner '%s': %s", miner,
1251 error->message);
1252 g_error_free (error);
1253 return FALSE;
1254 }
1255
1256 g_variant_get (v, "(^as^as)", &apps, &r);
1257 g_variant_unref (v);
1258
1259 paused = (g_strv_length (apps) > 0);
1260
1261 if (applications) {
1262 *applications = apps;
1263 } else {
1264 g_strfreev (apps);
1265 }
1266
1267 if (reasons) {
1268 *reasons = r;
1269 } else {
1270 g_strfreev (r);
1271 }
1272
1273 return paused;
1274 }
1275
1276 /**
1277 * tracker_miner_manager_get_display_name:
1278 * @manager: a #TrackerMinerManager
1279 * @miner: miner reference
1280 *
1281 * Returns a translated display name for @miner.
1282 *
1283 * Returns: (transfer none): A string which should not be freed or %NULL.
1284 *
1285 * Since: 0.8
1286 **/
1287 const gchar *
1288 tracker_miner_manager_get_display_name (TrackerMinerManager *manager,
1289 const gchar *miner)
1290 {
1291 TrackerMinerManagerPrivate *priv;
1292 GList *m;
1293
1294 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), NULL);
1295 g_return_val_if_fail (miner != NULL, NULL);
1296
1297 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
1298
1299 for (m = priv->miners; m; m = m->next) {
1300 MinerData *data = m->data;
1301
1302 if (strcmp (miner, data->dbus_name) == 0) {
1303 return data->display_name;
1304 }
1305 }
1306
1307 return NULL;
1308 }
1309
1310 /**
1311 * tracker_miner_manager_get_description:
1312 * @manager: a #TrackerMinerManager
1313 * @miner: miner reference
1314 *
1315 * Returns the description for the given @miner.
1316 *
1317 * Returns: (transfer none): A string which should not be freed or %NULL if none is specified.
1318 *
1319 * Since: 0.8
1320 **/
1321 const gchar *
1322 tracker_miner_manager_get_description (TrackerMinerManager *manager,
1323 const gchar *miner)
1324 {
1325 TrackerMinerManagerPrivate *priv;
1326 GList *m;
1327
1328 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), NULL);
1329 g_return_val_if_fail (miner != NULL, NULL);
1330
1331 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
1332
1333 for (m = priv->miners; m; m = m->next) {
1334 MinerData *data = m->data;
1335
1336 if (strcmp (miner, data->dbus_name) == 0) {
1337 return data->description;
1338 }
1339 }
1340
1341 return NULL;
1342 }
1343
1344 #ifndef TRACKER_DISABLE_DEPRECATED
1345
1346 /**
1347 * tracker_miner_manager_ignore_next_update:
1348 * @manager: a #TrackerMinerManager
1349 * @miner: miner reference
1350 * @urls: (in): the subjects to ignore the next updates of
1351 *
1352 * Tells the @miner to ignore any events for the next @urls. This is
1353 * used for cases where a file is updated by Tracker by the
1354 * tracker-writeback service. This API is used to avoid signalling up
1355 * the stack the changes to @urls.
1356 *
1357 * Returns: %TRUE on success, otherwise %FALSE.
1358 *
1359 * Since: 0.8
1360 *
1361 * Deprecated: 0.12
1362 **/
1363 gboolean
1364 tracker_miner_manager_ignore_next_update (TrackerMinerManager *manager,
1365 const gchar *miner,
1366 const gchar **urls)
1367 {
1368 GDBusProxy *proxy;
1369 GError *error = NULL;
1370 GVariant *v;
1371
1372 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
1373 g_return_val_if_fail (miner != NULL, FALSE);
1374
1375 proxy = find_miner_proxy (manager, miner, TRUE);
1376
1377 if (!proxy) {
1378 g_warning ("No D-Bus proxy found for miner '%s'", miner);
1379 return FALSE;
1380 }
1381
1382 v = g_dbus_proxy_call_sync (proxy,
1383 "IgnoreNextUpdate",
1384 g_variant_new ("(^as)", urls),
1385 G_DBUS_CALL_FLAGS_NONE,
1386 -1,
1387 NULL,
1388 &error);
1389
1390 if (error) {
1391 g_warning ("Could not ignore next update for miner '%s': %s", miner, error->message);
1392 g_error_free (error);
1393 return FALSE;
1394 }
1395
1396 g_variant_unref (v);
1397
1398 return TRUE;
1399 }
1400
1401 #endif /* TRACKER_DISABLE_DEPRECATED */
1402
1403 /**
1404 * tracker_miner_manager_error_quark:
1405 *
1406 * Returns: the #GQuark used to identify miner manager errors in
1407 * GError structures.
1408 *
1409 * Since: 0.8
1410 **/
1411 GQuark
1412 tracker_miner_manager_error_quark (void)
1413 {
1414 static GQuark error_quark = 0;
1415
1416 if (G_UNLIKELY (error_quark == 0)) {
1417 error_quark = g_quark_from_static_string ("tracker-miner-manager-error-quark");
1418 }
1419
1420 return error_quark;
1421 }
1422
1423 /**
1424 * tracker_miner_manager_reindex_by_mimetype:
1425 * @manager: a #TrackerMinerManager
1426 * @mimetypes: (in): an array of mimetypes (E.G. "text/plain"). All items
1427 * with a mimetype in that list will be reindexed.
1428 * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
1429 *
1430 * Tells the filesystem miner to reindex any file with a mimetype in
1431 * the @mimetypes list.
1432 *
1433 * On failure @error will be set.
1434 *
1435 * Returns: %TRUE on success, otherwise %FALSE.
1436 *
1437 * Since: 0.10
1438 **/
1439 gboolean
1440 tracker_miner_manager_reindex_by_mimetype (TrackerMinerManager *manager,
1441 const GStrv mimetypes,
1442 GError **error)
1443 {
1444 TrackerMinerManagerPrivate *priv;
1445 GVariant *v;
1446 GError *new_error = NULL;
1447
1448 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
1449 g_return_val_if_fail (mimetypes != NULL, FALSE);
1450
1451 if (!tracker_miner_manager_is_active (manager,
1452 "org.freedesktop.Tracker1.Miner.Files")) {
1453 g_set_error_literal (error,
1454 TRACKER_MINER_MANAGER_ERROR,
1455 TRACKER_MINER_MANAGER_ERROR_NOT_AVAILABLE,
1456 "Filesystem miner is not active");
1457 return FALSE;
1458 }
1459
1460 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
1461
1462 v = g_dbus_connection_call_sync (priv->connection,
1463 "org.freedesktop.Tracker1.Miner.Files.Index",
1464 "/org/freedesktop/Tracker1/Miner/Files/Index",
1465 "org.freedesktop.Tracker1.Miner.Files.Index",
1466 "ReindexMimeTypes",
1467 g_variant_new ("(^as)", mimetypes),
1468 NULL,
1469 G_DBUS_CALL_FLAGS_NONE,
1470 -1,
1471 NULL,
1472 &new_error);
1473
1474 if (new_error) {
1475 g_propagate_error (error, new_error);
1476 return FALSE;
1477 }
1478
1479 g_variant_unref (v);
1480
1481 return FALSE;
1482 }
1483
1484 static gboolean
1485 miner_manager_index_file_sync (TrackerMinerManager *manager,
1486 GFile *file,
1487 GCancellable *cancellable,
1488 GError **error)
1489 {
1490 TrackerMinerManagerPrivate *priv;
1491 gchar *uri;
1492 GVariant *v;
1493 GError *new_error = NULL;
1494
1495 if (!g_file_query_exists (file, cancellable)) {
1496 g_set_error_literal (error,
1497 TRACKER_MINER_MANAGER_ERROR,
1498 TRACKER_MINER_MANAGER_ERROR_NOENT,
1499 "File or directory does not exist");
1500 return FALSE;
1501 }
1502
1503 if (!tracker_miner_manager_is_active (manager,
1504 "org.freedesktop.Tracker1.Miner.Files")) {
1505 g_set_error_literal (error,
1506 TRACKER_MINER_MANAGER_ERROR,
1507 TRACKER_MINER_MANAGER_ERROR_NOT_AVAILABLE,
1508 "Filesystem miner is not active");
1509 return FALSE;
1510 }
1511
1512 priv = TRACKER_MINER_MANAGER_GET_PRIVATE (manager);
1513
1514 uri = g_file_get_uri (file);
1515
1516 v = g_dbus_connection_call_sync (priv->connection,
1517 "org.freedesktop.Tracker1.Miner.Files.Index",
1518 "/org/freedesktop/Tracker1/Miner/Files/Index",
1519 "org.freedesktop.Tracker1.Miner.Files.Index",
1520 "IndexFile",
1521 g_variant_new ("(s)", uri),
1522 NULL,
1523 G_DBUS_CALL_FLAGS_NONE,
1524 -1,
1525 cancellable,
1526 &new_error);
1527
1528 g_free (uri);
1529
1530 if (new_error) {
1531 g_propagate_error (error, new_error);
1532 return FALSE;
1533 }
1534
1535 g_variant_unref (v);
1536
1537 return FALSE;
1538 }
1539
1540 static void
1541 miner_manager_index_file_thread (GTask *task,
1542 gpointer source_object,
1543 gpointer task_data,
1544 GCancellable *cancellable)
1545 {
1546 TrackerMinerManager *manager = source_object;
1547 GFile *file = task_data;
1548 GError *error = NULL;
1549
1550 miner_manager_index_file_sync (manager, file, cancellable, &error);
1551 if (error != NULL) {
1552 g_task_return_error (task, error);
1553 } else {
1554 g_task_return_boolean (task, TRUE);
1555 }
1556 }
1557
1558 /**
1559 * tracker_miner_manager_index_file:
1560 * @manager: a #TrackerMinerManager
1561 * @file: a URL valid in GIO of a file to give to the miner for processing
1562 * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
1563 *
1564 * Tells the filesystem miner to index the @file.
1565 *
1566 * On failure @error will be set.
1567 *
1568 * Returns: %TRUE on success, otherwise %FALSE.
1569 *
1570 * Since: 0.10
1571 **/
1572 gboolean
1573 tracker_miner_manager_index_file (TrackerMinerManager *manager,
1574 GFile *file,
1575 GError **error)
1576 {
1577 g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
1578 g_return_val_if_fail (G_IS_FILE (file), FALSE);
1579
1580 return miner_manager_index_file_sync (manager, file, NULL, error);
1581 }
1582
1583 /**
1584 * tracker_miner_manager_index_file_async:
1585 * @manager: a #TrackerMinerManager
1586 * @file: a URL valid in GIO of a file to give to the miner for processing
1587 * @cancellable: (allow-none): a #GCancellable, or %NULL
1588 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
1589 * @user_data: the data to pass to the callback function
1590 *
1591 * Tells the filesystem miner to index the @file. When the operation is called,
1592 * @callback will be called. You can then call tracker_miner_manager_index_file_finish()
1593 * to get the result of the operation.
1594 *
1595 * Since: 0.16
1596 **/
1597 void
1598 tracker_miner_manager_index_file_async (TrackerMinerManager *manager,
1599 GFile *file,
1600 GCancellable *cancellable,
1601 GAsyncReadyCallback callback,
1602 gpointer user_data)
1603 {
1604 GTask *task = g_task_new (manager, cancellable, callback, user_data);
1605 g_task_set_task_data (task, g_object_ref (file), (GDestroyNotify) g_object_unref);
1606 g_task_run_in_thread (task, miner_manager_index_file_thread);
1607 g_object_unref (task);
1608 }
1609
1610 /**
1611 * tracker_miner_manager_index_file_finish:
1612 * @manager: a #TrackerMinerManager
1613 * @result: a #GAsyncResult
1614 * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
1615 *
1616 * Finishes a request to index a file. See tracker_miner_manager_index_file_async()
1617 *
1618 * On failure @error will be set.
1619 *
1620 * Returns: %TRUE on success, otherwise %FALSE.
1621 *
1622 * Since: 0.16
1623 **/
1624 gboolean
1625 tracker_miner_manager_index_file_finish (TrackerMinerManager *manager,
1626 GAsyncResult *result,
1627 GError **error)
1628 {
1629 return g_task_propagate_boolean (G_TASK (result), error);
1630 }