[tracker] Transient properties



commit 577a178dbae40783e5c1bf39b099dba509e57db5
Author: Philip Van Hoof <philip codeminded be>
Date:   Mon Apr 20 12:56:38 2009 +0200

    Transient properties
    
    Added support for transient properties. Right now the support for these
    properties still stores physically. This is done that way because if we'd use
    TEMPORARY tables in sqlite, the table wouldn't be shared between the processes
    of trackerd and tracker-indexer. When we refactor to letting trackerd do both
    writes and reads, we can instead start using TEMPORARY tables. I have added
    the code for this, but commented out in this commit.
---
 data/ontologies/11-rdf.ontology            |    4 +
 src/libtracker-common/tracker-property.c   |   55 +++++++-
 src/libtracker-common/tracker-property.h   |    3 +
 src/libtracker-data/tracker-data-manager.c |  220 ++++++++++++++++++++--------
 4 files changed, 218 insertions(+), 64 deletions(-)

diff --git a/data/ontologies/11-rdf.ontology b/data/ontologies/11-rdf.ontology
index ae3069c..f67957d 100644
--- a/data/ontologies/11-rdf.ontology
+++ b/data/ontologies/11-rdf.ontology
@@ -80,3 +80,7 @@ tracker:fulltextIndexed a rdf:Property ;
 	rdfs:domain rdf:Property ;
 	rdfs:range xsd:boolean .
 
+tracker:transient a rdf:Property ;
+	nrl:maxCardinality 1 ;
+	rdfs:domain rdf:Property ;
+	rdfs:range xsd:boolean .
diff --git a/src/libtracker-common/tracker-property.c b/src/libtracker-common/tracker-property.c
index 83f6b69..7138859 100644
--- a/src/libtracker-common/tracker-property.c
+++ b/src/libtracker-common/tracker-property.c
@@ -52,6 +52,7 @@ struct _TrackerPropertyPriv {
 	gboolean       embedded;
 	gboolean       multiple_values;
 	gboolean       filtered;
+	gboolean       transient;
 
 	GArray        *super_properties;
 };
@@ -78,7 +79,8 @@ enum {
 	PROP_FULLTEXT_INDEXED,
 	PROP_EMBEDDED,
 	PROP_MULTIPLE_VALUES,
-	PROP_FILTERED
+	PROP_FILTERED,
+	PROP_TRANSIENT
 };
 
 GType
@@ -236,6 +238,13 @@ tracker_property_class_init (TrackerPropertyClass *klass)
 							       "Filtered",
 							       TRUE,
 							       G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_TRANSIENT,
+					 g_param_spec_boolean ("transient",
+							       "transient",
+							       "Transient",
+							       FALSE,
+							       G_PARAM_READWRITE));
 
 	g_type_class_add_private (object_class, sizeof (TrackerPropertyPriv));
 }
@@ -250,6 +259,7 @@ tracker_property_init (TrackerProperty *field)
 	priv->weight = 1;
 	priv->embedded = TRUE;
 	priv->filtered = TRUE;
+	priv->transient = FALSE;
 	priv->multiple_values = TRUE;
 	priv->super_properties = g_array_new (TRUE, TRUE, sizeof (TrackerProperty *));
 }
