[tracker/writeback: 16/16] Handling writeback in tracker-miner-fs



commit adac8bbcdc732071640cbafcc14dc7d6e668cbbe
Author: Philip Van Hoof <philip codeminded be>
Date:   Fri Nov 20 14:15:11 2009 +0100

    Handling writeback in tracker-miner-fs
    
    When a writeback takes place, tracker-miner-fs must NOT create a SPARQL Update
    that contains any predicates that are marked as tracker:notify. For this
    reason I added a mechanism for marking a subject in tracker-miner-fs's queues:
    The first next time the subject is to be analyzed it checks whether the
    subject was marked. If it was marked then instead of doing a full extraction,
    tracker-miner-fs will only get a few properties (like mime, mtime, size).
    
    * MIME because the content-type of a file might have changed by writeback
    * Size because the size of the file might have changed by writeback
    * Mtime because the writeback will update the file's mtime, and we want
      to sync tracker-store with that too

 data/dbus/tracker-miner.xml                        |    5 +
 src/libtracker-miner/tracker-miner-dbus.h          |    4 +
 src/libtracker-miner/tracker-miner-fs.c            |  184 +++++++++++++++++++-
 src/libtracker-miner/tracker-miner-fs.h            |    5 +
 src/libtracker-miner/tracker-miner-manager.c       |   52 ++++++
 src/libtracker-miner/tracker-miner-manager.h       |    4 +
 src/libtracker-miner/tracker-miner.c               |   56 ++++++
 src/libtracker-miner/tracker-miner.h               |    5 +
 src/tracker-miner-fs/tracker-miner-files.c         |   70 ++++++++
 src/tracker-writeback/Makefile.am                  |   51 +++---
 .../tracker-writeback-dispatcher.c                 |    5 +
 src/tracker-writeback/tracker-writeback-file.c     |   55 ++++---
 src/tracker-writeback/tracker-writeback-file.h     |   11 +-
 src/tracker-writeback/tracker-writeback.c          |   12 ++
 src/tracker-writeback/tracker-writeback.h          |   12 +-
 15 files changed, 472 insertions(+), 59 deletions(-)
---
diff --git a/data/dbus/tracker-miner.xml b/data/dbus/tracker-miner.xml
index fe3d143..07e3ece 100644
--- a/data/dbus/tracker-miner.xml
+++ b/data/dbus/tracker-miner.xml
@@ -27,6 +27,11 @@
       <arg type="i" name="cookie" direction="in" />
     </method>
 
+    <method name="Writeback">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="as" name="subjects" direction="in" />
+    </method>
+
     <!-- Signals -->
     <signal name="Started" />
     <signal name="Stopped">
diff --git a/src/libtracker-miner/tracker-miner-dbus.h b/src/libtracker-miner/tracker-miner-dbus.h
index dd6d254..be62f6d 100644
--- a/src/libtracker-miner/tracker-miner-dbus.h
+++ b/src/libtracker-miner/tracker-miner-dbus.h
@@ -55,6 +55,10 @@ void tracker_miner_dbus_resume            (TrackerMiner           *miner,
 					   gint                    cookie,
 					   DBusGMethodInvocation  *context,
 					   GError                **error);
+void tracker_miner_dbus_writeback         (TrackerMiner           *miner,
+					   const GStrv             subjects,
+					   DBusGMethodInvocation  *context,
+					   GError                **error);
 
 G_END_DECLS
 
