tracker r1379 - in branches/indexer-split: . src/libtracker-common src/trackerd



Author: mr
Date: Thu May  8 16:39:43 2008
New Revision: 1379
URL: http://svn.gnome.org/viewvc/tracker?rev=1379&view=rev

Log:
	* src/libtracker-common/tracker-nfs-lock.c: Improve logging.

	* src/trackerd/tracker-dbus-daemon.c: Renamed  _do_cleanup() to
	_shutdown() and make it ONLY stop the main loop so we clean up
	every time after the mainloop stops.

	* src/trackerd/tracker-process-files.c: Removed
	tracker->update_count since it was redundant.


Modified:
   branches/indexer-split/ChangeLog
   branches/indexer-split/src/libtracker-common/tracker-nfs-lock.c
   branches/indexer-split/src/trackerd/tracker-dbus-daemon.c
   branches/indexer-split/src/trackerd/tracker-main.c
   branches/indexer-split/src/trackerd/tracker-main.h
   branches/indexer-split/src/trackerd/tracker-process-files.c

Modified: branches/indexer-split/src/libtracker-common/tracker-nfs-lock.c
==============================================================================
--- branches/indexer-split/src/libtracker-common/tracker-nfs-lock.c	(original)
+++ branches/indexer-split/src/libtracker-common/tracker-nfs-lock.c	Thu May  8 16:39:43 2008
@@ -79,7 +79,7 @@
 	}
 
         if (!is_initialized()) {
-                tracker_error ("Trying to use NFS Lock. It is NOT initialized\n");
+                tracker_error ("Could not initialise NFS lock");
                 return FALSE;
         }
  
@@ -119,7 +119,7 @@
 	}
 
 error:
-	tracker_error ("ERROR: lock failure");
+	tracker_error ("Could not get NFS lock state");
 	g_free (tmp_file);
 
 	return FALSE;
@@ -135,7 +135,7 @@
 	}
  
         if (!is_initialized()) {
-                tracker_error ("Trying to use NFS Lock. It is NOT initialized\n");
+                tracker_error ("Could not initialise NFS lock");
                 return;
         }
  
@@ -151,7 +151,7 @@
 tracker_nfs_lock_init (const gchar *root_dir)
 {
         if (is_initialized ()) {
-                tracker_error ("Trying to initialize tracker_db_lock for second time");
+		return;
         }
 
         if (lock_file == NULL) {
@@ -162,15 +162,15 @@
                 tmp_filepath = g_build_filename (root_dir, g_get_host_name (), NULL);
         }
 
-        tracker_log ("Initialized NFS lock %s", 
-                     use_nfs_safe_locking ? "" : "(Not in use)");
+        tracker_log ("NFS lock initialised %s", 
+                     use_nfs_safe_locking ? "" : "(safe locking not in use)");
 }
 
 void
 tracker_nfs_lock_term (void)
 {
         if (!is_initialized ()) {
-                tracker_error ("Trying to term tracker_db_lock not initialized");
+		return;
         }
 
         if (lock_file) {
@@ -181,5 +181,5 @@
                 g_free (tmp_filepath);
         }
 
-        tracker_log ("Tracker db NFS lock finalized");
+        tracker_log ("NFS lock finalised");
 }

Modified: branches/indexer-split/src/trackerd/tracker-dbus-daemon.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-dbus-daemon.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-dbus-daemon.c	Thu May  8 16:39:43 2008
@@ -543,7 +543,7 @@
 
 	priv->tracker->reindex = reindex;
 
-	g_timeout_add (500, (GSourceFunc) tracker_do_cleanup, NULL);
+	g_timeout_add (500, (GSourceFunc) tracker_shutdown, NULL);
 
 	tracker_dbus_request_success (request_id);
 

Modified: branches/indexer-split/src/trackerd/tracker-main.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-main.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-main.c	Thu May  8 16:39:43 2008
@@ -62,116 +62,134 @@
 #include "mingw-compat.h"
 #endif
 
-#define ABOUT								  \
-	"Tracker " VERSION "\n"						  \
-	"Copyright (c) 2005-2008 Jamie McCracken (jamiemcc gnome org)\n" 
-
-#define LICENSE								  \
-	"This program is free software and comes without any warranty.\n" \
-	"It is licensed under version 2 or later of the General Public "  \
-	"License which can be viewed at:\n"                               \
-        "\n"							          \
-	"  http://www.gnu.org/licenses/gpl.txt\n"; 
+/*
+ *   The workflow to process files and notified file change events are
+ *   as follows: 
+ *
+ *   1) File scan or file notification change (as reported by
+ *   FAM/iNotify).  
 
-typedef struct {
-	gchar	*uri;
-	gint	mtime;
-} IndexDir;
-
-Tracker		       *tracker;
-DBConnection	       *main_thread_db_con;
-DBConnection	       *main_thread_cache_con;
+ *   2) File Scheduler (we wait until a file's changes have stabilised
+ *   (NB not neccesary with inotify)) 
 
+ *   3) We process a file's basic metadata (stat) and determine what
+ *   needs doing in a seperate thread. 
 
-/*
- *   The workflow to process files and notified file change events are as follows:
+ *   4) We extract CPU intensive embedded metadata/text/thumbnail in
+ *   another thread and save changes to the DB 
  *
- *   1) File scan or file notification change (as reported by FAM/iNotify).
- *   2) File Scheduler (we wait until a file's changes have stabilised (NB not neccesary with inotify))
- *   3) We process a file's basic metadata (stat) and determine what needs doing in a seperate thread.
- *   4) We extract CPU intensive embedded metadata/text/thumbnail in another thread and save changes to the DB
  *
+ *  Three threads are used to fully process a file event. Files or
+ *  events to be processed are placed on asynchronous queues where
+ *  another thread takes over the work. 
  *
- *  Three threads are used to fully process a file event. Files or events to be processed are placed on
- *  asynchronous queues where another thread takes over the work.
+ *  The main thread is very lightweight and no cpu intensive or heavy
+ *  file I/O (or heavy DB access) is permitted here after
+ *  initialisation of the daemon. This ensures the main thread can
+ *  handle events and DBUS requests in a timely low latency manner. 
  *
- *  The main thread is very lightweight and no cpu intensive or heavy file I/O (or heavy DB access) is permitted
- *  here after initialisation of the daemon. This ensures the main thread can handle events and DBUS
- *  requests in a timely low latency manner.
+ *  The File Process thread is for moderate CPU intensive load and I/O
+ *  and involves calls to stat() and simple fast queries on the DB.
+ *  The main thread queues files to be processed by this thread via
+ *  the file_process async queue. As no heavily CPU intensive activity
+ *  occurs here, we can quickly keep the DB representation of the
+ *  watched file system up to date. Once a file has been processed
+ *  here it is then placed on the file metadata queue which is handled
+ *  by the File Metadata thread. 
  *
- *  The File Process thread is for moderate CPU intensive load and I/O and involves calls to stat()
- *  and simple fast queries on the DB. The main thread queues files to be processed by this thread
- *  via the file_process async queue. As no heavily CPU intensive activity occurs here, we can quickly
- *  keep the DB representation of the watched file system up to date. Once a file has been processed
- *  here it is then placed on the file metadata queue which is handled by the File Metadata thread.
+ *  The File Metadata thread is a low priority thread to handle the
+ *  highly CPU intensive parts. During this phase, embedded metadata
+ *  is extracted from files and if a text filter and/or thumbnailer is
+ *  available for the mime type of the file then these will be spawned
+ *  synchronously. Finally all metadata (including file's text
+ *  contents and path to thumbnails) is saved to the DB. 
  *
- *  The File Metadata thread is a low priority thread to handle the highly CPU intensive parts.
- *  During this phase, embedded metadata is extracted from files and if a text filter and/or
- *  thumbnailer is available for the mime type of the file then these will be spawned synchronously.
- *  Finally all metadata (including file's text contents and path to thumbnails) is saved to the DB.
- *
- *  All responses including user initiated requests are queued by the main thread onto an
- *  asynchronous queue where potentially multiple threads are waiting to process them.
+ *  All responses including user initiated requests are queued by the
+ *  main thread onto an asynchronous queue where potentially multiple
+ *  threads are waiting to process them. 
  */
 
