diff options
author | Ray Strode <rstrode@redhat.com> | 2007-05-02 17:58:45 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2007-05-02 17:58:45 -0400 |
commit | b690a4fd2c1a0976bb88b210ce96fadac705125f (patch) | |
tree | b100636b4d2e48b4b3f4c8b92722547f1f2aa9f4 | |
parent | b67c3b293ba1c7057559f2552b86e490ccc4ec46 (diff) |
flesh out the transaction bits a little more
-rw-r--r-- | src/pop-transaction.c | 133 |
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 |