summaryrefslogtreecommitdiff
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
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.
-rw-r--r--src/pop-transaction.c100
-rw-r--r--src/pop-transaction.h11
2 files changed, 97 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;
}
diff --git a/src/pop-transaction.h b/src/pop-transaction.h
index 4eb2b81..7768bf0 100644
--- a/src/pop-transaction.h
+++ b/src/pop-transaction.h
@@ -100,6 +100,17 @@ void pop_transaction_add_action_full (PopTransaction *transaction,
PopActionRollbackFunc action_rollback_func,
gpointer user_data,
GDestroyNotify free_func);
+void pop_transaction_set_action_data (PopTransaction *transaction,
+ const gchar *key,
+ gpointer data);
+
+void pop_transaction_unset_action_data (PopTransaction *transaction,
+ const gchar *key,
+ gpointer data);
+gpointer pop_transaction_get_action_data (PopTransaction *transaction,
+ const gchar *key);
+gboolean pop_transaction_has_action_data (PopTransaction *transaction,
+ const gchar *key);
void pop_transaction_add_subtransaction (PopTransaction *transaction,
PopTransaction *subtransaction);