+#define ABOUT								  \
+	"Tracker " VERSION "\n"						  \
+	"Copyright (c) 2005-2008 Jamie McCracken (jamiemcc gnome org)\n" 
 
-static gchar **no_watch_dirs = NULL;
-static gchar **watch_dirs = NULL;
-static gchar **crawl_dirs = NULL;
-static gchar *language = NULL;
-static gboolean disable_indexing = FALSE;
-static gboolean reindex = FALSE;
-static gboolean fatal_errors = FALSE;
-static gboolean low_memory;
-static gint throttle = -1;
-static gint verbosity = 0;
-static gint initial_sleep = -1; /* >= 0 is valid and will be set */
-
-static GOptionEntry entries[] = {
-	{"exclude-dir", 'e', 0, G_OPTION_ARG_STRING_ARRAY, &no_watch_dirs, N_("Directory to exclude from indexing"), N_("/PATH/DIR")},
-	{"include-dir", 'i', 0, G_OPTION_ARG_STRING_ARRAY, &watch_dirs, N_("Directory to include in indexing"), N_("/PATH/DIR")},
-	{"crawl-dir", 'c', 0, G_OPTION_ARG_STRING_ARRAY, &crawl_dirs, N_("Directory to crawl for indexing at start up only"), N_("/PATH/DIR")},
-	{"no-indexing", 'n', 0, G_OPTION_ARG_NONE, &disable_indexing, N_("Disable any indexing or watching taking place"), NULL },
-	{"verbosity", 'v', 0, G_OPTION_ARG_INT, &verbosity, N_("Value that controls the level of logging. Valid values are 0 (displays/logs only errors), 1 (minimal), 2 (detailed), and 3 (debug)"), N_("VALUE") },
-	{"throttle", 't', 0, G_OPTION_ARG_INT, &throttle, N_("Value to use for throttling indexing. Value must be in range 0-99 (default 0) with lower values increasing indexing speed"), N_("VALUE") },
-	{"low-memory", 'm', 0, G_OPTION_ARG_NONE, &low_memory, N_("Minimizes the use of memory but may slow indexing down"), NULL },
-	{"initial-sleep", 's', 0, G_OPTION_ARG_INT, &initial_sleep, N_("Initial sleep time, just before indexing, in seconds"), NULL },
-	{"language", 'l', 0, G_OPTION_ARG_STRING, &language, N_("Language to use for stemmer and stop words list (ISO 639-1 2 characters code)"), N_("LANG")},
-	{"reindex", 'R', 0, G_OPTION_ARG_NONE, &reindex, N_("Force a re-index of all content"), NULL },
-	{"fatal-errors", 'f', 0, G_OPTION_ARG_NONE, &fatal_errors, N_("Make tracker errors fatal"), NULL },
-	{NULL}
-};
-
-
-static gint
-get_update_count (DBConnection *db_con)
-{
-	TrackerDBResultSet *result_set;
-	gchar *str;
-	gint  count = 0;
-
-	result_set = tracker_exec_proc (db_con, "GetUpdateCount", NULL);
-
-	if (result_set) {
-		tracker_db_result_set_get (result_set, 0, &str, -1);
-
-		if (str) {
-			count = atoi (str);
-                }
-
-		g_free (str);
-		g_object_unref (result_set);
-	}
-
-	return count;
-}
+#define LICENSE								  \
+	"This program is free software and comes without any warranty.\n" \
+	"It is licensed under version 2 or later of the General Public "  \
+	"License which can be viewed at:\n"                               \
+        "\n"							          \
+	"  http://www.gnu.org/licenses/gpl.txt\n"; 
 
-gboolean
-tracker_die (void)
-{
-	tracker_error ("trackerd has failed to exit on time - terminating...");
-	exit (EXIT_FAILURE);
-}
+/* Public */
+Tracker	             *tracker;
+DBConnection         *main_thread_db_con;
+DBConnection         *main_thread_cache_con;
+
+static GMainLoop     *main_loop;
+
+static gchar        **no_watch_dirs;
+static gchar        **watch_dirs;
+static gchar        **crawl_dirs;
+static gchar         *language;
+static gboolean       disable_indexing;
+static gboolean       reindex;
+static gboolean       fatal_errors;
+static gboolean       low_memory;
+static gint           throttle = -1;
+static gint           verbosity;
+static gint           initial_sleep = -1; 
+
+static GOptionEntry   entries[] = {
+	{ "exclude-dir", 'e', 0, 
+	  G_OPTION_ARG_STRING_ARRAY, &no_watch_dirs, 
+	  N_("Directory to exclude from indexing"), 
+	  N_("/PATH/DIR") },
+	{ "include-dir", 'i', 0, 
+	  G_OPTION_ARG_STRING_ARRAY, &watch_dirs, 
+	  N_("Directory to include in indexing"), 
+	  N_("/PATH/DIR") },
+	{ "crawl-dir", 'c', 0, 
+	  G_OPTION_ARG_STRING_ARRAY, &crawl_dirs, 
+	  N_("Directory to crawl for indexing at start up only"), 
+	  N_("/PATH/DIR") },
+	{ "no-indexing", 'n', 0, 
+	  G_OPTION_ARG_NONE, &disable_indexing, 
+	  N_("Disable any indexing or watching taking place"), NULL },
+	{ "verbosity", 'v', 0, 
+	  G_OPTION_ARG_INT, &verbosity, 
+	  N_("Value that controls the level of logging. "
+	     "Valid values are 0 (displays/logs only errors), "
+	     "1 (minimal), 2 (detailed), and 3 (debug)"), 
+	  N_("VALUE") },
+	{ "throttle", 't', 0, 
+	  G_OPTION_ARG_INT, &throttle, 
+	  N_("Value to use for throttling indexing. "
+	     "Value must be in range 0-99 (default 0) "
+	     "with lower values increasing indexing speed"), 
+	  N_("VALUE") },
+	{ "low-memory", 'm', 0, 
+	  G_OPTION_ARG_NONE, &low_memory, 
+	  N_("Minimizes the use of memory but may slow indexing down"), 
+	  NULL },
+	{ "initial-sleep", 's', 0, 
+	  G_OPTION_ARG_INT, &initial_sleep, 
+	  N_("Initial sleep time, just before indexing, in seconds"), 
+	  NULL },
+	{ "language", 'l', 0, 
+	  G_OPTION_ARG_STRING, &language, 
+	  N_("Language to use for stemmer and stop words list "
+	     "(ISO 639-1 2 characters code)"), 
+	  N_("LANG")},
+	{ "reindex", 'R', 0, 
+	  G_OPTION_ARG_NONE, &reindex, 
+	  N_("Force a re-index of all content"), 
+	  NULL },
+	{ "fatal-errors", 'f', 0, 
+	  G_OPTION_ARG_NONE, &fatal_errors, 
+	  N_("Make tracker errors fatal"), 
+	  NULL },
+	{ NULL }
+};
 
 static void
 free_file_change_queue (gpointer data, gpointer user_data)
@@ -181,209 +199,294 @@
 }
 
 static void
