summaryrefslogtreecommitdiff
path: root/src/pop-transaction.c
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2007-05-08 08:49:41 -0400
committerRay Strode <rstrode@redhat.com>2007-05-08 08:49:41 -0400
commit9319b8f439e33c79d705b1714d6eb9f122b10096 (patch)
tree74043b89478c7e7bc4f711e3c8f9f81cdd7a9a62 /src/pop-transaction.c
parent3242f87693a6d8037b68a0f84a487916913fd2ff (diff)
add per-action state accessor apiHEADasync
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.c100
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;
}