@@ -313,6 +323,9 @@ property_get_property (GObject    *object,
 	case PROP_FILTERED:
 		g_value_set_boolean (value, priv->filtered);
 		break;
+	case PROP_TRANSIENT:
+		g_value_set_boolean (value, priv->transient);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 		break;
@@ -366,6 +379,10 @@ property_set_property (GObject	 *object,
 		tracker_property_set_filtered (TRACKER_PROPERTY (object),
 					    g_value_get_boolean (value));
 		break;
+	case PROP_TRANSIENT:
+		tracker_property_set_transient (TRACKER_PROPERTY (object),
+					    g_value_get_boolean (value));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 		break;
@@ -425,6 +442,19 @@ tracker_property_get_uri (TrackerProperty *field)
 	return priv->uri;
 }
 
+gboolean
+tracker_property_get_transient (TrackerProperty *field)
+{
+	TrackerPropertyPriv *priv;
+
+	g_return_val_if_fail (TRACKER_IS_PROPERTY (field), FALSE);
+
+	priv = GET_PRIV (field);
+
+	return priv->transient;
+}
+
+
 const gchar *
 tracker_property_get_name (TrackerProperty *field)
 {
@@ -605,6 +635,22 @@ tracker_property_set_uri (TrackerProperty *field,
 }
 
 void
+tracker_property_set_transient (TrackerProperty *field,
+			        gboolean value)
+{
+	TrackerPropertyPriv *priv;
+
+	g_return_if_fail (TRACKER_IS_PROPERTY (field));
+
+	priv = GET_PRIV (field);
+
+	priv->transient = value;
+	priv->multiple_values = TRUE;
+
+	g_object_notify (G_OBJECT (field), "transient");
+}
+
+void
 tracker_property_set_data_type (TrackerProperty     *field,
 			     TrackerPropertyType  value)
 {
@@ -747,7 +793,12 @@ tracker_property_set_multiple_values (TrackerProperty *field,
 
 	priv = GET_PRIV (field);
 
-	priv->multiple_values = value;
+	if (priv->transient) {
+		priv->multiple_values = TRUE;
+	} else {
+		priv->multiple_values = value;
+	}
+
 	g_object_notify (G_OBJECT (field), "multiple-values");
 }
 
diff --git a/src/libtracker-common/tracker-property.h b/src/libtracker-common/tracker-property.h
index 82a3230..8534851 100644
--- a/src/libtracker-common/tracker-property.h
+++ b/src/libtracker-common/tracker-property.h
@@ -88,6 +88,7 @@ gboolean	 tracker_property_get_fulltext_indexed(TrackerProperty     *property);
 gboolean	 tracker_property_get_embedded	   (TrackerProperty     *property);
 gboolean	 tracker_property_get_multiple_values (TrackerProperty     *property);
 gboolean	 tracker_property_get_filtered	   (TrackerProperty     *property);
+gboolean	 tracker_property_get_transient	   (TrackerProperty     *property);
 TrackerProperty **tracker_property_get_super_properties	     (TrackerProperty *property);
 
 void		 tracker_property_set_uri		   (TrackerProperty     *property,
@@ -110,6 +111,8 @@ void		 tracker_property_set_multiple_values (TrackerProperty     *property,
 						    gboolean	      value);
 void		 tracker_property_set_filtered	   (TrackerProperty     *property,
 						    gboolean	      value);
+void		 tracker_property_set_transient	   (TrackerProperty     *property,
+						    gboolean	      value);
 void             tracker_property_set_super_properties		(TrackerProperty  *property,
 								 TrackerProperty **super_properties);
 void             tracker_property_add_super_property		(TrackerProperty  *property,
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index d8d1eae..008fd2d 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -232,6 +232,18 @@ load_ontology_file_from_path (const gchar	 *ontology_file)
 			if (strcmp (object, "true") == 0) {
 				tracker_property_set_indexed (property, TRUE);
 			}
+		} else if (strcmp (predicate, TRACKER_PREFIX "transient") == 0) {
+			TrackerProperty *property;
+
+			property = tracker_ontology_get_property_by_uri (subject);
+			if (property == NULL) {
+				g_critical ("%s: Unknown property %s", ontology_file, subject);
+				continue;
+			}
+
+			if (strcmp (object, "true") == 0) {
+				tracker_property_set_transient (property, TRUE);
+			}
 		} else if (strcmp (predicate, TRACKER_PREFIX "fulltextIndexed") == 0) {
 			TrackerProperty *property;
 
@@ -437,7 +449,8 @@ db_get_static_data (TrackerDBInterface *iface)
 						      "(SELECT Uri FROM \"rdfs:Resource\" WHERE ID = \"rdfs:range\"), "
 						      "\"nrl:maxCardinality\", "
 						      "\"tracker:indexed\", "
-						      "\"tracker:fulltextIndexed\" "
+						      "\"tracker:fulltextIndexed\", "
+						      "\"tracker:transient\" "
 						      "FROM \"rdf:Property\" ORDER BY ID");
 	result_set = tracker_db_statement_execute (stmt, NULL);
 	g_object_unref (stmt);
@@ -450,6 +463,7 @@ db_get_static_data (TrackerDBInterface *iface)
 			TrackerProperty *property;
 			gchar	        *uri, *domain_uri, *range_uri;
 			gboolean         multi_valued, indexed, fulltext_indexed;
+			gboolean         transient = FALSE;
 
 			property = tracker_property_new ();
 
@@ -487,6 +501,16 @@ db_get_static_data (TrackerDBInterface *iface)
 				fulltext_indexed = FALSE;
 			}
 
+			_tracker_db_result_set_get_value (result_set, 6, &value);
+			if (G_VALUE_TYPE (&value) != 0) {
+				transient = (g_value_get_int (&value) == 1);
+				g_value_unset (&value);
+			} else {
+				/* NULL */
+				transient = FALSE;
+			}
+
+			tracker_property_set_transient (property, transient);
 			tracker_property_set_uri (property, uri);
 			tracker_property_set_domain (property, tracker_ontology_get_class_by_uri (domain_uri));
 			tracker_property_set_range (property, tracker_ontology_get_class_by_uri (range_uri));
@@ -509,6 +533,90 @@ db_get_static_data (TrackerDBInterface *iface)
 }
 
 static void
+create_decomposed_metadata_property_table (TrackerDBInterface *iface, 
+					   TrackerProperty   **property, 
+					   const gchar        *service_name,
+					   const gchar       **sql_type_for_single_value)
+{
+	const char *field_name;
+	const char *sql_type;
+	gboolean    transient;
+
+	field_name = tracker_property_get_name (*property);
+
+	transient = !sql_type_for_single_value;
+
+	if (!transient) {
+		transient = tracker_property_get_transient (*property);
+	}
+
+	switch (tracker_property_get_data_type (*property)) {
+	case TRACKER_PROPERTY_TYPE_STRING:
+		sql_type = "TEXT";
+		break;
+	case TRACKER_PROPERTY_TYPE_INTEGER:
+	case TRACKER_PROPERTY_TYPE_BOOLEAN:
+	case TRACKER_PROPERTY_TYPE_DATE:
+	case TRACKER_PROPERTY_TYPE_DATETIME:
+	case TRACKER_PROPERTY_TYPE_RESOURCE:
+		sql_type = "INTEGER";
+		break;
+	case TRACKER_PROPERTY_TYPE_DOUBLE:
+		sql_type = "REAL";
+		break;
+	default:
+		sql_type = "";
+		break;
+	}
+
+	/* TODO: When we refactor to having writes in trackerd, we can use 
+	 * TEMPORARY tables instead of deleting and storing physically */
+
+	if (transient || tracker_property_get_multiple_values (*property)) {
+		/* multiple values */
+		if (tracker_property_get_indexed (*property)) {
+			/* use different UNIQUE index for properties whose
+			 * value should be indexed to minimize index size */
+			tracker_db_interface_execute_query (iface, NULL,
+				"CREATE %sTABLE \"%s_%s\" ("
+				"ID INTEGER NOT NULL, "
+				"\"%s\" %s NOT NULL, "
+				"UNIQUE (\"%s\", ID))",
+				transient ? "" /*"TEMPORARY "*/ : "",
+				service_name,
+				field_name,
+				field_name,
+				sql_type,
+				field_name);
+
+			tracker_db_interface_execute_query (iface, NULL,
+				"CREATE INDEX \"%s_%s_ID\" ON \"%s_%s\" (ID)",
+				service_name,
+				field_name,
+				service_name,
+				field_name);
+		} else {
+			/* we still have to include the property value in
+			 * the unique index for proper constraints */
+			tracker_db_interface_execute_query (iface, NULL,
+				"CREATE %sTABLE \"%s_%s\" ("
+				"ID INTEGER NOT NULL, "
+				"\"%s\" %s NOT NULL, "
+				"UNIQUE (ID, \"%s\"))",
+				transient ? "" /*"TEMPORARY "*/ : "",
+				service_name,
+				field_name,
+				field_name,
+				sql_type,
+				field_name);
+		}
+	} else if (sql_type_for_single_value) {
+		*sql_type_for_single_value = sql_type;
+	}
+
+}
+
+static void
 create_decomposed_metadata_tables (TrackerDBInterface *iface,
 				   TrackerClass       *service,
 				   gint               *max_id)
@@ -536,72 +644,21 @@ create_decomposed_metadata_tables (TrackerDBInterface *iface,
 	properties = tracker_ontology_get_properties ();
 	class_properties = NULL;
 	for (property = properties; *property; property++) {
-		const char   *field_name;
-
-		field_name = tracker_property_get_name (*property);
 		if (tracker_property_get_domain (*property) == service) {
-			const char *sql_type;
-
-			switch (tracker_property_get_data_type (*property)) {
-			case TRACKER_PROPERTY_TYPE_STRING:
-				sql_type = "TEXT";
-				break;
-			case TRACKER_PROPERTY_TYPE_INTEGER:
-			case TRACKER_PROPERTY_TYPE_BOOLEAN:
-			case TRACKER_PROPERTY_TYPE_DATE:
-			case TRACKER_PROPERTY_TYPE_DATETIME:
-			case TRACKER_PROPERTY_TYPE_RESOURCE:
-				sql_type = "INTEGER";
-				break;
-			case TRACKER_PROPERTY_TYPE_DOUBLE:
-				sql_type = "REAL";
-				break;
-			default:
-				sql_type = "";
-				break;
-			}
+			const gchar *sql_type_for_single_value = NULL;
 
-			if (tracker_property_get_multiple_values (*property)) {
-				/* multiple values */
-				if (tracker_property_get_indexed (*property)) {
-					/* use different UNIQUE index for properties whose
-					 * value should be indexed to minimize index size */
-					tracker_db_interface_execute_query (iface, NULL,
-						"CREATE TABLE \"%s_%s\" ("
-						"ID INTEGER NOT NULL, "
-						"\"%s\" %s NOT NULL, "
-						"UNIQUE (\"%s\", ID))",
-						service_name,
-						field_name,
-						field_name,
-						sql_type,
-						field_name);
-
-					tracker_db_interface_execute_query (iface, NULL,
-						"CREATE INDEX \"%s_%s_ID\" ON \"%s_%s\" (ID)",
-						service_name,
-						field_name,
-						service_name,
-						field_name);
-				} else {
-					/* we still have to include the property value in
-					 * the unique index for proper constraints */
-					tracker_db_interface_execute_query (iface, NULL,
-						"CREATE TABLE \"%s_%s\" ("
-						"ID INTEGER NOT NULL, "
-						"\"%s\" %s NOT NULL, "
-						"UNIQUE (ID, \"%s\"))",
-						service_name,
-						field_name,
-						field_name,
-						sql_type,
-						field_name);
-				}
-			} else {
+			create_decomposed_metadata_property_table (iface, property, 
+								   service_name, 
+								   &sql_type_for_single_value);
+
+			if (sql_type_for_single_value) {
 				/* single value */
 
 				class_properties = g_slist_prepend (class_properties, *property);
-				g_string_append_printf (sql, ", \"%s\" %s", field_name, sql_type);
+
+				g_string_append_printf (sql, ", \"%s\" %s", 
+							tracker_property_get_name (*property), 
+							sql_type_for_single_value);
 			}
 		}
 	}
@@ -650,6 +707,44 @@ create_decomposed_metadata_tables (TrackerDBInterface *iface,
 	}
 }
 
+static void
+create_decomposed_transient_metadata_tables (TrackerDBInterface *iface)
+{
+	TrackerProperty **properties;
+	TrackerProperty **property;
+
+	properties = tracker_ontology_get_properties ();
+
+	for (property = properties; *property; property++) {
+		if (tracker_property_get_transient (*property)) {
+
+			TrackerClass *domain;
+			const gchar *service_name;
+			const char *field_name;
+
+			field_name = tracker_property_get_name (*property);
+
+			domain = tracker_property_get_domain (*property);
+			service_name = tracker_class_get_name (domain);
+
+			/* TODO: When we refactor to having writes in trackerd, we can use 
+	 		 * TEMPORARY tables instead of deleting and storing physically 
+
+			 * create_decomposed_metadata_property_table (iface, property,
+			 * 					   service_name,
+			 *					   NULL);
+			 */
+
+			tracker_db_interface_execute_query (iface, NULL,
+				"DELETE FROM \"%s_%s\"",
+				service_name,
+				field_name);
+		}
+	}
+
+	g_free (properties);
+}
+
 gboolean
 tracker_data_manager_init (TrackerConfig              *config,
 			   TrackerLanguage            *language,
@@ -781,6 +876,7 @@ tracker_data_manager_init (TrackerConfig              *config,
 	} else {
 		/* load ontology from database into memory */
 		db_get_static_data (iface);
+		create_decomposed_transient_metadata_tables (iface);
 	}
 
 	return TRUE;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]