-reset_blacklist_file (char *uri)
+reset_blacklist_file (gchar *uri)
 {
+	gchar *dirname;
+	gchar *dirname_parent;
+	gchar *basename;
 
-	char *parent = g_path_get_dirname (uri);
-	if (!parent) return;
-
-	char *parent_name = g_path_get_basename (parent);
-	if (!parent_name) return;
-
-	char *parent_path = g_path_get_dirname (parent);
-	if (!parent_path) return;	
-
-	tracker_log ("resetting black list file %s", uri);
-
-	/* reset mtime on parent folder of all outstanding black list files so they get indexed when next restarted */
-	tracker_exec_proc (main_thread_db_con, "UpdateFileMTime", "0", parent_path, parent_name, NULL);
-
-	g_free (parent);
-	g_free (parent_name);
-	g_free (parent_path);		 
+	dirname = g_path_get_dirname (uri);
+	if (!dirname) { 
+		return;
+	}
 
+	basename = g_path_get_basename (dirname);
+	if (!basename) {
+		return;
+	}
 
+	dirname_parent = g_path_get_dirname (dirname);
+	if (!dirname_parent) {
+		return;	
+	}
+
+	tracker_log ("Resetting black list file:'%s'", uri);
+
+	/* Reset mtime on parent folder of all outstanding black list
+	 * files so they get indexed when next restarted 
+	 */
+	tracker_exec_proc (main_thread_db_con, 
+			   "UpdateFileMTime", "0", 
+			   dirname_parent, basename, 
+			   NULL);
+
+	g_free (basename);
+	g_free (dirname_parent);
+	g_free (dirname);
 }
 
