tracker r1563 - in branches/indexer-split: . src/trackerd



Author: mr
Date: Mon Jun  2 18:17:52 2008
New Revision: 1563
URL: http://svn.gnome.org/viewvc/tracker?rev=1563&view=rev

Log:
	* src/trackerd/Makefile.am:
	* src/trackerd/tracker-db-sqlite.c:
	* src/trackerd/tracker-dbus.c:
	* src/trackerd/tracker-email-evolution.c:
	* src/trackerd/tracker-email-kmail.c:
	* src/trackerd/tracker-email-modest.c:
	* src/trackerd/tracker-email-thunderbird.c:
	* src/trackerd/tracker-email-utils.c:
	* src/trackerd/tracker-fam.c:
	* src/trackerd/tracker-inotify.c:
	* src/trackerd/tracker-main.c:
	* src/trackerd/tracker-poll.c:
	* src/trackerd/tracker-process-files.c:
	* src/trackerd/tracker-watch.h:
	* src/trackerd/tracker-watcher-fam.c: 
	* src/trackerd/tracker-watcher-inotify.c:
	* src/trackerd/tracker-watcher-poll.c:
	* src/trackerd/tracker-watcher-win.c: 
	* src/trackerd/tracker-watcher.h:
	* src/trackerd/tracker-win-fs-changes.c: Moved all watch files so
	they use the prefix tracker-watch-*. Updated the API to have a
	consistent tracker_watcher_() prefix. Refactored the FAM, inotify,
	poll and windows backends.


Added:
   branches/indexer-split/src/trackerd/tracker-watcher-fam.c
      - copied, changed from r1560, /branches/indexer-split/src/trackerd/tracker-fam.c
   branches/indexer-split/src/trackerd/tracker-watcher-inotify.c
      - copied, changed from r1561, /branches/indexer-split/src/trackerd/tracker-inotify.c
   branches/indexer-split/src/trackerd/tracker-watcher-poll.c
      - copied, changed from r1560, /branches/indexer-split/src/trackerd/tracker-poll.c
   branches/indexer-split/src/trackerd/tracker-watcher-win.c
      - copied, changed from r1560, /branches/indexer-split/src/trackerd/tracker-win-fs-changes.c
   branches/indexer-split/src/trackerd/tracker-watcher.h
      - copied, changed from r1561, /branches/indexer-split/src/trackerd/tracker-watch.h
Removed:
   branches/indexer-split/src/trackerd/tracker-fam.c
   branches/indexer-split/src/trackerd/tracker-inotify.c
   branches/indexer-split/src/trackerd/tracker-poll.c
   branches/indexer-split/src/trackerd/tracker-watch.h
   branches/indexer-split/src/trackerd/tracker-win-fs-changes.c
Modified:
   branches/indexer-split/ChangeLog
   branches/indexer-split/src/trackerd/Makefile.am
   branches/indexer-split/src/trackerd/tracker-db-sqlite.c
   branches/indexer-split/src/trackerd/tracker-dbus.c
   branches/indexer-split/src/trackerd/tracker-email-evolution.c
   branches/indexer-split/src/trackerd/tracker-email-kmail.c
   branches/indexer-split/src/trackerd/tracker-email-modest.c
   branches/indexer-split/src/trackerd/tracker-email-thunderbird.c
   branches/indexer-split/src/trackerd/tracker-email-utils.c
   branches/indexer-split/src/trackerd/tracker-main.c
   branches/indexer-split/src/trackerd/tracker-process-files.c

Modified: branches/indexer-split/src/trackerd/Makefile.am
==============================================================================
--- branches/indexer-split/src/trackerd/Makefile.am	(original)
+++ branches/indexer-split/src/trackerd/Makefile.am	Mon Jun  2 18:17:52 2008
@@ -17,22 +17,10 @@
 	$(GTHREAD_CFLAGS)						\
 	$(GLIB2_CFLAGS)
 
-if HAVE_INOTIFY
-watch_sources =								\
-	linux-inotify-syscalls.h					\
-	tracker-inotify.c
-else
-if HAVE_FAM
-watch_sources = tracker-fam.c
-else
-if OS_WIN32
-watch_sources = tracker-win-fs-changes.c
-else
-watch_sources = tracker-poll.c
-endif
-endif
-endif
 
+#
+# Mail sources
+#
 mail_modulesdir = $(libdir)/tracker/mail-modules
 mail_modules_LTLIBRARIES = \
 	libemail-evolution.la \
@@ -59,12 +47,32 @@
 libemail_kmail_la_LIBADD = $(GLIB2_LIBS)
 
 
+#
+# Use either inotify, fam, win32 or poll API to know about file
+# changes and in that order.
+#
+if HAVE_INOTIFY
+watcher_sources = tracker-watcher-inotify.c linux-inotify-syscalls.h
+else  # HAVE_INOTIFY 
+if HAVE_FAM
+watcher_sources = tracker-watcher-fam.c
+else  # HAVE_FAM 
+if OS_WIN32
+watcher_sources = tracker-watcher-win.c
+else  # OS_WIN32 
+watcher_sources = tracker-watcher-poll.c
+endif # OS_WIN32 
+endif # HAVE_FAM
+endif # HAVE_INOTIFY
+
+
+#
+# Daemon sources
+#
 bin_PROGRAMS = trackerd
 
 trackerd_SOURCES =							\
-	$(watch_sources)						\
-	$(win_sources)							\
-	$(unix_sources)							\
+	$(watcher_sources)						\
 	tracker-daemon.c						\
 	tracker-daemon.h						\
 	tracker-db.c							\

