tracker-0.16.2/src/libtracker-miner/tracker-sparql-buffer.c

Location Tool Test ID Function Issue
tracker-sparql-buffer.c:350:10 clang-analyzer Branch condition evaluates to a garbage value
  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 <libtracker-sparql/tracker-sparql.h>
 25 
 26 #include "tracker-sparql-buffer.h"
 27 
 28 /* Maximum time (seconds) before forcing a sparql buffer flush */
 29 #define MAX_SPARQL_BUFFER_TIME  15
 30 
 31 typedef struct _TrackerSparqlBufferPrivate TrackerSparqlBufferPrivate;
 32 typedef struct _SparqlTaskData SparqlTaskData;
 33 typedef struct _UpdateArrayData UpdateArrayData;
 34 typedef struct _UpdateData UpdateData;
 35 typedef struct _BulkOperationMerge BulkOperationMerge;
 36 
 37 enum {
 38 	PROP_0,
 39 	PROP_CONNECTION
 40 };
 41 
 42 enum {
 43 	TASK_TYPE_SPARQL_STR,
 44 	TASK_TYPE_SPARQL,
 45 	TASK_TYPE_BULK
 46 };
 47 
 48 struct _TrackerSparqlBufferPrivate
 49 {
 50 	TrackerSparqlConnection *connection;
 51 	guint flush_timeout_id;
 52 	GPtrArray *tasks;
 53 	gint n_updates;
 54 };
 55 
 56 struct _SparqlTaskData
 57 {
 58 	guint type;
 59 
 60 	union {
 61 		gchar *str;
 62 		TrackerSparqlBuilder *builder;
 63 
 64 		struct {
 65 			gchar *str;
 66 			guint flags;
 67 		} bulk;
 68 	} data;
 69 
 70 	GSimpleAsyncResult *result;
 71 };
 72 
 73 struct _UpdateData {
 74 	TrackerSparqlBuffer *buffer;
 75 	TrackerTask *task;
 76 };
 77 
 78 struct _UpdateArrayData {
 79 	TrackerSparqlBuffer *buffer;
 80 	GPtrArray *tasks;
 81 	GArray *sparql_array;
 82 	GArray *error_map;
 83 	GPtrArray *bulk_ops;
 84 	gint n_bulk_operations;
 85 };
 86 
 87 struct _BulkOperationMerge {
 88 	const gchar *bulk_operation;
 89 	GList *tasks;
 90 	gchar *sparql;
 91 };
 92 
 93 
 94 
 95 G_DEFINE_TYPE (TrackerSparqlBuffer, tracker_sparql_buffer, TRACKER_TYPE_TASK_POOL)
 96 
 97 static void
 98 tracker_sparql_buffer_finalize (GObject *object)
 99 {
100 	TrackerSparqlBufferPrivate *priv;
101 
102 	priv = TRACKER_SPARQL_BUFFER (object)->priv;
103 
104 	if (priv->flush_timeout_id != 0) {
105 		g_source_remove (priv->flush_timeout_id);
106 	}
107 
108 	G_OBJECT_CLASS (tracker_sparql_buffer_parent_class)->finalize (object);
109 }
110 
111 static void
112 tracker_sparql_buffer_set_property (GObject      *object,
113                                     guint         param_id,
114                                     const GValue *value,
115                                     GParamSpec   *pspec)
116 {
117 	TrackerSparqlBufferPrivate *priv;
118 
119 	priv = TRACKER_SPARQL_BUFFER (object)->priv;
120 
121 	switch (param_id) {
122 	case PROP_CONNECTION:
123 		priv->connection = g_value_dup_object (value);
124 		break;
125 	default:
126 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
127 		break;
128 	}
129 }
130 
131 static void
132 tracker_sparql_buffer_get_property (GObject    *object,
133                                     guint       param_id,
134                                     GValue     *value,
135                                     GParamSpec *pspec)
136 {
137 	TrackerSparqlBufferPrivate *priv;
138 
139 	priv = TRACKER_SPARQL_BUFFER (object)->priv;
140 
141 	switch (param_id) {
142 	case PROP_CONNECTION:
143 		g_value_set_object (value,
144 		                    priv->connection);
145 		break;
146 	default:
147 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
148 		break;
149 	}
150 }
151 
152 static void
153 tracker_sparql_buffer_class_init (TrackerSparqlBufferClass *klass)
154 {
155 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
156 
157 	object_class->finalize = tracker_sparql_buffer_finalize;
158 	object_class->set_property = tracker_sparql_buffer_set_property;
159 	object_class->get_property = tracker_sparql_buffer_get_property;
160 
161 	g_object_class_install_property (object_class,
162 	                                 PROP_CONNECTION,
163 	                                 g_param_spec_object ("connection",
164 	                                                      "sparql connection",
165 	                                                      "Sparql Connection",
166 	                                                      TRACKER_SPARQL_TYPE_CONNECTION,
167 	                                                      G_PARAM_READWRITE |
168 	                                                      G_PARAM_CONSTRUCT_ONLY));
169 
170 	g_type_class_add_private (object_class,
171 	                          sizeof (TrackerSparqlBufferPrivate));
172 }
173 
174 static gboolean
175 flush_timeout_cb (gpointer user_data)
176 {
177 	TrackerSparqlBuffer *buffer = user_data;
178 	TrackerSparqlBufferPrivate *priv = buffer->priv;
179 
180 	tracker_sparql_buffer_flush (buffer, "Buffer time reached");
181 	priv->flush_timeout_id = 0;
182 
183 	return FALSE;
184 }
185 
186 static void
187 reset_flush_timeout (TrackerSparqlBuffer *buffer)
188 {
189 	TrackerSparqlBufferPrivate *priv;
190 
191 	priv = buffer->priv;
192 
193 	if (priv->flush_timeout_id != 0) {
194 		g_source_remove (priv->flush_timeout_id);
195 	}
196 
197 	priv->flush_timeout_id = g_timeout_add_seconds (MAX_SPARQL_BUFFER_TIME,
198 	                                                flush_timeout_cb,
199 	                                                buffer);
200 }
201 
202 static void
203 tracker_sparql_buffer_init (TrackerSparqlBuffer *buffer)
204 {
205 	buffer->priv = G_TYPE_INSTANCE_GET_PRIVATE (buffer,
206 	                                            TRACKER_TYPE_SPARQL_BUFFER,
207 	                                            TrackerSparqlBufferPrivate);
208 }
209 
210 TrackerSparqlBuffer *
211 tracker_sparql_buffer_new (TrackerSparqlConnection *connection,
212                            guint                    limit)
213 {
214 	return g_object_new (TRACKER_TYPE_SPARQL_BUFFER,
215 	                     "connection", connection,
216 	                     "limit", limit,
217 	                     NULL);
218 }
219 
220 static void
221 remove_task_foreach (TrackerTask     *task,
222                      TrackerTaskPool *pool)
223 {
224 	tracker_task_pool_remove (pool, task);
225 }
226 
227 static void
228 update_array_data_free (UpdateArrayData *update_data)
229 {
230 	if (!update_data)
231 		return;
232 
233 	if (update_data->sparql_array) {
234 		/* The array contains pointers to strings in the tasks, so no need to
235 		 * deallocate its pointed contents, just the array itself. */
236 		g_array_free (update_data->sparql_array, TRUE);
237 	}
238 
239 	if (update_data->bulk_ops) {
240 		/* The BulkOperationMerge structs which contain the sparql strings
241 		 * are deallocated here */
242 		g_ptr_array_free (update_data->bulk_ops, TRUE);
243 	}
244 
245 	g_ptr_array_foreach (update_data->tasks,
246 	                     (GFunc) remove_task_foreach,
247 	                     update_data->buffer);
248 	g_ptr_array_free (update_data->tasks, TRUE);
249 
250 	g_array_free (update_data->error_map, TRUE);
251 	g_slice_free (UpdateArrayData, update_data);
252 }
253 
254 static void
255 tracker_sparql_buffer_update_array_cb (GObject      *object,
256                                        GAsyncResult *result,
257                                        gpointer      user_data)
258 {
259 	TrackerSparqlBufferPrivate *priv;
260 	GError *global_error = NULL;
261 	GPtrArray *sparql_array_errors;
262 	UpdateArrayData *update_data;
263 	gint i;
264 
265 	/* Get arrays of errors and queries */
266 	update_data = user_data;
267 	priv = TRACKER_SPARQL_BUFFER (update_data->buffer)->priv;
268 	priv->n_updates--;
269 
270 	g_debug ("(Sparql buffer) Finished array-update with %u tasks",
271 	         update_data->tasks->len);
272 
273 	sparql_array_errors = tracker_sparql_connection_update_array_finish (priv->connection,
274 	                                                                     result,
275 	                                                                     &global_error);
276 	if (global_error) {
277 		g_critical ("  (Sparql buffer) Error in array-update: %s",
278 		            global_error->message);
279 	}
280 
281 	/* Report status on each task of the batch update */
282 	for (i = 0; i < update_data->tasks->len; i++) {
283 		TrackerTask *task;
284 		SparqlTaskData *task_data;
285 		GError *error = NULL;
286 
287 		task = g_ptr_array_index (update_data->tasks, i);
288 		task_data = tracker_task_get_data (task);
289 
290 		if (global_error) {
291 			error = global_error;
292 		} else {
293 			gint error_pos;
294 
295 			error_pos = g_array_index (update_data->error_map, gint, i);
296 
297 			/* Find the corresponing error according to the passed map,
298 			 * numbers >= 0 are non-bulk tasks, and < 0 are bulk tasks,
299 			 * so the number of bulk operations must be added, as these
300 			 * tasks are prepended.
301 			 */
302 			error_pos += update_data->n_bulk_operations;
303 			error = g_ptr_array_index (sparql_array_errors, error_pos);
304 			if (error) {
305 				g_critical ("  (Sparql buffer) Error in task %u of the array-update: %s",
306 				            i, error->message);
307 
308 				if (error_pos < update_data->n_bulk_operations) {
309 					BulkOperationMerge *bulk;
310 					GList *tasks;
311 					gint bulk_pos;
312 
313 					bulk_pos = ABS (error_pos - update_data->n_bulk_operations + 1);
314 					bulk = g_ptr_array_index (update_data->bulk_ops, bulk_pos);
315 					tasks = bulk->tasks;
316 
317 					g_debug ("    Affected files:");
318 
319 					while (tasks) {
320 						TrackerTask *task = tasks->data;
321 						gchar *uri;
322 
323 						uri = g_file_get_uri (tracker_task_get_file (task));
324 						g_debug ("      - %s", uri);
325 						g_free (uri);
326 
327 						tasks = tasks->next;
328 					}
329 
330 					g_debug ("    Sparql: %s", bulk->sparql);
331 				} else {
332 					const gchar *sparql;
333 					gchar *uri;
334 
335 					uri = g_file_get_uri (tracker_task_get_file (task));
336 					g_debug ("    Affected file: %s", uri);
337 					g_free (uri);
338 
339 					switch (task_data->type) {
340 					case TASK_TYPE_SPARQL_STR:
341 						sparql = task_data->data.str;
342 						break;
343 					case TASK_TYPE_SPARQL:
344 						sparql = tracker_sparql_builder_get_result (task_data->data.builder);
345 						break;
346 					default:
347 						break;
348 					}
349 
350 					if (sparql) {
Branch condition evaluates to a garbage value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

351 g_debug (" Sparql: %s", sparql); 352 } 353 } 354 } 355 } 356 357 /* Call finished handler with the error, if any */ 358 g_simple_async_result_set_op_res_gpointer (task_data->result, 359 task, NULL); 360 if (error) { 361 g_simple_async_result_set_from_error (task_data->result, error); 362 } 363 364 g_simple_async_result_complete (task_data->result); 365 366 /* No need to deallocate the task here, it will be done when 367 * unref-ing the UpdateArrayData below */ 368 } 369 370 /* Unref the arrays of errors and queries */ 371 if (sparql_array_errors) { 372 g_ptr_array_unref (sparql_array_errors); 373 } 374 375 /* Note that tasks are actually deallocated here */ 376 update_array_data_free (update_data); 377 378 if (global_error) { 379 g_error_free (global_error); 380 } 381 } 382 383 static void 384 bulk_operation_merge_finish (BulkOperationMerge *merge) 385 { 386 if (merge->sparql) { 387 g_free (merge->sparql); 388 merge->sparql = NULL; 389 } 390 391 if (merge->bulk_operation && merge->tasks) { 392 GString *equals_string = NULL, *children_string = NULL, *sparql; 393 gint n_equals = 0; 394 gboolean include_logical_resources = FALSE; 395 GList *l; 396 397 for (l = merge->tasks; l; l = l->next) { 398 SparqlTaskData *task_data; 399 TrackerTask *task = l->data; 400 gchar *uri; 401 402 task_data = tracker_task_get_data (task); 403 uri = g_file_get_uri (tracker_task_get_file (task)); 404 405 if (task_data->data.bulk.flags & TRACKER_BULK_MATCH_EQUALS) { 406 if (!equals_string) { 407 equals_string = g_string_new (""); 408 } else { 409 g_string_append_c (equals_string, ','); 410 } 411 412 g_string_append_printf (equals_string, "\"%s\"", uri); 413 n_equals++; 414 } 415 416 if (task_data->data.bulk.flags & TRACKER_BULK_MATCH_CHILDREN) { 417 if (!children_string) { 418 children_string = g_string_new (""); 419 } else { 420 g_string_append_c (children_string, ','); 421 } 422 423 g_string_append_printf (children_string, "\"%s\"", uri); 424 } 425 426 if (task_data->data.bulk.flags & TRACKER_BULK_MATCH_LOGICAL_RESOURCES) { 427 include_logical_resources = TRUE; 428 } 429 430 g_free (uri); 431 } 432 433 sparql = g_string_new (""); 434 435 if (equals_string) { 436 g_string_append (sparql, merge->bulk_operation); 437 g_string_append_printf (sparql, " WHERE { "); 438 439 if (n_equals == 1) { 440 g_string_append_printf (sparql, 441 " ?f nie:url %s .", 442 equals_string->str); 443 } else { 444 g_string_append_printf (sparql, 445 " ?f nie:url ?u ." 446 " FILTER (?u IN (%s))", 447 equals_string->str); 448 } 449 g_string_free (equals_string, TRUE); 450 451 if (include_logical_resources) { 452 g_string_append (sparql, " ?ie nie:isStoredAs ?f ."); 453 } 454 g_string_append_printf (sparql, " } "); 455 } 456 457 if (children_string) { 458 g_string_append (sparql, merge->bulk_operation); 459 g_string_append_printf (sparql, 460 " WHERE { " 461 " ?f nie:url ?u ." 462 " FILTER (tracker:uri-is-descendant (%s, ?u))", 463 children_string->str); 464 g_string_free (children_string, TRUE); 465 466 if (include_logical_resources) { 467 g_string_append (sparql, " ?ie nie:isStoredAs ?f ."); 468 } 469 g_string_append_printf (sparql, "} "); 470 } 471 472 merge->sparql = g_string_free (sparql, FALSE); 473 } 474 } 475 476 static BulkOperationMerge * 477 bulk_operation_merge_new (const gchar *bulk_operation) 478 { 479 BulkOperationMerge *operation; 480 481 operation = g_slice_new0 (BulkOperationMerge); 482 operation->bulk_operation = bulk_operation; 483 484 return operation; 485 } 486 487 static void 488 bulk_operation_merge_free (BulkOperationMerge *operation) 489 { 490 g_list_foreach (operation->tasks, 491 (GFunc) tracker_task_unref, 492 NULL); 493 g_list_free (operation->tasks); 494 g_free (operation->sparql); 495 g_slice_free (BulkOperationMerge, operation); 496 } 497 498 gboolean 499 tracker_sparql_buffer_flush (TrackerSparqlBuffer *buffer, 500 const gchar *reason) 501 { 502 TrackerSparqlBufferPrivate *priv; 503 GPtrArray *bulk_ops = NULL; 504 GArray *sparql_array, *error_map; 505 UpdateArrayData *update_data; 506 gint i, j; 507 508 priv = buffer->priv; 509 510 if (priv->n_updates > 0) { 511 return FALSE; 512 } 513 514 if (!priv->tasks || 515 priv->tasks->len == 0) { 516 return FALSE; 517 } 518 519 g_debug ("Flushing SPARQL buffer, reason: %s", reason); 520 521 if (priv->flush_timeout_id != 0) { 522 g_source_remove (priv->flush_timeout_id); 523 priv->flush_timeout_id = 0; 524 } 525 526 /* Loop buffer and construct array of strings */ 527 sparql_array = g_array_new (FALSE, TRUE, sizeof (gchar *)); 528 error_map = g_array_new (TRUE, TRUE, sizeof (gint)); 529 530 for (i = 0; i < priv->tasks->len; i++) { 531 SparqlTaskData *task_data; 532 TrackerTask *task; 533 gint pos; 534 535 task = g_ptr_array_index (priv->tasks, i); 536 task_data = tracker_task_get_data (task); 537 538 if (task_data->type == TASK_TYPE_SPARQL_STR) { 539 g_array_append_val (sparql_array, task_data->data.str); 540 pos = sparql_array->len - 1; 541 } else if (task_data->type == TASK_TYPE_SPARQL) { 542 const gchar *str; 543 544 str = tracker_sparql_builder_get_result (task_data->data.builder); 545 g_array_append_val (sparql_array, str); 546 pos = sparql_array->len - 1; 547 } else if (task_data->type == TASK_TYPE_BULK) { 548 BulkOperationMerge *bulk = NULL; 549 gint j; 550 551 if (G_UNLIKELY (!bulk_ops)) { 552 bulk_ops = g_ptr_array_new_with_free_func ((GDestroyNotify) bulk_operation_merge_free); 553 } 554 555 for (j = 0; j < bulk_ops->len; j++) { 556 BulkOperationMerge *cur; 557 558 cur = g_ptr_array_index (bulk_ops, j); 559 560 /* This is a comparison of intern strings */ 561 if (cur->bulk_operation == task_data->data.bulk.str) { 562 bulk = cur; 563 pos = - 1 - j; 564 break; 565 } 566 } 567 568 if (!bulk) { 569 bulk = bulk_operation_merge_new (task_data->data.bulk.str); 570 g_ptr_array_add (bulk_ops, bulk); 571 pos = - bulk_ops->len; 572 } 573 574 bulk->tasks = g_list_prepend (bulk->tasks, 575 tracker_task_ref (task)); 576 } 577 578 g_array_append_val (error_map, pos); 579 } 580 581 if (bulk_ops) { 582 for (j = 0; j < bulk_ops->len; j++) { 583 BulkOperationMerge *bulk; 584 585 bulk = g_ptr_array_index (bulk_ops, j); 586 bulk_operation_merge_finish (bulk); 587 588 if (bulk->sparql) { 589 g_array_prepend_val (sparql_array, 590 bulk->sparql); 591 } 592 } 593 } 594 595 update_data = g_slice_new0 (UpdateArrayData); 596 update_data->buffer = buffer; 597 update_data->tasks = g_ptr_array_ref (priv->tasks); 598 update_data->bulk_ops = bulk_ops; 599 update_data->n_bulk_operations = bulk_ops ? bulk_ops->len : 0; 600 update_data->error_map = error_map; 601 update_data->sparql_array = sparql_array; 602 603 /* Empty pool, update_data will keep 604 * references to the tasks to keep 605 * these alive. 606 */ 607 g_ptr_array_unref (priv->tasks); 608 priv->tasks = NULL; 609 priv->n_updates++; 610 611 /* Start the update */ 612 tracker_sparql_connection_update_array_async (priv->connection, 613 (gchar **) update_data->sparql_array->data, 614 update_data->sparql_array->len, 615 G_PRIORITY_DEFAULT, 616 NULL, 617 tracker_sparql_buffer_update_array_cb, 618 update_data); 619 620 return TRUE; 621 } 622 623 static void 624 tracker_sparql_buffer_update_cb (GObject *object, 625 GAsyncResult *result, 626 gpointer user_data) 627 { 628 UpdateData *update_data = user_data; 629 SparqlTaskData *task_data; 630 GError *error = NULL; 631 632 tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (object), 633 result, &error); 634 635 task_data = tracker_task_get_data (update_data->task); 636 637 /* Call finished handler with the error, if any */ 638 g_simple_async_result_set_op_res_gpointer (task_data->result, 639 update_data->task, 640 NULL); 641 if (error) { 642 g_simple_async_result_set_from_error (task_data->result, error); 643 g_error_free (error); 644 } 645 646 g_simple_async_result_complete (task_data->result); 647 648 tracker_task_pool_remove (TRACKER_TASK_POOL (update_data->buffer), 649 update_data->task); 650 g_slice_free (UpdateData, update_data); 651 } 652 653 void 654 tracker_sparql_buffer_push (TrackerSparqlBuffer *buffer, 655 TrackerTask *task, 656 gint priority, 657 GAsyncReadyCallback cb, 658 gpointer user_data) 659 { 660 TrackerSparqlBufferPrivate *priv; 661 SparqlTaskData *data; 662 663 g_return_if_fail (TRACKER_IS_SPARQL_BUFFER (buffer)); 664 g_return_if_fail (task != NULL); 665 666 priv = buffer->priv; 667 668 data = tracker_task_get_data (task); 669 data->result = g_simple_async_result_new (G_OBJECT (buffer), 670 cb, user_data, NULL); 671 672 if (priority <= G_PRIORITY_HIGH && 673 data->type != TASK_TYPE_BULK) { 674 UpdateData *update_data; 675 const gchar *sparql = NULL; 676 677 /* High priority task */ 678 update_data = g_slice_new0 (UpdateData); 679 update_data->buffer = buffer; 680 update_data->task = task; 681 682 if (data->type == TASK_TYPE_SPARQL_STR) { 683 sparql = data->data.str; 684 } else if (data->type == TASK_TYPE_SPARQL) { 685 sparql = tracker_sparql_builder_get_result (data->data.builder); 686 } 687 688 tracker_task_pool_add (TRACKER_TASK_POOL (buffer), task); 689 tracker_sparql_connection_update_async (priv->connection, 690 sparql, 691 G_PRIORITY_HIGH, 692 NULL, 693 tracker_sparql_buffer_update_cb, 694 update_data); 695 } else { 696 if (tracker_task_pool_get_size (TRACKER_TASK_POOL (buffer)) == 0) { 697 reset_flush_timeout (buffer); 698 } 699 700 tracker_task_pool_add (TRACKER_TASK_POOL (buffer), task); 701 702 if (!priv->tasks) { 703 priv->tasks = g_ptr_array_new_with_free_func ((GDestroyNotify) tracker_task_unref); 704 } 705 706 g_ptr_array_add (priv->tasks, task); 707 708 if (tracker_task_pool_limit_reached (TRACKER_TASK_POOL (buffer))) { 709 tracker_sparql_buffer_flush (buffer, "SPARQL buffer limit reached"); 710 } else if (priv->tasks->len > tracker_task_pool_get_limit (TRACKER_TASK_POOL (buffer)) / 2) { 711 /* We've filled half of the buffer, flush it as we receive more tasks */ 712 tracker_sparql_buffer_flush (buffer, "SPARQL buffer half-full"); 713 } 714 } 715 } 716 717 static SparqlTaskData * 718 sparql_task_data_new (guint type, 719 gpointer data, 720 guint flags) 721 { 722 SparqlTaskData *task_data; 723 724 task_data = g_slice_new0 (SparqlTaskData); 725 task_data->type = type; 726 727 switch (type) { 728 case TASK_TYPE_SPARQL_STR: 729 task_data->data.str = data; 730 break; 731 case TASK_TYPE_SPARQL: 732 task_data->data.builder = g_object_ref (data); 733 break; 734 case TASK_TYPE_BULK: 735 task_data->data.bulk.str = data; 736 task_data->data.bulk.flags = flags; 737 break; 738 } 739 740 return task_data; 741 } 742 743 static void 744 sparql_task_data_free (SparqlTaskData *data) 745 { 746 switch (data->type) { 747 case TASK_TYPE_SPARQL_STR: 748 g_free (data->data.str); 749 break; 750 case TASK_TYPE_SPARQL: 751 g_object_unref (data->data.builder); 752 break; 753 case TASK_TYPE_BULK: 754 /* nothing to free, the string is interned */ 755 break; 756 } 757 758 if (data->result) { 759 g_object_unref (data->result); 760 } 761 762 g_slice_free (SparqlTaskData, data); 763 } 764 765 TrackerTask * 766 tracker_sparql_task_new_take_sparql_str (GFile *file, 767 gchar *sparql_str) 768 { 769 SparqlTaskData *data; 770 771 data = sparql_task_data_new (TASK_TYPE_SPARQL_STR, sparql_str, 0); 772 return tracker_task_new (file, data, 773 (GDestroyNotify) sparql_task_data_free); 774 } 775 776 TrackerTask * 777 tracker_sparql_task_new_with_sparql_str (GFile *file, 778 const gchar *sparql_str) 779 { 780 SparqlTaskData *data; 781 782 data = sparql_task_data_new (TASK_TYPE_SPARQL_STR, 783 g_strdup (sparql_str), 0); 784 return tracker_task_new (file, data, 785 (GDestroyNotify) sparql_task_data_free); 786 } 787 788 TrackerTask * 789 tracker_sparql_task_new_with_sparql (GFile *file, 790 TrackerSparqlBuilder *builder) 791 { 792 SparqlTaskData *data; 793 794 data = sparql_task_data_new (TASK_TYPE_SPARQL, builder, 0); 795 return tracker_task_new (file, data, 796 (GDestroyNotify) sparql_task_data_free); 797 } 798 799 TrackerTask * 800 tracker_sparql_task_new_bulk (GFile *file, 801 const gchar *sparql_str, 802 TrackerBulkTaskFlags flags) 803 { 804 SparqlTaskData *data; 805 806 data = sparql_task_data_new (TASK_TYPE_BULK, 807 (gchar *) g_intern_string (sparql_str), 808 flags); 809 return tracker_task_new (file, data, 810 (GDestroyNotify) sparql_task_data_free); 811 }