-gboolean
-tracker_do_cleanup (const gchar *sig_msg)
+static void
+signal_handler (gint signo)
 {
-        GSList *black_list;
-
-	tracker->shutdown = TRUE;
-
-	tracker_status_set (TRACKER_STATUS_SHUTDOWN);
+	static gboolean in_loop = FALSE;
 
-	if (sig_msg) {
-		tracker_log ("Received signal '%s' so now shutting down", sig_msg);
+  	/* Die if we get re-entrant signals handler calls */
+	if (in_loop) {
+		exit (EXIT_FAILURE);
 	}
-
-	/* set kill timeout */
-	g_timeout_add_full (G_PRIORITY_LOW,
-	     		    20000,
- 	    		    (GSourceFunc) tracker_die,
-	     		    NULL, NULL
-	   		    );
-
-
-	/* stop threads from further processing of events if possible */
-
-	//set_update_count (main_thread_db_con, tracker->update_count);
-
-	/* wait for files thread to sleep */
-	while (!g_mutex_trylock (tracker->files_signal_mutex)) {
-		g_usleep (100);
+	
+  	switch (signo) {
+	case SIGSEGV:
+		/* We are screwed if we get this so exit immediately! */
+		exit (EXIT_FAILURE);
+		
+	case SIGBUS:
+	case SIGILL:
+	case SIGFPE:
+	case SIGPIPE:
+	case SIGABRT:
+	case SIGTERM:
+	case SIGINT:
+		in_loop = TRUE;
+		
+		tracker->is_running = FALSE;
+		tracker_end_watching ();
+		
+		g_timeout_add_full (G_PRIORITY_LOW, 1,
+				    (GSourceFunc) tracker_shutdown,
+				    g_strdup (g_strsignal (signo)), NULL);
+		
+	default:
+		if (g_strsignal (signo)) {
+			tracker_log ("Received signal:%d->'%s'", 
+				     signo, 
+				     g_strsignal (signo));
+		}
+		break;
 	}
+}
 
-	g_mutex_unlock (tracker->files_signal_mutex);
+static void
+log_option_list (GSList      *list,
+		 const gchar *str)
+{
+	GSList *l;
 
-	while (!g_mutex_trylock (tracker->metadata_signal_mutex)) {
-		g_usleep (100);
+	if (!list) {
+		tracker_log ("%s: NONE!", str);
+		return;
 	}
 
-	g_mutex_unlock (tracker->metadata_signal_mutex);
+	tracker_log ("%s:", str);
 
-	tracker_log ("Shutting down threads");
+	for (l = list; l; l = l->next) {
+		tracker_log ("  %s", l->data);
+	}
+}
 
-	/* send signals to each thread to wake them up and then stop them */
-	g_mutex_lock (tracker->metadata_signal_mutex);
-	g_cond_signal (tracker->metadata_signal_cond);
-	g_mutex_unlock (tracker->metadata_signal_mutex);
+static void
+sanity_check_option_values (void)
+{
+        GSList *watch_directory_roots;
+        GSList *crawl_directory_roots;
+        GSList *no_watch_directory_roots;
+        GSList *no_index_file_types;
 
-	g_mutex_unlock (tracker->files_check_mutex);
+        watch_directory_roots = tracker_config_get_watch_directory_roots (tracker->config);
+        crawl_directory_roots = tracker_config_get_crawl_directory_roots (tracker->config);
+        no_watch_directory_roots = tracker_config_get_no_watch_directory_roots (tracker->config);
 
-	g_mutex_lock (tracker->files_signal_mutex);
-	g_cond_signal (tracker->files_signal_cond);
-	g_mutex_unlock (tracker->files_signal_mutex);
+        no_index_file_types = tracker_config_get_no_index_file_types (tracker->config);
 
-	/* wait for threads to exit and unlock check mutexes to prevent any deadlocks*/
+	tracker_log ("Tracker configuration options:");
+	tracker_log ("  Verbosity  ............................  %d", 
+                     tracker_config_get_verbosity (tracker->config));
+ 	tracker_log ("  Low memory mode  ......................  %s", 
+                     tracker_config_get_low_memory_mode (tracker->config) ? "yes" : "no");
+ 	tracker_log ("  Indexing enabled  .....................  %s", 
+                     tracker_config_get_enable_indexing (tracker->config) ? "yes" : "no");
+ 	tracker_log ("  Watching enabled  .....................  %s", 
+                     tracker_config_get_enable_watches (tracker->config) ? "yes" : "no");
+ 	tracker_log ("  File content indexing enabled  ........  %s", 
+                     tracker_config_get_enable_content_indexing (tracker->config) ? "yes" : "no");
+	tracker_log ("  Thumbnailing enabled  .................  %s", 
+                     tracker_config_get_enable_thumbnails (tracker->config) ? "yes" : "no");
+	tracker_log ("  Email client to index .................  %s",
+		     tracker_config_get_email_client (tracker->config));
 
-	g_mutex_unlock (tracker->metadata_check_mutex);
+	tracker_log ("Tracker indexer parameters:");
+	tracker_log ("  Indexer language code  ................  %s", 
+                     tracker_config_get_language (tracker->config));
+	tracker_log ("  Minimum index word length  ............  %d", 
+                     tracker_config_get_min_word_length (tracker->config));
+	tracker_log ("  Maximum index word length  ............  %d", 
+                     tracker_config_get_max_word_length (tracker->config));
+	tracker_log ("  Stemmer enabled  ......................  %s", 
+                     tracker_config_get_enable_stemmer (tracker->config) ? "yes" : "no");
 
-	g_mutex_unlock (tracker->files_check_mutex);
+	tracker->word_count = 0;
+	tracker->word_detail_count = 0;
+	tracker->word_update_count = 0;
 
-	tracker_indexer_close (tracker->file_index);
-	tracker_indexer_close (tracker->file_update_index);
-	tracker_indexer_close (tracker->email_index);
+	tracker->file_word_table = g_hash_table_new (g_str_hash, g_str_equal);
+	tracker->file_update_word_table = g_hash_table_new (g_str_hash, g_str_equal);
+	tracker->email_word_table = g_hash_table_new (g_str_hash, g_str_equal);
 
-	tracker_email_end_email_watching ();
+	if (!tracker_config_get_low_memory_mode (tracker->config)) {
+		tracker->memory_limit = 16000 *1024;
+	
+		tracker->max_process_queue_size = 5000;
+		tracker->max_extract_queue_size = 5000;
+	} else {
+		tracker->memory_limit = 8192 * 1024;
 
-	/* reset integrity status as threads have closed cleanly */
-	tracker_db_set_option_int (main_thread_db_con, "IntegrityCheck", 0);
+		tracker->max_process_queue_size = 500;
+		tracker->max_extract_queue_size = 500;
+	}
 
+	log_option_list (watch_directory_roots, "Watching directory roots");
+	log_option_list (crawl_directory_roots, "Crawling directory roots");
+	log_option_list (no_watch_directory_roots, "NOT watching directory roots");
+	log_option_list (no_index_file_types, "NOT indexing file types");
 
-	/* reset black list files */
-        black_list = tracker_process_files_get_temp_black_list ();
-	g_slist_foreach (black_list,
-                         (GFunc) reset_blacklist_file, 
-                         NULL);
-        g_slist_free (black_list);
+        tracker_log ("Throttle level is %d\n", tracker_config_get_throttle (tracker->config));
 
-	tracker_db_close (main_thread_db_con);
+	tracker->metadata_table = g_hash_table_new_full (g_str_hash,
+                                                         g_str_equal, 
+                                                         NULL, 
+                                                         NULL);
+}
 
-	/* This must be called after all other db functions */
-	tracker_db_finalize ();
+static void
+create_index (gboolean need_data)
+{
+	DBConnection *db_con;
+	
+	tracker->first_time_index = TRUE;
 
+	/* Create files db and emails db */
+	db_con = tracker_db_connect ();
 
-	if (tracker->reindex) {
-		tracker_dir_remove (tracker->data_dir);
-		g_mkdir_with_parents (tracker->data_dir, 00755);
+	/* Reset stats for embedded services if they are being reindexed */
+	if (!need_data) {
+		tracker_log ("*** DELETING STATS *** ");
+		tracker_db_exec_no_reply (db_con, 
+					  "update ServiceTypes set TypeCount = 0 where Embedded = 1");
 	}
 
-        if (tracker->hal) {
-                g_object_unref (tracker->hal);
-                tracker->hal = NULL;
-        }
-
-	tracker_debug ("Shutting down main thread");
-
-	tracker_log_term ();
-
-	tracker_nfs_lock_term ();
+	tracker_db_close (db_con);
+	g_free (db_con);
 
-	/* remove sys tmp directory */
-	if (tracker->sys_tmp_root_dir) {
-		tracker_dir_remove (tracker->sys_tmp_root_dir);
-	}
+	/* Create databases */
+	db_con = tracker_db_connect_file_content ();
+	tracker_db_close (db_con);
+	g_free (db_con);
 
-	/* remove file change queue */
-	if (tracker->file_change_queue) {
-		g_queue_foreach (tracker->file_change_queue,
-				 free_file_change_queue, NULL);
-		g_queue_free (tracker->file_change_queue);
-		tracker->file_change_queue = NULL;
-	}
+	db_con = tracker_db_connect_email_content ();
+	tracker_db_close (db_con);
+	g_free (db_con);
 
-        if (tracker->language) {
-                tracker_language_free (tracker->language);
-        }
+	db_con = tracker_db_connect_emails ();
+	tracker_db_close (db_con);
+	g_free (db_con);
 
-        if (tracker->config) {
-                g_object_unref (tracker->config);
-        }
+}
 
-	g_main_loop_quit (tracker->loop);
+static void
+initialise_signal_handler (void)
+{
+#ifndef OS_WIN32
+  	struct sigaction   act;
+	sigset_t 	   empty_mask;
 
-	exit (EXIT_SUCCESS);
+	sigemptyset (&empty_mask);
+	act.sa_handler = signal_handler;
+	act.sa_mask    = empty_mask;
+	act.sa_flags   = 0;
 
-	return FALSE;
+	sigaction (SIGTERM, &act, NULL);
+	sigaction (SIGILL,  &act, NULL);
+	sigaction (SIGBUS,  &act, NULL);
+	sigaction (SIGFPE,  &act, NULL);
+	sigaction (SIGHUP,  &act, NULL);
+	sigaction (SIGSEGV, &act, NULL);
+	sigaction (SIGABRT, &act, NULL);
+	sigaction (SIGUSR1, &act, NULL);
+	sigaction (SIGINT,  &act, NULL);
+#endif
 }
 
 static void
-signal_handler (gint signo)
+initialise_directories (void)
 {
-	static gboolean in_loop = FALSE;
+	gchar *str;
+	gchar *filename;
 
-  	/* die if we get re-entrant signals handler calls */
-	if (in_loop) {
-		exit (EXIT_FAILURE);
-	}
+	str = g_strdup_printf ("Tracker-%s.%d", g_get_user_name (), getpid ());
+	tracker->sys_tmp_root_dir = g_build_filename (g_get_tmp_dir (), str, NULL);
+	g_free (str);
 
-  	switch (signo) {
+	tracker->root_dir = g_build_filename (g_get_user_data_dir (), "tracker", NULL);
+	tracker->data_dir = g_build_filename (g_get_user_cache_dir (), "tracker", NULL);
+	tracker->config_dir = g_strdup (g_get_user_config_dir ());
+	tracker->user_data_dir = g_build_filename (tracker->root_dir, "data", NULL);
+	tracker->xesam_dir = g_build_filename (g_get_home_dir (), ".xesam", NULL);
 
-  		case SIGSEGV:
+	/* Remove an existing one */
+	if (g_file_test (tracker->sys_tmp_root_dir, G_FILE_TEST_EXISTS)) {
+		tracker_dir_remove (tracker->sys_tmp_root_dir);
+	}
 
-			/* we are screwed if we get this so exit immediately! */
-			exit (EXIT_FAILURE);
+	/* Remove old tracker dirs */
+        filename = g_build_filename (g_get_home_dir (), ".Tracker", NULL);
 
-	  	case SIGBUS:
-		case SIGILL:
-  		case SIGFPE:
-  		case SIGPIPE:
-		case SIGABRT:
-		case SIGTERM:
-		case SIGINT:
+	if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
+		tracker_dir_remove (filename);
+	}
 
-		  	in_loop = TRUE;
+	g_free (filename);
 
-			tracker->is_running = FALSE;
-			tracker_end_watching ();
+        /* Create other directories we need */
+	if (!g_file_test (tracker->user_data_dir, G_FILE_TEST_EXISTS)) {
+		g_mkdir_with_parents (tracker->user_data_dir, 00755);
+	}
 
-			g_timeout_add_full (G_PRIORITY_LOW,
-			     		    1,
-		 	    		    (GSourceFunc) tracker_do_cleanup,
-			     		    g_strdup (g_strsignal (signo)), NULL
-			   		    );
+	if (!g_file_test (tracker->data_dir, G_FILE_TEST_EXISTS)) {
+		g_mkdir_with_parents (tracker->data_dir, 00755);
+	}
 
+        tracker->email_attachements_dir = g_build_filename (tracker->sys_tmp_root_dir, "Attachments", NULL);
+	g_mkdir_with_parents (tracker->email_attachements_dir, 00700);
 
-			default:
-			if (g_strsignal (signo)) {
-	   			tracker_log ("Received signal %s ", g_strsignal (signo));
-		}
-			break;
-	}
+	/* Remove existing log files */
+	tracker->log_filename = g_build_filename (tracker->root_dir, "tracker.log", NULL);
+	tracker_file_unlink (tracker->log_filename);
 }
 
-static inline void
-queue_dir (const gchar *uri)
+static void
+initialise_threading (void)
 {
-	TrackerDBFileInfo *info = tracker_db_file_info_new (uri, TRACKER_DB_ACTION_DIRECTORY_CHECK, 0, 0);
-	g_async_queue_push (tracker->file_process_queue, info);
-}
+	tracker->files_check_mutex = g_mutex_new ();
+	tracker->files_signal_mutex = g_mutex_new ();
+	tracker->files_signal_cond = g_cond_new ();
 
+	tracker->metadata_check_mutex = g_mutex_new ();
+	tracker->metadata_signal_mutex = g_mutex_new ();
+	tracker->metadata_signal_cond = g_cond_new ();
+}
 
 static void
-set_defaults (void)
+initialise_defaults (void)
 {
 	tracker->grace_period = 0;
 
@@ -402,7 +505,6 @@
 
 	tracker->watch_limit = 0;
 	tracker->index_count = 0;
-	tracker->update_count = 0;
 
 	tracker->max_process_queue_size = MAX_PROCESS_QUEUE_SIZE;
 	tracker->max_extract_queue_size = MAX_EXTRACT_QUEUE_SIZE;
@@ -418,147 +520,214 @@
 }
 
 static void
-log_option_list (GSList      *list,
-		 const gchar *str)
+initialise_databases (gboolean need_index)
 {
-	GSList *l;
+	Indexer      *index;
+	DBConnection *db_con;
+	gchar        *final_index_name;
+	gboolean      need_data;
+	
+	/* FIXME: is this actually necessary? */
+	db_con = tracker_db_connect_cache ();
+	tracker_db_close (db_con);
 
-	if (!list) {
-		tracker_log ("%s: NONE!", str);
-		return;
+	need_data = tracker_db_needs_data ();
+
+	if (need_data) {
+		tracker_create_common_db ();
 	}
 
-	tracker_log ("%s:", str);
+	if (!tracker->readonly && need_index) {
+		create_index (need_data);
+	} else {
+		tracker->first_time_index = FALSE;
+	}
 
-	for (l = list; l; l = l->next) {
-		tracker_log ("  %s", l->data);
+        /* Set up main database connection */
+	db_con = tracker_db_connect ();
+
+	/* Check db integrity if not previously shut down cleanly */
+	if (!tracker->readonly && 
+	    !need_index && 
+	    tracker_db_get_option_int (db_con, "IntegrityCheck") == 1) {
+		tracker_log ("Performing integrity check as the daemon was not shutdown cleanly");
+		/* FIXME: Finish */
+	} 
+
+	if (!tracker->readonly) {
+		tracker_db_set_option_int (db_con, "IntegrityCheck", 1);
+	} 
+
+	if (tracker->first_time_index) {
+		tracker_db_set_option_int (db_con, "InitialIndex", 1);
 	}
-}
 
-static void
-sanity_check_option_values (void)
-{
-        GSList *watch_directory_roots;
-        GSList *crawl_directory_roots;
-        GSList *no_watch_directory_roots;
-        GSList *no_index_file_types;
+	/* Create connections */
+	db_con->cache = tracker_db_connect_cache ();
+	db_con->common = tracker_db_connect_common ();
 
-        watch_directory_roots = tracker_config_get_watch_directory_roots (tracker->config);
-        crawl_directory_roots = tracker_config_get_crawl_directory_roots (tracker->config);
-        no_watch_directory_roots = tracker_config_get_no_watch_directory_roots (tracker->config);
+	main_thread_db_con = db_con;
+	
+	/* Move final file to index file if present and no files left
+	 * to merge.
+	 */
+	final_index_name = g_build_filename (tracker->data_dir, 
+					     "file-index-final", 
+					     NULL);
+	
+	if (g_file_test (final_index_name, G_FILE_TEST_EXISTS) && 
+	    !tracker_indexer_has_tmp_merge_files (INDEX_TYPE_FILES)) {
+		gchar *file_index_name;
+
+		file_index_name = g_build_filename (tracker->data_dir, 
+						    TRACKER_INDEXER_FILE_INDEX_DB_FILENAME, 
+						    NULL);
+	
+		tracker_log ("Overwriting '%s' with '%s'", 
+			     file_index_name, 
+			     final_index_name);	
+		rename (final_index_name, file_index_name);
+		g_free (file_index_name);
+	}
+	
+	g_free (final_index_name);
+	
+	final_index_name = g_build_filename (tracker->data_dir, 
+					     "email-index-final", 
+					     NULL);
+	
+	if (g_file_test (final_index_name, G_FILE_TEST_EXISTS) && 
+	    !tracker_indexer_has_tmp_merge_files (INDEX_TYPE_EMAILS)) {
+		gchar *file_index_name;
+
+		file_index_name = g_build_filename (tracker->data_dir, 
+						    TRACKER_INDEXER_EMAIL_INDEX_DB_FILENAME, 
+						    NULL);
+	
+		tracker_log ("Overwriting '%s' with '%s'", 
+			     file_index_name, 
+			     final_index_name);	
+		rename (final_index_name, file_index_name);
+		g_free (file_index_name);
+	}
+	
+	g_free (final_index_name);
 
-        no_index_file_types = tracker_config_get_no_index_file_types (tracker->config);
+	/* Create indexers */
+	index = tracker_indexer_open (TRACKER_INDEXER_FILE_INDEX_DB_FILENAME, TRUE);
+	tracker->file_index = index;
 
-	tracker_log ("Tracker configuration options:");
-	tracker_log ("  Verbosity  ............................  %d", 
-                     tracker_config_get_verbosity (tracker->config));
- 	tracker_log ("  Low memory mode  ......................  %s", 
-                     tracker_config_get_low_memory_mode (tracker->config) ? "yes" : "no");
- 	tracker_log ("  Indexing enabled  .....................  %s", 
-                     tracker_config_get_enable_indexing (tracker->config) ? "yes" : "no");
- 	tracker_log ("  Watching enabled  .....................  %s", 
-                     tracker_config_get_enable_watches (tracker->config) ? "yes" : "no");
- 	tracker_log ("  File content indexing enabled  ........  %s", 
-                     tracker_config_get_enable_content_indexing (tracker->config) ? "yes" : "no");
-	tracker_log ("  Thumbnailing enabled  .................  %s", 
-                     tracker_config_get_enable_thumbnails (tracker->config) ? "yes" : "no");
-	tracker_log ("  Email client to index .................  %s",
-		     tracker_config_get_email_client (tracker->config));
+	index = tracker_indexer_open (TRACKER_INDEXER_FILE_UPDATE_INDEX_DB_FILENAME, FALSE);
+	tracker->file_update_index = index;
 
-	tracker_log ("Tracker indexer parameters:");
-	tracker_log ("  Indexer language code  ................  %s", 
-                     tracker_config_get_language (tracker->config));
-	tracker_log ("  Minimum index word length  ............  %d", 
-                     tracker_config_get_min_word_length (tracker->config));
-	tracker_log ("  Maximum index word length  ............  %d", 
-                     tracker_config_get_max_word_length (tracker->config));
-	tracker_log ("  Stemmer enabled  ......................  %s", 
-                     tracker_config_get_enable_stemmer (tracker->config) ? "yes" : "no");
+	index = tracker_indexer_open (TRACKER_INDEXER_EMAIL_INDEX_DB_FILENAME, TRUE);
+	tracker->email_index = index;
 
-	tracker->word_count = 0;
-	tracker->word_detail_count = 0;
-	tracker->word_update_count = 0;
+	db_con->word_index = tracker->file_index;
 
-	tracker->file_word_table = g_hash_table_new (g_str_hash, g_str_equal);
-	tracker->file_update_word_table = g_hash_table_new (g_str_hash, g_str_equal);
-	tracker->email_word_table = g_hash_table_new (g_str_hash, g_str_equal);
+	tracker_db_get_static_data (db_con);
 
-	if (!tracker_config_get_low_memory_mode (tracker->config)) {
-		tracker->memory_limit = 16000 *1024;
-	
-		tracker->max_process_queue_size = 5000;
-		tracker->max_extract_queue_size = 5000;
-	} else {
-		tracker->memory_limit = 8192 * 1024;
+	tracker->file_metadata_queue = g_async_queue_new ();
+
+	if (!tracker->readonly) {
+		tracker->file_process_queue = g_async_queue_new ();
+	}
+}
+
+static gboolean 
+shutdown_timeout_cb (gpointer user_data)
+{
+	tracker_error ("Could not exit in a timely fashion - terminating...");
+	exit (EXIT_FAILURE);
+
+	return FALSE;
+}
+
+static void
+shutdown_threads (void)
+{
+	tracker_log ("Shutting down threads");
+
+	/* Wait for files thread to sleep */
+	while (!g_mutex_trylock (tracker->files_signal_mutex)) {
+		g_usleep (100);
+	}
 
-		tracker->max_process_queue_size = 500;
-		tracker->max_extract_queue_size = 500;
+	g_mutex_unlock (tracker->files_signal_mutex);
+
+	while (!g_mutex_trylock (tracker->metadata_signal_mutex)) {
+		g_usleep (100);
 	}
 
-	log_option_list (watch_directory_roots, "Watching directory roots");
-	log_option_list (crawl_directory_roots, "Crawling directory roots");
-	log_option_list (no_watch_directory_roots, "NOT watching directory roots");
-	log_option_list (no_index_file_types, "NOT indexing file types");
+	g_mutex_unlock (tracker->metadata_signal_mutex);
 
-        tracker_log ("Throttle level is %d\n", tracker_config_get_throttle (tracker->config));
+	/* Send signals to each thread to wake them up and then stop
+	 * them.
+	 */
+	g_mutex_lock (tracker->metadata_signal_mutex);
+	g_cond_signal (tracker->metadata_signal_cond);
+	g_mutex_unlock (tracker->metadata_signal_mutex);
 
-	tracker->metadata_table = g_hash_table_new_full (g_str_hash,
-                                                         g_str_equal, 
-                                                         NULL, 
-                                                         NULL);
+	g_mutex_unlock (tracker->files_check_mutex);
+
+	g_mutex_lock (tracker->files_signal_mutex);
+	g_cond_signal (tracker->files_signal_cond);
+	g_mutex_unlock (tracker->files_signal_mutex);
+
+	/* Wait for threads to exit and unlock check mutexes to
+	 * prevent any deadlocks 
+	 */
+	g_mutex_unlock (tracker->metadata_check_mutex);
+	g_mutex_unlock (tracker->files_check_mutex);
 }
 
 static void
-create_index (gboolean need_data)
+shutdown_indexer (void)
 {
-	tracker->first_time_index = TRUE;
-
-	/* create files db and emails db */
-	DBConnection *db_con_tmp = tracker_db_connect ();
-
-	/* reset stats for embedded services if they are being reindexed */
-	if (!need_data) {
-		tracker_log ("*** DELETING STATS *** ");
-		tracker_db_exec_no_reply (db_con_tmp, "update ServiceTypes set TypeCount = 0 where Embedded = 1");
-	}
+	tracker_indexer_close (tracker->file_index);
+	tracker_indexer_close (tracker->file_update_index);
+	tracker_indexer_close (tracker->email_index);
 
-	tracker_db_close (db_con_tmp);
-	g_free (db_con_tmp);
+	tracker_email_end_email_watching ();
+}
 
-	/* create databases */
+static void
+shutdown_databases (void)
+{
+	/* Reset integrity status as threads have closed cleanly */
+	tracker_db_set_option_int (main_thread_db_con, "IntegrityCheck", 0);
 
-	db_con_tmp = tracker_db_connect_file_content ();
-	tracker_db_close (db_con_tmp);
-	g_free (db_con_tmp);
+	tracker_db_close (main_thread_db_con);
 
-	db_con_tmp = tracker_db_connect_email_content ();
-	tracker_db_close (db_con_tmp);
-	g_free (db_con_tmp);
+	/* This must be called after all other db functions */
+	tracker_db_finalize ();
+}
 
-	db_con_tmp = tracker_db_connect_emails ();
-	tracker_db_close (db_con_tmp);
-	g_free (db_con_tmp);
+static void
+shutdown_directories (void)
+{
+	/* If we are reindexing, just remove the databases */
+	if (tracker->reindex) {
+		tracker_dir_remove (tracker->data_dir);
+		g_mkdir_with_parents (tracker->data_dir, 00755);
+	}
 
+	/* Remove sys tmp directory */
+	if (tracker->sys_tmp_root_dir) {
+		tracker_dir_remove (tracker->sys_tmp_root_dir);
+	}
 }
 
 gint
 main (gint argc, gchar *argv[])
 {
-	gint               lfp;
-#ifndef OS_WIN32
-  	struct sigaction   act;
-	sigset_t 	   empty_mask;
-#endif
-	gchar 		  *lock_file, *str, *lock_str;
-	GOptionContext    *context = NULL;
-	GError            *error = NULL;
-	gchar             *example;
-	gboolean 	   need_index = FALSE;
-        gboolean           need_data;
-	DBConnection      *db_con;
-	gchar             *tmp_dir;
-	gchar             *old_tracker_dir;
-	gchar             *log_filename;
+	GOptionContext *context = NULL;
+	GError         *error = NULL;
+	GSList         *l;
+	gint            lfp;
+	gchar          *lock_file, *str, *lock_str;
+	gchar          *example;
+	gboolean        need_index = FALSE;
 
         g_type_init ();
         
@@ -573,14 +742,17 @@
         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
         textdomain (GETTEXT_PACKAGE);
 
-	/* set timezone info */
+	/* Set timezone info */
 	tzset ();
 
-        /* Translators: this messagge will apper immediately after the  */
-        /* usage string - Usage: COMMAND <THIS_MESSAGE>     */
+        /* Translators: this messagge will apper immediately after the
+	 * usage string - Usage: COMMAND <THIS_MESSAGE> 
+	 */
 	context = g_option_context_new (_("- start the tracker daemon"));
-        example = g_strconcat ("-i ", _("DIRECTORY"), " -i ", _("DIRECTORY"),
-			       " -e ", _("DIRECTORY"), " -e ", _("DIRECTORY"),
+        example = g_strconcat ("-i ", _("DIRECTORY"), 
+			       " -i ", _("DIRECTORY"),
+			       " -e ", _("DIRECTORY"), 
+			       " -e ", _("DIRECTORY"),
 			       NULL);
 
 #ifdef HAVE_RECENT_GLIB
@@ -591,7 +763,8 @@
                                                     "at the same time, join multiple options like:"),
 
                                                   "\n\n\t",
-                                                  example, NULL));
+                                                  example, 
+						  NULL));
 
 #endif /* HAVE_RECENT_GLIB */
 
@@ -601,98 +774,44 @@
 	g_option_context_free (context);
 	g_free (example);
 
+	if (error) {
+		g_printerr ("Invalid arguments, %s\n", error->message);
+		g_clear_error (&error);
+		return EXIT_FAILURE;
+	}
+
+	/* Print information */
 	g_print ("\n" ABOUT "\n" LICENSE "\n");
 	g_print ("Initialising tracker...\n");
 
-#ifndef OS_WIN32
-	/* trap signals */
-	sigemptyset (&empty_mask);
-	act.sa_handler = signal_handler;
-	act.sa_mask    = empty_mask;
-	act.sa_flags   = 0;
-	sigaction (SIGTERM, &act, NULL);
-	sigaction (SIGILL,  &act, NULL);
-	sigaction (SIGBUS,  &act, NULL);
-	sigaction (SIGFPE,  &act, NULL);
-	sigaction (SIGHUP,  &act, NULL);
-	sigaction (SIGSEGV, &act, NULL);
-	sigaction (SIGABRT, &act, NULL);
-	sigaction (SIGUSR1, &act, NULL);
-	sigaction (SIGINT,  &act, NULL);
-#endif
+	initialise_signal_handler ();
 
 	tracker = g_new0 (Tracker, 1);
 
-	tracker_xesam_init ();
+	tracker->pid = getpid ();
+	tracker->dir_queue = g_async_queue_new ();
 
 	/* Set up directories */
-	tracker->pid = (int) getpid ();
-	tmp_dir = g_strdup_printf ("Tracker-%s.%d", g_get_user_name (), tracker->pid);
-	tracker->sys_tmp_root_dir = g_build_filename (g_get_tmp_dir (), tmp_dir, NULL);
-	g_free (tmp_dir);
+	initialise_directories ();
+	umask (077);
 
-	tracker->root_dir = g_build_filename (g_get_user_data_dir  (), "tracker", NULL);
-	tracker->data_dir = g_build_filename (g_get_user_cache_dir (), "tracker", NULL);
-	tracker->config_dir = g_strdup (g_get_user_config_dir ());
-	tracker->user_data_dir = g_build_filename (tracker->root_dir, "data", NULL);
-	
         /* Set up the config */
         tracker->config = tracker_config_new ();
         tracker->language = tracker_language_new (tracker->config);
 
 	/* Set up the log */
-	log_filename = g_build_filename (tracker->root_dir, "tracker.log", NULL);
-	tracker_file_unlink (log_filename);
-
-	tracker_log_init (log_filename, 
+	tracker_log_init (tracker->log_filename, 
                           tracker_config_get_verbosity (tracker->config), 
                           fatal_errors);
 	tracker_log ("Starting log");
 
+	/* Set up locking */
 	tracker_nfs_lock_init (tracker->root_dir);
+	
+	/* Set up xesam */
+	tracker_xesam_init ();
 
-        /* Set up mutexes and intitial state */
- 	tracker->is_running = FALSE;
-	tracker->shutdown = FALSE;
-
-	tracker->files_check_mutex = g_mutex_new ();
-	tracker->files_signal_mutex = g_mutex_new ();
-	tracker->files_signal_cond = g_cond_new ();
-
-	tracker->metadata_check_mutex = g_mutex_new ();
-	tracker->metadata_signal_mutex = g_mutex_new ();
-	tracker->metadata_signal_cond = g_cond_new ();
-
-	/* Remove an existing one */
-	if (g_file_test (tracker->sys_tmp_root_dir, G_FILE_TEST_EXISTS)) {
-		tracker_dir_remove (tracker->sys_tmp_root_dir);
-	}
-
-	/* Remove old tracker dirs */
-        old_tracker_dir = g_build_filename (g_get_home_dir (), ".Tracker", NULL);
-
-	if (g_file_test (old_tracker_dir ,G_FILE_TEST_EXISTS)) {
-		tracker_dir_remove (old_tracker_dir);
-	}
-
-	g_free (old_tracker_dir);
-
-        /* Create other directories we need */
-	if (!g_file_test (tracker->user_data_dir, G_FILE_TEST_EXISTS)) {
-		g_mkdir_with_parents (tracker->user_data_dir, 00755);
-	}
-
-	if (!g_file_test (tracker->data_dir, G_FILE_TEST_EXISTS)) {
-		g_mkdir_with_parents (tracker->data_dir, 00755);
-	}
-
-        tracker->email_attachements_dir = g_build_filename (tracker->sys_tmp_root_dir, "Attachments", NULL);
-	g_mkdir_with_parents (tracker->email_attachements_dir, 00700);
-	tracker_log ("Made email attachments directory %s\n", tracker->email_attachements_dir);
-
-	tracker->dir_queue = g_async_queue_new ();
-
-	tracker->xesam_dir = g_build_filename (g_get_home_dir (), ".xesam", NULL);
+	initialise_threading ();
 
 	if (reindex || tracker_db_needs_setup ()) {
 		tracker_dir_remove (tracker->data_dir);
@@ -700,37 +819,33 @@
 		need_index = TRUE;
 	}
 
-	umask (077);
-
 	str = g_strconcat (g_get_user_name (), "_tracker_lock", NULL);
 
-	/* check if setup for NFS usage (and enable atomic NFS safe locking) */
-	//lock_str = tracker_get_config_option ("NFSLocking");
+	/* Check if setup for NFS usage (and enable atomic NFS safe locking) */
 	lock_str = NULL;
 
 	if (lock_str != NULL) {
-
 		tracker->use_nfs_safe_locking = (strcmp (str, "1") == 0);
 
-		/* place lock file in tmp dir to allow multiple sessions on NFS */
+		/* Place lock file in tmp dir to allow multiple
+		 * sessions on NFS.
+		 */
 		lock_file = g_build_filename (tracker->sys_tmp_root_dir, str, NULL);
-
 		g_free (lock_str);
-
 	} else {
-
 		tracker->use_nfs_safe_locking = FALSE;
 
-		/* place lock file in home dir to prevent multiple sessions on NFS (as standard locking might be broken on NFS) */
+		/* Place lock file in home dir to prevent multiple
+		 * sessions on NFS (as standard locking might be
+		 * broken on NFS) 
+		 */
 		lock_file = g_build_filename (tracker->root_dir, str, NULL);
 	}
 
 	g_free (str);
 
-	/* prevent muliple instances  */
-	tracker->readonly = FALSE;
-
-	lfp = g_open (lock_file, O_RDWR|O_CREAT, 0640);
+	/* Prevent muliple instances  */
+	lfp = g_open (lock_file, O_RDWR | O_CREAT, 0640);
 	g_free (lock_file);
 
 	if (lfp < 0) {
@@ -745,25 +860,24 @@
 
 	/* Set child's niceness to 19 */
         errno = 0;
-        /* nice() uses attribute "warn_unused_result" and so complains if we do not check its
-           returned value. But it seems that since glibc 2.2.4, nice() can return -1 on a
-           successful call so we have to check value of errno too. Stupid... */
+
+        /* nice() uses attribute "warn_unused_result" and so complains
+	 * if we do not check its returned value. But it seems that
+	 * since glibc 2.2.4, nice() can return -1 on a successful
+	 * call so we have to check value of errno too. Stupid... 
+	 */
         if (nice (19) == -1 && errno) {
-                g_printerr ("ERROR: trying to set nice value\n");
+                tracker_log ("Couldn't set nice() value");
         }
 
 #ifdef IOPRIO_SUPPORT
 	ioprio ();
 #endif
 
-	
-	/* deal with config options with defaults, config file and option params */
-	set_defaults ();
-
-	if (error) {
-		g_printerr ("invalid arguments: %s\n", error->message);
-		return 1;
-	}
+	/* Deal with config options with defaults, config file and
+	 * option params.
+	 */
+	initialise_defaults ();
 
 	if (watch_dirs) {
                 tracker_config_add_watch_directory_roots (tracker->config, watch_dirs);
@@ -803,7 +917,7 @@
 
 	sanity_check_option_values ();
 
-        /* Initialize the service manager */
+        /* Initialise the service manager */
         tracker_service_manager_init ();
 
 	/* Set thread safe DB connection */
@@ -814,118 +928,7 @@
 		return EXIT_FAILURE;
         }
 
-	/* FIXME: is this actually necessary? */
-	db_con = tracker_db_connect_cache ();
-	tracker_db_close (db_con);
-
-	need_data = tracker_db_needs_data ();
-
-	if (need_data) {
-		tracker_create_common_db ();
-	}
-
-	if (!tracker->readonly && need_index) {
-		create_index (need_data);
-	} else {
-		tracker->first_time_index = FALSE;
-	}
-
-        /* Set up main database connection */
-	db_con = tracker_db_connect ();
-
-	/* check db integrity if not previously shut down cleanly */
-	if (!tracker->readonly && !need_index && tracker_db_get_option_int (db_con, "IntegrityCheck") == 1) {
-
-		tracker_log ("performing integrity check as trackerd was not shutdown cleanly");
-
-
-/*		turn off corruption check as it can hog cpu for long time 
-
-		if (!tracker_db_integrity_check (db_con) || 
-		    !tracker_indexer_repair (TRACKER_INDEXER_FILE_INDEX_DB_FILENAME) || 
-		    !tracker_indexer_repair (TRACKER_INDEXER_EMAIL_INDEX_DB_FILENAME)) {
-			tracker_error ("db or index corruption detected - prepare for reindex...");
-			tracker_db_close (db_con);	
-
-			tracker_dir_remove (tracker->data_dir);
-			g_mkdir_with_parents (tracker->data_dir, 00755);
-			create_index (need_data);
-			db_con = tracker_db_connect ();
-			db_con->thread = "main";
-
-		}
-*/
-	} 
-
-	
-	if (!tracker->readonly) {
-		tracker_db_set_option_int (db_con, "IntegrityCheck", 1);
-	} 
-
-	if (tracker->first_time_index) {
-		tracker_db_set_option_int (db_con, "InitialIndex", 1);
-	}
-
-	db_con->cache = tracker_db_connect_cache ();
-	db_con->common = tracker_db_connect_common ();
-
-	main_thread_db_con = db_con;
-	
-	/* move final file to index file if present and no files left to merge */
-	char *final_index_name = g_build_filename (tracker->data_dir, "file-index-final", NULL);
-	
-	if (g_file_test (final_index_name, G_FILE_TEST_EXISTS) && !tracker_indexer_has_tmp_merge_files (INDEX_TYPE_FILES)) {
-	
-		char *file_index_name = g_build_filename (tracker->data_dir, TRACKER_INDEXER_FILE_INDEX_DB_FILENAME, NULL);
-	
-		tracker_log ("overwriting %s with %s", file_index_name, final_index_name);	
-
-		rename (final_index_name, file_index_name);
-		
-		g_free (file_index_name);
-	}
-	
-	g_free (final_index_name);
-	
-	final_index_name = g_build_filename (tracker->data_dir, "email-index-final", NULL);
-	
-	if (g_file_test (final_index_name, G_FILE_TEST_EXISTS) && !tracker_indexer_has_tmp_merge_files (INDEX_TYPE_EMAILS)) {
-	
-		char *file_index_name = g_build_filename (tracker->data_dir, TRACKER_INDEXER_EMAIL_INDEX_DB_FILENAME, NULL);
-	
-		tracker_log ("overwriting %s with %s", file_index_name, final_index_name);	
-	
-		rename (final_index_name, file_index_name);
-		
-		g_free (file_index_name);
-	}
-	
-	g_free (final_index_name);
-	
-	
-
-	Indexer *index = tracker_indexer_open (TRACKER_INDEXER_FILE_INDEX_DB_FILENAME, TRUE);
-	tracker->file_index = index;
-
-	index = tracker_indexer_open (TRACKER_INDEXER_FILE_UPDATE_INDEX_DB_FILENAME, FALSE);
-	tracker->file_update_index = index;
-
-	index = tracker_indexer_open (TRACKER_INDEXER_EMAIL_INDEX_DB_FILENAME, TRUE);
-	tracker->email_index = index;
-
-	db_con->word_index = tracker->file_index;
-
-	tracker->update_count = get_update_count (main_thread_db_con);
-
-	tracker_db_get_static_data (db_con);
-
-	tracker->file_metadata_queue = g_async_queue_new ();
-
-	if (!tracker->readonly) {
-		tracker->file_process_queue = g_async_queue_new ();
-	}
-
-  	tracker->loop = g_main_loop_new (NULL, FALSE);
+	initialise_databases (need_index);
 
 	tracker_email_init ();
 
@@ -934,9 +937,12 @@
  	tracker->hal = tracker_hal_new ();       
 #endif
 
-	/* this var is used to tell the threads when to quit */
+	/* Set our status as running, if this is FALSE, threads stop
+	 * doing what they do and shutdown.
+	 */
 	tracker->is_running = TRUE;
 
+	/* Connect to databases */
         tracker->index_db = tracker_db_connect_all ();
 
         /* If we are already running, this should return some
@@ -947,22 +953,76 @@
         }
 
 	if (!tracker->readonly) {
-		if (!tracker_start_watching ()) {
-			tracker_error ("ERROR: file monitoring failed to start");
-			tracker_do_cleanup ("File watching failure");
-			return EXIT_FAILURE;
+		if (G_UNLIKELY (!tracker_start_watching ())) {
+			tracker->is_running = FALSE;
+			tracker_error ("File monitoring failed to start");
+		} else {
+			g_thread_create_full ((GThreadFunc) tracker_process_files, 
+					      tracker,
+					      (gulong) tracker_config_get_thread_stack_size (tracker->config),
+					      FALSE, 
+					      FALSE, 
+					      G_THREAD_PRIORITY_NORMAL, 
+					      NULL);
 		}
-
-                g_thread_create_full ((GThreadFunc) tracker_process_files, 
-                                      tracker,
-                                      (gulong) tracker_config_get_thread_stack_size (tracker->config),
-                                      FALSE, 
-                                      FALSE, 
-                                      G_THREAD_PRIORITY_NORMAL, 
-                                      NULL);
 	}
 	
-	g_main_loop_run (tracker->loop);
+	if (tracker->is_running) {
+		main_loop = g_main_loop_new (NULL, FALSE);
+		g_main_loop_run (main_loop);
+	}
+
+	/* 
+	 * Shutdown the daemon
+	 */
+	tracker->shutdown = TRUE;
+	tracker_status_set (TRACKER_STATUS_SHUTDOWN);
+
+	/* Reset black list files */
+        l = tracker_process_files_get_temp_black_list ();
+	g_slist_foreach (l, (GFunc) reset_blacklist_file, NULL);
+	g_slist_free (l);
+
+	/* Remove file change queue */
+	if (tracker->file_change_queue) {
+		g_queue_foreach (tracker->file_change_queue,
+				 free_file_change_queue, NULL);
+		g_queue_free (tracker->file_change_queue);
+		tracker->file_change_queue = NULL;
+	}
+
+	/* Set kill timeout */
+	g_timeout_add_full (G_PRIORITY_LOW, 20000, shutdown_timeout_cb, NULL, NULL);
+
+	shutdown_threads ();
+	shutdown_indexer ();
+	shutdown_databases ();
+	shutdown_directories ();
+
+	/* Shutdown major subsystems */
+        if (tracker->hal) {
+                g_object_unref (tracker->hal);
+                tracker->hal = NULL;
+        }
+
+        if (tracker->language) {
+                tracker_language_free (tracker->language);
+        }
+
+        if (tracker->config) {
+                g_object_unref (tracker->config);
+        }
+
+	tracker_nfs_lock_term ();
+	tracker_log_term ();
+
+	/* FIXME: we need to clean up Tracker struct members */
 
 	return EXIT_SUCCESS;
 }
+
+void
+tracker_shutdown (void)
+{
+	g_main_loop_quit (main_loop);
+}

Modified: branches/indexer-split/src/trackerd/tracker-main.h
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-main.h	(original)
+++ branches/indexer-split/src/trackerd/tracker-main.h	Thu May  8 16:39:43 2008
@@ -53,8 +53,6 @@
 } IndexStatus;
 
 typedef struct {
-	GMainLoop   *loop; 
-
  	gboolean     is_running; 
 	gboolean     readonly;
 
@@ -79,6 +77,8 @@
 	gchar       *services_dir;
 	gchar       *xesam_dir;
 
+	gchar       *log_filename;
+
 	/* Performance and memory usage options */
 	gint         max_process_queue_size;
 	gint         max_extract_queue_size;
@@ -133,7 +133,6 @@
 	
 	/* Application run time values */
 	gint         index_count; 
-	gint	     update_count; 
 
 	/* Cache words before saving to word index */
 	GHashTable  *file_word_table;
@@ -159,12 +158,12 @@
 	GHashTable  *xesam_sessions; 
 } Tracker;
 
+void     tracker_shutdown                   (void);
 GSList * tracker_get_watch_root_dirs        (void);
 gboolean tracker_spawn                      (gchar       **argv,
                                              gint          timeout,
                                              gchar       **tmp_stdout,
                                              gint         *exit_status);
-gboolean tracker_do_cleanup                 (const gchar  *sig_msg);
 gboolean tracker_watch_dir                  (const gchar  *uri);
 void     tracker_scan_directory             (const gchar  *uri);
 

Modified: branches/indexer-split/src/trackerd/tracker-process-files.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-process-files.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-process-files.c	Thu May  8 16:39:43 2008
@@ -1189,8 +1189,6 @@
 
                 tracker_db_set_option_int (db_con, "InitialIndex", 0);
                 
-                tracker->update_count = 0;
-                
                 tracker_log ("Updating database stats, please wait...");
                 
                 tracker_db_interface_start_transaction (db_con->db);



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