summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2007-05-02 17:58:45 -0400
committerRay Strode <rstrode@redhat.com>2007-05-02 17:58:45 -0400
commitb690a4fd2c1a0976bb88b210ce96fadac705125f (patch)
treeb100636b4d2e48b4b3f4c8b92722547f1f2aa9f4
parentb67c3b293ba1c7057559f2552b86e490ccc4ec46 (diff)
flesh out the transaction bits a little more
-rw-r--r--src/pop-transaction.c133
1 files changed, 120 insertions, 13 deletions
diff --git a/src/pop-transaction.c b/src/pop-transaction.c
index 50b9ac9..5fc1c77 100644
--- a/src/pop-transaction.c
+++ b/src/pop-transaction.c
@@ -27,8 +27,11 @@
#include <glib-object.h>
#include <glib/gi18n.h>
+typedef enum _PopTransactionState PopTransactionState;
+
struct _PopTransactionPrivate
{
+ PopTransactionState state;
PopTransactionStatus status;
GQueue *actions;
GList *current_action_node;
@@ -36,10 +39,19 @@ struct _PopTransactionPrivate
GClosure *completion_closure;
GMainContext *context;
- guint32 is_commited : 1;
- guint idle_id;
+ guint process_idle_id;
+ guint rollback_idle_id;
+ guint wait_id;
};
+enum _PopTransactionState
+{
+ POP_TRANSACTION_STATE_UNCOMMITED = 0,
+ POP_TRANSACTION_STATE_COMMITED,
+ POP_TRANSACTION_STATE_PROCESSING,
+ POP_TRANSACTION_STATE_ROLLING_BACK,
+}
+
typedef struct
{
PopActionProcessFunc process_func;
@@ -105,12 +117,33 @@ pop_transaction_class_install_signals (PopTransactionClass *
object_class = G_OBJECT_CLASS (transaction_class);
- pop_transaction_signals[FOO] =
- g_signal_new ("foo", G_OBJECT_CLASS_TYPE (object_class),
+ pop_transaction_signals[PROCESS] =
+ g_signal_new ("process", G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (PopTransactionClass, foo),
+ G_STRUCT_OFFSET (PopTransactionClass, process),
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
- transaction_class->foo = NULL;
+ transaction_class->process = NULL;
+
+ pop_transaction_signals[WAIT] =
+ g_signal_new ("wait", G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PopTransactionClass, wait),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ transaction_class->wait = NULL;
+
+ pop_transaction_signals[RESUME] =
+ g_signal_new ("resume", G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PopTransactionClass, resume),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ transaction_class->resume = NULL;
+
+ pop_transaction_signals[CANCELED] =
+ g_signal_new ("canceled", G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PopTransactionClass, canceled),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ transaction_class->canceled = NULL;
}
static void
@@ -135,7 +168,6 @@ pop_transaction_init (PopTransaction *transaction)
transaction->priv = G_TYPE_INSTANCE_GET_PRIVATE (transaction,
POP_TYPE_TRANSACTION,
PopTransactionPrivate);
-
}
static void
@@ -269,8 +301,15 @@ pop_transaction_wait_for_fd (PopTransaction *transaction,
GIOCondition condition,
GDestroyNotify destroy_notify)
{
- g_return_if_fail (POP_IS_TRANSACTION (transaction));
+ GIOChannel *channel;
+ GSource *source;
+ g_return_if_fail (POP_IS_TRANSACTION (transaction));
+ channel = g_io_channel_unix_new (fd);
+ source = g_io_create_watch (channel, condition);
+ pop_transaction_wait_for_source (transaction, source);
+ g_source_unref (source);
+ g_io_channel_unref (channel);
}
void
@@ -278,8 +317,39 @@ pop_transaction_wait_for_timeout (PopTransaction *transaction,
const char *key,
int milliseconds)
{
+ GSource *source;
g_return_if_fail (POP_IS_TRANSACTION (transaction));
+ source = g_timeout_source_new (milliseconds);
+ pop_transaction_wait_for_source (transaction, source);
+ g_source_unref (source);
+}
+
+static gboolean
+pop_transaction_wait_callback (PopTransaction *transaction)
+{
+
+ switch (transaction->priv->state)
+ {
+ case POP_TRANSACTION_STATE_PROCESSING:
+ pop_transaction_process_on_idle (transaction);
+ break;
+
+ case POP_TRANSACTION_STATE_ROLLING_BACK:
+ pop_transaction_rollback_on_idle (transaction);
+ break;
+ }
+
+ g_source_remove (transaction->priv->wait_id);
+ transaction->priv->wait_id = 0;
+
+ return FALSE;
+}
+
+static gboolean
+pop_transaction_is_active (PopTransaction *transaction)
+{
+ return transaction->priv->state >= POP_TRANSACTION_STATE_PROCESSING;
}
void
@@ -287,6 +357,33 @@ pop_transaction_wait_for_source (PopTransaction *transaction,
GSource *source)
{
g_return_if_fail (POP_IS_TRANSACTION (transaction));
+ g_return_if_fail (pop_transaction_is_active (transaction));
+
+ switch (transaction->priv->state)
+ {
+ case POP_TRANSACTION_STATE_PROCESSING:
+ g_assert (transaction->priv->process_idle_id != 0);
+ g_assert (transaction->priv->rollback_idle_id == 0);
+ g_source_remove (transaction->priv->process_idle_id);
+ transaction->priv->process_idle_id = 0;
+ break;
+
+ case POP_TRANSACTION_STATE_ROLLING_BACK:
+ g_assert (transaction->priv->rollback_idle_id != 0);
+ g_assert (transaction->priv->process_idle_id == 0);
+ g_source_remove (transaction->priv->rollback_idle_id);
+ transaction->priv->rollback_idle_id = 0;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ g_source_set_callback (source, (GSourceFunc) pop_transaction_wait_callback, transaction, NULL);
+ transaction->priv->wait_id = g_source_attach (source,
+ transaction->priv->context);
+ g_source_unref (source);
}
@@ -307,7 +404,7 @@ pop_transaction_attach (PopTransaction *transaction,
}
static void
-pop_transaction_complete (PopTransaction *transaction)
+pop_transaction_finish (PopTransaction *transaction)
{
transaction->priv->status = POP_TRANSACTION_STATUS_FINISHED;
}
@@ -359,6 +456,11 @@ pop_transaction_rollback_current_action_and_rewind (PopTransaction *transaction)
g_assert (transaction->priv->current_action_node != NULL);
+ if (transaction->priv->state == POP_TRANSACTION_STATE_PROCESSING)
+ transaction->priv->state = POP_TRANSACTION_STATE_ROLLING_BACK;
+
+ g_assert (transaction->priv->state == POP_TRANSACTION_STATE_ROLLING_BACK);
+
action = (PopAction *) transaction->priv->current_action_node->data;
status = action->rollback_func (transaction);
@@ -384,7 +486,7 @@ pop_transaction_rollback_current_action_and_rewind (PopTransaction *transaction)
}
if (!should_continue)
- pop_transaction_complete (transaction);
+ pop_transaction_finish (transaction);
return should_continue;
}
@@ -415,6 +517,11 @@ pop_transaction_process_current_action_and_seek_forward (PopTransaction *transac
g_assert (transaction->priv->current_action_node != NULL);
+ if (transaction->priv->state == POP_TRANSACTION_STATE_COMMITED)
+ transaction->priv->state = POP_TRANSACTION_STATE_PROCESSING;
+
+ g_assert (transaction->priv->state == POP_TRANSACTION_STATE_PROCESSING);
+
action = (PopAction *) transaction->priv->current_action_node->data;
status = action->process_func (transaction);
@@ -428,7 +535,7 @@ pop_transaction_process_current_action_and_seek_forward (PopTransaction *transac
case POP_ACTION_PROCESS_STATUS_FINISHED:
if (!pop_transaction_seek_forward (transaction))
{
- pop_transaction_complete (transaction);
+ pop_transaction_finish (transaction);
should_continue = FALSE;
}
else
@@ -470,7 +577,7 @@ pop_transaction_is_empty (PopTransaction *transaction)
static gboolean
pop_transaction_is_committed (PopTransaction *transaction)
{
- return transaction->priv->is_commited;
+ return transaction->priv->state >= POP_TRANSACTION_STATE_COMMITED;
}
void
@@ -482,7 +589,7 @@ pop_transaction_commit (PopTransaction *transaction)
pop_transaction_process_on_idle (transaction);
- transaction->priv->is_commited = TRUE;
+ transaction->priv->state = POP_TRANSACTION_STATE_COMMITED;
}
gboolean