Modified: branches/indexer-split/src/trackerd/tracker-db-sqlite.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-db-sqlite.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-db-sqlite.c	Mon Jun  2 18:17:52 2008
@@ -43,7 +43,7 @@
 #include "tracker-indexer.h"
 #include "tracker-main.h"
 #include "tracker-utils.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 #include "tracker-query-tree.h"
 #include "tracker-xesam-ontology.h"
 

Modified: branches/indexer-split/src/trackerd/tracker-dbus.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-dbus.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-dbus.c	Mon Jun  2 18:17:52 2008
@@ -39,7 +39,7 @@
 #include "tracker-xesam-glue.h"
 #include "tracker-indexer-client.h"
 #include "tracker-utils.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 
 static DBusGConnection *connection;
 static DBusGProxy      *proxy;

Modified: branches/indexer-split/src/trackerd/tracker-email-evolution.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-email-evolution.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-email-evolution.c	Mon Jun  2 18:17:52 2008
@@ -43,7 +43,7 @@
 #include "tracker-db-email.h"
 #include "tracker-dbus.h"
 #include "tracker-daemon.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 #include "tracker-status.h"
 #include "tracker-utils.h"
 #include "tracker-main.h"

Modified: branches/indexer-split/src/trackerd/tracker-email-kmail.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-email-kmail.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-email-kmail.c	Mon Jun  2 18:17:52 2008
@@ -35,7 +35,7 @@
 #include "tracker-db-email.h"
 #include "tracker-main.h"
 #include "tracker-process-files.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 
 typedef struct {
         gchar            *imap_path;

Modified: branches/indexer-split/src/trackerd/tracker-email-modest.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-email-modest.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-email-modest.c	Mon Jun  2 18:17:52 2008
@@ -42,7 +42,7 @@
 #include "tracker-dbus.h"
 #include "tracker-daemon.h"
 #include "tracker-status.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 
 
 #define MODEST_HOME	".modest"

Modified: branches/indexer-split/src/trackerd/tracker-email-thunderbird.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-email-thunderbird.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-email-thunderbird.c	Mon Jun  2 18:17:52 2008
@@ -28,7 +28,7 @@
 #include <libtracker-common/tracker-config.h>
 
 #include "tracker-db-email.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 #include "tracker-main.h"
 
 typedef enum

Modified: branches/indexer-split/src/trackerd/tracker-email-utils.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-email-utils.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-email-utils.c	Mon Jun  2 18:17:52 2008
@@ -39,7 +39,7 @@
 #include "tracker-dbus.h"
 #include "tracker-daemon.h"
 #include "tracker-email-utils.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 
 extern Tracker *tracker;
 

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	Mon Jun  2 18:17:52 2008
@@ -50,7 +50,7 @@
 #include "tracker-indexer.h"
 #include "tracker-process-files.h"
 #include "tracker-status.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 #include "tracker-xesam-manager.h"
 
 #ifdef OS_WIN32

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	Mon Jun  2 18:17:52 2008
@@ -46,7 +46,7 @@
 #include "tracker-daemon.h"
 #include "tracker-email.h"
 #include "tracker-indexer.h"
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 #include "tracker-status.h"
 #include "tracker-process-files.h"
 

Copied: branches/indexer-split/src/trackerd/tracker-watcher-fam.c (from r1560, /branches/indexer-split/src/trackerd/tracker-fam.c)
==============================================================================
--- /branches/indexer-split/src/trackerd/tracker-fam.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-watcher-fam.c	Mon Jun  2 18:17:52 2008
@@ -1,5 +1,7 @@
-/* Tracker - indexer and metadata database engine
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* 
  * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -16,50 +18,33 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301, USA.
  */
+
 #include <string.h>
 #include <unistd.h>
 #include <fam.h>
+
 #include <glib.h>
 #include <glib/gstdio.h>
 
-#include "tracker-watch.h"
-
-
-extern Tracker 	    *tracker;
-extern DBConnection *main_thread_db_con;
-
+#include "tracker-watcher.h"
 
 typedef struct {
-	char 	   *watch_directory;
+	gchar 	   *watch_directory;
 	FAMRequest *fr;
-	WatchTypes watch_type;
+	WatchTypes  watch_type;
 } DirWatch;
 
+extern Tracker 	     *tracker;
+extern DBConnection  *main_thread_db_con;
 
-static gint	     fam_watch_id = 0;
-static FAMConnection fc;
+static gint	      fam_watch_id;
+static FAMConnection  fc;
 
-/* table to store all active directory watches  */
 static GHashTable    *watch_table;
-
-
-gboolean
-tracker_is_directory_watched (const char *dir, DBConnection *db_con)
-{
-	DirWatch *watch;
-
-	if (!dir) {
-		return FALSE;
-	}
-
-	watch = g_hash_table_lookup (watch_table, dir);
-
-	return (watch != NULL);
-}
-
+static gint           monitor_limit = 300;
 
 static WatchTypes
-tracker_get_directory_watch_type (const char *dir)
+get_directory_watch_type (const gchar *dir)
 {
 	DirWatch *watch;
 
@@ -72,58 +57,34 @@
 	return WATCH_OTHER;
 }
 
-
 static void
-free_watch_func (gpointer user_data)
+watch_table_value_destroy_func (gpointer user_data)
 {
 	DirWatch *fw;
 
 	fw = user_data;
 
-	if (fw->fr) {
-		g_free (fw->fr);
-	}
-
-	if (fw->watch_directory) {
-		g_free (fw->watch_directory);
-	}
-
-	if (fw) {
-		g_free (fw);
-	}
-}
-
-
-void
-tracker_end_watching (void)
-{
-	FAMClose (&fc);
-
-	if (fam_watch_id > 0) {
-		g_source_remove (fam_watch_id);
-		fam_watch_id = 0;
-	}
-
-	g_hash_table_destroy  (watch_table);
+        g_free (fw->fr);
+        g_free (fw->watch_directory);
+        g_free (fw);
 }
 
-
 static gboolean
 is_delete_event (TrackerAction event_type)
 {
-	return (event_type == TRACKER_ACTION_DELETE ||
+	return 
+                event_type == TRACKER_ACTION_DELETE ||
 		event_type == TRACKER_ACTION_DELETE_SELF ||
 		event_type == TRACKER_ACTION_FILE_DELETED ||
-		event_type == TRACKER_ACTION_DIRECTORY_DELETED);
+		event_type == TRACKER_ACTION_DIRECTORY_DELETED;
 }
 
-
 static gboolean
-fam_callback (GIOChannel *source,
-	      GIOCondition condition,
-	      gpointer data)
+fam_callback (GIOChannel   *source,
+	      GIOCondition  condition,
+	      gpointer      data)
 {
-	int counter;
+	gint counter;
 
 	counter = 1;
 
@@ -141,42 +102,40 @@
 		event_type = TRACKER_ACTION_IGNORE;
 
 		switch (ev.code) {
-
-			case FAMChanged:
-				event_type = TRACKER_ACTION_CHECK;
-				counter = 1;
-				break;
-			case FAMDeleted:
-				event_type = TRACKER_ACTION_DELETE;
-				counter = 0;
-				break;
-			case FAMCreated:
-				event_type = TRACKER_ACTION_CREATE;
-				counter = 1;
-				break;
-
-			case FAMStartExecuting:
-			case FAMStopExecuting:
-			case FAMAcknowledge:
-			case FAMExists:
-			case FAMEndExist:
-			case FAMMoved:
-				continue;
-				break;
+                case FAMChanged:
+                        event_type = TRACKER_ACTION_CHECK;
+                        counter = 1;
+                        break;
+                case FAMDeleted:
+                        event_type = TRACKER_ACTION_DELETE;
+                        counter = 0;
+                        break;
+                case FAMCreated:
+                        event_type = TRACKER_ACTION_CREATE;
+                        counter = 1;
+                        break;
+                        
+                case FAMStartExecuting:
+                case FAMStopExecuting:
+                case FAMAcknowledge:
+                case FAMExists:
+                case FAMEndExist:
+                case FAMMoved:
+                        continue;
 		}
-
+                
 		if (event_type != TRACKER_ACTION_IGNORE) {
-			char	 *file_uri, *file_utf8_uri;
+			gchar	 *file_uri, *file_utf8_uri;
 			FileInfo *info;
-
+                        
 			if (tracker_is_empty_string (ev.filename)) {
 				continue;
 			}
-
+                        
 			if (ev.filename[0] == G_DIR_SEPARATOR) {
 				file_uri = g_strdup (ev.filename);
 			} else {
-				char *s;
+				gchar *s;
 
 				s = g_filename_to_utf8 (ev.filename, -1, NULL, NULL, NULL);
 
@@ -184,37 +143,39 @@
 					g_free (s);
 					continue;
 				} else {
-					file_uri = g_build_filename (watch->watch_directory, ev.filename, NULL);
+					file_uri = g_build_filename (watch->watch_directory, 
+                                                                     ev.filename, NULL);
 				}
 
 				g_free (s);
 			}
 
 			file_utf8_uri = g_filename_to_utf8 (file_uri, -1, NULL, NULL, NULL);
-
 			g_free (file_uri);
 
 			if (!file_utf8_uri) {
-				tracker_error ("ERROR: FAM file uri could not be converted to utf8 format");
+                                g_critical ("File uri:'%s' could not be converted to utf8 format",
+                                            filename);
 				continue;
 			}
 
-			if (file_utf8_uri[0] != '/' || 
+                        if (file_utf8_uri[0] == G_DIR_SEPARATOR ||
                             tracker_process_files_should_be_ignored (tracker->config, file_utf8_uri) ||  
                             tracker_process_files_should_be_crawled (tracker, file_utf8_uri) || 
                             tracker_process_files_should_be_watched (tracker->config, file_utf8_uri)) {
 				g_free (file_utf8_uri);
 				continue;
-
 			}
 
-			info = tracker_create_file_info (file_utf8_uri, event_type, counter, WATCH_OTHER);
+			info = tracker_create_file_info (file_utf8_uri, 
+                                                         event_type, 
+                                                         counter, 
+                                                         WATCH_OTHER);
 
 			if (tracker_file_info_is_valid (info)) {
-
-				/* process deletions immediately - schedule (make pending) all others */
+				/* Process deletions immediately, schedule all others */
 				if (is_delete_event (event_type)) {
-					char *uri_in_locale, *parent;
+					gchar *uri_in_locale, *parent;
 
 					uri_in_locale = g_filename_from_utf8 (info->uri, -1, NULL, NULL, NULL);
 
@@ -224,26 +185,41 @@
 					}
 
 					parent = g_path_get_dirname (uri_in_locale);
-
 					g_free (uri_in_locale);
 
-					if (tracker_is_directory_watched (parent, NULL) || tracker_is_directory_watched (info->uri, NULL)) {
+					if (tracker_is_directory_watched (parent, NULL) || 
+                                            tracker_is_directory_watched (info->uri, NULL)) {
 						g_async_queue_push (tracker->file_process_queue, info);
-						tracker_add_io_grace (info->uri);
 						tracker_notify_file_data_available ();
 					} else {
 						tracker_free_file_info (info);
 					}
 
 					g_free (parent);
-
 				} else {
-					tracker_add_io_grace (info->uri);
 					if (event_type == TRACKER_ACTION_CREATE) {
-						tracker_db_insert_pending_file (main_thread_db_con, info->file_id, info->uri, NULL, info->mime, info->counter, info->action, info->is_directory, TRUE, -1);
+						tracker_db_insert_pending_file (main_thread_db_con,
+                                                                                info->file_id, 
+                                                                                info->uri, NULL, 
+                                                                                info->mime, 
+                                                                                info->counter, 
+                                                                                info->action, 
+                                                                                info->is_directory, 
+                                                                                TRUE,
+                                                                                -1);
 					} else {
-						tracker_db_insert_pending_file (main_thread_db_con, info->file_id, info->uri, NULL, info->mime, info->counter, info->action, info->is_directory, FALSE, -1);
+						tracker_db_insert_pending_file (main_thread_db_con, 
+                                                                                info->file_id, 
+                                                                                info->uri, 
+                                                                                NULL, 
+                                                                                info->mime, 
+                                                                                info->counter, 
+                                                                                info->action, 
+                                                                                info->is_directory, 
+                                                                                FALSE, 
+                                                                                -1);
 					}
+
 					tracker_free_file_info (info);
 				}
 			}
@@ -255,37 +231,63 @@
 	return TRUE;
 }
 
-
 gboolean
-tracker_start_watching (void)
+tracker_watcher_init (void)
 {
-	GIOChannel *ioc;
+	GIOChannel *channel;
+
+        if (fam_watch_id != 0) {
+                return TRUE;
+        }
 
 	if (FAMOpen2 (&fc, "Tracker") != 0) {
 		return FALSE;
 	}
 
-	ioc = g_io_channel_unix_new (FAMCONNECTION_GETFD (&fc));
+        g_message ("Using inotify monitor limit of %d", monitor_limit);
 
-	fam_watch_id = g_io_add_watch (ioc,
-				       G_IO_IN | G_IO_HUP | G_IO_ERR,
-				       fam_callback, &fc);
-	g_io_channel_unref (ioc);
+	watch_table = g_hash_table_new_full (g_str_hash, 
+                                             g_str_equal, 
+                                             g_free, 
+                                             watch_table_value_destroy_func);
 
-	watch_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_watch_func);
+	channel = g_io_channel_unix_new (FAMCONNECTION_GETFD (&fc));
 
-	if (tracker->watch_limit == 0) {
-		tracker->watch_limit = 300;
-	}
+	fam_watch_id = g_io_add_watch (channel,
+				       G_IO_IN | G_IO_HUP | G_IO_ERR,
+				       fam_callback,
+                                       &fc);
+
+        /* Should we be unrefing here? */
+	g_io_channel_unref (channel);
 
 	return TRUE;
 }
 
+void
+tracker_watcher_shutdown (void)
+{
+	FAMClose (&fc);
+
+	if (fam_watch_id > 0) {
+		g_source_remove (fam_watch_id);
+		fam_watch_id = 0;
+	}
+
+        if (watch_table) {
+                g_hash_table_unref (watch_table);
+                watch_table = NULL;
+        }
+}
 
 gboolean
-tracker_add_watch_dir (const char *dir, DBConnection *db_con)
+tracker_watcher_add_dir (const gchar  *dir, 
+                         DBConnection *db_con)
 {
-	char *dir_in_locale;
+	gchar *dir_in_locale;
+        
+        g_return_val_if_fail (dir != NULL, FALSE);
+        g_return_val_if_fail (db_con != NULL, FALSE);
 
 	if (!tracker_file_is_valid (dir)) {
 		return FALSE;
@@ -295,24 +297,27 @@
 		return FALSE;
 	}
 
-
-	if (g_hash_table_size (watch_table) >= tracker->watch_limit) {
-		tracker_error ("ERROR: watch Limit has been exceeded - unable to watch any more directories");
+	if (g_hash_table_size (watch_table) >= monitor_limit) {
+                g_warning ("The directory watch limit (%d) has been reached, "
+                           "you should increase the number of inotify watches on your system",
+                           monitor_limit);
 		return FALSE;
 	}
 
 	dir_in_locale = g_filename_from_utf8 (dir, -1, NULL, NULL, NULL);
 
 	if (!dir_in_locale) {
-		tracker_error ("ERROR: FAM dir could not be converted to locale format");
+                g_critical ("File uri:'%s' could not be converted to utf8 format",
+                            filename);
 		return FALSE;
 	}
 
 	/* check directory permissions are okay */
-	if (g_access (dir_in_locale, F_OK) == 0 && g_access (dir_in_locale, R_OK) == 0) {
+	if (g_access (dir_in_locale, F_OK) == 0 &&
+            g_access (dir_in_locale, R_OK) == 0) {
 		DirWatch   *fwatch;
 		FAMRequest *fr;
-		int	   rc;
+		gint        rc;
 
 		fwatch = g_new (DirWatch, 1);
 		fr = g_new (FAMRequest, 1);
@@ -322,14 +327,20 @@
 		rc = FAMMonitorDirectory (&fc, dir_in_locale, fr, fwatch);
 
 	 	if (rc > 0) {
-			tracker_error ("ERROR: FAM watch on %s has failed", dir);
+			g_critical ("Could not watch directory:'%s', FAMMonitorDirectory() failed",
+                                    dir);
+
 			g_free (dir_in_locale);
 			free_watch_func (fwatch);
+
 			return FALSE;
 		} else {
 			g_hash_table_insert (watch_table, g_strdup (dir), fwatch);
 			g_free (dir_in_locale);
-			tracker_log ("Watching directory %s (total watches = %d)", dir, g_hash_table_size (watch_table));
+
+                        g_message ("Watching directory:'%s' (total = %d)", 
+                                   dir, g_hash_table_size (watch_table));
+
 			return TRUE;
 		}
 	}
@@ -339,27 +350,28 @@
 	return FALSE;
 }
 
-
 static gboolean
-delete_watch 	(gpointer key,
-		 gpointer value,
-		 gpointer user_data)
+watcher_remove_dir_foreach (gpointer key,
+                            gpointer value,
+                            gpointer user_data)
 {
-	DirWatch   *fwatch;
-	const char *dir;
+	DirWatch    *fwatch;
+	const gchar *dir;
 
 	dir = user_data;
 	fwatch = value;
 
 	if (fwatch && dir) {
-		char *dir_part;
+		gchar *dir_part;
 
 		dir_part = g_strconcat (dir, G_DIR_SEPARATOR_S, NULL);
 
-		/* need to delete subfolders of dir as well */
-		if ((strcmp (fwatch->watch_directory, dir) == 0) || (g_str_has_prefix (fwatch->watch_directory, dir_part))) {
+		/* Need to delete subfolders of dir as well */
+		if (strcmp (fwatch->watch_directory, dir) == 0 || 
+                    g_str_has_prefix (fwatch->watch_directory, dir_part)) {
 			FAMCancelMonitor (&fc, fwatch->fr);
 			g_free (dir_part);
+
 			return TRUE;
 		}
 
@@ -369,23 +381,19 @@
 	return FALSE;
 }
 
-
-int
-tracker_count_watch_dirs (void)
-{
-	return g_hash_table_size (watch_table);
-}
-
-
 void
-tracker_remove_watch_dir (const char *dir, gboolean delete_subdirs, DBConnection *db_con)
+tracker_watcher_remove_dir (const gchar  *dir, 
+                            gboolean      delete_subdirs, 
+                            DBConnection *db_con)
 {
-	char *str;
+	gchar *str;
 
 	str = g_strdup (dir);
 
 	if (delete_subdirs) {
-		g_hash_table_foreach_remove (watch_table, delete_watch, str);
+		g_hash_table_foreach_remove (watch_table, 
+                                             watcher_remove_dir_foreach, 
+                                             str);
 	} else {
 		DirWatch *fwatch;
 
@@ -396,3 +404,19 @@
 
 	g_free (str);
 }
+
+gboolean
+tracker_watcher_is_dir_watched (const gchar  *dir,
+                                DBConnection *db_con)
+{
+        g_return_val_if_fail (dir != NULL, FALSE);
+        g_return_val_if_fail (db_con != NULL, FALSE);
+
+	return g_hash_table_lookup (watch_table, dir) != NULL;
+}
+
+gint
+tracker_watcher_get_dir_count (void)
+{
+	return g_hash_table_size (watch_table);
+}

Copied: branches/indexer-split/src/trackerd/tracker-watcher-inotify.c (from r1561, /branches/indexer-split/src/trackerd/tracker-inotify.c)
==============================================================================
--- /branches/indexer-split/src/trackerd/tracker-inotify.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-watcher-inotify.c	Mon Jun  2 18:17:52 2008
@@ -1,5 +1,7 @@
-/* Tracker - indexer and metadata database engine
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* 
  * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -39,7 +41,7 @@
 
 #include <libtracker-db/tracker-db-action.h>
 
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 #include "tracker-process-files.h"
 #include "tracker-utils.h"
 

Copied: branches/indexer-split/src/trackerd/tracker-watcher-poll.c (from r1560, /branches/indexer-split/src/trackerd/tracker-poll.c)
==============================================================================
--- /branches/indexer-split/src/trackerd/tracker-poll.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-watcher-poll.c	Mon Jun  2 18:17:52 2008
@@ -1,5 +1,7 @@
-/* Tracker - indexer and metadata database engine
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* 
  * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -16,19 +18,62 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301, USA.
  */
-#include <string.h>
-#include <unistd.h>
-#include <glib.h>
 
-#include "tracker-watch.h"
+#include "tracker-watcher.h"
 
-extern Tracker  *tracker;
+gboolean 	
+tracker_watcher_init (void)
+{
+        g_warning ("%s is not implemented", __FUNCTION__);
+        return TRUE;
+}
 
-gboolean 	tracker_start_watching 		(void){tracker->watch_limit = 0; return TRUE;}
-void     	tracker_end_watching 		(void){return;}
+void
+tracker_watcher_shutdown (void)
+{
+        g_warning ("%s is not implemented", __FUNCTION__);
+}
 
-gboolean 	tracker_add_watch_dir 		(const gchar *dir, DBConnection *db_con){return FALSE;}
-void     	tracker_remove_watch_dir 	(const gchar *dir, gboolean delete_subdirs, DBConnection *db_con) {return;}
-gboolean 	tracker_is_directory_watched 	(const gchar *dir, DBConnection *db_con) {return FALSE;}
-int		tracker_count_watch_dirs 	(void) {return 0;}
+gboolean 	
+tracker_watcher_add_dir (const gchar  *dir, 
+                         DBConnection *db_con)
+{
+        g_return_val_if_fail (dir != NULL, FALSE);
+        g_return_val_if_fail (db_con != NULL, FALSE);
+
+        g_warning ("%s is not implemented", __FUNCTION__);
+        
+        return FALSE;
+}
+
+void     	
+tracker_watcher_remove_dir (const gchar  *dir,
+                            gboolean      delete_subdirs, 
+                            DBConnection *db_con) 
+{
+        g_return_val_if_fail (dir != NULL, FALSE);
+        g_return_val_if_fail (db_con != NULL, FALSE);
+
+        g_warning ("%s is not implemented", __FUNCTION__);
+}
+
+gboolean 	
+tracker_watcher_is_dir_watched (const gchar  *dir, 
+                                DBConnection *db_con) 
+{
+        g_return_val_if_fail (dir != NULL, FALSE);
+        g_return_val_if_fail (db_con != NULL, FALSE);
+
+        g_warning ("%s is not implemented", __FUNCTION__);
+
+        return FALSE;
+}
+
+gint
+tracker_watcher_get_dir_count (void) 
+{
+        g_warning ("%s is not implemented", __FUNCTION__);
+
+        return 0;
+}
 

Copied: branches/indexer-split/src/trackerd/tracker-watcher-win.c (from r1560, /branches/indexer-split/src/trackerd/tracker-win-fs-changes.c)
==============================================================================
--- /branches/indexer-split/src/trackerd/tracker-win-fs-changes.c	(original)
+++ branches/indexer-split/src/trackerd/tracker-watcher-win.c	Mon Jun  2 18:17:52 2008
@@ -1,5 +1,7 @@
-/* Tracker - indexer and metadata database engine
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* 
  * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -17,8 +19,6 @@
  * Boston, MA  02110-1301, USA.
  */
 
-#include "tracker-watch.h"
-
 #include <unistd.h>
 
 #include <glib.h>
@@ -26,235 +26,256 @@
 
 #include <windows.h>
 
-// private stuff
+#include "tracker-watcher.h"
+
+#define MAX_DIRECTORIES      1024 
+#define MAX_FILENAME_LENGTH  1024 
 
-static GHashTable *watch_table;
+gboolean monitor_dir (int dir_id);
 
+static GHashTable   *watch_table;
 extern Tracker	    *tracker;
 static DBConnection *win_db_con;
+static gint          dir_id;
+static gint          monitor_limit = 8191;
 
-static void
-free_watch_func (gpointer user_data)
-{
-  g_free (user_data);
-}
-
-static DWORD sleep_thread_id;
-static HANDLE sleep_thread;
-
-#define MAX_DIRECTORIES  1024 // should be more than enough
-#define MAX_FILENAME_LENGTH  1024 // should be more than enough
+static DWORD         sleep_thread_id;
+static HANDLE        sleep_thread;
 
-static int dir_id = 0;
+static char          buffer[MAX_DIRECTORIES][256];
+static HANDLE        monitor_handle[MAX_DIRECTORIES];
+static OVERLAPPED    overlapped_buffer[MAX_DIRECTORIES];
+static char          dirs[MAX_DIRECTORIES][256];
 
-static char buffer[MAX_DIRECTORIES][256];
-static HANDLE monitor_handle[MAX_DIRECTORIES];
-static OVERLAPPED overlapped_buffer[MAX_DIRECTORIES];
-static char dirs[MAX_DIRECTORIES][256];
-
-unsigned int __stdcall ThreadProc( LPVOID param ) 
+unsigned int __stdcall 
+ThreadProc (LPVOID param) 
 { 
-  while (TRUE) {
-    SleepEx(INFINITE, TRUE); // 10000 might be better
-  }
-}
-
-void CALLBACK init_db (DWORD param)
-{
-  tracker_db_thread_init ();
-
-  win_db_con = tracker_db_connect ();
-
-  win_db_con->blob = tracker_db_connect_full_text ();
-  win_db_con->cache = tracker_db_connect_cache ();
-
-  win_db_con->thread = "notify";
+        while (TRUE) {
+                SleepEx (INFINITE, TRUE); 
+        }
+}
+
+void CALLBACK 
+init_db (DWORD param)
+{
+        tracker_db_thread_init ();
+        
+        win_db_con = tracker_db_connect ();
+        
+        win_db_con->blob = tracker_db_connect_full_text ();
+        win_db_con->cache = tracker_db_connect_cache ();
+        
+        win_db_con->thread = "notify";
 }
 
-// public stuff
-
 gboolean 
-tracker_start_watching (void)
+tracker_watcher_init (void)
 {
-  if (tracker->watch_limit == 0) {
-    tracker->watch_limit = 8191;
-  }
-
-  watch_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_watch_func);
+        g_message ("Using windows monitor limit of %d", monitor_limit);
 
-  // create a windows thread to synchonize all metadata changes in one thread
-  sleep_thread = _beginthreadex( NULL, 0, ThreadProc, 0, 0, &sleep_thread_id );
-
-  QueueUserAPC(init_db, sleep_thread, (DWORD) 0 );
-
-  return TRUE;
+        watch_table = g_hash_table_new_full (g_str_hash, 
+                                             g_str_equal, 
+                                             g_free, 
+                                             g_free);
+
+        /* Create a windows thread to synchonize all metadata changes in one thread */
+        sleep_thread = _beginthreadex (NULL, 
+                                       0, 
+                                       ThreadProc, 
+                                       0,
+                                       0,
+                                       &sleep_thread_id);
+        
+        QueueUserAPC (init_db, sleep_thread, (DWORD) 0);
+        
+        return TRUE;
 }
 
 void
-tracker_end_watching (void)
+tracker_watcher_shutdown (void)
 {
-  // kill thread and call these just before it dies
-
-#if 0
-  tracker_db_close (win_db_con);
-  tracker_db_thread_end ();
-#endif
+        if (watch_table) {
+                g_hash_table_unref (watch_table);
+                watch_table = NULL;
+        }
+}
+
+VOID CALLBACK 
+callback (DWORD        error_code,
+          DWORD        bytes_transferred,
+          LPOVERLAPPED overlapped)       
+{
+        int callback_dir_id = (int) overlapped->hEvent;
+        
+        if (bytes_transferred > 0) {
+                FILE_NOTIFY_INFORMATION *p = (FILE_NOTIFY_INFORMATION *) buffer[callback_dir_id];
+                
+                TrackerAction event_type = TRACKER_ACTION_IGNORE;
+                int counter = 1;
+                
+                while (p) {
+                        TrackerAction event_type;
+                        
+                        switch (p->Action) {
+                        case FILE_ACTION_MODIFIED:
+                                event_type = TRACKER_ACTION_CHECK;
+                                counter = 1;
+                                break;
+                        case FILE_ACTION_REMOVED:
+                                event_type = TRACKER_ACTION_DELETE;
+                                counter = 0;
+                                break;
+                        case FILE_ACTION_ADDED:
+                                event_type = TRACKER_ACTION_CREATE;
+                                counter = 1;
+                                break;
+                        default:
+                                break;
+                        }
+                        
+                        if (event_type != TRACKER_ACTION_IGNORE) {
+                                FileInfo *info;
+                                char file_utf8_uri[MAX_FILENAME_LENGTH];
+                                int status = WideCharToMultiByte (CP_UTF8, 
+                                                                  0,
+                                                                  p->FileName, 
+                                                                  p->FileNameLength, 
+                                                                  file_utf8_uri, 
+                                                                  MAX_FILENAME_LENGTH, 
+                                                                  NULL, 
+                                                                  NULL);
+                                
+                                file_utf8_uri[p->FileNameLength / sizeof (WCHAR)] = '\0';
+
+                                char *file_uri = g_build_filename (dirs[callback_dir_id], 
+                                                                   file_utf8_uri, NULL);
+
+                                info = tracker_create_file_info (file_uri, 
+                                                                 event_type, 
+                                                                 counter, 
+                                                                 WATCH_OTHER);
+
+                                if (tracker_file_info_is_valid (info)) {
+                                        tracker_db_insert_pending_file (win_db_con, 
+                                                                        info->file_id, 
+                                                                        info->uri,  
+                                                                        NULL, 
+                                                                        info->mime, 
+                                                                        info->counter, 
+                                                                        info->action, 
+                                                                        info->is_directory, 
+                                                                        event_type == TRACKER_ACTION_CREATE, 
+                                                                        -1);
+                                        tracker_free_file_info (info);
+                                } 
+                                
+                                g_free(file_uri);
+                        }
+                        
+                        if (p->NextEntryOffset == 0)
+                                p = NULL;
+                        else
+                                p = (FILE_NOTIFY_INFORMATION*) ((char*) p + p->NextEntryOffset);
+                }
+        }
 
-  // release all watched dirs
-
-  g_hash_table_destroy  (watch_table);
-}
-
-gboolean monitor_dir(int dir_id);
-
-VOID CALLBACK callback(DWORD error_code,
-		       DWORD bytes_transferred,
-		       LPOVERLAPPED overlapped)        // I/O information buffer
-{
-  int callback_dir_id = (int) overlapped->hEvent;
-
-  if (bytes_transferred > 0) {
-
-    FILE_NOTIFY_INFORMATION *p = (FILE_NOTIFY_INFORMATION *) buffer[callback_dir_id];
-
-    TrackerAction event_type = TRACKER_ACTION_IGNORE;
-    int counter = 1;
-
-    while (p) {
-      TrackerAction event_type;
-
-      switch (p->Action) {
-      case FILE_ACTION_MODIFIED:
-	event_type = TRACKER_ACTION_CHECK;
-	counter = 1;
-	break;
-      case FILE_ACTION_REMOVED:
-	event_type = TRACKER_ACTION_DELETE;
-	counter = 0;
-	break;
-      case FILE_ACTION_ADDED:
-	event_type = TRACKER_ACTION_CREATE;
-	counter = 1;
-	break;
-      default:
-	break;
-      }
-
-      if (event_type != TRACKER_ACTION_IGNORE) {
-
-	FileInfo *info;
-	char file_utf8_uri[MAX_FILENAME_LENGTH];
-
-	int status = WideCharToMultiByte(CP_UTF8, 0, p->FileName, p->FileNameLength, 
-					 file_utf8_uri, MAX_FILENAME_LENGTH, NULL, NULL);
-
-	file_utf8_uri[p->FileNameLength/sizeof(WCHAR)] = '\0';
-
-	char *file_uri = g_build_filename (dirs[callback_dir_id], file_utf8_uri, NULL);
-
-	info = tracker_create_file_info (file_uri, event_type, counter, WATCH_OTHER);
-
-	if (tracker_file_info_is_valid (info)) {
-
-	  tracker_db_insert_pending_file (win_db_con, info->file_id, info->uri,  NULL, info->mime, 
-					  info->counter, info->action, info->is_directory, (event_type == TRACKER_ACTION_CREATE), -1);
-	  tracker_free_file_info (info);
-	} 
-
-	g_free(file_uri);
-      }
-
-      if (p->NextEntryOffset == 0)
-	p = NULL;
-      else
-	p = (FILE_NOTIFY_INFORMATION *) ((char *) p + p->NextEntryOffset);
-    }
-  }
-
-  // reschedule
-  monitor_dir(callback_dir_id);
+        monitor_dir (callback_dir_id);
 }
 
 gboolean
-monitor_dir(int dir_id) 
+monitor_dir (int dir_id) 
 {
-  return ReadDirectoryChangesW( monitor_handle[dir_id], buffer[dir_id], sizeof(buffer[dir_id]),
-				TRUE, 
-				//				FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE |
-				FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME,
-				NULL, &overlapped_buffer[dir_id], callback);
-}
-
-
-void CALLBACK tracker_add_watch_dir_wrapped (DWORD param)
-{
-  char *dir = (char *) param;
-
-  char *dir_in_locale;
-
-  dir_in_locale = g_filename_from_utf8 (dir, -1, NULL, NULL, NULL);
-
-  if (!dir_in_locale) {
-    free(dir);
-    return;
-  }
-
-  /* check directory permissions are okay */
-  if (g_access (dir_in_locale, F_OK) == 0 && g_access (dir_in_locale, R_OK) == 0) {
-
-    monitor_handle[dir_id] = CreateFile( dir_in_locale, FILE_LIST_DIRECTORY, 
-					 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, 
-					 NULL, OPEN_EXISTING, 
-					 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, 
-					 NULL );
-
-    if (monitor_handle[dir_id] == INVALID_HANDLE_VALUE) {
-      free(dir);
-    } else if (monitor_dir(dir_id)) {  
-      g_hash_table_insert (watch_table, g_strdup (dir), monitor_handle[dir_id]);
-      strcpy(dirs[dir_id], dir);
-
-      g_free (dir_in_locale);
-      free(dir);
-
-      ++dir_id;
-    }
-  } else {
-
-    g_free (dir_in_locale);
-    free(dir);
-  }
+        return ReadDirectoryChangesW (monitor_handle[dir_id], 
+                                      buffer[dir_id], 
+                                      sizeof(buffer[dir_id]),
+                                      TRUE, 
+                                      FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME,
+                                      NULL, 
+                                      &overlapped_buffer[dir_id], 
+                                      callback);
+}
+
+void CALLBACK 
+tracker_add_watch_dir_wrapped (DWORD param)
+{
+        char *dir = (char*) param;
+        char *dir_in_locale;
+
+        dir_in_locale = g_filename_from_utf8 (dir, -1, NULL, NULL, NULL);
+        
+        if (!dir_in_locale) {
+                free(dir);
+                return;
+        }
+        
+        /* Check directory permissions are okay */
+        if (g_access (dir_in_locale, F_OK) == 0 && 
+            g_access (dir_in_locale, R_OK) == 0) {
+                monitor_handle[dir_id] = 
+                        CreateFile (dir_in_locale, 
+                                    FILE_LIST_DIRECTORY, 
+                                    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 
+                                    NULL, 
+                                    OPEN_EXISTING, 
+                                    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 
+                                    NULL );
+                
+                if (monitor_handle[dir_id] == INVALID_HANDLE_VALUE) {
+                        free (dir);
+                } else if (monitor_dir (dir_id)) {  
+                        g_hash_table_insert (watch_table, 
+                                             g_strdup (dir), 
+                                             monitor_handle[dir_id]);
+                        strcpy (dirs[dir_id], dir);
+                        g_free (dir_in_locale);
+                        free (dir);
+
+                        ++dir_id;
+                }
+        } else {
+                g_free (dir_in_locale);
+                free (dir);
+        }
 }
 
 gboolean
-tracker_add_watch_dir (const char *dir, DBConnection *db_con)
+tracker_watcher_add_dir (const gchar  *dir, 
+                         DBConnection *db_con)
 {
-  // create a copy so that the string is still available when we are called in the file notify thread
-  char *something = g_strdup(dir);
-  return QueueUserAPC( tracker_add_watch_dir_wrapped, sleep_thread, (DWORD) something );
+        g_return_val_if_fail (dir != NULL, FALSE);
+        g_return_val_if_fail (db_con != NULL, FALSE);
+               
+        /* Create a copy so that the string is still available when we
+         * are called in the file notify thread.
+         */
+        return QueueUserAPC (tracker_add_watch_dir_wrapped, 
+                             sleep_thread, 
+                             (DWORD) g_strdup (dir));
 }
 
 void
-tracker_remove_watch_dir (const char *dir, gboolean delete_subdirs, DBConnection *db_con)
+tracker_watcher_remove_dir (const gchar  *dir, 
+                            gboolean      delete_subdirs, 
+                            DBConnection *db_con)
 {
-#if 0
-  char *something = g_strdup(dir);
-  QueueUserAPC( tracker_remove_watch_dir_wrapped, sleep_thread, (DWORD) something );
-#endif
+        g_return_val_if_fail (dir != NULL, FALSE);
+        g_return_val_if_fail (db_con != NULL, FALSE);
+
+        g_warning ("%s is not implemented", __FUNCTION__);
 }
 
 gboolean
-tracker_is_directory_watched (const char *dir, DBConnection *db_con)
+tracker_watcher_is_dir_watched (const gchar  *dir, 
+                                DBConnection *db_con)
 {
-  if (!dir) {
-    return FALSE;
-  }
+        g_return_val_if_fail (dir != NULL, FALSE);
+        g_return_val_if_fail (db_con != NULL, FALSE);
 
-  return (g_hash_table_lookup (watch_table, dir) != NULL);
+        return g_hash_table_lookup (watch_table, dir) != NULL;
 }
 
-int
-tracker_count_watch_dirs (void)
+gint
+tracker_watcher_get_dir_count (void)
 {
-  return g_hash_table_size (watch_table);
+        return g_hash_table_size (watch_table);
 }

Copied: branches/indexer-split/src/trackerd/tracker-watcher.h (from r1561, /branches/indexer-split/src/trackerd/tracker-watch.h)
==============================================================================
--- /branches/indexer-split/src/trackerd/tracker-watch.h	(original)
+++ branches/indexer-split/src/trackerd/tracker-watcher.h	Mon Jun  2 18:17:52 2008
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /* 
  * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -18,8 +19,8 @@
  * Boston, MA  02110-1301, USA.
  */
 
-#ifndef __TRACKERD_WATCH_H__
-#define __TRACKERD_WATCH_H__
+#ifndef __TRACKERD_WATCHER_H__
+#define __TRACKERD_WATCHER_H__
 
 #include "tracker-db.h"
 
@@ -34,8 +35,8 @@
 					 DBConnection *db_con);
 gboolean tracker_watcher_is_dir_watched (const char   *dir,
 					 DBConnection *db_con);
-gint      tracker_watcher_get_dir_count (void);
+gint     tracker_watcher_get_dir_count  (void);
 
 G_END_DECLS
 
-#endif /* __TRACKERD_WATCH_H__ */
+#endif /* __TRACKERD_WATCHER_H__ */



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