[tracker/miner-fs-refactor: 30/110] libtracker-miner: Add TrackerFileNotifier



commit 3f8e54b98559de9dcf56b46cd1032741cc9f201d
Author: Carlos Garnacho <carlos lanedo com>
Date:   Tue Sep 27 15:26:17 2011 +0200

    libtracker-miner: Add TrackerFileNotifier
    
    TrackerFileNotifier is meant to be a high-level object that notifies
    about any update/addition/removal affecting the indexed content of
    a miner. At the moment only basic infrastructure has been added, so
    it only crawls the contents.

 src/libtracker-miner/Makefile.am             |    5 +-
 src/libtracker-miner/tracker-file-notifier.c |  444 ++++++++++++++++++++++++++
 src/libtracker-miner/tracker-file-notifier.h |   72 +++++
 src/libtracker-miner/tracker-miner.h         |    1 +
 4 files changed, 521 insertions(+), 1 deletions(-)
---
diff --git a/src/libtracker-miner/Makefile.am b/src/libtracker-miner/Makefile.am
index 6b6c140..1c2fd7f 100644
--- a/src/libtracker-miner/Makefile.am
+++ b/src/libtracker-miner/Makefile.am
@@ -68,6 +68,8 @@ libtracker_miner_ TRACKER_API_VERSION@_la_SOURCES =    \
 	$(password_provider_sources)                   \
 	$(crawler_sources)			       \
 	$(miner_sources)			       \
+	tracker-file-notifier.h                        \
+	tracker-file-notifier.c                        \
 	tracker-file-system.h                          \
 	tracker-file-system.c                          \
 	tracker-indexing-tree.c                        \
@@ -82,6 +84,7 @@ libtracker_miner_ TRACKER_API_VERSION@_la_SOURCES =    \
 libtracker_minerinclude_HEADERS =                      \
 	tracker-albumart.h                             \
 	tracker-crawler.h                              \
+	tracker-file-notifier.h                        \
 	tracker-file-system.h                          \
 	tracker-indexing-tree.h                        \
 	tracker-miner.h                                \
@@ -101,7 +104,7 @@ if !ENABLE_GCOV
 # Using enable_gcov instead of have_unit_test because when doing a release
 #  we disable gcov but NOT the unit tests
 libtracker_miner_ TRACKER_API_VERSION@_la_LDFLAGS +=    \
-	-export-symbols-regex '^tracker_(miner|thumbnailer|crawler|storage|password_provider|network_provider|indexing_tree|file_system)_.*'
+	-export-symbols-regex '^tracker_(miner|thumbnailer|crawler|storage|password_provider|network_provider|indexing_tree|file_system|file_notifier)_.*'
 endif
 
 libtracker_miner_ TRACKER_API_VERSION@_la_LIBADD =     \
