More fixes for #24210
2002-09-19 Rodrigo Moya <rodrigo@ximian.com> More fixes for #24210 * pcs/query.c: added list of cached queries and changed the Query class to work with several listeners, not only one. (query_init): initialize new members. (query_destroy): free new members. (add_component, remove_component, parse_sexp, match_component, process_components_cb): notify all listeners. (notify_uid_cb, start_cached_query_cb): implemented integration of cached queries. (query_new): search the query in the cache before creating a new one. And if we create a new one, store it in the cache. svn path=/trunk/; revision=18120
This commit is contained in:
committed by
Rodrigo Moya
parent
939ed95a48
commit
b8ea035b9f
@ -1,3 +1,18 @@
|
||||
2002-09-19 Rodrigo Moya <rodrigo@ximian.com>
|
||||
|
||||
More fixes for #24210
|
||||
|
||||
* pcs/query.c: added list of cached queries and changed the Query
|
||||
class to work with several listeners, not only one.
|
||||
(query_init): initialize new members.
|
||||
(query_destroy): free new members.
|
||||
(add_component, remove_component, parse_sexp, match_component,
|
||||
process_components_cb): notify all listeners.
|
||||
(notify_uid_cb, start_cached_query_cb): implemented integration of
|
||||
cached queries.
|
||||
(query_new): search the query in the cache before creating a new
|
||||
one. And if we create a new one, store it in the cache.
|
||||
|
||||
2002-09-19 JP Rosevear <jpr@ximian.com>
|
||||
|
||||
* gui/dialogs/recurrence-page.c (simple_recur_to_comp): bump the
|
||||
|
||||
@ -39,6 +39,12 @@
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
Query *query;
|
||||
GNOME_Evolution_Calendar_QueryListener ql;
|
||||
guint tid;
|
||||
} StartCachedQueryInfo;
|
||||
|
||||
/* States of a query */
|
||||
typedef enum {
|
||||
QUERY_WAIT_FOR_BACKEND, /* the query is not populated and the backend is not loaded */
|
||||
@ -59,8 +65,8 @@ struct _QueryPrivate {
|
||||
/* The default timezone for the calendar. */
|
||||
icaltimezone *default_zone;
|
||||
|
||||
/* Listener to which we report changes in the live query */
|
||||
GNOME_Evolution_Calendar_QueryListener ql;
|
||||
/* Listeners to which we report changes in the live query */
|
||||
GList *listeners;
|
||||
|
||||
/* Sexp that defines the query */
|
||||
char *sexp;
|
||||
@ -70,6 +76,8 @@ struct _QueryPrivate {
|
||||
guint timeout_id;
|
||||
QueryState state;
|
||||
|
||||
GList *cached_timeouts;
|
||||
|
||||
/* List of UIDs that we still have to process */
|
||||
GList *pending_uids;
|
||||
int n_pending;
|
||||
@ -91,6 +99,7 @@ static void query_init (Query *query);
|
||||
static void query_destroy (GtkObject *object);
|
||||
|
||||
static BonoboXObjectClass *parent_class;
|
||||
static GList *cached_queries = NULL;
|
||||
|
||||
|
||||
|
||||
@ -128,12 +137,14 @@ query_init (Query *query)
|
||||
priv->backend = NULL;
|
||||
priv->qb = NULL;
|
||||
priv->default_zone = NULL;
|
||||
priv->ql = CORBA_OBJECT_NIL;
|
||||
priv->listeners = NULL;
|
||||
priv->sexp = NULL;
|
||||
|
||||
priv->timeout_id = 0;
|
||||
priv->state = QUERY_WAIT_FOR_BACKEND;
|
||||
|
||||
priv->cached_timeouts = NULL;
|
||||
|
||||
priv->pending_uids = NULL;
|
||||
priv->uids = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
@ -182,18 +193,22 @@ query_destroy (GtkObject *object)
|
||||
|
||||
priv->qb = NULL;
|
||||
|
||||
if (priv->ql != CORBA_OBJECT_NIL) {
|
||||
if (priv->listeners != NULL) {
|
||||
CORBA_Environment ev;
|
||||
GList *l;
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
bonobo_object_release_unref (priv->ql, &ev);
|
||||
for (l = priv->listeners; l != NULL; l = l->next) {
|
||||
bonobo_object_release_unref (l->data, &ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("query_destroy(): Could not unref the listener\n");
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("query_destroy(): Could not unref the listener\n");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
|
||||
priv->ql = CORBA_OBJECT_NIL;
|
||||
g_list_free (priv->listeners);
|
||||
priv->listeners = NULL;
|
||||
}
|
||||
|
||||
if (priv->sexp) {
|
||||
@ -211,6 +226,16 @@ query_destroy (GtkObject *object)
|
||||
priv->timeout_id = 0;
|
||||
}
|
||||
|
||||
if (priv->cached_timeouts) {
|
||||
GList *l;
|
||||
|
||||
for (l = priv->cached_timeouts; l != NULL; l = l->next)
|
||||
g_source_remove (GPOINTER_TO_INT (l->data));
|
||||
|
||||
g_list_free (priv->cached_timeouts);
|
||||
priv->cached_timeouts = NULL;
|
||||
}
|
||||
|
||||
if (priv->pending_uids) {
|
||||
GList *l;
|
||||
|
||||
@ -933,6 +958,7 @@ add_component (Query *query, const char *uid, gboolean query_in_progress, int n_
|
||||
QueryPrivate *priv;
|
||||
char *old_uid;
|
||||
CORBA_Environment ev;
|
||||
GList *l;
|
||||
|
||||
if (query_in_progress)
|
||||
g_assert (n_scanned > 0 || n_scanned <= total);
|
||||
@ -947,17 +973,19 @@ add_component (Query *query, const char *uid, gboolean query_in_progress, int n_
|
||||
g_hash_table_insert (priv->uids, g_strdup (uid), NULL);
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyObjUpdated (
|
||||
priv->ql,
|
||||
(char *) uid,
|
||||
query_in_progress,
|
||||
n_scanned,
|
||||
total,
|
||||
&ev);
|
||||
for (l = priv->listeners; l != NULL; l = l->next) {
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyObjUpdated (
|
||||
l->data,
|
||||
(char *) uid,
|
||||
query_in_progress,
|
||||
n_scanned,
|
||||
total,
|
||||
&ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("add_component(): Could not notify the listener of an "
|
||||
"updated component");
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("add_component(): Could not notify the listener of an "
|
||||
"updated component");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
}
|
||||
@ -969,6 +997,7 @@ remove_component (Query *query, const char *uid)
|
||||
QueryPrivate *priv;
|
||||
char *old_uid;
|
||||
CORBA_Environment ev;
|
||||
GList *l;
|
||||
|
||||
priv = query->priv;
|
||||
|
||||
@ -983,14 +1012,16 @@ remove_component (Query *query, const char *uid)
|
||||
g_free (old_uid);
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyObjRemoved (
|
||||
priv->ql,
|
||||
(char *) uid,
|
||||
&ev);
|
||||
for (l = priv->listeners; l != NULL; l = l->next) {
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyObjRemoved (
|
||||
l->data,
|
||||
(char *) uid,
|
||||
&ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("remove_component(): Could not notify the listener of a "
|
||||
"removed component");
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("remove_component(): Could not notify the listener of a "
|
||||
"removed component");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
}
|
||||
@ -1081,24 +1112,27 @@ parse_sexp (Query *query)
|
||||
if (e_sexp_parse (priv->esexp) == -1) {
|
||||
const char *error_str;
|
||||
CORBA_Environment ev;
|
||||
GList *l;
|
||||
|
||||
priv->state = QUERY_PARSE_ERROR;
|
||||
|
||||
/* Report the error to the listener */
|
||||
/* Report the error to the listeners */
|
||||
|
||||
error_str = e_sexp_error (priv->esexp);
|
||||
g_assert (error_str != NULL);
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
|
||||
priv->ql,
|
||||
GNOME_Evolution_Calendar_QueryListener_PARSE_ERROR,
|
||||
error_str,
|
||||
&ev);
|
||||
for (l = priv->listeners; l != NULL; l = l->next) {
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
|
||||
l->data,
|
||||
GNOME_Evolution_Calendar_QueryListener_PARSE_ERROR,
|
||||
error_str,
|
||||
&ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("parse_sexp(): Could not notify the listener of "
|
||||
"a parse error");
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("parse_sexp(): Could not notify the listener of "
|
||||
"a parse error");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
|
||||
@ -1142,35 +1176,41 @@ match_component (Query *query, const char *uid,
|
||||
if (!result) {
|
||||
const char *error_str;
|
||||
CORBA_Environment ev;
|
||||
GList *l;
|
||||
|
||||
error_str = e_sexp_error (priv->esexp);
|
||||
g_assert (error_str != NULL);
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyEvalError (
|
||||
priv->ql,
|
||||
error_str,
|
||||
&ev);
|
||||
for (l = priv->listeners; l != NULL; l = l->next) {
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyEvalError (
|
||||
l->data,
|
||||
error_str,
|
||||
&ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("match_component(): Could not notify the listener of "
|
||||
"an evaluation error");
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("match_component(): Could not notify the listener of "
|
||||
"an evaluation error");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
return;
|
||||
} else if (result->type != ESEXP_RES_BOOL) {
|
||||
CORBA_Environment ev;
|
||||
GList *l;
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyEvalError (
|
||||
priv->ql,
|
||||
_("Evaluation of the search expression did not yield a boolean value"),
|
||||
&ev);
|
||||
for (l = priv->listeners; l != NULL; l = l->next) {
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyEvalError (
|
||||
l->data,
|
||||
_("Evaluation of the search expression did not yield a boolean value"),
|
||||
&ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("match_component(): Could not notify the listener of "
|
||||
"an unexpected result value type when evaluating the "
|
||||
"search expression");
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("match_component(): Could not notify the listener of "
|
||||
"an unexpected result value type when evaluating the "
|
||||
"search expression");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
} else {
|
||||
@ -1233,22 +1273,24 @@ process_components_cb (gpointer data)
|
||||
}
|
||||
|
||||
bonobo_object_unref (BONOBO_OBJECT (query));
|
||||
if (!priv || !priv->ql)
|
||||
if (!priv || !priv->listeners)
|
||||
return FALSE;
|
||||
|
||||
/* notify listener that the query ended */
|
||||
/* notify listeners that the query ended */
|
||||
priv->state = QUERY_DONE;
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
|
||||
priv->ql,
|
||||
GNOME_Evolution_Calendar_QueryListener_SUCCESS,
|
||||
"",
|
||||
&ev);
|
||||
for (l = priv->listeners; l != NULL; l = l->next) {
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
|
||||
l->data,
|
||||
GNOME_Evolution_Calendar_QueryListener_SUCCESS,
|
||||
"",
|
||||
&ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("start_query(): Could not notify the listener of "
|
||||
"a finished query");
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("start_query(): Could not notify the listener of "
|
||||
"a finished query");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
|
||||
@ -1344,6 +1386,79 @@ start_query_cb (gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
notify_uid_cb (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
CORBA_Environment ev;
|
||||
char *uid = (char *) key;
|
||||
StartCachedQueryInfo *info = (StartCachedQueryInfo *) data;
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyObjUpdated (
|
||||
info->ql,
|
||||
uid,
|
||||
FALSE,
|
||||
g_hash_table_size (info->query->priv->uids),
|
||||
g_hash_table_size (info->query->priv->uids),
|
||||
&ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("notify_uid_cb(): Could not notify the listener of an "
|
||||
"updated component");
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
}
|
||||
|
||||
/* Idle handler for starting a cached query */
|
||||
static gboolean
|
||||
start_cached_query_cb (gpointer data)
|
||||
{
|
||||
CORBA_Environment ev;
|
||||
QueryPrivate *priv;
|
||||
StartCachedQueryInfo *info = (StartCachedQueryInfo *) data;
|
||||
|
||||
priv = info->query->priv;
|
||||
|
||||
/* if the query hasn't started yet, we add the listener */
|
||||
if (priv->state == QUERY_START_PENDING ||
|
||||
priv->state == QUERY_WAIT_FOR_BACKEND) {
|
||||
priv->listeners = g_list_append (priv->listeners, info->ql);
|
||||
|
||||
g_free (info);
|
||||
priv->cached_timeouts = g_list_remove (priv->cached_timeouts,
|
||||
GPOINTER_TO_INT (info->tid));
|
||||
|
||||
return FALSE;
|
||||
} else if (priv->state == QUERY_IN_PROGRESS) {
|
||||
/* if it's in progress, we just wait */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* if the query is done, then we just notify the listener */
|
||||
g_source_remove (info->tid);
|
||||
priv->cached_timeouts = g_list_remove (priv->cached_timeouts,
|
||||
GPOINTER_TO_INT (info->tid));
|
||||
|
||||
g_hash_table_foreach (priv->uids, (GHFunc) notify_uid_cb, info);
|
||||
|
||||
priv->listeners = g_list_append (priv->listeners, info->ql);
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
|
||||
info->ql,
|
||||
GNOME_Evolution_Calendar_QueryListener_SUCCESS,
|
||||
"",
|
||||
&ev);
|
||||
if (BONOBO_EX (&ev))
|
||||
g_message ("start_cached_query_cb(): Could not notify the listener of "
|
||||
"a finished query");
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
g_free (info);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Callback used when the backend gets loaded; we just queue the query to be
|
||||
* started later.
|
||||
*/
|
||||
@ -1368,6 +1483,18 @@ backend_opened_cb (CalBackend *backend, CalBackendOpenStatus status, gpointer da
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback used when the backend for a cached query is destroyed */
|
||||
static void
|
||||
backend_destroyed_cb (GtkObject *object, gpointer data)
|
||||
{
|
||||
Query *query;
|
||||
|
||||
query = QUERY (data);
|
||||
|
||||
cached_queries = g_list_remove (cached_queries, query);
|
||||
bonobo_object_unref (query);
|
||||
}
|
||||
|
||||
/**
|
||||
* query_construct:
|
||||
* @query: A live search query.
|
||||
@ -1401,10 +1528,10 @@ query_construct (Query *query,
|
||||
priv = query->priv;
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
priv->ql = CORBA_Object_duplicate (ql, &ev);
|
||||
priv->listeners = g_list_append (NULL, CORBA_Object_duplicate (ql, &ev));
|
||||
if (BONOBO_EX (&ev)) {
|
||||
g_message ("query_construct(): Could not duplicate the listener");
|
||||
priv->ql = CORBA_OBJECT_NIL;
|
||||
priv->listeners = NULL;
|
||||
CORBA_exception_free (&ev);
|
||||
return NULL;
|
||||
}
|
||||
@ -1448,12 +1575,54 @@ query_new (CalBackend *backend,
|
||||
const char *sexp)
|
||||
{
|
||||
Query *query;
|
||||
GList *l;
|
||||
|
||||
/* first, see if we've got this query in our cache */
|
||||
for (l = cached_queries; l != NULL; l = l->next) {
|
||||
query = QUERY (l->data);
|
||||
|
||||
g_assert (query != NULL);
|
||||
|
||||
if (query->priv->backend == backend &&
|
||||
!strcmp (query->priv->sexp, sexp)) {
|
||||
StartCachedQueryInfo *info;
|
||||
CORBA_Environment ev;
|
||||
|
||||
info = g_new0 (StartCachedQueryInfo, 1);
|
||||
info->query = query;
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
info->ql = CORBA_Object_duplicate (ql, &ev);
|
||||
if (BONOBO_EX (&ev)) {
|
||||
g_message ("query_new(): Could not duplicate listener object");
|
||||
g_free (info);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
CORBA_exception_free (&ev);
|
||||
|
||||
info->tid = g_timeout_add (100, (GSourceFunc) start_cached_query_cb, info);
|
||||
query->priv->cached_timeouts = g_list_append (query->priv->cached_timeouts,
|
||||
GINT_TO_POINTER (info->tid));
|
||||
|
||||
bonobo_object_ref (BONOBO_OBJECT (query));
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
/* not found, so create a new one */
|
||||
query = QUERY (gtk_type_new (QUERY_TYPE));
|
||||
if (!query_construct (query, backend, ql, sexp)) {
|
||||
bonobo_object_unref (BONOBO_OBJECT (query));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add the new query to our cache */
|
||||
gtk_signal_connect (GTK_OBJECT (query->priv->backend), "destroy",
|
||||
GTK_SIGNAL_FUNC (backend_destroyed_cb), query);
|
||||
|
||||
bonobo_object_ref (BONOBO_OBJECT (query));
|
||||
cached_queries = g_list_append (cached_queries, query);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user