aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog30
-rw-r--r--calendar/pcs/query.c67
2 files changed, 72 insertions, 25 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 067afc7e8a..ac5fdd96fa 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,33 @@
+2001-11-09 Federico Mena Quintero <federico@ximian.com>
+
+ (committed by Damon)
+
+ Fix bug #14699.
+
+ * pcs/query.c (QueryState): Added a state QUERY_WAIT_FOR_BACKEND
+ to indicate that the query is not populated as we are waiting for
+ the backend to be opened.
+ (query_init): Start in the QUERY_WAIT_FOR_BACKEND state.
+ (query_destroy): Only disconnect from the backend if we are in a
+ state that implies that we are connected to its signals.
+ (query_construct): If the backend is already loaded, immediately
+ set the state to QUERY_START_PENDING.
+ (backend_opened_cb): Disconnect from the backend's "opened"
+ signal. Set the state to QUERY_START_PENDING.
+ (match_component): We can now only match components if the query
+ is in progress or if it is done. Assert to that effect, and do
+ not ensure_sexp().
+ (match_component): Do not check for a nonexistent component using
+ g_return_if_fail(). Also, there is no need to ref/unref the
+ component.
+ (backend_obj_updated_cb): Assert to the effect of our state.
+ (backend_obj_removed_cb): Likewise.
+ (parse_sexp): Renamed from ensure_sexp(). Assert that the query
+ has not started. Do not disconnect from the backend's signals
+ here, since we have no connections.
+ (start_query_cb): Set the state to QUERY_IN_PROGRESS here instead
+ of in populate_query().
+
2001-12-07 Rodrigo Moya <rodrigo@ximian.com>
* gui/calendar-config.c (calendar_config_get_default_uri):
diff --git a/calendar/pcs/query.c b/calendar/pcs/query.c
index 33289ed107..bf008ab655 100644
--- a/calendar/pcs/query.c
+++ b/calendar/pcs/query.c
@@ -38,7 +38,8 @@
/* States of a query */
typedef enum {
- QUERY_START_PENDING, /* the query is not populated yet */
+ QUERY_WAIT_FOR_BACKEND, /* the query is not populated and the backend is not loaded */
+ QUERY_START_PENDING, /* the query is not populated yet, but the backend is loaded */
QUERY_IN_PROGRESS, /* the query is populated; components are still being processed */
QUERY_DONE, /* the query is done, but still accepts object changes */
QUERY_PARSE_ERROR /* a parse error occurred when initially creating the ESexp */
@@ -124,7 +125,7 @@ query_init (Query *query)
priv->sexp = NULL;
priv->idle_id = 0;
- priv->state = QUERY_START_PENDING;
+ priv->state = QUERY_WAIT_FOR_BACKEND;
priv->pending_uids = NULL;
priv->uids = g_hash_table_new (g_str_hash, g_str_equal);
@@ -156,7 +157,18 @@ query_destroy (GtkObject *object)
priv = query->priv;
if (priv->backend) {
- gtk_signal_disconnect_by_data (GTK_OBJECT (priv->backend), query);
+ /* If we are waiting for the backend to be opened, we'll be
+ * connected to its "opened" signal. If we are in the middle of
+ * a query or if we are just waiting for object update
+ * notifications, we'll have the "obj_removed" and "obj_updated"
+ * connections. Otherwise, we are either in a parse error state
+ * or waiting for the query to be populated, and in both cases
+ * we have no signal connections.
+ */
+ if (priv->state == QUERY_WAIT_FOR_BACKEND
+ || priv->state == QUERY_IN_PROGRESS || priv->state == QUERY_DONE)
+ gtk_signal_disconnect_by_data (GTK_OBJECT (priv->backend), query);
+
gtk_object_unref (GTK_OBJECT (priv->backend));
priv->backend = NULL;
}
@@ -1040,22 +1052,17 @@ create_sexp (Query *query)
return esexp;
}
-/* Ensures that the sexp has been parsed and the ESexp has been created. If a
- * parse error occurs, it sets the query state to QUERY_PARSE_ERROR and returns
- * FALSE.
+/* Creates the ESexp and parses the esexp. If a parse error occurs, it sets the
+ * query state to QUERY_PARSE_ERROR and returns FALSE.
*/
static gboolean
-ensure_sexp (Query *query)
+parse_sexp (Query *query)
{
QueryPrivate *priv;
priv = query->priv;
- if (priv->state == QUERY_PARSE_ERROR)
- g_assert_not_reached (); /* we should already have terminated everything */
-
- if (priv->esexp)
- return TRUE;
+ g_assert (priv->state == QUERY_START_PENDING);
/* Compile the query string */
@@ -1068,10 +1075,7 @@ ensure_sexp (Query *query)
const char *error_str;
CORBA_Environment ev;
- /* Change the state and disconnect from any notifications */
-
priv->state = QUERY_PARSE_ERROR;
- gtk_signal_disconnect_by_data (GTK_OBJECT (priv->backend), query);
/* Report the error to the listener */
@@ -1086,7 +1090,7 @@ ensure_sexp (Query *query)
&ev);
if (BONOBO_EX (&ev))
- g_message ("ensure_sexp(): Could not notify the listener of "
+ g_message ("parse_sexp(): Could not notify the listener of "
"a parse error");
CORBA_exception_free (&ev);
@@ -1113,14 +1117,12 @@ match_component (Query *query, const char *uid,
priv = query->priv;
- g_assert (priv->state != QUERY_PARSE_ERROR);
-
- if (!ensure_sexp (query))
- return;
+ g_assert (priv->state == QUERY_IN_PROGRESS || priv->state == QUERY_DONE);
+ g_assert (priv->esexp != NULL);
comp = cal_backend_get_object_component (priv->backend, uid);
- g_return_if_fail (comp != NULL);
- gtk_object_ref (GTK_OBJECT (comp));
+ if (!comp)
+ return;
/* Eval the sexp */
@@ -1128,7 +1130,6 @@ match_component (Query *query, const char *uid,
priv->next_comp = comp;
result = e_sexp_eval (priv->esexp);
- gtk_object_unref (GTK_OBJECT (comp));
priv->next_comp = NULL;
if (!result) {
@@ -1262,7 +1263,6 @@ populate_query (Query *query)
priv->n_pending = priv->pending_total;
priv->idle_id = g_idle_add (process_component_cb, query);
- priv->state = QUERY_IN_PROGRESS;
}
/* Callback used when a component changes in the backend */
@@ -1270,8 +1270,12 @@ static void
backend_obj_updated_cb (CalBackend *backend, const char *uid, gpointer data)
{
Query *query;
+ QueryPrivate *priv;
query = QUERY (data);
+ priv = query->priv;
+
+ g_assert (priv->state == QUERY_IN_PROGRESS || priv->state == QUERY_DONE);
bonobo_object_ref (BONOBO_OBJECT (query));
@@ -1291,6 +1295,8 @@ backend_obj_removed_cb (CalBackend *backend, const char *uid, gpointer data)
query = QUERY (data);
priv = query->priv;
+ g_assert (priv->state == QUERY_IN_PROGRESS || priv->state == QUERY_DONE);
+
bonobo_object_ref (BONOBO_OBJECT (query));
remove_component (query, uid);
@@ -1309,9 +1315,11 @@ start_query_cb (gpointer data)
query = QUERY (data);
priv = query->priv;
+ g_assert (priv->state == QUERY_START_PENDING);
+
priv->idle_id = 0;
- if (!ensure_sexp (query))
+ if (!parse_sexp (query))
return FALSE;
/* Populate the query with UIDs so that we can process them asynchronously */
@@ -1325,6 +1333,8 @@ start_query_cb (gpointer data)
GTK_SIGNAL_FUNC (backend_obj_removed_cb),
query);
+ priv->state = QUERY_IN_PROGRESS;
+
return FALSE;
}
@@ -1340,6 +1350,11 @@ backend_opened_cb (CalBackend *backend, CalBackendOpenStatus status, gpointer da
query = QUERY (data);
priv = query->priv;
+ g_assert (priv->state == QUERY_WAIT_FOR_BACKEND);
+
+ gtk_signal_disconnect_by_data (GTK_OBJECT (priv->backend), query);
+ priv->state = QUERY_START_PENDING;
+
if (status == CAL_BACKEND_OPEN_SUCCESS) {
g_assert (cal_backend_is_loaded (backend));
g_assert (priv->idle_id == 0);
@@ -1400,6 +1415,8 @@ query_construct (Query *query,
/* Queue the query to be started asynchronously */
if (cal_backend_is_loaded (priv->backend)) {
+ priv->state = QUERY_START_PENDING;
+
g_assert (priv->idle_id == 0);
priv->idle_id = g_idle_add (start_query_cb, query);
} else