[tracker] libtracker-miner, tracker-miner-fs: Only update FileLastModified and FileLastAccessed on file attrib
- From: Aleksander Morgado <aleksm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker] libtracker-miner, tracker-miner-fs: Only update FileLastModified and FileLastAccessed on file attrib
- Date: Thu, 23 Sep 2010 15:53:46 +0000 (UTC)
commit e90189ec93ec1f1a586e6c82686dae5268622ed9
Author: Aleksander Morgado <aleksander lanedo com>
Date: Tue Sep 21 11:54:10 2010 +0200
libtracker-miner, tracker-miner-fs: Only update FileLastModified and FileLastAccessed on file attributes updated
src/libtracker-miner/tracker-miner-fs.c | 95 +++++++++++++++++++----
src/libtracker-miner/tracker-miner-fs.h | 4 +
src/miners/fs/tracker-miner-applications.c | 47 ++++++++---
src/miners/fs/tracker-miner-files.c | 118 ++++++++++++++++++++++++++++
4 files changed, 235 insertions(+), 29 deletions(-)
---
diff --git a/src/libtracker-miner/tracker-miner-fs.c b/src/libtracker-miner/tracker-miner-fs.c
index 2bab374..1d65618 100644
--- a/src/libtracker-miner/tracker-miner-fs.c
+++ b/src/libtracker-miner/tracker-miner-fs.c
@@ -184,6 +184,7 @@ enum {
CHECK_DIRECTORY_CONTENTS,
MONITOR_DIRECTORY,
PROCESS_FILE,
+ PROCESS_FILE_ATTRIBUTES,
IGNORE_NEXT_UPDATE_FILE,
FINISHED,
LAST_SIGNAL
@@ -455,6 +456,40 @@ tracker_miner_fs_class_init (TrackerMinerFSClass *klass)
3, G_TYPE_FILE, TRACKER_SPARQL_TYPE_BUILDER, G_TYPE_CANCELLABLE);
/**
+ * TrackerMinerFS::process-file-attributes:
+ * @miner_fs: the #TrackerMinerFS
+ * @file: a #GFile
+ * @builder: a #TrackerSparqlBuilder
+ * @cancellable: a #GCancellable
+ *
+ * The ::process-file-attributes signal is emitted whenever a file should
+ * be processed, but only the attribute-related metadata extracted.
+ *
+ * @builder is the #TrackerSparqlBuilder where all sparql updates
+ * to be performed for @file will be appended. For the properties being
+ * updated, the DELETE statements should be included as well.
+ *
+ * This signal allows both synchronous and asynchronous extraction,
+ * in the synchronous case @cancellable can be safely ignored. In
+ * either case, on successful metadata extraction, implementations
+ * must call tracker_miner_fs_file_notify() to indicate that
+ * processing has finished on @file, so the miner can execute
+ * the SPARQL updates and continue processing other files.
+ *
+ * Returns: %TRUE if the file is accepted for processing,
+ * %FALSE if the file should be ignored.
+ **/
+ signals[PROCESS_FILE_ATTRIBUTES] =
+ g_signal_new ("process-file-attributes",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TrackerMinerFSClass, process_file_attributes),
+ NULL, NULL,
+ tracker_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT,
+ G_TYPE_BOOLEAN,
+ 3, G_TYPE_FILE, TRACKER_SPARQL_TYPE_BUILDER, G_TYPE_CANCELLABLE);
+
+ /**
* TrackerMinerFS::ignore-next-update-file:
* @miner_fs: the #TrackerMinerFS
* @file: a #GFile
@@ -1428,18 +1463,28 @@ do_process_file (TrackerMinerFS *fs,
{
TrackerMinerFSPrivate *priv;
gboolean processing;
+ gboolean attribute_update_only;
+ gchar *uri;
+ uri = g_file_get_uri (data->file);
priv = fs->private;
- g_signal_emit (fs, signals[PROCESS_FILE], 0,
- data->file, data->builder, data->cancellable,
- &processing);
-
- if (!processing) {
- gchar *uri;
+ attribute_update_only = GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (data->file),
+ priv->quark_attribute_updated));
- uri = g_file_get_uri (data->file);
+ if (!attribute_update_only) {
+ g_debug ("Processing file '%s'...", uri);
+ g_signal_emit (fs, signals[PROCESS_FILE], 0,
+ data->file, data->builder, data->cancellable,
+ &processing);
+ } else {
+ g_debug ("Processing attributes in file '%s'...", uri);
+ g_signal_emit (fs, signals[PROCESS_FILE_ATTRIBUTES], 0,
+ data->file, data->builder, data->cancellable,
+ &processing);
+ }
+ if (!processing) {
/* Re-fetch data, since it might have been
* removed in broken implementations
*/
@@ -1456,10 +1501,10 @@ do_process_file (TrackerMinerFS *fs,
priv->processing_pool = g_list_remove (priv->processing_pool, data);
process_data_free (data);
}
-
- g_free (uri);
}
+ g_free (uri);
+
return processing;
}
@@ -1510,13 +1555,31 @@ item_add_or_update_cb (TrackerMinerFS *fs,
gchar *full_sparql;
if (data->urn) {
- g_debug ("Updating item '%s' with urn '%s'", uri, data->urn);
-
- /* update, delete all statements inserted by miner
- except for rdf:type statements as they could cause implicit deletion of user data */
- full_sparql = g_strdup_printf ("DELETE { GRAPH <%s> { <%s> ?p ?o } } WHERE { GRAPH <%s> { <%s> ?p ?o FILTER (?p != rdf:type) } } %s",
- TRACKER_MINER_FS_GRAPH_URN, data->urn, TRACKER_MINER_FS_GRAPH_URN,
- data->urn, tracker_sparql_builder_get_result (data->builder));
+ gboolean attribute_update_only;
+
+ attribute_update_only = GPOINTER_TO_INT (g_object_steal_qdata (G_OBJECT (data->file),
+ fs->private->quark_attribute_updated));
+ g_debug ("Updating item '%s' with urn '%s'%s",
+ uri,
+ data->urn,
+ attribute_update_only ? " (attributes only)" : "");
+
+ if (!attribute_update_only) {
+ /* update, delete all statements inserted by miner
+ * except for rdf:type statements as they could cause implicit deletion of user data */
+ full_sparql = g_strdup_printf ("DELETE { GRAPH <%s> { <%s> ?p ?o } } "
+ "WHERE { GRAPH <%s> { <%s> ?p ?o FILTER (?p != rdf:type) } } %s",
+ TRACKER_MINER_FS_GRAPH_URN,
+ data->urn,
+ TRACKER_MINER_FS_GRAPH_URN,
+ data->urn,
+ tracker_sparql_builder_get_result (data->builder));
+ } else {
+ /* Do not drop graph if only updating attributes, the SPARQL builder
+ * will already contain the necessary DELETE statements for the properties
+ * being updated */
+ full_sparql = g_strdup (tracker_sparql_builder_get_result (data->builder));
+ }
} else {
g_debug ("Creating new item '%s'", uri);
diff --git a/src/libtracker-miner/tracker-miner-fs.h b/src/libtracker-miner/tracker-miner-fs.h
index 3e7acac..c8f1757 100644
--- a/src/libtracker-miner/tracker-miner-fs.h
+++ b/src/libtracker-miner/tracker-miner-fs.h
@@ -92,6 +92,10 @@ typedef struct {
gboolean (* monitor_directory) (TrackerMinerFS *fs,
GFile *file);
void (* finished) (TrackerMinerFS *fs);
+ gboolean (* process_file_attributes) (TrackerMinerFS *fs,
+ GFile *file,
+ TrackerSparqlBuilder *builder,
+ GCancellable *cancellable);
} TrackerMinerFSClass;
GType tracker_miner_fs_get_type (void) G_GNUC_CONST;
diff --git a/src/miners/fs/tracker-miner-applications.c b/src/miners/fs/tracker-miner-applications.c
index 6b756f9..3ad4346 100644
--- a/src/miners/fs/tracker-miner-applications.c
+++ b/src/miners/fs/tracker-miner-applications.c
@@ -31,19 +31,23 @@
#define SOFTWARE_CATEGORY_URN_PREFIX "urn:software-category:"
#define THEME_ICON_URN_PREFIX "urn:theme-icon:"
-static void miner_applications_finalize (GObject *object);
-static void miner_applications_constructed (GObject *object);
-
-static gboolean miner_applications_check_file (TrackerMinerFS *fs,
- GFile *file);
-static gboolean miner_applications_check_directory (TrackerMinerFS *fs,
- GFile *file);
-static gboolean miner_applications_process_file (TrackerMinerFS *fs,
- GFile *file,
- TrackerSparqlBuilder *sparql,
- GCancellable *cancellable);
-static gboolean miner_applications_monitor_directory (TrackerMinerFS *fs,
- GFile *file);
+static void miner_applications_finalize (GObject *object);
+static void miner_applications_constructed (GObject *object);
+
+static gboolean miner_applications_check_file (TrackerMinerFS *fs,
+ GFile *file);
+static gboolean miner_applications_check_directory (TrackerMinerFS *fs,
+ GFile *file);
+static gboolean miner_applications_process_file (TrackerMinerFS *fs,
+ GFile *file,
+ TrackerSparqlBuilder *sparql,
+ GCancellable *cancellable);
+static gboolean miner_applications_process_file_attributes (TrackerMinerFS *fs,
+ GFile *file,
+ TrackerSparqlBuilder *sparql,
+ GCancellable *cancellable);
+static gboolean miner_applications_monitor_directory (TrackerMinerFS *fs,
+ GFile *file);
static GQuark miner_applications_error_quark = 0;
@@ -73,6 +77,7 @@ tracker_miner_applications_class_init (TrackerMinerApplicationsClass *klass)
miner_fs_class->check_directory = miner_applications_check_directory;
miner_fs_class->monitor_directory = miner_applications_monitor_directory;
miner_fs_class->process_file = miner_applications_process_file;
+ miner_fs_class->process_file_attributes = miner_applications_process_file_attributes;
miner_applications_error_quark = g_quark_from_static_string ("TrackerMinerApplications");
}
@@ -615,6 +620,22 @@ miner_applications_process_file (TrackerMinerFS *fs,
return TRUE;
}
+static gboolean
+miner_applications_process_file_attributes (TrackerMinerFS *fs,
+ GFile *file,
+ TrackerSparqlBuilder *sparql,
+ GCancellable *cancellable)
+{
+ gchar *uri;
+
+ /* We don't care about file attribute changes here */
+ uri = g_file_get_uri (file);
+ g_debug ("Ignoring file attribute changes in '%s'", uri);
+ g_free (uri);
+
+ return FALSE;
+}
+
TrackerMiner *
tracker_miner_applications_new (void)
{
diff --git a/src/miners/fs/tracker-miner-files.c b/src/miners/fs/tracker-miner-files.c
index 1ab9577..a5d2170 100644
--- a/src/miners/fs/tracker-miner-files.c
+++ b/src/miners/fs/tracker-miner-files.c
@@ -187,6 +187,10 @@ static gboolean miner_files_process_file (TrackerMinerFS *f
GFile *file,
TrackerSparqlBuilder *sparql,
GCancellable *cancellable);
+static gboolean miner_files_process_file_attributes (TrackerMinerFS *fs,
+ GFile *file,
+ TrackerSparqlBuilder *sparql,
+ GCancellable *cancellable);
static gboolean miner_files_monitor_directory (TrackerMinerFS *fs,
GFile *file);
static gboolean miner_files_ignore_next_update_file (TrackerMinerFS *fs,
@@ -233,6 +237,7 @@ tracker_miner_files_class_init (TrackerMinerFilesClass *klass)
miner_fs_class->check_directory_contents = miner_files_check_directory_contents;
miner_fs_class->monitor_directory = miner_files_monitor_directory;
miner_fs_class->process_file = miner_files_process_file;
+ miner_fs_class->process_file_attributes = miner_files_process_file_attributes;
miner_fs_class->ignore_next_update_file = miner_files_ignore_next_update_file;
miner_fs_class->finished = miner_files_finished;
@@ -2219,6 +2224,119 @@ miner_files_process_file (TrackerMinerFS *fs,
return TRUE;
}
+static void
+process_file_attributes_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TrackerSparqlBuilder *sparql;
+ ProcessFileData *data;
+ const gchar *urn;
+ GFileInfo *file_info;
+ guint64 time_;
+ GFile *file;
+ gchar *uri;
+ GError *error = NULL;
+ gboolean is_iri;
+
+ data = user_data;
+ file = G_FILE (object);
+ sparql = data->sparql;
+ file_info = g_file_query_info_finish (file, result, &error);
+
+ if (error) {
+ /* Something bad happened, notify about the error */
+ tracker_miner_fs_file_notify (TRACKER_MINER_FS (data->miner), file, error);
+ process_file_data_free (data);
+ g_error_free (error);
+ return;
+ }
+
+ uri = g_file_get_uri (file);
+ urn = miner_files_get_file_urn (TRACKER_MINER_FILES (data->miner), file, &is_iri);
+
+ /* We MUST have an IRI in attributes updating */
+ if (!is_iri) {
+ error = g_error_new_literal (miner_files_error_quark,
+ 0,
+ "Received request to update attributes but no IRI available!");
+ /* Notify about the error */
+ tracker_miner_fs_file_notify (TRACKER_MINER_FS (data->miner), file, error);
+ process_file_data_free (data);
+ g_error_free (error);
+ return;
+ }
+
+ /* DELETE old property values */
+ tracker_sparql_builder_delete_open (sparql, TRACKER_MINER_FS_GRAPH_URN);
+ tracker_sparql_builder_subject_iri (sparql, urn);
+ tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified");
+ tracker_sparql_builder_object_variable (sparql, "lastmodified");
+ tracker_sparql_builder_predicate (sparql, "nfo:fileLastAccessed");
+ tracker_sparql_builder_object_variable (sparql, "lastaccessed");
+ tracker_sparql_builder_delete_close (sparql);
+
+ tracker_sparql_builder_where_open (sparql);
+ tracker_sparql_builder_subject_iri (sparql, urn);
+ tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified");
+ tracker_sparql_builder_object_variable (sparql, "lastmodified");
+ tracker_sparql_builder_predicate (sparql, "nfo:fileLastAccessed");
+ tracker_sparql_builder_object_variable (sparql, "lastaccessed");
+ tracker_sparql_builder_where_close (sparql);
+
+ /* INSERT new property values */
+ tracker_sparql_builder_insert_open (sparql, TRACKER_MINER_FS_GRAPH_URN);
+ tracker_sparql_builder_subject_iri (sparql, urn);
+
+ time_ = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+ tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified");
+ tracker_sparql_builder_object_date (sparql, (time_t *) &time_);
+
+ time_ = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_ACCESS);
+ tracker_sparql_builder_predicate (sparql, "nfo:fileLastAccessed");
+ tracker_sparql_builder_object_date (sparql, (time_t *) &time_);
+
+ tracker_sparql_builder_insert_close (sparql);
+
+ g_object_unref (file_info);
+ g_free (uri);
+
+ /* Notify about the success */
+ tracker_miner_fs_file_notify (TRACKER_MINER_FS (data->miner), data->file, NULL);
+
+ process_file_data_free (data);
+}
+
+static gboolean
+miner_files_process_file_attributes (TrackerMinerFS *fs,
+ GFile *file,
+ TrackerSparqlBuilder *sparql,
+ GCancellable *cancellable)
+{
+ ProcessFileData *data;
+ const gchar *attrs;
+
+ data = g_slice_new0 (ProcessFileData);
+ data->miner = g_object_ref (fs);
+ data->cancellable = g_object_ref (cancellable);
+ data->sparql = g_object_ref (sparql);
+ data->file = g_object_ref (file);
+
+ /* Query only attributes that may change in an ATTRIBUTES_UPDATED event */
+ attrs = G_FILE_ATTRIBUTE_TIME_MODIFIED ","
+ G_FILE_ATTRIBUTE_TIME_ACCESS;
+
+ g_file_query_info_async (file,
+ attrs,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ process_file_attributes_cb,
+ data);
+
+ return TRUE;
+}
+
static gboolean
miner_files_ignore_next_update_file (TrackerMinerFS *fs,
GFile *file,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]