diff --git a/src/libtracker-miner/tracker-miner-fs.c b/src/libtracker-miner/tracker-miner-fs.c
index c821b69..5f5e181 100644
--- a/src/libtracker-miner/tracker-miner-fs.c
+++ b/src/libtracker-miner/tracker-miner-fs.c
@@ -80,6 +80,7 @@ struct TrackerMinerFSPrivate {
 	GQueue         *items_updated;
 	GQueue         *items_deleted;
 	GQueue         *items_moved;
+	GHashTable     *items_writeback;
 
 	GQuark          quark_ignore_file;
 
@@ -120,7 +121,8 @@ enum {
 	QUEUE_CREATED,
 	QUEUE_UPDATED,
 	QUEUE_DELETED,
-	QUEUE_MOVED
+	QUEUE_MOVED,
+	QUEUE_WRITEBACK
 };
 
 enum {
@@ -129,6 +131,7 @@ enum {
 	CHECK_DIRECTORY_CONTENTS,
 	MONITOR_DIRECTORY,
 	PROCESS_FILE,
+	WRITEBACK_FILE,
 	FINISHED,
 	LAST_SIGNAL
 };
@@ -158,6 +161,8 @@ static void           miner_started                (TrackerMiner   *miner);
 static void           miner_stopped                (TrackerMiner   *miner);
 static void           miner_paused                 (TrackerMiner   *miner);
 static void           miner_resumed                (TrackerMiner   *miner);
+static void           miner_writeback              (TrackerMiner   *miner,
+                                                    const GStrv     subjects);
 
 static DirectoryData *directory_data_new           (GFile          *file,
 						    gboolean        recurse);
@@ -230,6 +235,7 @@ tracker_miner_fs_class_init (TrackerMinerFSClass *klass)
         miner_class->stopped = miner_stopped;
 	miner_class->paused  = miner_paused;
 	miner_class->resumed = miner_resumed;
+	miner_class->writeback = miner_writeback;
 
 	fs_class->check_file        = fs_defaults;
 	fs_class->check_directory   = fs_defaults;
@@ -365,6 +371,33 @@ tracker_miner_fs_class_init (TrackerMinerFSClass *klass)
 			      tracker_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT,
 			      G_TYPE_BOOLEAN,
 			      3, G_TYPE_FILE, TRACKER_TYPE_SPARQL_BUILDER, G_TYPE_CANCELLABLE),
+
+	/**
+	 * TrackerMinerFS::writeback-file:
+	 * @miner_fs: the #TrackerMinerFS
+	 * @file: a #GFile
+	 * @builder: a #TrackerSparqlBuilder
+	 * @cancellable: a #GCancellable
+	 *
+	 * The ::writeback-file signal is emitted whenever a file should
+	 * be marked as writeback, and it's metadata prepared for that.
+	 *
+	 * @builder is the #TrackerSparqlBuilder where all sparql updates
+	 * to be performed for @file will be appended.
+	 *
+	 * Returns: %TRUE on success
+	 *          %FALSE on failure
+	 **/
+	signals[WRITEBACK_FILE] =
+		g_signal_new ("writeback-file",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (TrackerMinerFSClass, writeback_file),
+			      NULL, NULL,
+			      tracker_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT,
+			      G_TYPE_BOOLEAN,
+			      3, G_TYPE_FILE, TRACKER_TYPE_SPARQL_BUILDER, G_TYPE_CANCELLABLE),
+
 	/**
 	 * TrackerMinerFS::finished:
 	 * @miner_fs: the #TrackerMinerFS
@@ -411,6 +444,9 @@ tracker_miner_fs_init (TrackerMinerFS *object)
 	priv->items_updated = g_queue_new ();
 	priv->items_deleted = g_queue_new ();
 	priv->items_moved = g_queue_new ();
+	priv->items_writeback = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                                               (GDestroyNotify) g_free,
+	                                               (GDestroyNotify) NULL);
 
 	/* Set up the crawlers now we have config and hal */
 	priv->crawler = tracker_crawler_new ();
@@ -542,6 +578,8 @@ fs_finalize (GObject *object)
 	g_queue_foreach (priv->items_created, (GFunc) g_object_unref, NULL);
 	g_queue_free (priv->items_created);
 
+	g_hash_table_unref (priv->items_writeback);
+
 	G_OBJECT_CLASS (tracker_miner_fs_parent_class)->finalize (object);
 }
 
@@ -671,6 +709,25 @@ miner_resumed (TrackerMiner *miner)
 	}
 }
 
+
+static void
+miner_writeback (TrackerMiner *miner, const GStrv subjects)
+{
+	TrackerMinerFS *fs;
+	guint n;
+
+	fs = TRACKER_MINER_FS (miner);
+
+	for (n = 0; subjects[n] != NULL; n++) {
+		g_hash_table_insert (fs->private->items_writeback,
+		                     g_strdup (subjects[n]),
+		                     GINT_TO_POINTER (TRUE));
+	}
+
+	item_queue_handlers_set_up (fs);
+}
+
+
 static DirectoryData *
 directory_data_new (GFile    *file,
 		    gboolean  recurse)
@@ -1008,6 +1065,100 @@ item_remove (TrackerMinerFS *fs,
 	return FALSE;
 }
 
