[tracker/wip/carlosg/iterative-update] libtracker-data: Process Update rule iteratively
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/iterative-update] libtracker-data: Process Update rule iteratively
- Date: Sun, 11 Oct 2020 17:26:48 +0000 (UTC)
commit 2b9b3118549bc3251a5c340cc1d471af513fdc88
Author: Carlos Garnacho <carlosg gnome org>
Date: Sun Oct 11 18:33:44 2020 +0200
libtracker-data: Process Update rule iteratively
The Update rule is defined upon itself, we interpret this a bit too
literally, and do the same thing when interpreting the parse tree. This
makes the maximum stack size an indirect factor that limits how big a
series of updates can possibly be. (e.g. the array at
tracker_sparql_connection_update_array_async)
This is obviously bad, so process the updates iteratively, this will avoid
hitting stack limits by just concatenating legit updates together.
Fixes: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/91
src/libtracker-data/tracker-sparql.c | 45 ++++++++++++++++++++++++------------
1 file changed, 30 insertions(+), 15 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 2ff43d045..34571e131 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -2538,32 +2538,47 @@ static gboolean
translate_Update (TrackerSparql *sparql,
GError **error)
{
+ gboolean cont = TRUE;
+
/* Update ::= Prologue ( Update1 ( ';' Update )? )?
*
* TRACKER EXTENSION:
* ';' separator is made optional.
+ *
+ * Note: Even though the rule is defined recursively, we
+ * process it iteratively here. This is in order to avoid
+ * making maximum update buffer depend on stack size.
*/
- _call_rule (sparql, NAMED_RULE_Prologue, error);
+ while (cont) {
+ _call_rule (sparql, NAMED_RULE_Prologue, error);
- if (!sparql->current_state->blank_node_map) {
- sparql->current_state->blank_node_map =
- g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
- }
+ if (!sparql->current_state->blank_node_map) {
+ sparql->current_state->blank_node_map =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_free);
+ }
- if (_check_in_rule (sparql, NAMED_RULE_Update1)) {
- if (sparql->blank_nodes)
- g_variant_builder_open (sparql->blank_nodes, G_VARIANT_TYPE ("aa{ss}"));
+ if (_check_in_rule (sparql, NAMED_RULE_Update1)) {
+ if (sparql->blank_nodes)
+ g_variant_builder_open (sparql->blank_nodes, G_VARIANT_TYPE ("aa{ss}"));
- _call_rule (sparql, NAMED_RULE_Update1, error);
+ _call_rule (sparql, NAMED_RULE_Update1, error);
- if (sparql->blank_nodes)
- g_variant_builder_close (sparql->blank_nodes);
+ if (sparql->blank_nodes)
+ g_variant_builder_close (sparql->blank_nodes);
- _optional (sparql, RULE_TYPE_LITERAL, LITERAL_SEMICOLON);
+ _optional (sparql, RULE_TYPE_LITERAL, LITERAL_SEMICOLON);
- if (_check_in_rule (sparql, NAMED_RULE_Update))
- _call_rule (sparql, NAMED_RULE_Update, error);
+ if (_check_in_rule (sparql, NAMED_RULE_Update)) {
+ /* Handle the rule inline in the next iteration */
+ tracker_sparql_iter_next (sparql);
+ cont = TRUE;
+ } else {
+ cont = FALSE;
+ }
+ } else {
+ cont = FALSE;
+ }
}
return TRUE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]