diff --git a/src/libtracker-miner/tracker-file-notifier.c b/src/libtracker-miner/tracker-file-notifier.c
new file mode 100644
index 0000000..cf9ba82
--- /dev/null
+++ b/src/libtracker-miner/tracker-file-notifier.c
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2011, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Carlos Garnacho  <carlos lanedo com>
+ */
+
+#include <libtracker-common/tracker-log.h>
+
+#include "tracker-file-notifier.h"
+#include "tracker-file-system.h"
+#include "tracker-crawler.h"
+#include "tracker-monitor.h"
+
+enum {
+	PROP_0,
+	PROP_INDEXING_TREE
+};
+
+typedef struct {
+	TrackerIndexingTree *indexing_tree;
+	TrackerFileSystem *file_system;
+
+	TrackerCrawler *crawler;
+	TrackerMonitor *monitor;
+
+	GTimer *crawling_timer;
+
+	/* List of pending directory
+	 * trees to get data from
+	 */
+	GList *pending_index_roots;
+
+	guint stopped : 1;
+} TrackerFileNotifierPrivate;
+
+G_DEFINE_TYPE (TrackerFileNotifier, tracker_file_notifier, G_TYPE_OBJECT)
+
+static void
+tracker_file_notifier_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	priv = TRACKER_FILE_NOTIFIER (object)->priv;
+
+	switch (prop_id) {
+	case PROP_INDEXING_TREE:
+		priv->indexing_tree = g_value_dup_object (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+tracker_file_notifier_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	priv = TRACKER_FILE_NOTIFIER (object)->priv;
+
+	switch (prop_id) {
+	case PROP_INDEXING_TREE:
+		g_value_set_object (value, priv->indexing_tree);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/* Crawler signal handlers */
+static gboolean
+crawler_check_file_cb (TrackerCrawler *crawler,
+                       GFile          *file,
+                       gpointer        user_data)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	priv = TRACKER_FILE_NOTIFIER (user_data)->priv;
+
+	return tracker_indexing_tree_file_is_indexable (priv->indexing_tree,
+							file,
+							G_FILE_TYPE_REGULAR);
+}
+
+static gboolean
+crawler_check_directory_cb (TrackerCrawler *crawler,
+                            GFile          *directory,
+                            gpointer        user_data)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	priv = TRACKER_FILE_NOTIFIER (user_data)->priv;
+
+	return tracker_indexing_tree_file_is_indexable (priv->indexing_tree,
+							directory,
+							G_FILE_TYPE_DIRECTORY);
+}
+
+static gboolean
+crawler_check_directory_contents_cb (TrackerCrawler *crawler,
+                                     GFile          *parent,
+                                     GList          *children,
+                                     gpointer        user_data)
+{
+	TrackerFileNotifierPrivate *priv;
+	gboolean process;
+
+	priv = TRACKER_FILE_NOTIFIER (user_data)->priv;
+	process = tracker_indexing_tree_parent_is_indexable (priv->indexing_tree,
+	                                                     parent, children);
+#if 0
+	if (process) {
+		TrackerDirectoryFlags parent_flags;
+		gboolean add_monitor;
+
+		tracker_indexing_tree_get_root (priv->indexing_tree,
+						parent, &parent_flags);
+
+		add_monitor = (parent_flags & TRACKER_DIRECTORY_FLAG_MONITOR) != 0;
+
+		/* FIXME: add monitor */
+	}
+#endif
+
+	return process;
+}
+
+typedef struct {
+	TrackerFileNotifier *notifier;
+	GNode *cur_parent_node;
+	TrackerFile *cur_parent;
+} DirectoryCrawledData;
+
+static gboolean
+file_notifier_add_node_foreach (GNode    *node,
+				gpointer  user_data)
+{
+	DirectoryCrawledData *data = user_data;
+	TrackerFileNotifierPrivate *priv;
+	GFile *file;
+
+	priv = data->notifier->priv;
+	file = node->data;
+
+	if (node->parent &&
+	    node->parent != data->cur_parent_node) {
+		data->cur_parent_node = node->parent;
+		data->cur_parent = tracker_file_system_peek_file (priv->file_system,
+								  node->parent->data);
+	} else {
+		data->cur_parent_node = NULL;
+		data->cur_parent = NULL;
+	}
+
+	tracker_file_system_get_file (priv->file_system,
+				      file,
+				      G_FILE_TYPE_UNKNOWN,
+				      data->cur_parent);
+	return FALSE;
+}
+
+static void
+crawler_directory_crawled_cb (TrackerCrawler *crawler,
+                              GFile          *directory,
+                              GNode          *tree,
+                              guint           directories_found,
+                              guint           directories_ignored,
+                              guint           files_found,
+                              guint           files_ignored,
+                              gpointer        user_data)
+{
+	DirectoryCrawledData data = { 0 };
+
+	data.notifier = user_data;
+	g_node_traverse (tree,
+			 G_PRE_ORDER,
+			 G_TRAVERSE_ALL,
+			 -1,
+			 file_notifier_add_node_foreach,
+			 &data);
+
+	g_message ("  Found %d directories, ignored %d directories",
+	           directories_found,
+	           directories_ignored);
+	g_message ("  Found %d files, ignored %d files",
+	           files_found,
+	           files_ignored);
+}
+
+static gboolean
+crawl_directories_start (TrackerFileNotifier *notifier)
+{
+	TrackerFileNotifierPrivate *priv = notifier->priv;
+	TrackerDirectoryFlags flags;
+	GFile *directory;
+
+	if (!priv->pending_index_roots) {
+		return FALSE;
+	}
+
+	if (priv->stopped) {
+		return FALSE;
+	}
+
+	while (priv->pending_index_roots) {
+		directory = tracker_file_system_resolve_file (priv->file_system,
+							      priv->pending_index_roots->data);
+
+		tracker_indexing_tree_get_root (priv->indexing_tree,
+						directory,
+						&flags);
+
+		if (tracker_crawler_start (priv->crawler,
+					   directory,
+					   (flags & TRACKER_DIRECTORY_FLAG_RECURSE) != 0)) {
+			g_timer_reset (priv->crawling_timer);
+			return TRUE;
+		}
+
+		/* Remove index root and try the next one */
+		priv->pending_index_roots = g_list_remove_link (priv->pending_index_roots,
+								priv->pending_index_roots);
+	}
+
+	return FALSE;
+}
+
+static void
+crawler_finished_cb (TrackerCrawler *crawler,
+                     gboolean        was_interrupted,
+                     gpointer        user_data)
+{
+	TrackerFileNotifier *notifier = user_data;
+	TrackerFileNotifierPrivate *priv = notifier->priv;
+
+	tracker_info ("%s crawling files after %2.2f seconds",
+	              was_interrupted ? "Stopped" : "Finished",
+	              g_timer_elapsed (priv->crawling_timer, NULL));
+
+	if (!was_interrupted) {
+		/* FIXME: signal delete signals for files found
+		 * during crawling but not during querying */
+
+		/* We've finished indexing on the first element
+		 * of the pending list, continue onto the next */
+		priv->pending_index_roots = g_list_remove_link (priv->pending_index_roots,
+								priv->pending_index_roots);
+
+		crawl_directories_start (notifier);
+	}
+}
+
+/* Indexing tree signal handlers */
+static void
+indexing_tree_directory_added (TrackerIndexingTree *indexing_tree,
+                               GFile               *directory,
+                               gpointer             user_data)
+{
+	TrackerFileNotifier *notifier = user_data;
+	TrackerFileNotifierPrivate *priv = notifier->priv;
+	gboolean start_crawler = FALSE;
+	TrackerDirectoryFlags flags;
+	TrackerFile *file;
+
+	tracker_indexing_tree_get_root (indexing_tree, directory, &flags);
+
+	file = tracker_file_system_get_file (priv->file_system, directory,
+	                                     G_FILE_TYPE_DIRECTORY, NULL);
+
+	if (!priv->stopped &&
+	    !priv->pending_index_roots) {
+		start_crawler = TRUE;
+	}
+
+	priv->pending_index_roots = g_list_append (priv->pending_index_roots,
+	                                           file);
+	if (start_crawler) {
+		crawl_directories_start (notifier);
+	}
+}
+
+static void
+indexing_tree_directory_removed (TrackerIndexingTree *indexing_tree,
+                                 GFile               *directory,
+                                 gpointer             user_data)
+{
+	/* Signal as removed? depends on delete vs unmount */
+}
+
+static void
+tracker_file_notifier_finalize (GObject *object)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	priv = TRACKER_FILE_NOTIFIER (object)->priv;
+
+	if (priv->indexing_tree) {
+		g_object_unref (priv->indexing_tree);
+	}
+
+	g_object_unref (priv->file_system);
+	g_object_unref (priv->crawler);
+
+	g_list_free (priv->pending_index_roots);
+
+	G_OBJECT_CLASS (tracker_file_notifier_parent_class)->finalize (object);
+}
+
+static void
+tracker_file_notifier_constructed (GObject *object)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	priv = TRACKER_FILE_NOTIFIER (object)->priv;
+	g_assert (priv->indexing_tree);
+
+	g_signal_connect (priv->indexing_tree, "directory-added",
+	                  G_CALLBACK (indexing_tree_directory_added), object);
+	g_signal_connect (priv->indexing_tree, "directory-removed",
+	                  G_CALLBACK (indexing_tree_directory_removed), object);
+}
+
+static void
+tracker_file_notifier_class_init (TrackerFileNotifierClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = tracker_file_notifier_finalize;
+	object_class->set_property = tracker_file_notifier_set_property;
+	object_class->get_property = tracker_file_notifier_get_property;
+	object_class->constructed = tracker_file_notifier_constructed;
+
+	g_object_class_install_property (object_class,
+	                                 PROP_INDEXING_TREE,
+	                                 g_param_spec_object ("indexing-tree",
+	                                                      "Indexing tree",
+	                                                      "Indexing tree",
+	                                                      TRACKER_TYPE_INDEXING_TREE,
+	                                                      G_PARAM_READWRITE |
+	                                                      G_PARAM_CONSTRUCT_ONLY));
+	g_type_class_add_private (object_class,
+	                          sizeof (TrackerFileNotifierClass));
+}
+
+static void
+tracker_file_notifier_init (TrackerFileNotifier *notifier)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	priv = notifier->priv =
+		G_TYPE_INSTANCE_GET_PRIVATE (notifier,
+		                             TRACKER_TYPE_FILE_NOTIFIER,
+		                             TrackerFileNotifierPrivate);
+
+	priv->file_system = tracker_file_system_new ();
+	priv->crawling_timer = g_timer_new ();
+	priv->stopped = TRUE;
+
+	/* Set up crawler */
+	priv->crawler = tracker_crawler_new ();
+	g_signal_connect (priv->crawler, "check-file",
+	                  G_CALLBACK (crawler_check_file_cb),
+	                  notifier);
+	g_signal_connect (priv->crawler, "check-directory",
+	                  G_CALLBACK (crawler_check_directory_cb),
+	                  notifier);
+	g_signal_connect (priv->crawler, "check-directory-contents",
+	                  G_CALLBACK (crawler_check_directory_contents_cb),
+	                  notifier);
+	g_signal_connect (priv->crawler, "directory-crawled",
+	                  G_CALLBACK (crawler_directory_crawled_cb),
+	                  notifier);
+	g_signal_connect (priv->crawler, "finished",
+	                  G_CALLBACK (crawler_finished_cb),
+	                  notifier);
+}
+
+TrackerFileNotifier *
+tracker_file_notifier_new (TrackerIndexingTree *indexing_tree)
+{
+	g_return_val_if_fail (TRACKER_IS_INDEXING_TREE (indexing_tree), NULL);
+
+	return g_object_new (TRACKER_TYPE_FILE_NOTIFIER,
+			     "indexing-tree", indexing_tree,
+			     NULL);
+}
+
+gboolean
+tracker_file_notifier_start (TrackerFileNotifier *notifier)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	g_return_val_if_fail (TRACKER_IS_FILE_NOTIFIER (notifier), FALSE);
+
+	priv = notifier->priv;
+
+	if (priv->stopped) {
+		priv->stopped = FALSE;
+
+		if (priv->pending_index_roots) {
+			crawl_directories_start (notifier);
+		}
+	}
+
+	return TRUE;
+}
+
+void
+tracker_file_notifier_stop (TrackerFileNotifier *notifier)
+{
+	TrackerFileNotifierPrivate *priv;
+
+	g_return_if_fail (TRACKER_IS_FILE_NOTIFIER (notifier));
+
+	priv = notifier->priv;
+
+	if (!priv->stopped) {
+		tracker_crawler_stop (priv->crawler);
+		priv->stopped = TRUE;
+	}
+}
diff --git a/src/libtracker-miner/tracker-file-notifier.h b/src/libtracker-miner/tracker-file-notifier.h
new file mode 100644
index 0000000..304171d
--- /dev/null
+++ b/src/libtracker-miner/tracker-file-notifier.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Carlos Garnacho  <carlos lanedo com>
+ */
+
+#ifndef __TRACKER_FILE_NOTIFIER_H__
+#define __TRACKER_FILE_NOTIFIER_H__
+
+#if !defined (__LIBTRACKER_MINER_H_INSIDE__) && !defined (TRACKER_COMPILATION)
+#error "Only <libtracker-miner/tracker-miner.h> can be included directly."
+#endif
+
+#include <gio/gio.h>
+#include "tracker-indexing-tree.h"
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_FILE_NOTIFIER         (tracker_file_notifier_get_type ())
+#define TRACKER_FILE_NOTIFIER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_FILE_NOTIFIER, TrackerFileNotifier))
+#define TRACKER_FILE_NOTIFIER_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_FILE_NOTIFIER, TrackerFileNotifierClass))
+#define TRACKER_IS_FILE_NOTIFIER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_FILE_NOTIFIER))
+#define TRACKER_IS_FILE_NOTIFIER_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c),    TRACKER_TYPE_FILE_NOTIFIER))
+#define TRACKER_FILE_NOTIFIER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  TRACKER_TYPE_FILE_NOTIFIER, TrackerFileNotifierClass))
+
+typedef struct _TrackerFileNotifier TrackerFileNotifier;
+typedef struct _TrackerFileNotifierClass TrackerFileNotifierClass;
+
+struct _TrackerFileNotifier {
+	GObject parent_instance;
+	gpointer priv;
+};
+
+struct _TrackerFileNotifierClass {
+	GObjectClass parent_class;
+
+	void (* file_added)   (TrackerFileNotifier *notifier,
+			       GFile               *file);
+	void (* file_updated) (TrackerFileNotifier *notifier,
+			       GFile               *file);
+	void (* file_deleted) (TrackerFileNotifier *notifier,
+			       GFile               *file);
+	void (* file_moved)   (TrackerFileNotifier *notifier,
+			       GFile               *from,
+			       GFile               *to);
+};
+
+GType         tracker_file_notifier_get_type      (void) G_GNUC_CONST;
+
+TrackerFileNotifier* tracker_file_notifier_new  (TrackerIndexingTree *indexing_tree);
+
+gboolean      tracker_file_notifier_start (TrackerFileNotifier *notifier);
+void          tracker_file_notifier_stop  (TrackerFileNotifier *notifier);
+
+G_END_DECLS
+
+#endif /* __TRACKER_FILE_SYSTEM_H__ */
diff --git a/src/libtracker-miner/tracker-miner.h b/src/libtracker-miner/tracker-miner.h
index 824d897..0d3460b 100644
--- a/src/libtracker-miner/tracker-miner.h
+++ b/src/libtracker-miner/tracker-miner.h
@@ -35,6 +35,7 @@
 #include <libtracker-miner/tracker-miner-enums.h>
 #include <libtracker-miner/tracker-indexing-tree.h>
 #include <libtracker-miner/tracker-file-system.h>
+#include <libtracker-miner/tracker-file-notifier.h>
 
 
 #undef __LIBTRACKER_MINER_H_INSIDE__



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