[tracker/tracker-0.6] Fixes: NB#109891, If deleting last music track or last video...
- From: Martyn James Russell <mr src gnome org>
- To: svn-commits-list gnome org
- Subject: [tracker/tracker-0.6] Fixes: NB#109891, If deleting last music track or last video...
- Date: Thu, 16 Apr 2009 14:47:18 -0400 (EDT)
commit cf3fdf2471002b72e8f4f0ba50e0acea554689b6
Author: Martyn Russell <martyn imendio com>
Date: Thu Apr 16 19:46:56 2009 +0100
Fixes: NB#109891, If deleting last music track or last video...
The cache expires now after 3 minutes instead of 1 minute which was
too short. We now use GetServices every time to fix the case where 0
items for a service type doesn't show up in the
SERVICE_STATISTICS_UPDATED signal.
---
src/trackerd/tracker-daemon.c | 345 +++++++++++++++++++----------------------
1 files changed, 158 insertions(+), 187 deletions(-)
diff --git a/src/trackerd/tracker-daemon.c b/src/trackerd/tracker-daemon.c
index 2670a87..12fce8a 100644
--- a/src/trackerd/tracker-daemon.c
+++ b/src/trackerd/tracker-daemon.c
@@ -45,8 +45,8 @@
#define TRACKER_TYPE_G_STRV_ARRAY (dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRV))
-/* Seconds */
-#define STATS_CACHE_LIFETIME 60
+/* In seconds (3 minutes for now) */
+#define STATS_CACHE_LIFETIME 180
typedef struct {
TrackerConfig *config;
@@ -66,9 +66,10 @@ enum {
LAST_SIGNAL
};
-static void tracker_daemon_finalize (GObject *object);
-static gboolean stats_cache_timeout (gpointer user_data);
-static void stats_cache_update (TrackerDaemon *object);
+static void tracker_daemon_finalize (GObject *object);
+static gboolean stats_cache_timeout (gpointer user_data);
+static GHashTable *stats_cache_get_latest (void);
+static void stats_cache_update (TrackerDaemon *object);
static guint signals[LAST_SIGNAL] = {0};
@@ -204,11 +205,7 @@ tracker_daemon_init (TrackerDaemon *object)
{
TrackerDaemonPrivate *priv;
TrackerDBInterface *iface;
- TrackerDBResultSet *result_set;
DBusGProxy *proxy;
- GHashTable *values;
- GHashTableIter iter;
- gpointer key, value;
priv = TRACKER_DAEMON_GET_PRIVATE (object);
@@ -230,33 +227,9 @@ tracker_daemon_init (TrackerDaemon *object)
iface = tracker_db_manager_get_db_interface (TRACKER_DB_COMMON);
- /* Prepare cache */
- priv->stats_cache = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- NULL);
-
- result_set = tracker_data_manager_exec_proc (iface, "GetServices", 0);
- values = tracker_dbus_query_result_to_hash_table (result_set);
-
- if (result_set) {
- g_object_unref (result_set);
- }
-
- g_hash_table_iter_init (&iter, values);
-
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- g_hash_table_replace (priv->stats_cache,
- g_strdup (key),
- GINT_TO_POINTER (0));
- }
-
- g_hash_table_destroy (values);
-
- /* First time update */
- stats_cache_update (object);
+ /* Do first time stats lookup */
+ priv->stats_cache = stats_cache_get_latest ();
- /* Future updates */
priv->stats_cache_timeout_id =
g_timeout_add_seconds (STATS_CACHE_LIFETIME,
stats_cache_timeout,
@@ -406,31 +379,93 @@ tracker_daemon_get_services (TrackerDaemon *object,
tracker_dbus_request_success (request_id);
}
-
static void
-stats_cache_update (TrackerDaemon *object)
+stats_cache_filter_dups_func (gpointer data,
+ gpointer user_data)
{
- TrackerDaemonPrivate *priv;
- TrackerDBResultSet *result_set;
- GPtrArray *stats, *parent_stats;
- GPtrArray *values;
- guint i;
- const gchar *services_to_fetch[3] = {
+ GHashTable *values;
+ GStrv strv;
+ gpointer p;
+ gint count;
+
+ /* FIXME: There is a really shit bug here that needs
+ * fixing. If a file has "Files" as its main category
+ * and not its *parent* category, then we end up with
+ * 2 "Files" listings. This sounds like a bug with
+ * the indexer's insert mechanisms. So far this seems
+ * to only happen for removable media files
+ *
+ * For now, we will concatenate values to sort out the
+ * duplicates:
+ */
+ strv = data;
+ values = user_data;
+
+ count = atoi (strv[1]);
+
+ p = g_hash_table_lookup (values, strv[0]);
+
+ if (G_UNLIKELY (p)) {
+ count += GPOINTER_TO_INT (p);
+ }
+
+ g_hash_table_replace (values,
+ g_strdup (strv[0]),
+ GINT_TO_POINTER (count));
+}
+
+static GHashTable *
+stats_cache_get_latest (void)
+{
+ TrackerDBResultSet *result_set;
+ TrackerDBInterface *iface;
+ GHashTable *services;
+ GHashTable *values;
+ GHashTableIter iter;
+ gpointer key, value;
+ guint i;
+ const gchar *services_to_fetch[3] = {
TRACKER_DB_FOR_FILE_SERVICE,
TRACKER_DB_FOR_EMAIL_SERVICE,
NULL
};
- priv = TRACKER_DAEMON_GET_PRIVATE (object);
+ /* Set up empty list of services because SQL queries won't give us 0 items. */
+ g_message ("Requesting statistics from database for an accurate signal");
- values = g_ptr_array_new ();
+ iface = tracker_db_manager_get_db_interface (TRACKER_DB_COMMON);
+ result_set = tracker_data_manager_exec_proc (iface, "GetServices", 0);
+ services = tracker_dbus_query_result_to_hash_table (result_set);
+
+ if (result_set) {
+ g_object_unref (result_set);
+ }
- for (i = 0; services_to_fetch[i]; i++) {
+ values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+
+ /* Put services with 0 counts into new hash table */
+ g_hash_table_iter_init (&iter, services);
+
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ g_hash_table_replace (values, g_strdup (key), GINT_TO_POINTER (0));
+ }
+
+ g_hash_table_unref (services);
+
+ /* Populate with real stats */
+ for (i = 0; services_to_fetch[i]; i++) {
TrackerDBInterface *iface;
- gint j;
+ GPtrArray *stats, *parent_stats;
iface = tracker_db_manager_get_db_interface_by_service (services_to_fetch[i]);
+ /* GetStats has asc in its query. Therefore we don't have to
+ * lookup the in a to compare in b, just compare index based.
+ * Maybe we want to change this nonetheless later?
+ */
result_set = tracker_data_manager_exec_proc (iface, "GetStats", 0);
stats = tracker_dbus_query_result_to_ptr_array (result_set);
@@ -444,37 +479,45 @@ stats_cache_update (TrackerDaemon *object)
if (result_set) {
g_object_unref (result_set);
}
-
- /* Concatenate stats */
- for (j = 0; j < stats->len; j++) {
- g_ptr_array_add (values, g_ptr_array_index (stats, j));
- }
- for (j = 0; j < parent_stats->len; j++) {
- g_ptr_array_add (values, g_ptr_array_index (parent_stats, j));
- }
+ g_ptr_array_foreach (stats, stats_cache_filter_dups_func, values);
+ g_ptr_array_foreach (parent_stats, stats_cache_filter_dups_func, values);
g_ptr_array_free (parent_stats, TRUE);
g_ptr_array_free (stats, TRUE);
}
- /* Update local cache */
- for (i = 0; i < values->len; i++) {
- gchar **p;
- const gchar *service_type = NULL;
- gint new_count;
+ return values;
+}
- p = g_ptr_array_index (values, i);
- service_type = p[0];
- new_count = atoi (p[1]);
+static void
+stats_cache_update (TrackerDaemon *object)
+{
+ TrackerDaemonPrivate *priv;
+ GHashTable *values;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ priv = TRACKER_DAEMON_GET_PRIVATE (object);
+
+ /* Get latest */
+ values = stats_cache_get_latest ();
+
+ /* Update local cache */
+ g_hash_table_iter_init (&iter, values);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ const gchar *service_type;
+ gint new_count;
+
+ service_type = key;
+ new_count = GPOINTER_TO_INT (value);
g_hash_table_replace (priv->stats_cache,
g_strdup (service_type),
GINT_TO_POINTER (new_count));
}
- g_ptr_array_foreach (values, (GFunc) g_strfreev, NULL);
- g_ptr_array_free (values, TRUE);
+ g_hash_table_unref (values);
}
static gboolean
@@ -525,9 +568,9 @@ tracker_daemon_get_stats (TrackerDaemon *object,
g_hash_table_iter_init (&iter, priv->stats_cache);
while (g_hash_table_iter_next (&iter, &key, &value)) {
- GStrv strv;
- const gchar *service_type;
- gint count;
+ GStrv strv;
+ const gchar *service_type;
+ gint count;
service_type = key;
count = GPOINTER_TO_INT (value);
@@ -775,153 +818,81 @@ tracker_daemon_signal_statistics (void)
{
GObject *daemon;
TrackerDaemonPrivate *priv;
- TrackerDBResultSet *result_set;
- GPtrArray *stats, *parent_stats;
+ GHashTable *stats;
+ GHashTableIter iter;
+ gpointer key, value;
GPtrArray *values;
- gint i;
- const gchar *services_to_fetch[3] = {
- TRACKER_DB_FOR_FILE_SERVICE,
- TRACKER_DB_FOR_EMAIL_SERVICE,
- NULL
- };
daemon = tracker_dbus_get_object (TRACKER_TYPE_DAEMON);
priv = TRACKER_DAEMON_GET_PRIVATE (daemon);
- values = g_ptr_array_new ();
-
- g_message ("Requesting statistics from database for an accurate signal");
-
- for (i = 0; services_to_fetch[i]; i++) {
- TrackerDBInterface *iface;
- gint j;
-
- iface = tracker_db_manager_get_db_interface_by_service (services_to_fetch[i]);
-
- /* GetStats has asc in its query. Therefore we don't have to
- * lookup the in a to compare in b, just compare index based.
- * Maybe we want to change this nonetheless later?
- */
- result_set = tracker_data_manager_exec_proc (iface, "GetStats", 0);
- stats = tracker_dbus_query_result_to_ptr_array (result_set);
-
- if (result_set) {
- g_object_unref (result_set);
- }
-
- result_set = tracker_data_manager_exec_proc (iface, "GetStatsForParents", 0);
- parent_stats = tracker_dbus_query_result_to_ptr_array (result_set);
-
- if (result_set) {
- g_object_unref (result_set);
- }
-
- for (j = 0; j < stats->len; j++) {
- g_ptr_array_add (values, g_ptr_array_index (stats, j));
- }
-
- for (j = 0; j < parent_stats->len; j++) {
- g_ptr_array_add (values, g_ptr_array_index (parent_stats, j));
- }
-
- g_ptr_array_free (parent_stats, TRUE);
- g_ptr_array_free (stats, TRUE);
- }
+ /* Get latest */
+ stats = stats_cache_get_latest ();
/* There are 3 situations here:
* - 1. No new stats
* Action: Do nothing
- * - 2. No previous stats
- * Action: Emit all new stats
- * - 3. New stats and old stats
+ * - 2. New stats and old stats
* Action: Check what has changed and emit new stats
*/
g_message ("Checking for statistics changes and signalling clients...");
/* Situation #1 */
- if (!values || values->len < 1) {
+ if (g_hash_table_size (stats) < 1) {
+ g_hash_table_unref (stats);
g_message (" No new statistics, doing nothing");
return;
}
- if (g_hash_table_size (priv->stats_cache) < 1) {
- /* Situation #2 */
- g_message (" No previous statistics");
-
- for (i = 0; i < values->len; i++) {
- const gchar **p;
- const gchar *service_type = NULL;
- gint new_count;
-
- p = g_ptr_array_index (values, i);
+ /* Situation #2 */
+ values = g_ptr_array_new ();
- service_type = p[0];
- new_count = atoi (p[1]);
+ g_hash_table_iter_init (&iter, stats);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ const gchar *service_type;
+ gpointer data;
+ gint old_count, new_count;
+
+ service_type = key;
+ new_count = GPOINTER_TO_INT (value);
- if (!service_type) {
- continue;
- }
+ data = g_hash_table_lookup (priv->stats_cache, service_type);
+ old_count = GPOINTER_TO_INT (data);
+
+ if (old_count != new_count) {
+ GStrv strv;
- g_message (" Adding '%s' with count:%d",
+ g_message (" Updating '%s' with new count:%d, old count:%d, diff:%d",
service_type,
- new_count);
- g_hash_table_insert (priv->stats_cache,
- g_strdup (service_type),
- GINT_TO_POINTER (new_count));
+ new_count,
+ old_count,
+ new_count - old_count);
+
+ g_hash_table_replace (priv->stats_cache,
+ g_strdup (service_type),
+ GINT_TO_POINTER (new_count));
+
+ strv = g_new (gchar*, 3);
+ strv[0] = g_strdup (service_type);
+ strv[1] = g_strdup_printf ("%d", new_count);
+ strv[2] = NULL;
+
+ g_ptr_array_add (values, strv);
}
+ }
+
+ g_hash_table_unref (stats);
- /* Emit signal */
+ if (values->len > 0) {
+ /* Make sure we sort the results first */
+ g_ptr_array_sort (values, stats_cache_sort_func);
+
g_signal_emit (daemon, signals[SERVICE_STATISTICS_UPDATED], 0, values);
} else {
- /* Situation #3 */
- for (i = 0; i < values->len; i++) {
- gchar **p;
- const gchar *service_type = NULL;
- gpointer data;
- gint old_count, new_count;
-
- p = g_ptr_array_index (values, i);
- service_type = p[0];
- new_count = atoi (p[1]);
-
- if (!service_type) {
- continue;
- }
-
- data = g_hash_table_lookup (priv->stats_cache, service_type);
- old_count = GPOINTER_TO_INT (data);
-
- if (old_count != new_count) {
- g_message (" Updating '%s' with new count:%d, old count:%d, diff:%d",
- service_type,
- new_count,
- old_count,
- new_count - old_count);
-
- g_hash_table_replace (priv->stats_cache,
- g_strdup (service_type),
- GINT_TO_POINTER (new_count));
- } else {
- /* Remove from values since the value is the same */
- g_strfreev (p);
- g_ptr_array_remove (values, p);
-
- /* Decrement i since we are about to
- * increment it and we just removed
- * an item. Otherwise we miss items.
- */
- i--;
- }
- }
-
- if (values->len > 0) {
- g_signal_emit (daemon, signals[SERVICE_STATISTICS_UPDATED], 0, values);
- } else {
- g_message (" No changes in the statistics");
- }
+ g_message (" No changes in the statistics");
}
-
+
g_ptr_array_foreach (values, (GFunc) g_strfreev, NULL);
g_ptr_array_free (values, TRUE);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]