1 /*
2 * Copyright (C) 2010 Nokia <ivan.frade@nokia.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program 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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #include <glib/gi18n.h>
23
24 #include <libtracker-common/tracker-common.h>
25 #include <libtracker-miner/tracker-miner.h>
26
27 #include "tracker-control.h"
28
29 /* Note:
30 * Every time a new option is added, make sure it is considered in the
31 * 'MINERS_OPTIONS_ENABLED' macro below
32 */
33 static const gchar **reindex_mime_types;
34 static gchar *index_file;
35 static gchar *miner_name;
36 static gchar *pause_reason;
37 static gchar *pause_for_process_reason;
38 static gint resume_cookie = -1;
39 static gboolean list_miners_running;
40 static gboolean list_miners_available;
41 static gboolean pause_details;
42
43 #define MINERS_OPTIONS_ENABLED() \
44 (reindex_mime_types || \
45 index_file || \
46 miner_name || \
47 pause_reason || \
48 pause_for_process_reason || \
49 resume_cookie != -1 || \
50 list_miners_running || \
51 list_miners_available || \
52 pause_details)
53
54 static GOptionEntry entries[] = {
55 { "reindex-mime-type", 'm', 0, G_OPTION_ARG_STRING_ARRAY, &reindex_mime_types,
56 N_("Tell miners to reindex files which match the mime type supplied (for new extractors), use -m MIME1 -m MIME2"),
57 N_("MIME") },
58 { "index-file", 'f', 0, G_OPTION_ARG_FILENAME, &index_file,
59 N_("Tell miners to (re)index a given file"),
60 N_("FILE") },
61 { "pause", 0 , 0, G_OPTION_ARG_STRING, &pause_reason,
62 N_("Pause a miner (you must use this with --miner)"),
63 N_("REASON")
64 },
65 { "pause-for-process", 0 , 0, G_OPTION_ARG_STRING, &pause_for_process_reason,
66 N_("Pause a miner while the calling process is alive or until resumed (you must use this with --miner)"),
67 N_("REASON")
68 },
69 { "resume", 0 , 0, G_OPTION_ARG_INT, &resume_cookie,
70 N_("Resume a miner (you must use this with --miner)"),
71 N_("COOKIE")
72 },
73 { "miner", 0 , 0, G_OPTION_ARG_STRING, &miner_name,
74 N_("Miner to use with --resume or --pause (you can use suffixes, e.g. Files or Applications)"),
75 N_("MINER")
76 },
77 { "list-miners-running", 'l', 0, G_OPTION_ARG_NONE, &list_miners_running,
78 N_("List all miners currently running"),
79 NULL
80 },
81 { "list-miners-available", 'a', 0, G_OPTION_ARG_NONE, &list_miners_available,
82 N_("List all miners installed"),
83 NULL
84 },
85 { "pause-details", 'i', 0, G_OPTION_ARG_NONE, &pause_details,
86 N_("List pause reasons"),
87 NULL
88 },
89 { NULL }
90 };
91
92 gboolean
93 tracker_control_miners_options_enabled (void)
94 {
95 return MINERS_OPTIONS_ENABLED ();
96 }
97
98 static gint
99 miner_pause (const gchar *miner,
100 const gchar *reason,
101 gboolean for_process)
102 {
103 TrackerMinerManager *manager;
104 GError *error = NULL;
105 gchar *str;
106 gint cookie;
107
108 /* Don't auto-start the miners here */
109 manager = tracker_miner_manager_new_full (FALSE, &error);
110 if (!manager) {
111 g_printerr (_("Could not pause miner, manager could not be created, %s"),
112 error ? error->message : "unknown error");
113 g_printerr ("\n");
114 g_clear_error (&error);
115 return EXIT_FAILURE;
116 }
117
118 str = g_strdup_printf (_("Attempting to pause miner '%s' with reason '%s'"),
119 miner,
120 reason);
121 g_print ("%s\n", str);
122 g_free (str);
123
124 if (for_process) {
125 if (!tracker_miner_manager_pause_for_process (manager, miner, reason, &cookie)) {
pointer targets in passing argument 4 of 'tracker_miner_manager_pause_for_process' differ in signedness
(emitted by gcc)
126 g_printerr (_("Could not pause miner: %s"), miner);
127 g_printerr ("\n");
128 return EXIT_FAILURE;
129 }
130 } else {
131 if (!tracker_miner_manager_pause (manager, miner, reason, &cookie)) {
132 g_printerr (_("Could not pause miner: %s"), miner);
133 g_printerr ("\n");
134 return EXIT_FAILURE;
135 }
136 }
137
138 str = g_strdup_printf (_("Cookie is %d"), cookie);
139 g_print (" %s\n", str);
140 g_free (str);
141
142 if (for_process) {
143 GMainLoop *main_loop;
144
145 g_print ("%s\n", _("Press Ctrl+C to end pause"));
146
147 main_loop = g_main_loop_new (NULL, FALSE);
148 /* Block until Ctrl+C */
149 g_main_loop_run (main_loop);
150 g_object_unref (main_loop);
151 }
152
153 g_object_unref (manager);
154
155 return EXIT_SUCCESS;
156 }
157
158 static gint
159 miner_resume (const gchar *miner,
160 gint cookie)
161 {
162 TrackerMinerManager *manager;
163 GError *error = NULL;
164 gchar *str;
165
166 /* Don't auto-start the miners here */
167 manager = tracker_miner_manager_new_full (FALSE, &error);
168 if (!manager) {
169 g_printerr (_("Could not resume miner, manager could not be created, %s"),
170 error ? error->message : "unknown error");
171 g_printerr ("\n");
172 g_clear_error (&error);
173 return EXIT_FAILURE;
174 }
175
176 str = g_strdup_printf (_("Attempting to resume miner %s with cookie %d"),
177 miner,
178 cookie);
179 g_print ("%s\n", str);
180 g_free (str);
181
182 if (!tracker_miner_manager_resume (manager, miner, cookie)) {
183 g_printerr (_("Could not resume miner: %s"), miner);
184 return EXIT_FAILURE;
185 }
186
187 g_print (" %s\n", _("Done"));
188
189 g_object_unref (manager);
190
191 return EXIT_SUCCESS;
192 }
193
194 static gint
195 miner_reindex_mime_types (const gchar **mime_types)
196 {
197 GError *error = NULL;
198 TrackerMinerManager *manager;
199
200 /* Auto-start the miners here if we need to */
201 manager = tracker_miner_manager_new_full (TRUE, &error);
202 if (!manager) {
203 g_printerr (_("Could not reindex mimetypes, manager could not be created, %s"),
204 error ? error->message : "unknown error");
205 g_printerr ("\n");
206 g_clear_error (&error);
207 return EXIT_FAILURE;
208 }
209
210 tracker_miner_manager_reindex_by_mimetype (manager, (GStrv)reindex_mime_types, &error);
211 if (error) {
212 g_printerr ("%s: %s\n",
213 _("Could not reindex mimetypes"),
214 error->message);
215 g_error_free (error);
216 return EXIT_FAILURE;
217 }
218
219 g_print ("%s\n", _("Reindexing mime types was successful"));
220 g_object_unref (manager);
221
222 return EXIT_SUCCESS;
223 }
224
225 static gint
226 miner_index_file (const gchar *filepath)
227 {
228 TrackerMinerManager *manager;
229 GError *error = NULL;
230 GFile *file;
231
232 /* Auto-start the miners here if we need to */
233 manager = tracker_miner_manager_new_full (TRUE, &error);
234 if (!manager) {
235 g_printerr (_("Could not (re)index file, manager could not be created, %s"),
236 error ? error->message : "unknown error");
237 g_printerr ("\n");
238 g_clear_error (&error);
239 return EXIT_FAILURE;
240 }
241
242 file = g_file_new_for_commandline_arg (index_file);
243
244 tracker_miner_manager_index_file (manager, file, &error);
245
246 if (error) {
247 g_printerr ("%s: %s\n",
248 _("Could not (re)index file"),
249 error->message);
250 g_error_free (error);
251 return EXIT_FAILURE;
252 }
253
254 g_print ("%s\n", _("(Re)indexing file was successful"));
255
256 g_object_unref (manager);
257 g_object_unref (file);
258
259 return EXIT_SUCCESS;
260 }
261
262 static gint
263 miner_list (gboolean available,
264 gboolean running)
265 {
266 TrackerMinerManager *manager;
267 GError *error = NULL;
268
269 /* Don't auto-start the miners here */
270 manager = tracker_miner_manager_new_full (FALSE, &error);
271 if (!manager) {
272 g_printerr (_("Could not list miners, manager could not be created, %s"),
273 error ? error->message : "unknown error");
274 g_printerr ("\n");
275 g_clear_error (&error);
276 return EXIT_FAILURE;
277 }
278
279 if (available) {
280 GSList *miners_available;
281 gchar *str;
282 GSList *l;
283
284 miners_available = tracker_miner_manager_get_available (manager);
285
286 str = g_strdup_printf (ngettext ("Found %d miner installed",
287 "Found %d miners installed",
288 g_slist_length (miners_available)),
289 g_slist_length (miners_available));
290
291 g_print ("%s%s\n", str, g_slist_length (miners_available) > 0 ? ":" : "");
292 g_free (str);
293
294 for (l = miners_available; l; l = l->next) {
295 g_print (" %s\n", (gchar*) l->data);
296 }
297
298 g_slist_foreach (miners_available, (GFunc) g_free, NULL);
299 g_slist_free (miners_available);
300 }
301
302 if (running) {
303 GSList *miners_running;
304 gchar *str;
305 GSList *l;
306
307 miners_running = tracker_miner_manager_get_running (manager);
308
309 str = g_strdup_printf (ngettext ("Found %d miner running",
310 "Found %d miners running",
311 g_slist_length (miners_running)),
312 g_slist_length (miners_running));
313
314 g_print ("%s%s\n", str, g_slist_length (miners_running) > 0 ? ":" : "");
315 g_free (str);
316
317 for (l = miners_running; l; l = l->next) {
318 g_print (" %s\n", (gchar*) l->data);
319 }
320
321 g_slist_foreach (miners_running, (GFunc) g_free, NULL);
322 g_slist_free (miners_running);
323 }
324
325 g_object_unref (manager);
326
327 return EXIT_SUCCESS;
328 }
329
330 static gint
331 miner_pause_details (void)
332 {
333 TrackerMinerManager *manager;
334 GError *error = NULL;
335 GSList *miners_running, *l;
336 gint paused_miners = 0;
337
338 /* Don't auto-start the miners here */
339 manager = tracker_miner_manager_new_full (FALSE, &error);
340 if (!manager) {
341 g_printerr (_("Could not get pause details, manager could not be created, %s"),
342 error ? error->message : "unknown error");
343 g_printerr ("\n");
344 g_clear_error (&error);
345 return EXIT_FAILURE;
346 }
347
348 miners_running = tracker_miner_manager_get_running (manager);
349
350 if (!miners_running) {
351 g_print ("%s\n", _("No miners are running"));
352
353 g_slist_foreach (miners_running, (GFunc) g_free, NULL);
354 g_slist_free (miners_running);
355 g_object_unref (manager);
356
357 return EXIT_SUCCESS;
358 }
359
360 for (l = miners_running; l; l = l->next) {
361 const gchar *name;
362 GStrv pause_applications, pause_reasons;
363 gint i;
364
365 name = tracker_miner_manager_get_display_name (manager, l->data);
366
367 if (!name) {
368 g_critical ("Could not get name for '%s'", (gchar *) l->data);
369 continue;
370 }
371
372 tracker_miner_manager_is_paused (manager,
373 l->data,
374 &pause_applications,
375 &pause_reasons);
376
377 if (!pause_applications || !pause_reasons) {
378 /* unable to get pause details,
379 already logged by tracker_miner_manager_is_paused */
380 continue;
381 }
382
383 if (!(*pause_applications) || !(*pause_reasons)) {
384 g_strfreev (pause_applications);
385 g_strfreev (pause_reasons);
386 continue;
387 }
388
389 paused_miners++;
390 if (paused_miners == 1) {
391 g_print ("%s:\n", _("Miners"));
392 }
393
394 g_print (" %s:\n", name);
395
396 for (i = 0; pause_applications[i] != NULL; i++) {
397 g_print (" %s: '%s', %s: '%s'\n",
398 _("Application"),
399 pause_applications[i],
400 _("Reason"),
401 pause_reasons[i]);
402 }
403
404 g_strfreev (pause_applications);
405 g_strfreev (pause_reasons);
406 }
407
408 if (paused_miners < 1) {
409 g_print ("%s\n", _("No miners are paused"));
410 }
411
412 g_slist_foreach (miners_running, (GFunc) g_free, NULL);
413 g_slist_free (miners_running);
414
415 g_object_unref (manager);
416
417 return EXIT_SUCCESS;
418 }
419
420 void
421 tracker_control_miners_run_default (void)
422 {
423 /* No miners output in the default run */
424 }
425
426 gint
427 tracker_control_miners_run (void)
428 {
429 /* Constraints */
430
431 if (pause_reason && resume_cookie != -1) {
432 g_printerr ("%s\n",
433 _("You can not use miner pause and resume switches together"));
434 return EXIT_FAILURE;
435 }
436
437 if ((pause_reason || pause_for_process_reason || resume_cookie != -1) && !miner_name) {
438 g_printerr ("%s\n",
439 _("You must provide the miner for pause or resume commands"));
440 return EXIT_FAILURE;
441 }
442
443 if ((!pause_reason && !pause_for_process_reason && resume_cookie == -1) && miner_name) {
444 g_printerr ("%s\n",
445 _("You must provide a pause or resume command for the miner"));
446 return EXIT_FAILURE;
447 }
448
449 /* Known actions */
450
451 if (list_miners_running || list_miners_available) {
452 return miner_list (list_miners_available,
453 list_miners_running);
454 }
455
456 if (reindex_mime_types) {
457 return miner_reindex_mime_types (reindex_mime_types);
458 }
459
460 if (index_file) {
461 return miner_index_file (index_file);
462 }
463
464 if (pause_reason) {
465 return miner_pause (miner_name, pause_reason, FALSE);
466 }
467
468 if (pause_for_process_reason) {
469 return miner_pause (miner_name, pause_for_process_reason, TRUE);
470 }
471
472 if (resume_cookie != -1) {
473 return miner_resume (miner_name, resume_cookie);
474 }
475
476 if (pause_details) {
477 return miner_pause_details ();
478 }
479
480 /* All known options have their own exit points */
481 g_warn_if_reached ();
482
483 return EXIT_FAILURE;
484 }
485
486 GOptionGroup *
487 tracker_control_miners_get_option_group (void)
488 {
489 GOptionGroup *group;
490
491 /* Status options */
492 group = g_option_group_new ("miners",
493 _("Miner options"),
494 _("Show miner options"),
495 NULL,
496 NULL);
497 g_option_group_add_entries (group, entries);
498
499 return group;
500 }