+static gboolean
+item_writeback (TrackerMinerFS *fs,
+                GFile          *file,
+                GFile          *source_file)
+{
+	TrackerSparqlBuilder *sparql;
+	gchar *uri;
+	gboolean success = FALSE;
+	GCancellable *cancellable;
+	GFile *working_file;
+
+	/* While we are in writeback:
+	 * o. We always ignore deletes because it's never the final operation
+	 *    of a writeback. We have a delete when both are null.
+	 * o. A create means the writeback used rename(). This is the final 
+	 *    operation of a writeback and thus we make the update query.
+	 *    We have a create when file == null and source_file != null
+	 * o. A move means the writeback used rename(). This is the final 
+	 *    operation of a writeback and thus we make the update query.
+	 *    We have a move when both file and source_file aren't null.
+	 * o. A update means the writeback didn't use rename(). This is the
+	 *    final operation of a writeback and thus we make the update query.
+	 *    An update means that file != null and source_file == null. */
+
+	/* Happens on delete while in writeback */
+	if (!file && !source_file) {
+		return TRUE;
+	}
+
+	/* Create or update, we are the final one so we make the update query */
+
+	if (!file && source_file) {
+		/* Happens on create while in writeback */
+		working_file = source_file;
+	} else {
+		/* Happens on update while in writeback */
+		working_file = file;
+	}
+
+	uri = g_file_get_uri (working_file);
+
+	g_debug ("Updating item: '%s' (Writeback event)", uri);
+
+	if (!item_query_exists (fs, working_file)) {
+		g_debug ("  File does not exist anyway (uri:'%s')", uri);
+		return TRUE;
+	}
+
+	cancellable = g_cancellable_new ();
+	sparql = tracker_sparql_builder_new_update ();
+	g_object_ref (working_file);
+
+	/* Writeback */
+	g_signal_emit (fs, signals[WRITEBACK_FILE], 0,
+	               working_file, sparql, cancellable, &success);
+
+	if (success) {
+		gchar *query;
+
+		/* Perhaps we should move the DELETE to tracker-miner-files.c? 
+		 * Or we add support for DELETE to TrackerSparqlBuilder ofcrs */
+
+		query = g_strdup_printf ("DELETE FROM <%s> { <%s> "
+		                           "nfo:fileSize ?unknown1 ;\n\t"
+		                           "nfo:fileLastModified ?unknown2 ;\n\t"
+		                           "nfo:fileLastAccessed ?unknown3 ;\n\t"
+		                           "nie:mimeType ?unknown4 \n"
+		                         "} WHERE { <%s> "
+		                           "nfo:fileSize ?unknown1 ;\n\t"
+		                           "nfo:fileLastModified ?unknown2 ;\n\t"
+		                           "nfo:fileLastAccessed ?unknown3 ;\n\t"
+		                           "nie:mimeType ?unknown4 \n"
+		                         "} \n %s", 
+		                         uri, uri, uri,
+		                         tracker_sparql_builder_get_result (sparql));
+
+		tracker_miner_execute_batch_update (TRACKER_MINER (fs),
+		                                    query,
+		                                    NULL, NULL, NULL);
+
+		g_free (query);
+	}
+
+	g_hash_table_remove (fs->private->items_writeback, uri);
+
+	g_object_unref (sparql);
+	g_object_unref (working_file);
+	g_object_unref (cancellable);
+
+	g_free (uri);
+
+	return FALSE;
+}
+
 static void
 item_update_uri_recursively_cb (TrackerMiner *miner,
 				GPtrArray    *result,
@@ -1166,6 +1317,18 @@ item_move (TrackerMinerFS *fs,
 	return TRUE;
 }
 
+static gboolean
+check_writeback (TrackerMinerFS *fs, GFile *queue_file)
+{
+	gchar *uri = g_file_get_uri (queue_file);
+	if (g_hash_table_lookup (fs->private->items_writeback, uri)) {
+		g_free (uri);
+		return TRUE;
+	}
+	g_free (uri);
+	return FALSE;
+}
+
 static gint
 item_queue_get_next_file (TrackerMinerFS  *fs,
 			  GFile          **file,
@@ -1177,14 +1340,23 @@ item_queue_get_next_file (TrackerMinerFS  *fs,
 	/* Deleted items first */
 	queue_file = g_queue_pop_head (fs->private->items_deleted);
 	if (queue_file) {
-		*file = queue_file;
 		*source_file = NULL;
+		if (check_writeback (fs, queue_file)) {
+			*file = NULL;
+			return QUEUE_WRITEBACK;
+		}
+		*file = queue_file;
 		return QUEUE_DELETED;
 	}
 
 	/* Created items next */
 	queue_file = g_queue_pop_head (fs->private->items_created);
 	if (queue_file) {
+		if (check_writeback (fs, queue_file)) {
+			*file = NULL;
+			*source_file = queue_file;
+			return QUEUE_WRITEBACK;
+		}
 		*file = queue_file;
 		*source_file = NULL;
 		return QUEUE_CREATED;
@@ -1195,6 +1367,8 @@ item_queue_get_next_file (TrackerMinerFS  *fs,
 	if (queue_file) {
 		*file = queue_file;
 		*source_file = NULL;
+		if (check_writeback (fs, queue_file))
+			return QUEUE_WRITEBACK;
 		return QUEUE_UPDATED;
 	}
 
@@ -1204,7 +1378,8 @@ item_queue_get_next_file (TrackerMinerFS  *fs,
 		*file = g_object_ref (data->file);
 		*source_file = g_object_ref (data->source_file);
 		item_moved_data_free (data);
-
+		if (check_writeback (fs, *file))
+			return QUEUE_WRITEBACK;
 		return QUEUE_MOVED;
 	}
 
@@ -1297,6 +1472,9 @@ item_queue_handlers_cb (gpointer user_data)
 	case QUEUE_UPDATED:
 		keep_processing = item_add_or_update (fs, file);
 		break;
+	case QUEUE_WRITEBACK:
+		keep_processing = item_writeback (fs, file, source_file);
+		break;
 	default:
 		g_assert_not_reached ();
 	}
diff --git a/src/libtracker-miner/tracker-miner-fs.h b/src/libtracker-miner/tracker-miner-fs.h
index 6d933b0..f041da7 100644
--- a/src/libtracker-miner/tracker-miner-fs.h
+++ b/src/libtracker-miner/tracker-miner-fs.h
@@ -79,6 +79,11 @@ typedef struct {
 					    GFile                *file,
 					    TrackerSparqlBuilder *builder,
 					    GCancellable         *cancellable);
+	gboolean (* writeback_file)        (TrackerMinerFS       *fs,
+					    GFile                *file,
+					    TrackerSparqlBuilder *builder,
+					    GCancellable         *cancellable);
+
 	gboolean (* monitor_directory)     (TrackerMinerFS       *fs,
 					    GFile                *file);
 	void     (* finished)              (TrackerMinerFS       *fs);
diff --git a/src/libtracker-miner/tracker-miner-manager.c b/src/libtracker-miner/tracker-miner-manager.c
index ca1e75f..813032b 100644
--- a/src/libtracker-miner/tracker-miner-manager.c
+++ b/src/libtracker-miner/tracker-miner-manager.c
@@ -914,3 +914,55 @@ tracker_miner_manager_get_description (TrackerMinerManager *manager,
 
 	return NULL;
 }
+
+
+/**
+ * tracker_miner_manager_writeback:
+ * @manager: a #TrackerMinerManager.
+ * @miner: miner reference
+ * @subjects: subjects to mark as writeback
+ *
+ * Asks @miner to mark @subjects as writeback
+ *
+ * Returns: %TRUE if the miner was asked to writeback successfully.
+ **/
+gboolean
+tracker_miner_manager_writeback (TrackerMinerManager *manager,
+                                 const gchar         *miner,
+                                 const gchar        **subjects)
+{
+	DBusGProxy *proxy;
+	const gchar *app_name;
+	GError *error = NULL;
+
+	g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
+	g_return_val_if_fail (miner != NULL, FALSE);
+
+	proxy = find_miner_proxy (manager, miner);
+
+	if (!proxy) {
+		g_warning ("No D-Bus proxy found for miner '%s'", miner);
+		return FALSE;
+	}
+
+	/* Find a reasonable app name */
+	app_name = g_get_application_name ();
+
+	if (!app_name) {
+		app_name = g_get_prgname ();
+	}
+
+	if (!app_name) {
+		app_name = "TrackerMinerManager client";
+	}
+
+	org_freedesktop_Tracker1_Miner_writeback (proxy, subjects, &error);
+
+	if (error) {
+		g_warning ("Could not writeback miner '%s': %s", miner, error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	return TRUE;
+}
diff --git a/src/libtracker-miner/tracker-miner-manager.h b/src/libtracker-miner/tracker-miner-manager.h
index bd8f28e..ce3148a 100644
--- a/src/libtracker-miner/tracker-miner-manager.h
+++ b/src/libtracker-miner/tracker-miner-manager.h
@@ -93,12 +93,16 @@ gboolean tracker_miner_manager_get_status (TrackerMinerManager  *manager,
 					   const gchar          *miner,
 					   gchar               **status,
 					   gdouble              *progress);
+gboolean tracker_miner_manager_writeback  (TrackerMinerManager *manager,
+					   const gchar         *miner,
+					   const gchar        **subjects);
 
 const gchar * tracker_miner_manager_get_display_name (TrackerMinerManager *manager,
 						      const gchar         *miner);
 const gchar * tracker_miner_manager_get_description  (TrackerMinerManager *manager,
 						      const gchar         *miner);
 
+
 G_END_DECLS
 
 #endif /* __LIBTRACKERMINER_MANAGER_H__ */
diff --git a/src/libtracker-miner/tracker-miner.c b/src/libtracker-miner/tracker-miner.c
index 5d02e46..74db4b4 100644
--- a/src/libtracker-miner/tracker-miner.c
+++ b/src/libtracker-miner/tracker-miner.c
@@ -100,6 +100,7 @@ enum {
 	TERMINATED,
 	PROGRESS,
 	ERROR,
+	WRITEBACK,
 	LAST_SIGNAL
 };
 
@@ -247,6 +248,25 @@ tracker_miner_class_init (TrackerMinerClass *klass)
 			      G_TYPE_NONE, 1,
 			      G_TYPE_POINTER);
 
+	/**
+	 * TrackerMiner::writeback:
+	 * @miner: the #TrackerMiner
+	 * @subjects: the subjects to mark as writeback
+	 *
+	 * the ::writeback signal is emitted in the miner
+	 * right after it has been asked to mark @subjects as writeback through
+	 * tracker_miner_writeback().
+	 **/
+	signals[WRITEBACK] =
+		g_signal_new ("writeback",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (TrackerMinerClass, writeback),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__BOXED,
+			      G_TYPE_NONE, 1,
+			      G_TYPE_STRV);
+
 	g_object_class_install_property (object_class,
 					 PROP_NAME,
 					 g_param_spec_string ("name",
@@ -711,6 +731,21 @@ tracker_miner_stop (TrackerMiner *miner)
 }
 
 /**
+ * tracker_miner_writeback:
+ * @miner: a #TrackerMiner
+ * @subjects: the subjects to mark as writeback
+ *
+ * Tells the miner to mark @subjects are writeback.
+ **/
+void
+tracker_miner_writeback (TrackerMiner *miner, const GStrv subjects)
+{
+	g_return_if_fail (TRACKER_IS_MINER (miner));
+
+	g_signal_emit (miner, signals[WRITEBACK], 0, subjects);
+}
+
+/**
  * tracker_miner_is_started:
  * @miner: a #TrackerMiner
  *
@@ -1288,3 +1323,24 @@ tracker_miner_dbus_resume (TrackerMiner           *miner,
 
 	tracker_dbus_request_success (request_id);
 }
+
+void
+tracker_miner_dbus_writeback (TrackerMiner           *miner,
+                              const GStrv             subjects,
+                              DBusGMethodInvocation  *context,
+                              GError                **error)
+{
+	guint request_id;
+
+	request_id = tracker_dbus_get_next_request_id ();
+
+	tracker_dbus_async_return_if_fail (miner != NULL, context);
+
+	tracker_dbus_request_new (request_id, "%s()", __PRETTY_FUNCTION__);
+
+	tracker_miner_writeback (miner, subjects);
+
+	dbus_g_method_return (context);
+
+	tracker_dbus_request_success (request_id);
+}
diff --git a/src/libtracker-miner/tracker-miner.h b/src/libtracker-miner/tracker-miner.h
index af046e4..04f456e 100644
--- a/src/libtracker-miner/tracker-miner.h
+++ b/src/libtracker-miner/tracker-miner.h
@@ -81,6 +81,9 @@ typedef struct {
 
 	void (* error)      (TrackerMiner *miner,
 			     GError       *error);
+	void (* writeback)  (TrackerMiner *miner,
+			     const GStrv   subjects);
+
 } TrackerMinerClass;
 
 typedef void (* TrackerMinerUpdateCallback) (TrackerMiner *miner,
@@ -96,6 +99,8 @@ GQuark	       tracker_miner_error_quark    (void);
 
 void           tracker_miner_start          (TrackerMiner  *miner);
 void           tracker_miner_stop           (TrackerMiner  *miner);
+void           tracker_miner_writeback      (TrackerMiner  *miner,
+                                             const GStrv    subjects);
 
 gboolean       tracker_miner_is_started     (TrackerMiner  *miner);
 
diff --git a/src/tracker-miner-fs/tracker-miner-files.c b/src/tracker-miner-fs/tracker-miner-files.c
index 0e0bbdb..bacf4bd 100644
--- a/src/tracker-miner-fs/tracker-miner-files.c
+++ b/src/tracker-miner-fs/tracker-miner-files.c
@@ -136,6 +136,10 @@ static gboolean miner_files_process_file      (TrackerMinerFS       *fs,
 					       GCancellable         *cancellable);
 static gboolean miner_files_monitor_directory (TrackerMinerFS       *fs,
 					       GFile                *file);
+static gboolean miner_files_writeback_file    (TrackerMinerFS       *fs,
+					       GFile                *file,
+					       TrackerSparqlBuilder *sparql,
+					       GCancellable         *cancellable);
 
 G_DEFINE_TYPE (TrackerMinerFiles, tracker_miner_files, TRACKER_TYPE_MINER_FS)
 
@@ -155,6 +159,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->writeback_file = miner_files_writeback_file;
 
        	g_object_class_install_property (object_class,
 					 PROP_CONFIG,
@@ -1379,6 +1384,71 @@ miner_files_process_file (TrackerMinerFS       *fs,
 	return TRUE;
 }
 
+static gboolean
+miner_files_writeback_file (TrackerMinerFS       *fs,
+                            GFile                *file,
+                            TrackerSparqlBuilder *sparql,
+                            GCancellable         *cancellable)
+{
+	const gchar *attrs;
+	const gchar *mime_type;
+	GFileInfo *file_info;
+	guint64 time_;
+	gchar *uri;
+	GError *error = NULL;
+
+	attrs = G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+		G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+		G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+		G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+		G_FILE_ATTRIBUTE_TIME_MODIFIED ","
+		G_FILE_ATTRIBUTE_TIME_ACCESS;
+
+	file_info = g_file_query_info (file, attrs,
+	                               G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+	                               cancellable, &error);
+
+	if (error) {
+		g_warning ("Can't writeback: '%s'", error->message);
+		g_clear_error (&error);
+		return FALSE;
+	}
+
+	uri = g_file_get_uri (file);
+	mime_type = g_file_info_get_content_type (file_info);
+
+	/* For writeback we only write a few properties back. These properties
+	 * should NEVER be marked as tracker:writeback in the ontology ! */
+
+	tracker_sparql_builder_insert_open (sparql, uri);
+
+	tracker_sparql_builder_subject_iri (sparql, uri);
+	tracker_sparql_builder_predicate (sparql, "a");
+	tracker_sparql_builder_object (sparql, "nfo:FileDataObject");
+
+	tracker_sparql_builder_predicate (sparql, "nfo:fileSize");
+	tracker_sparql_builder_object_int64 (sparql, g_file_info_get_size (file_info));
+
+	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_predicate (sparql, "nie:mimeType");
+	tracker_sparql_builder_object_string (sparql, mime_type);
+
+	g_object_unref (file_info);
+	g_free (uri);
+
+	tracker_sparql_builder_insert_close (sparql);
+
+	return TRUE;
+}
+
+
 TrackerMiner *
 tracker_miner_files_new (TrackerConfig *config)
 {
diff --git a/src/tracker-writeback/Makefile.am b/src/tracker-writeback/Makefile.am
index 8ba7a20..1354efa 100644
--- a/src/tracker-writeback/Makefile.am
+++ b/src/tracker-writeback/Makefile.am
@@ -3,19 +3,20 @@ include $(top_srcdir)/Makefile.decl
 module_flags = -module -avoid-version -no-undefined
 modulesdir = $(libdir)/tracker-$(TRACKER_API_VERSION)/writeback-modules
 
-INCLUDES = 								\
-	-DLOCALEDIR=\""$(localedir)"\" 					\
-	-DMODULESDIR=\"$(modulesdir)\"					\
-	-DG_LOG_DOMAIN=\"Tracker\"					\
-	-DTRACKER_COMPILATION						\
-	-DWRITEBACK_MODULES_DIR=\""$(modulesdir)"\"			\
-	-I$(top_srcdir)/src 						\
-	$(WARN_CFLAGS)							\
-	$(GLIB2_CFLAGS)							\
-	$(GCOV_CFLAGS)							\
-	$(GMODULE_CFLAGS) 						\
-	$(DBUS_CFLAGS)							\
-	$(ID3LIB_CFLAGS)						\
+INCLUDES = 							\
+	-DLOCALEDIR=\""$(localedir)"\" 				\
+	-DMODULESDIR=\"$(modulesdir)\"				\
+	-DG_LOG_DOMAIN=\"Tracker\"				\
+	-DTRACKER_COMPILATION					\
+	-DWRITEBACK_MODULES_DIR=\""$(modulesdir)"\" 		\
+	-I$(top_srcdir)/src 					\
+	$(TRACKER_APPS_CFLAGS)					\
+	$(WARN_CFLAGS)						\
+	$(GLIB2_CFLAGS)						\
+	$(GCOV_CFLAGS)						\
+	$(GMODULE_CFLAGS) 					\
+	$(DBUS_CFLAGS)						\
+	$(ID3LIB_CFLAGS)					\
 	$(EXEMPI_CFLAGS)
 
 modules_LTLIBRARIES =
@@ -41,22 +42,24 @@ endif
 #
 libexec_PROGRAMS = tracker-writeback
 
-tracker_writeback_SOURCES = 						\
-	$(marshal_sources)						\
-	$(dbus_sources)							\
-	tracker-writeback-dispatcher.c					\
-	tracker-writeback-dispatcher.h					\
-	tracker-writeback-file.c					\
-	tracker-writeback-file.h					\
-	tracker-writeback-module.c					\
-	tracker-writeback-module.h					\
-	tracker-writeback.c						\
-	tracker-writeback.h						\
+tracker_writeback_SOURCES = 				\
+	$(marshal_sources)				\
+	$(dbus_sources)					\
+	tracker-writeback-dispatcher.c			\
+	tracker-writeback-dispatcher.h			\
+	tracker-writeback-file.c			\
+	tracker-writeback-file.h			\
+	tracker-writeback-module.c			\
+	tracker-writeback-module.h			\
+	tracker-writeback.c				\
+	tracker-writeback.h				\
 	tracker-main.c
 
 tracker_writeback_LDADD = 						\
 	$(top_builddir)/src/libtracker-common/libtracker-common.la	\
 	$(top_builddir)/src/libtracker-client/libtracker-client- TRACKER_API_VERSION@.la \
+	$(top_builddir)/src/libtracker-miner/libtracker-miner.la 	\
+	$(TRACKER_APPS_LIBS)						\
 	$(DBUS_LIBS)							\
 	$(GMODULE_LIBS)							\
 	$(GTHREAD_LIBS)							\
diff --git a/src/tracker-writeback/tracker-writeback-dispatcher.c b/src/tracker-writeback/tracker-writeback-dispatcher.c
index 165c01a..c91c485 100644
--- a/src/tracker-writeback/tracker-writeback-dispatcher.c
+++ b/src/tracker-writeback/tracker-writeback-dispatcher.c
@@ -36,6 +36,7 @@ typedef struct {
 	GHashTable *modules;
 	DBusData *dbus_data;
 	TrackerClient *client;
+	TrackerMinerManager *manager;
 } TrackerWritebackDispatcherPrivate;
 
 typedef struct {
@@ -208,6 +209,8 @@ tracker_writeback_dispatcher_init (TrackerWritebackDispatcher *dispatcher)
 	                             G_CALLBACK (on_writeback_cb),
 	                             dispatcher,
 	                             NULL);
+
+	priv->manager = tracker_writeback_get_miner_manager ();
 }
 
 static void
@@ -221,6 +224,8 @@ tracker_writeback_dispatcher_finalize (GObject *object)
 		tracker_disconnect (priv->client);
 	}
 
+	g_object_unref (priv->manager);
+
 	dbus_data_free (priv->dbus_data);
 
 	G_OBJECT_CLASS (tracker_writeback_dispatcher_parent_class)->finalize (object);
diff --git a/src/tracker-writeback/tracker-writeback-file.c b/src/tracker-writeback/tracker-writeback-file.c
index 6233a76..a6b370e 100644
--- a/src/tracker-writeback/tracker-writeback-file.c
+++ b/src/tracker-writeback/tracker-writeback-file.c
@@ -19,6 +19,7 @@
  */
 
 #include <libtracker-common/tracker-file-utils.h>
+
 #include "tracker-writeback-file.h"
 
 static gboolean tracker_writeback_file_update_metadata (TrackerWriteback *writeback,
@@ -26,49 +27,59 @@ static gboolean tracker_writeback_file_update_metadata (TrackerWriteback *writeb
 
 G_DEFINE_ABSTRACT_TYPE (TrackerWritebackFile, tracker_writeback_file, TRACKER_TYPE_WRITEBACK)
 
+
+
 static void
 tracker_writeback_file_class_init (TrackerWritebackFileClass *klass)
 {
-        TrackerWritebackClass *writeback_class = TRACKER_WRITEBACK_CLASS (klass);
+	TrackerWritebackClass *writeback_class = TRACKER_WRITEBACK_CLASS (klass);
 
-        writeback_class->update_metadata = tracker_writeback_file_update_metadata;
+	writeback_class->update_metadata = tracker_writeback_file_update_metadata;
 }
 
 static void
 tracker_writeback_file_init (TrackerWritebackFile *writeback_file)
 {
-
 }
 
 static gboolean
 tracker_writeback_file_update_metadata (TrackerWriteback *writeback,
                                         GPtrArray        *values)
 {
-        TrackerWritebackFileClass *writeback_file_class;
-        gboolean retval;
-        GFile *file;
-        GStrv row;
+	TrackerWritebackFileClass *writeback_file_class;
+	gboolean retval;
+	GFile *file;
+	const gchar *subjects[2] = { NULL, NULL };
+	GStrv row;
+	TrackerWritebackFile *self;
+
+	writeback_file_class = TRACKER_WRITEBACK_FILE_GET_CLASS (writeback);
+	self = TRACKER_WRITEBACK_FILE (writeback);
+
+	if (!writeback_file_class->update_file_metadata) {
+		g_critical ("%s doesn't implement update_file_metadata()",
+		            G_OBJECT_TYPE_NAME (writeback));
+		return FALSE;
+	}
 
-        writeback_file_class = TRACKER_WRITEBACK_FILE_GET_CLASS (writeback);
+	/* Get the file from the first row */
+	row = g_ptr_array_index (values, 0);
+	file = g_file_new_for_uri (row[0]);
 
-        if (!writeback_file_class->update_file_metadata) {
-                g_critical ("%s doesn't implement update_file_metadata()",
-                            G_OBJECT_TYPE_NAME (writeback));
-                return FALSE;
-        }
+	tracker_file_lock (file);
 
-        /* Get the file from the first row */
-        row = g_ptr_array_index (values, 0);
-        file = g_file_new_for_uri (row[0]);
+	subjects[0] = row[0];
 
-        tracker_file_lock (file);
+	tracker_miner_manager_writeback (tracker_writeback_get_miner_manager (),
+	                                 "org.freedesktop.Tracker1.Miner.Files",
+	                                 subjects);
 
-        retval = (writeback_file_class->update_file_metadata) (TRACKER_WRITEBACK_FILE (writeback),
-                                                               file, values);
+	retval = (writeback_file_class->update_file_metadata) (TRACKER_WRITEBACK_FILE (writeback),
+	                                                       file, values);
 
-        tracker_file_unlock (file);
+	tracker_file_unlock (file);
 
-        g_object_unref (file);
+	g_object_unref (file);
 
-        return retval;
+	return retval;
 }
diff --git a/src/tracker-writeback/tracker-writeback-file.h b/src/tracker-writeback/tracker-writeback-file.h
index 3e7f539..c646066 100644
--- a/src/tracker-writeback/tracker-writeback-file.h
+++ b/src/tracker-writeback/tracker-writeback-file.h
@@ -19,6 +19,7 @@
  */
 
 #include <gio/gio.h>
+
 #include "tracker-writeback.h"
 
 #ifndef __TRACKER_WRITEBACK_FILE_H__
@@ -37,15 +38,15 @@ typedef struct TrackerWritebackFile TrackerWritebackFile;
 typedef struct TrackerWritebackFileClass TrackerWritebackFileClass;
 
 struct TrackerWritebackFile {
-        TrackerWriteback parent_instance;
+	TrackerWriteback parent_instance;
 };
 
 struct TrackerWritebackFileClass {
-        TrackerWritebackClass parent_class;
+	TrackerWritebackClass parent_class;
 
-        gboolean (* update_file_metadata) (TrackerWritebackFile *writeback_file,
-                                           GFile                *file,
-                                           GPtrArray            *values);
+	gboolean (* update_file_metadata) (TrackerWritebackFile *writeback_file,
+	                                   GFile                *file,
+	                                   GPtrArray            *values);
 };
 
 GType tracker_writeback_file_get_type (void) G_GNUC_CONST;
diff --git a/src/tracker-writeback/tracker-writeback.c b/src/tracker-writeback/tracker-writeback.c
index 0ee37ea..eb878a7 100644
--- a/src/tracker-writeback/tracker-writeback.c
+++ b/src/tracker-writeback/tracker-writeback.c
@@ -22,6 +22,8 @@
 
 G_DEFINE_ABSTRACT_TYPE (TrackerWriteback, tracker_writeback, G_TYPE_OBJECT)
 
+static TrackerMinerManager *manager = NULL;
+
 static void
 tracker_writeback_class_init (TrackerWritebackClass *klass)
 {
@@ -47,3 +49,13 @@ tracker_writeback_update_metadata (TrackerWriteback *writeback,
 
         return FALSE;
 }
+
+TrackerMinerManager*
+tracker_writeback_get_miner_manager (void)
+{
+	if (!manager) {
+		manager = tracker_miner_manager_new ();
+	}
+
+	return manager;
+}
diff --git a/src/tracker-writeback/tracker-writeback.h b/src/tracker-writeback/tracker-writeback.h
index 74bb6b6..26a842f 100644
--- a/src/tracker-writeback/tracker-writeback.h
+++ b/src/tracker-writeback/tracker-writeback.h
@@ -20,6 +20,8 @@
 
 #include <glib-object.h>
 
+#include <libtracker-miner/tracker-miner-manager.h>
+
 #ifndef __TRACKER_WRITEBACK_H__
 #define __TRACKER_WRITEBACK_H__
 
@@ -36,14 +38,14 @@ typedef struct TrackerWriteback TrackerWriteback;
 typedef struct TrackerWritebackClass TrackerWritebackClass;
 
 struct TrackerWriteback {
-        GObject parent_instance;
+	GObject parent_instance;
 };
 
 struct TrackerWritebackClass {
-        GObjectClass parent_class;
+	GObjectClass parent_class;
 
-        gboolean (* update_metadata) (TrackerWriteback *writeback,
-                                      GPtrArray        *values);
+	gboolean (* update_metadata) (TrackerWriteback *writeback,
+	                              GPtrArray        *values);
 };
 
 GType          tracker_writeback_get_type (void) G_GNUC_CONST;
@@ -54,7 +56,7 @@ const gchar**      writeback_module_get_rdftypes  (void);
 
 gboolean tracker_writeback_update_metadata (TrackerWriteback *writeback,
                                             GPtrArray        *values);
-
+TrackerMinerManager* tracker_writeback_get_miner_manager (void);
 
 G_END_DECLS
 



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