1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * anjuta_trunk
4  * Copyright (C) Massimo Cora' 2008 <maxcvs@email.it>
5  *
6  * anjuta_trunk is free software.
7  *
8  * You may redistribute it and/or modify it under the terms of the
9  * GNU General Public License, as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * anjuta_trunk is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with anjuta_trunk.  If not, write to:
20  * 	The Free Software Foundation, Inc.,
21  * 	51 Franklin Street, Fifth Floor
22  * 	Boston, MA  02110-1301, USA.
23  */
24 
25 
26 #include "symbol-db-system.h"
27 #include "plugin.h"
28 
29 #include <glib.h>
30 #include <glib/gstdio.h>
31 #include <libanjuta/anjuta-debug.h>
32 #include <libanjuta/anjuta-launcher.h>
33 #include <libanjuta/interfaces/ianjuta-language.h>
34 #include <string.h>
35 
36 struct _SymbolDBSystemPriv
37 {
38 	AnjutaLauncher  *single_package_scan_launcher;
39 	IAnjutaLanguage *lang_manager;
40 	SymbolDBEngine  *sdbe_globals;
41 
42 	GQueue *sscan_queue;
43 	GQueue *engine_queue;
44 };
45 
46 typedef struct _SingleScanData {
47 	SymbolDBSystem *sdbs;
48 	gchar *package_name;
49 	gchar *contents;
50 	gboolean engine_scan;
51 
52 	PackageParseableCallback parseable_cb;
53 	gpointer parseable_data;
54 
55 } SingleScanData;
56 
57 typedef struct _EngineScanData {
58 	SymbolDBSystem *sdbs;
59 	gchar *package_name;
60 	GList *cflags;
61 	gboolean special_abort_scan;
62 	GPtrArray *files_to_scan_array;
63 	GPtrArray *languages_array;
64 
65 } EngineScanData;
66 
67 enum
68 {
69 	SCAN_PACKAGE_START,
70 	SCAN_PACKAGE_END,
71 	SINGLE_FILE_SCAN_END,
72 	LAST_SIGNAL
73 };
74 
75 static unsigned int signals[LAST_SIGNAL] = { 0 };
76 
77 G_DEFINE_TYPE (SymbolDBSystem, sdb_system, G_TYPE_OBJECT);
78 
79 /* forward decl */
80 static void
81 on_pkg_config_exit (AnjutaLauncher * launcher, int child_pid,
82 				   int exit_status, gulong time_taken_in_seconds,
83 				   gpointer user_data);
84 
85 static void
86 on_engine_package_scan_end (SymbolDBEngine *dbe, gint process_id, gpointer user_data);
87 
88 static void
destroy_single_scan_data(SingleScanData * ss_data)89 destroy_single_scan_data (SingleScanData *ss_data)
90 {
91 	g_return_if_fail (ss_data != NULL);
92 
93 	g_free (ss_data->package_name);
94 	g_free (ss_data->contents);
95 
96 	g_free (ss_data);
97 }
98 
99 static void
destroy_engine_scan_data(EngineScanData * es_data)100 destroy_engine_scan_data (EngineScanData *es_data)
101 {
102 	if (es_data->cflags)
103 	{
104 		g_list_foreach (es_data->cflags, (GFunc)g_free, NULL);
105 		g_list_free (es_data->cflags);
106 	}
107 
108 	g_free (es_data->package_name);
109 
110 	if (es_data->special_abort_scan == TRUE)
111 	{
112 		g_ptr_array_foreach (es_data->files_to_scan_array, (GFunc)g_free, NULL);
113 		g_ptr_array_free (es_data->files_to_scan_array, TRUE);
114 
115 		g_ptr_array_foreach (es_data->languages_array, (GFunc)g_free, NULL);
116 		g_ptr_array_free (es_data->languages_array, TRUE);
117 	}
118 	g_free (es_data);
119 }
120 
121 static void
on_engine_package_single_file_scan_end(SymbolDBEngine * dbe,gpointer user_data)122 on_engine_package_single_file_scan_end (SymbolDBEngine *dbe, gpointer user_data)
123 {
124 	SymbolDBSystem *sdbs;
125 
126 	sdbs = SYMBOL_DB_SYSTEM (user_data);
127 
128 	g_signal_emit (sdbs, signals[SINGLE_FILE_SCAN_END], 0);
129 }
130 
131 static void
sdb_system_init(SymbolDBSystem * object)132 sdb_system_init (SymbolDBSystem *object)
133 {
134 	SymbolDBSystem *sdbs;
135 
136 	sdbs = SYMBOL_DB_SYSTEM (object);
137 	sdbs->priv = g_new0 (SymbolDBSystemPriv, 1);
138 
139 	/* create launcher for single global package scan */
140 	sdbs->priv->single_package_scan_launcher = anjuta_launcher_new ();
141 	anjuta_launcher_set_check_passwd_prompt (sdbs->priv->single_package_scan_launcher,
142 											 FALSE);
143 
144 	/* single scan launcher's queue */
145 	sdbs->priv->sscan_queue = g_queue_new ();
146 	sdbs->priv->engine_queue = g_queue_new ();
147 
148 }
149 
150 static void
sdb_system_finalize(GObject * object)151 sdb_system_finalize (GObject *object)
152 {
153 	SymbolDBSystem *sdbs;
154 	SymbolDBSystemPriv *priv;
155 
156 	sdbs = SYMBOL_DB_SYSTEM (object);
157 	priv = sdbs->priv;
158 
159 	/* disconnect all signals */
160 	g_signal_handlers_disconnect_by_func (G_OBJECT (priv->sdbe_globals),
161 									  on_engine_package_single_file_scan_end,
162 									  sdbs);
163 	g_signal_handlers_disconnect_matched (G_OBJECT (priv->sdbe_globals),
164 									  G_SIGNAL_MATCH_FUNC,
165 									  0,
166 									  0,
167 									  NULL,
168 									  on_engine_package_scan_end,
169 									  NULL);
170 
171 	if (priv->single_package_scan_launcher)
172 	{
173 		anjuta_launcher_reset (priv->single_package_scan_launcher);
174 		g_object_unref (priv->single_package_scan_launcher);
175 		priv->single_package_scan_launcher = NULL;
176 	}
177 
178 	/* free also the queue */
179 	g_queue_foreach (priv->sscan_queue, (GFunc)g_free, NULL);
180 	g_queue_free (priv->sscan_queue);
181 	priv->sscan_queue = NULL;
182 
183 	/* free engine queue */
184 	g_queue_foreach (priv->engine_queue, (GFunc)destroy_engine_scan_data, NULL);
185 	g_queue_free (priv->engine_queue);
186 	priv->engine_queue = NULL;
187 
188 	G_OBJECT_CLASS (sdb_system_parent_class)->finalize (object);
189 }
190 
191 static void
sdb_system_class_init(SymbolDBSystemClass * klass)192 sdb_system_class_init (SymbolDBSystemClass *klass)
193 {
194 	GObjectClass* object_class = G_OBJECT_CLASS (klass);
195 
196 	signals[SCAN_PACKAGE_START]
197 		= g_signal_new ("scan-package-start",
198 						G_OBJECT_CLASS_TYPE (object_class),
199 						G_SIGNAL_RUN_FIRST,
200 						G_STRUCT_OFFSET (SymbolDBSystemClass, scan_package_start),
201 						NULL, NULL,
202 						g_cclosure_marshal_VOID__UINT_POINTER, G_TYPE_NONE,
203 						2,
204 						G_TYPE_UINT,
205 						G_TYPE_POINTER);
206 
207 	signals[SCAN_PACKAGE_END]
208 		= g_signal_new ("scan-package-end",
209 						G_OBJECT_CLASS_TYPE (object_class),
210 						G_SIGNAL_RUN_FIRST,
211 						G_STRUCT_OFFSET (SymbolDBSystemClass, scan_package_end),
212 						NULL, NULL,
213 						g_cclosure_marshal_VOID__STRING, G_TYPE_NONE,
214 						1,
215 						G_TYPE_STRING);
216 
217 	signals[SINGLE_FILE_SCAN_END]
218 		= g_signal_new ("single-file-scan-end",
219 						G_OBJECT_CLASS_TYPE (object_class),
220 						G_SIGNAL_RUN_FIRST,
221 						G_STRUCT_OFFSET (SymbolDBSystemClass, single_file_scan_end),
222 						NULL, NULL,
223 						g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
224 
225 	object_class->finalize = sdb_system_finalize;
226 }
227 
228 /**
229  * @return GList of cflags (strings) in a format like /usr/include/my_foo_lib.
230  * @return NULL on error.
231  */
232 static GList *
sdb_system_get_normalized_cflags(const gchar * chars)233 sdb_system_get_normalized_cflags (const gchar *chars)
234 {
235 	gchar **flags;
236 	gint i;
237 	GList *good_flags;
238 	const gchar *curr_flag;
239 
240 	/* We should receive here something like
241 	* '-I/usr/include/gimp-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include'.
242 	* Split up the chars and take a decision if we like it or not.
243 	*/
244 	flags = g_strsplit (chars, " ", -1);
245 
246 	i = 0;
247 	/* if, after the while loop, good_flags is != NULL that means that we found
248 	 * some good flags to include for a future scan
249 	 */
250 	good_flags = NULL;
251 	while ((curr_flag = flags[i++]) != NULL)
252 	{
253 		/* '-I/usr/include/gimp-2.0' would be good, but '/usr/include/' wouldn't. */
254 		if (g_regex_match_simple ("\\.*/include/\\w+", curr_flag, 0, 0) == TRUE)
255 		{
256 			/* FIXME the +2. It's to skip the -I */
257 			DEBUG_PRINT ("adding %s to good_flags", curr_flag +2);
258 			/* FIXME the +2. It's to skip the -I */
259 			good_flags = g_list_prepend (good_flags, g_strdup (curr_flag + 2));
260 		}
261 	}
262 
263 	g_strfreev (flags);
264 	return good_flags;
265 }
266 
267 
268 SymbolDBSystem *
symbol_db_system_new(SymbolDBPlugin * sdb_plugin,const SymbolDBEngine * sdbe)269 symbol_db_system_new (SymbolDBPlugin *sdb_plugin,
270 					  const SymbolDBEngine *sdbe)
271 {
272 	SymbolDBSystem *sdbs;
273 	SymbolDBSystemPriv *priv;
274 
275 	g_return_val_if_fail (sdbe != NULL, NULL);
276 	sdbs = g_object_new (SYMBOL_TYPE_DB_SYSTEM, NULL);
277 
278 	priv = sdbs->priv;
279 	priv->sdbe_globals = (SymbolDBEngine*)sdbe;
280 
281 	priv->lang_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN(sdb_plugin)->shell,
282 													IAnjutaLanguage, NULL);
283 
284 	g_signal_connect (G_OBJECT (priv->sdbe_globals), "single-file-scan-end",
285 	  			G_CALLBACK (on_engine_package_single_file_scan_end), sdbs);
286 
287 	return sdbs;
288 }
289 
290 /**
291  * Check on globals db if the project 'package_name' is present or not.
292  */
293 gboolean
symbol_db_system_is_package_parsed(SymbolDBSystem * sdbs,const gchar * package_name,const gchar * package_version)294 symbol_db_system_is_package_parsed (SymbolDBSystem *sdbs,
295 								   	const gchar * package_name,
296     								const gchar * package_version)
297 {
298 	SymbolDBSystemPriv *priv;
299 
300 	g_return_val_if_fail (sdbs != NULL, FALSE);
301 	g_return_val_if_fail (package_name != NULL, FALSE);
302 
303 	priv = sdbs->priv;
304 
305 	return symbol_db_engine_project_exists (priv->sdbe_globals,
306 											package_name, package_version);
307 }
308 
309 static void
on_pkg_config_output(AnjutaLauncher * launcher,AnjutaLauncherOutputType output_type,const gchar * chars,gpointer user_data)310 on_pkg_config_output (AnjutaLauncher * launcher,
311 					AnjutaLauncherOutputType output_type,
312 					const gchar * chars, gpointer user_data)
313 {
314 	SingleScanData *ss_data;
315 
316 	if (output_type == ANJUTA_LAUNCHER_OUTPUT_STDERR)
317 	{
318 		/* no way. We don't like errors on stderr... */
319 		return;
320 	}
321 
322 	ss_data = (SingleScanData *)user_data;
323 
324 	if (ss_data->contents != NULL)
325 	{
326 		gchar *to_be_freed;
327 		to_be_freed = ss_data->contents;
328 
329 		/* concatenate the output to the relative package's object */
330 		ss_data->contents = g_strconcat (ss_data->contents, chars, NULL);
331 		g_free (to_be_freed);
332 	}
333 	else
334 	{
335 		ss_data->contents = g_strdup (chars);
336 	}
337 }
338 
339 static GList **
sdb_system_files_visit_dir(GList ** files_list,GFile * file)340 sdb_system_files_visit_dir (GList **files_list, GFile *file)
341 {
342 	GFileEnumerator *enumerator;
343 
344 	if ((enumerator = g_file_enumerate_children (file, "standard::name,standard::type",
345 												G_FILE_QUERY_INFO_NONE, NULL, NULL)))
346 	{
347 		GFileInfo *info;
348 
349 		info = g_file_enumerator_next_file (enumerator, NULL, NULL);
350 		while (info)
351 		{
352 			GFileType type;
353 			GFile *child_file;
354 
355 			type = g_file_info_get_file_type (info);
356 			child_file = g_file_resolve_relative_path (file, g_file_info_get_name (info));
357 
358 			if (type == G_FILE_TYPE_DIRECTORY)
359 			{
360 				/* recurse */
361 				files_list = sdb_system_files_visit_dir (files_list, child_file);
362 
363 				g_object_unref (child_file);
364 			}
365 			else
366 				*files_list = g_list_prepend (*files_list, child_file);
367 
368 			g_object_unref (info);
369 
370 			info = g_file_enumerator_next_file (enumerator, NULL, NULL);
371 		}
372 
373 		g_object_unref (enumerator);
374 	}
375 
376 	return files_list;
377 }
378 
379 static void
prepare_files_to_be_scanned(SymbolDBSystem * sdbs,GList * cflags,GPtrArray * OUT_files_to_scan_array,GPtrArray * OUT_languages_array)380 prepare_files_to_be_scanned (SymbolDBSystem *sdbs,
381 							 GList *cflags,
382 							 GPtrArray *OUT_files_to_scan_array,
383 							 GPtrArray *OUT_languages_array)
384 {
385 	SymbolDBSystemPriv *priv;
386 	GList *node;
387 
388 	priv = sdbs->priv;
389 	node = cflags;
390 
391 	do
392 	{
393 		GList *files_tmp_list = NULL;
394 		GFile *file;
395 
396 
397 		file = g_file_new_for_path ((gchar *)node->data);
398 
399 		/* files_tmp_list needs to be freed */
400 		sdb_system_files_visit_dir (&files_tmp_list, file);
401 		g_object_unref (file);
402 
403 		if (files_tmp_list != NULL)
404 		{
405 			/* last loop here. With files_visit_dir we'll retrieve all files nodes
406 			 * under the passed directory
407 			 */
408 			GList *tmp_node;
409 			tmp_node = files_tmp_list;
410 			do {
411 				GFileInfo *info;
412 
413 				if ((info = g_file_query_info ((GFile *)tmp_node->data, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
414 											  G_FILE_QUERY_INFO_NONE, NULL, NULL)))
415 				{
416 					IAnjutaLanguageId lang_id;
417 					const char *lang;
418 
419 					lang_id = ianjuta_language_get_from_mime_type (priv->lang_manager,
420 																   g_file_info_get_content_type (info),
421 																   NULL);
422 
423 					g_object_unref (info);
424 
425 					/* No supported language... */
426 					if (!lang_id)
427 					{
428 						continue;
429 					}
430 
431 					lang = ianjuta_language_get_name (priv->lang_manager, lang_id, NULL);
432 
433 					g_ptr_array_add (OUT_languages_array, g_strdup (lang));
434 					g_ptr_array_add (OUT_files_to_scan_array,
435 									 g_file_get_path ((GFile *)tmp_node->data));
436 				}
437 			} while ((tmp_node = tmp_node->next) != NULL);
438 
439 			/* free the tmp files list */
440 			g_list_foreach (files_tmp_list, (GFunc)g_object_unref, NULL);
441 			g_list_free (files_tmp_list);
442 		}
443 	} while ((node = node->next) != NULL);
444 }
445 
446 static GNUC_INLINE void
sdb_system_do_scan_package_1(SymbolDBSystem * sdbs,SingleScanData * ss_data)447 sdb_system_do_scan_package_1 (SymbolDBSystem *sdbs,
448 							SingleScanData *ss_data)
449 {
450 	SymbolDBSystemPriv *priv;
451 	gchar *exe_string;
452 	priv = sdbs->priv;
453 
454 	DEBUG_PRINT ("SCANNING %s",
455 				 ss_data->package_name);
456 	exe_string = g_strdup_printf ("pkg-config --cflags %s",
457 								  ss_data->package_name);
458 
459 	g_signal_connect (G_OBJECT (priv->single_package_scan_launcher),
460 					  "child-exited", G_CALLBACK (on_pkg_config_exit), ss_data);
461 
462 	anjuta_launcher_execute (priv->single_package_scan_launcher,
463 							 	exe_string, on_pkg_config_output,
464 							 	ss_data);
465 	g_free (exe_string);
466 }
467 
468 /**
469  * Scan the next package in queue, if exists.
470  */
471 static void
sdb_system_do_scan_next_package(SymbolDBSystem * sdbs)472 sdb_system_do_scan_next_package (SymbolDBSystem *sdbs)
473 {
474 	SymbolDBSystemPriv *priv;
475 	priv = sdbs->priv;
476 
477 	if (g_queue_get_length (priv->sscan_queue) > 0)
478 	{
479 		/* get the next one without storing it into queue */
480 		SingleScanData *ss_data = g_queue_peek_head (priv->sscan_queue);
481 
482 		/* enjoy */
483 		sdb_system_do_scan_package_1 (sdbs, ss_data);
484 	}
485 }
486 
487 static GNUC_INLINE void
sdb_system_do_engine_scan(SymbolDBSystem * sdbs,EngineScanData * es_data)488 sdb_system_do_engine_scan (SymbolDBSystem *sdbs, EngineScanData *es_data)
489 {
490 	SymbolDBSystemPriv *priv;
491 	GPtrArray *files_to_scan_array;
492 	GPtrArray *languages_array;
493 	gint proc_id;
494 	gboolean special_abort_scan;
495 
496 	priv = sdbs->priv;
497 	special_abort_scan = es_data->special_abort_scan ;
498 
499 	if (special_abort_scan == FALSE)
500 	{
501 		files_to_scan_array = g_ptr_array_new ();
502 		languages_array = g_ptr_array_new();
503 
504 		/* the above arrays will be populated with this function */
505 		prepare_files_to_be_scanned (sdbs, es_data->cflags, files_to_scan_array,
506 								 languages_array);
507 
508 		symbol_db_engine_add_new_project (priv->sdbe_globals, NULL,
509 								  		es_data->package_name, "1.0");
510 	}
511 	else
512 	{
513 		files_to_scan_array = es_data->files_to_scan_array;
514 		languages_array = es_data->languages_array;
515 	}
516 
517 
518 	/* note the FALSE as last parameter: we don't want
519 	 * to re-scan an already present file. There's the possibility
520 	 * infact to have more references of the same files in different
521 	 * packages
522 	 */
523 	proc_id = symbol_db_engine_add_new_files_full_async (priv->sdbe_globals,
524 							es_data->special_abort_scan == FALSE ?
525 									es_data->package_name : NULL,
526 	    					"1.0",
527 							files_to_scan_array,
528 							languages_array,
529 							es_data->special_abort_scan == FALSE ?
530 									FALSE : TRUE);
531 
532 	if (proc_id > 0)
533 	{
534 		/* will be disconnected automatically when callback is called. */
535 		g_signal_connect (G_OBJECT (priv->sdbe_globals), "scan-end",
536  				G_CALLBACK (on_engine_package_scan_end), es_data);
537 
538 		/* notify the listeners about our intention of adding new files
539 	 	* to the db
540 	 	*/
541 		g_signal_emit (sdbs, signals[SCAN_PACKAGE_START], 0,
542 					   files_to_scan_array->len,
543 					   es_data->package_name);
544 	}
545 	/* if no scan has started destroy the engine data here */
546 	else
547 	{
548 		g_queue_remove (priv->engine_queue, es_data);
549 		destroy_engine_scan_data (es_data);
550 		es_data = NULL;
551 
552 		/* having not connected the signal to on_engine_package_scan_end () it's
553 		 * likely that the queue won't be processed more. So here it is the call
554 		 * to unlock it
555 		 */
556 		/* have we got something left in the queue? */
557 		if (g_queue_get_length (priv->engine_queue) > 0)
558 		{
559 			/* peek the head */
560 			es_data = g_queue_peek_head (priv->engine_queue);
561 
562 			DEBUG_PRINT ("adding %s", es_data->package_name);
563 			sdb_system_do_engine_scan (sdbs, es_data);
564 		}
565 	}
566 
567 	if (special_abort_scan == FALSE)
568 	{
569 		DEBUG_PRINT ("special_abort_scan");
570 		g_ptr_array_foreach (files_to_scan_array, (GFunc)g_free, NULL);
571 		g_ptr_array_free (files_to_scan_array, TRUE);
572 
573 		g_ptr_array_foreach (languages_array, (GFunc)g_free, NULL);
574 		g_ptr_array_free (languages_array, TRUE);
575 	}
576 }
577 
578 static void
on_engine_package_scan_end(SymbolDBEngine * dbe,gint process_id,gpointer user_data)579 on_engine_package_scan_end (SymbolDBEngine *dbe, gint process_id, gpointer user_data)
580 {
581 	SymbolDBSystem *sdbs;
582 	SymbolDBSystemPriv *priv;
583 	EngineScanData *es_data;
584 
585 	es_data = (EngineScanData *)user_data;
586 	sdbs = es_data->sdbs;
587 	priv = sdbs->priv;
588 
589 	/* first of all disconnect the signals */
590 	g_signal_handlers_disconnect_by_func (dbe, on_engine_package_scan_end,
591 										  user_data);
592 
593 	DEBUG_PRINT ("emitting scan_package_end");
594 	/* notify listeners that we ended the scan of the package */
595 	g_signal_emit (sdbs, signals[SCAN_PACKAGE_END], 0, es_data->package_name);
596 
597 	/* remove the data from the queue */
598 	DEBUG_PRINT ("removing %s", es_data->package_name);
599 	g_queue_remove (priv->engine_queue, es_data);
600 	destroy_engine_scan_data (es_data);
601 
602 	/* have we got something left in the queue? */
603 	if (g_queue_get_length (priv->engine_queue) > 0)
604 	{
605 		/* peek the head */
606 		es_data = g_queue_peek_head (priv->engine_queue);
607 
608 		DEBUG_PRINT ("adding %s", es_data->package_name);
609 		sdb_system_do_engine_scan (sdbs, es_data);
610 	}
611 }
612 
613 /**
614  * Scan a new package storing it in queue either for later retrieval or
615  * for signaling the 'busy status'.
616  */
617 static void
sdb_system_do_scan_new_package(SymbolDBSystem * sdbs,SingleScanData * ss_data)618 sdb_system_do_scan_new_package (SymbolDBSystem *sdbs,
619 							SingleScanData *ss_data)
620 {
621 	SymbolDBSystemPriv *priv;
622 	priv = sdbs->priv;
623 
624 	if (g_queue_get_length (priv->sscan_queue) > 0)
625 	{
626 		/* there's something already working... being this function called in a
627 		 * single-threaded fashion we can put the the next parameter on the queue
628 		 */
629 		DEBUG_PRINT ("%s", "pushed on queue for later scanning");
630 		g_queue_push_tail (priv->sscan_queue, ss_data);
631 		return;
632 	}
633 
634 	g_queue_push_tail (priv->sscan_queue, ss_data);
635 	sdb_system_do_scan_package_1 (sdbs, ss_data);
636 	return;
637 }
638 
639 static void
on_pkg_config_exit(AnjutaLauncher * launcher,int child_pid,int exit_status,gulong time_taken_in_seconds,gpointer user_data)640 on_pkg_config_exit (AnjutaLauncher * launcher, int child_pid,
641 				   int exit_status, gulong time_taken_in_seconds,
642 				   gpointer user_data)
643 {
644 	SymbolDBSystem *sdbs;
645 	SymbolDBSystemPriv *priv;
646 	SingleScanData *ss_data;
647 	GList *cflags = NULL;
648 
649 	ss_data = (SingleScanData *)user_data;
650 	sdbs = ss_data->sdbs;
651 	priv = sdbs->priv;
652 
653 	/* first of all disconnect the signals */
654 	g_signal_handlers_disconnect_by_func (launcher, on_pkg_config_exit,
655 										  user_data);
656 
657 	if (ss_data->contents != NULL && strlen (ss_data->contents) > 0)
658 	{
659 		cflags = sdb_system_get_normalized_cflags (ss_data->contents);
660 	}
661 
662 	/* check our ss_data struct. If it has a != null callback then we should
663 	 * call it right now..
664 	 */
665 	if (ss_data->parseable_cb != NULL)
666 	{
667 		DEBUG_PRINT ("%s", "on_pkg_config_exit parseable activated");
668 		ss_data->parseable_cb (sdbs, cflags == NULL ? FALSE : TRUE,
669 							   ss_data->parseable_data);
670 	}
671 
672 	/* no callback to call. Just parse the package on */
673 	if (ss_data->engine_scan == TRUE && cflags != NULL)
674 	{
675 		EngineScanData *es_data;
676 
677 		es_data = g_new0 (EngineScanData, 1);
678 		es_data->sdbs = sdbs;
679 		es_data->cflags = cflags;
680 		es_data->package_name = g_strdup (ss_data->package_name);
681 		es_data->special_abort_scan = FALSE;
682 
683 		/* is the engine queue already full && working? */
684 		if (g_queue_get_length (priv->engine_queue) > 0)
685 		{
686 			/* just push the tail waiting for a later processing [i.e. after
687 			 * a scan-end received
688 			 */
689 			DEBUG_PRINT ("pushing on engine queue [length %d] %s",
690 						 g_queue_get_length (priv->engine_queue),
691 						 es_data->package_name);
692 			g_queue_push_tail (priv->engine_queue, es_data);
693 		}
694 		else
695 		{
696 			/* push the tail to signal a 'working engine' */
697 			DEBUG_PRINT ("scanning with engine queue [length %d] %s",
698 						 g_queue_get_length (priv->engine_queue),
699 						 es_data->package_name);
700 
701 			g_queue_push_tail (priv->engine_queue, es_data);
702 
703 			sdb_system_do_engine_scan (sdbs, es_data);
704 		}
705 	}
706 
707 	/* destroys, after popping, the ss_data from the queue */
708 	g_queue_remove (priv->sscan_queue, ss_data);
709 	destroy_single_scan_data (ss_data);
710 
711 	/* proceed with another scan */
712 	sdb_system_do_scan_next_package (sdbs);
713 }
714 
715 gboolean
symbol_db_system_scan_package(SymbolDBSystem * sdbs,const gchar * package_name)716 symbol_db_system_scan_package (SymbolDBSystem *sdbs,
717 							  const gchar * package_name)
718 {
719 	SingleScanData *ss_data;
720 
721 	g_return_val_if_fail (sdbs != NULL, FALSE);
722 	g_return_val_if_fail (package_name != NULL, FALSE);
723 
724 	/* does is already exist on db? */
725 	if (symbol_db_system_is_package_parsed (sdbs, package_name, "1.0") == TRUE)
726 	{
727 		DEBUG_PRINT ("symbol_db_system_scan_package (): no need to scan %s",
728 					 package_name);
729 		return FALSE;
730 	}
731 	else
732 	{
733 		DEBUG_PRINT ("symbol_db_system_scan_package (): NEED to scan %s",
734 					 package_name);
735 	}
736 
737 	/* create the object to store in the queue */
738 	ss_data = (SingleScanData*)g_new0 (SingleScanData, 1);
739 
740 	/* we don't have chars now. Just fill with the package_name */
741 	ss_data->sdbs = sdbs;
742 	ss_data->package_name = g_strdup (package_name);
743 	ss_data->contents = NULL;
744 	ss_data->parseable_cb = NULL;
745 	ss_data->parseable_data = NULL;
746 	ss_data->engine_scan = TRUE;
747 
748 	/* package is a new one. No worries about scan queue */
749 	sdb_system_do_scan_new_package (sdbs, ss_data);
750 	return TRUE;
751 }
752 
753 void
symbol_db_system_is_package_parseable(SymbolDBSystem * sdbs,const gchar * package_name,PackageParseableCallback parseable_cb,gpointer user_data)754 symbol_db_system_is_package_parseable (SymbolDBSystem *sdbs,
755 								   const gchar * package_name,
756 								   PackageParseableCallback parseable_cb,
757 								   gpointer user_data)
758 {
759 	SingleScanData *ss_data;
760 
761 	g_return_if_fail (sdbs != NULL);
762 	g_return_if_fail (package_name != NULL);
763 
764 	/* create the object to store in the queue */
765 	ss_data = (SingleScanData*)g_new0 (SingleScanData, 1);
766 
767 	/* we don't have chars now. Just fill with the package_name */
768 	ss_data->sdbs = sdbs;
769 	ss_data->package_name = g_strdup (package_name);
770 	ss_data->contents = NULL;
771 	ss_data->parseable_cb = parseable_cb;
772 	ss_data->parseable_data = user_data;
773 	/* this is just an info single_scan_data */
774 	ss_data->engine_scan = FALSE;
775 
776 	/* package is a new one. No worries about scan queue */
777 	sdb_system_do_scan_new_package (sdbs, ss_data);
778 }
779 
780 void
symbol_db_system_parse_aborted_package(SymbolDBSystem * sdbs,GPtrArray * files_to_scan_array,GPtrArray * languages_array)781 symbol_db_system_parse_aborted_package (SymbolDBSystem *sdbs,
782 								 GPtrArray *files_to_scan_array,
783 								 GPtrArray *languages_array)
784 {
785 	SymbolDBSystemPriv *priv;
786 	EngineScanData *es_data;
787 
788 	g_return_if_fail (sdbs != NULL);
789 	g_return_if_fail (files_to_scan_array != NULL);
790 	g_return_if_fail (languages_array != NULL);
791 
792 	priv = sdbs->priv;
793 
794 	/* create a special EngineScanData */
795 	es_data = g_new0 (EngineScanData, 1);
796 	es_data->sdbs = sdbs;
797 	es_data->cflags = NULL;
798 	es_data->package_name = g_strdup (_("Resuming glb scan."));
799 	es_data->special_abort_scan = TRUE;
800 	es_data->files_to_scan_array = g_ptr_array_ref (files_to_scan_array);
801 	es_data->languages_array = g_ptr_array_ref (languages_array);
802 
803 
804 	DEBUG_PRINT ("SYSTEM ABORT PARSING.....");
805 
806 	/* is the engine queue already full && working? */
807 	if (g_queue_get_length (priv->engine_queue) > 0)
808 	{
809 		/* just push the tail waiting for a later processing [i.e. after
810 		 * a scan-end received
811 		 */
812 		DEBUG_PRINT ("pushing on engine queue %s", es_data->package_name);
813 		g_queue_push_tail (priv->engine_queue, es_data);
814 	}
815 	else
816 	{
817 		DEBUG_PRINT ("aborted package");
818 		/* push the tail to signal a 'working engine' */
819 		g_queue_push_tail (priv->engine_queue, es_data);
820 
821 		sdb_system_do_engine_scan (sdbs, es_data);
822 	}
823 }
824 
825