diff options
author | Ray Strode <rstrode@redhat.com> | 2007-05-08 08:49:41 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2007-05-08 08:49:41 -0400 |
commit | 9319b8f439e33c79d705b1714d6eb9f122b10096 (patch) | |
tree | 74043b89478c7e7bc4f711e3c8f9f81cdd7a9a62 /src/pop-transaction.c | |
parent | 3242f87693a6d8037b68a0f84a487916913fd2ff (diff) |
We want to keep a solid distinction between the three types of
data that are used in a transaction. One is per-transaction,
inter-action state. This is currently handled by gobject data
on the transaction object. Another is per-action input arguments.
These come from the initiator of the transaction and are passed to
the action every time the action is run. The last is per-action
internal state. Since action processing and rollback functions
are reentrant (they get called until the action says its complete)
each action needs to some how track what work its already done and
what work it needs to do to be finished. Previously, this was handled
ad-hoc as per-transaction gobject data, but now there is a dedicated
api.
Diffstat (limited to 'src/pop-transaction.c')
-rw-r--r-- | src/pop-transaction.c | 100 |
1 files changed, 86 insertions, 14 deletions
diff --git a/src/pop-transaction.c b/src/pop-transaction.c index 37a70a0..6a4556b 100644 --- a/src/pop-transaction.c +++ b/src/pop-transaction.c @@ -143,8 +143,8 @@ static gboolean pop_action_tree_is_at_first_action (PopActionTree *action_tree); static gboolean pop_action_tree_is_empty (PopActionTree *action_tree); static gboolean pop_action_tree_seek (PopActionTree *action_tree, PopActionTreeWalkDirection direction); -static void pop_action_tree_add_action (PopActionTree *action_tree, - PopAction *action); +static void pop_action_tree_add_action (PopActionTree *action_tree, + PopAction *action); static PopAction *pop_action_tree_get_current_action (PopActionTree *tree); static void pop_action_tree_foreach (PopActionTree *action_tree, GFunc func, @@ -159,6 +159,8 @@ struct _PopAction PopActionRollbackFunc rollback_func; PopActionRollbackStatus rollback_status; + GHashTable *state; + gpointer user_data; GDestroyNotify free_func; }; @@ -678,6 +680,7 @@ pop_action_new (PopActionProcessFunc action_process_func, action->process_status = POP_ACTION_PROCESS_STATUS_NOT_FINISHED; action->rollback_func = action_rollback_func; action->rollback_status = POP_ACTION_ROLLBACK_STATUS_NOT_FINISHED; + action->state = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); action->user_data = user_data; action->free_func = free_func; @@ -694,9 +697,76 @@ pop_action_free (PopAction *action) action->free_func (action->user_data); } + g_hash_table_destroy (action->state); g_slice_free (PopAction, action); } +void +pop_transaction_set_action_data (PopTransaction *transaction, + const char *key, + gpointer data) +{ + PopAction *action; + + g_return_if_fail (POP_IS_TRANSACTION (transaction)); + g_return_if_fail (key != NULL); + g_return_if_fail (!pop_transaction_has_action_data (transaction, key)); + + action = pop_action_tree_get_current_action (transaction->priv->action_tree); + + g_hash_table_insert (action->state, g_strdup (key), data); +} + +void +pop_transaction_unset_action_data (PopTransaction *transaction, + const gchar *key, + gpointer data) +{ + PopAction *action; + gboolean data_was_removed; + + g_return_if_fail (POP_IS_TRANSACTION (transaction)); + g_return_if_fail (key != NULL); + g_return_if_fail (!pop_transaction_has_action_data (transaction, key)); + + action = pop_action_tree_get_current_action (transaction->priv->action_tree); + + data_was_removed = g_hash_table_remove (action->state, key); + g_assert (data_was_removed); +} + +gpointer +pop_transaction_get_action_data (PopTransaction *transaction, + const gchar *key) +{ + PopAction *action; + gpointer data; + + g_return_val_if_fail (POP_IS_TRANSACTION (transaction), NULL); + g_return_val_if_fail (key != NULL, NULL); + + action = pop_action_tree_get_current_action (transaction->priv->action_tree); + + data = NULL; + g_hash_table_lookup_extended (action->state, key, NULL, &data); + + return data; +} + +gboolean +pop_transaction_has_action_data (PopTransaction *transaction, + const gchar *key) +{ + PopAction *action; + + g_return_val_if_fail (POP_IS_TRANSACTION (transaction), FALSE); + g_return_val_if_fail (key != NULL, FALSE); + + action = pop_action_tree_get_current_action (transaction->priv->action_tree); + + return g_hash_table_lookup_extended (action->state, key, NULL, NULL); +} + static PopActionProcessStatus pop_transaction_process_subtransaction (PopTransaction *transaction, PopTransaction *subtransaction) @@ -1383,6 +1453,7 @@ proces_io_action (PopTransaction *transaction, gboolean is_ready; size_t bytes_left, bytes_done; ssize_t bytes_done_this_time; + gpointer action_data; g_assert (POP_IS_TRANSACTION (transaction)); g_return_val_if_fail (arguments->fd >= 0, @@ -1395,18 +1466,20 @@ proces_io_action (PopTransaction *transaction, if (!is_ready) { g_printerr ("waiting for fd %d to become ready.\n", arguments->fd); + /* pause transaction until fd is ready for reading (or writing * depending on the io_func) */ pop_transaction_wait_for_fd (transaction, arguments->fd, condition, NULL); - g_object_set_data (G_OBJECT (transaction), "bytes-left-to-process", - GINT_TO_POINTER (arguments->number_of_bytes_to_process)); + action_data = GINT_TO_POINTER (arguments->number_of_bytes_to_process); + g_object_set_data (transaction, "bytes-left-to-process", action_data); /* when the transaction gets unpaused we want to continue on */ - g_object_set_data (G_OBJECT (transaction), "is-ready", - GINT_TO_POINTER (TRUE)); + action_data = GINT_TO_POINTER (TRUE) + pop_transaction_set_action_data (G_OBJECT (transaction), "is-ready", + action_data); return POP_ACTION_PROCESS_STATUS_NOT_FINISHED; } @@ -1476,8 +1549,8 @@ proces_io_action (PopTransaction *transaction, g_object_set_data (G_OBJECT (transaction), "bytes-already-processed", GINT_TO_POINTER (0)); - g_object_set_data (G_OBJECT (transaction), "is-ready", - GINT_TO_POINTER (FALSE)); + pop_transaction_set_action_data (G_OBJECT (transaction), "is-ready", + GINT_TO_POINTER (FALSE)); return POP_ACTION_PROCESS_STATUS_SUCCEEDED; } @@ -1527,8 +1600,8 @@ process_set_fd_nonblocking_action (PopTransaction *transaction, return POP_ACTION_PROCESS_STATUS_FAILED; } - g_object_set_data (G_OBJECT (transaction), "file-flags", - GINT_TO_POINTER (flags)); + pop_transaction_set_action_data (G_OBJECT (transaction), "file-flags", + GINT_TO_POINTER (flags)); return POP_ACTION_PROCESS_STATUS_SUCCEEDED; } @@ -1538,11 +1611,12 @@ rollback_set_fd_nonblocking_action (PopTransaction *transaction, gpointer data) { int fd, flags; + gpointer action_data; fd = GPOINTER_TO_INT (data); - flags = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (transaction), - "file-flags")); + action_data = pop_transaction_get_action_data (transaction, "file-flags"); + flags = GPOINTER_TO_INT (action_data); fcntl (fd, F_SETFL, flags); @@ -1658,12 +1732,10 @@ rollback_cat_action (PopTransaction *transaction, input_arguments = g_object_get_data (G_OBJECT (transaction), "cat-input-args"); g_slice_free (InputOutputArguments, input_arguments); - g_object_set_data (G_OBJECT (transaction), "cat-input-args", NULL); output_arguments = g_object_get_data (G_OBJECT (transaction), "cat-output-args"); g_slice_free (InputOutputArguments, output_arguments); g_free (output_arguments->buffer); - g_object_set_data (G_OBJECT (transaction), "cat-input-args", NULL); return POP_ACTION_ROLLBACK_STATUS_FINISHED; } |