daemon: Share Transaction address for identical requests

If a client makes a request that is identical (that is, same method name
and same parameters) to an ongoing transaction, return the bus address of
that transaction.  The client can then "tune in" to the progress messages.
(Remember the Transaction.Start() method returns a boolean to distinguish
a newly-started transaction from an ongoing transaction.)

The driving use case for this is a dropped ssh connection during a long
running transaction -- like "upgrade" -- and being able to reattach to
the transaction's progress messages mid-stream.
This commit is contained in:
Matthew Barnes 2015-08-27 11:14:50 -04:00
parent b3189b6ae4
commit 9c0e87bc75
3 changed files with 141 additions and 30 deletions

View File

@ -415,11 +415,20 @@ os_handle_download_update_rpm_diff (RPMOSTreeOS *interface,
glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object RpmostreedTransaction *transaction = NULL;
glnx_unref_object OstreeSysroot *sysroot = NULL; glnx_unref_object OstreeSysroot *sysroot = NULL;
glnx_unref_object GCancellable *cancellable = NULL; glnx_unref_object GCancellable *cancellable = NULL;
const char *client_address;
const char *osname; const char *osname;
const char *sysroot_path; const char *sysroot_path;
GError *local_error = NULL; GError *local_error = NULL;
/* If a compatible transaction is in progress, share its bus address. */
transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor);
if (transaction != NULL)
{
if (rpmostreed_transaction_is_compatible (transaction, invocation))
goto out;
g_clear_object (&transaction);
}
cancellable = g_cancellable_new (); cancellable = g_cancellable_new ();
sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ()); sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ());
@ -444,12 +453,17 @@ os_handle_download_update_rpm_diff (RPMOSTreeOS *interface,
rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction);
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_download_update_rpm_diff (interface, invocation, client_address);
out: out:
if (local_error != NULL) if (local_error != NULL)
{
g_dbus_method_invocation_take_error (invocation, local_error); g_dbus_method_invocation_take_error (invocation, local_error);
}
else
{
const char *client_address;
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_download_update_rpm_diff (interface, invocation, client_address);
}
return TRUE; return TRUE;
} }
@ -465,11 +479,20 @@ os_handle_upgrade (RPMOSTreeOS *interface,
glnx_unref_object GCancellable *cancellable = NULL; glnx_unref_object GCancellable *cancellable = NULL;
GVariantDict options_dict; GVariantDict options_dict;
gboolean opt_allow_downgrade = FALSE; gboolean opt_allow_downgrade = FALSE;
const char *client_address;
const char *osname; const char *osname;
const char *sysroot_path; const char *sysroot_path;
GError *local_error = NULL; GError *local_error = NULL;
/* If a compatible transaction is in progress, share its bus address. */
transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor);
if (transaction != NULL)
{
if (rpmostreed_transaction_is_compatible (transaction, invocation))
goto out;
g_clear_object (&transaction);
}
cancellable = g_cancellable_new (); cancellable = g_cancellable_new ();
sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ()); sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ());
@ -506,12 +529,17 @@ os_handle_upgrade (RPMOSTreeOS *interface,
rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction);
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_upgrade (interface, invocation, client_address);
out: out:
if (local_error != NULL) if (local_error != NULL)
{
g_dbus_method_invocation_take_error (invocation, local_error); g_dbus_method_invocation_take_error (invocation, local_error);
}
else
{
const char *client_address;
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_upgrade (interface, invocation, client_address);
}
return TRUE; return TRUE;
} }
@ -524,11 +552,20 @@ os_handle_rollback (RPMOSTreeOS *interface,
glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object RpmostreedTransaction *transaction = NULL;
glnx_unref_object OstreeSysroot *sysroot = NULL; glnx_unref_object OstreeSysroot *sysroot = NULL;
glnx_unref_object GCancellable *cancellable = NULL; glnx_unref_object GCancellable *cancellable = NULL;
const char *client_address;
const char *osname; const char *osname;
const char *sysroot_path; const char *sysroot_path;
GError *local_error = NULL; GError *local_error = NULL;
/* If a compatible transaction is in progress, share its bus address. */
transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor);
if (transaction != NULL)
{
if (rpmostreed_transaction_is_compatible (transaction, invocation))
goto out;
g_clear_object (&transaction);
}
cancellable = g_cancellable_new (); cancellable = g_cancellable_new ();
sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ()); sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ());
@ -552,12 +589,17 @@ os_handle_rollback (RPMOSTreeOS *interface,
rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction);
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_rollback (interface, invocation, client_address);
out: out:
if (local_error != NULL) if (local_error != NULL)
{
g_dbus_method_invocation_take_error (invocation, local_error); g_dbus_method_invocation_take_error (invocation, local_error);
}
else
{
const char *client_address;
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_rollback (interface, invocation, client_address);
}
return TRUE; return TRUE;
} }
@ -570,11 +612,20 @@ os_handle_clear_rollback_target (RPMOSTreeOS *interface,
glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object RpmostreedTransaction *transaction = NULL;
glnx_unref_object OstreeSysroot *sysroot = NULL; glnx_unref_object OstreeSysroot *sysroot = NULL;
glnx_unref_object GCancellable *cancellable = NULL; glnx_unref_object GCancellable *cancellable = NULL;
const char *client_address;
const char *osname; const char *osname;
const char *sysroot_path; const char *sysroot_path;
GError *local_error = NULL; GError *local_error = NULL;
/* If a compatible transaction is in progress, share its bus address. */
transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor);
if (transaction != NULL)
{
if (rpmostreed_transaction_is_compatible (transaction, invocation))
goto out;
g_clear_object (&transaction);
}
cancellable = g_cancellable_new (); cancellable = g_cancellable_new ();
sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ()); sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ());
@ -598,12 +649,17 @@ os_handle_clear_rollback_target (RPMOSTreeOS *interface,
rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction);
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_clear_rollback_target (interface, invocation, client_address);
out: out:
if (local_error != NULL) if (local_error != NULL)
{
g_dbus_method_invocation_take_error (invocation, local_error); g_dbus_method_invocation_take_error (invocation, local_error);
}
else
{
const char *client_address;
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_clear_rollback_target (interface, invocation, client_address);
}
return TRUE; return TRUE;
} }
@ -622,11 +678,20 @@ os_handle_rebase (RPMOSTreeOS *interface,
glnx_unref_object GCancellable *cancellable = NULL; glnx_unref_object GCancellable *cancellable = NULL;
GVariantDict options_dict; GVariantDict options_dict;
gboolean opt_skip_purge = FALSE; gboolean opt_skip_purge = FALSE;
const char *client_address;
const char *osname; const char *osname;
const char *sysroot_path; const char *sysroot_path;
GError *local_error = NULL; GError *local_error = NULL;
/* If a compatible transaction is in progress, share its bus address. */
transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor);
if (transaction != NULL)
{
if (rpmostreed_transaction_is_compatible (transaction, invocation))
goto out;
g_clear_object (&transaction);
}
cancellable = g_cancellable_new (); cancellable = g_cancellable_new ();
sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ()); sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ());
@ -663,12 +728,17 @@ os_handle_rebase (RPMOSTreeOS *interface,
rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction);
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_rebase (interface, invocation, client_address);
out: out:
if (local_error != NULL) if (local_error != NULL)
{
g_dbus_method_invocation_take_error (invocation, local_error); g_dbus_method_invocation_take_error (invocation, local_error);
}
else
{
const char *client_address;
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_rebase (interface, invocation, client_address);
}
return TRUE; return TRUE;
} }
@ -706,11 +776,20 @@ os_handle_download_rebase_rpm_diff (RPMOSTreeOS *interface,
glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object RpmostreedTransaction *transaction = NULL;
glnx_unref_object OstreeSysroot *sysroot = NULL; glnx_unref_object OstreeSysroot *sysroot = NULL;
glnx_unref_object GCancellable *cancellable = NULL; glnx_unref_object GCancellable *cancellable = NULL;
const char *client_address;
const char *osname; const char *osname;
const char *sysroot_path; const char *sysroot_path;
GError *local_error = NULL; GError *local_error = NULL;
/* If a compatible transaction is in progress, share its bus address. */
transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor);
if (transaction != NULL)
{
if (rpmostreed_transaction_is_compatible (transaction, invocation))
goto out;
g_clear_object (&transaction);
}
cancellable = g_cancellable_new (); cancellable = g_cancellable_new ();
sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ()); sysroot_path = rpmostreed_sysroot_get_sysroot_path (rpmostreed_sysroot_get ());
@ -735,12 +814,17 @@ os_handle_download_rebase_rpm_diff (RPMOSTreeOS *interface,
rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction);
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_download_rebase_rpm_diff (interface, invocation, client_address);
out: out:
if (local_error != NULL) if (local_error != NULL)
{
g_dbus_method_invocation_take_error (invocation, local_error); g_dbus_method_invocation_take_error (invocation, local_error);
}
else
{
const char *client_address;
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_download_rebase_rpm_diff (interface, invocation, client_address);
}
return TRUE; return TRUE;
} }

View File

@ -726,6 +726,31 @@ rpmostreed_transaction_emit_message_printf (RpmostreedTransaction *transaction,
formatted_message); formatted_message);
} }
gboolean
rpmostreed_transaction_is_compatible (RpmostreedTransaction *transaction,
GDBusMethodInvocation *invocation)
{
RpmostreedTransactionPrivate *priv;
const char *method_name_a;
const char *method_name_b;
GVariant *parameters_a;
GVariant *parameters_b;
g_return_val_if_fail (RPMOSTREED_IS_TRANSACTION (transaction), FALSE);
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
priv = rpmostreed_transaction_get_private (transaction);
method_name_a = g_dbus_method_invocation_get_method_name (priv->invocation);
method_name_b = g_dbus_method_invocation_get_method_name (invocation);
parameters_a = g_dbus_method_invocation_get_parameters (priv->invocation);
parameters_b = g_dbus_method_invocation_get_parameters (invocation);
return g_str_equal (method_name_a, method_name_b) &&
g_variant_equal (parameters_a, parameters_b);
}
void void
rpmostreed_transaction_connect_download_progress (RpmostreedTransaction *transaction, rpmostreed_transaction_connect_download_progress (RpmostreedTransaction *transaction,
OstreeAsyncProgress *progress) OstreeAsyncProgress *progress)

View File

@ -51,6 +51,8 @@ const char * rpmostreed_transaction_get_client_address (RpmostreedTransactio
void rpmostreed_transaction_emit_message_printf (RpmostreedTransaction *transaction, void rpmostreed_transaction_emit_message_printf (RpmostreedTransaction *transaction,
const char *format, const char *format,
...) G_GNUC_PRINTF (2, 3); ...) G_GNUC_PRINTF (2, 3);
gboolean rpmostreed_transaction_is_compatible (RpmostreedTransaction *transaction,
GDBusMethodInvocation *invocation);
void rpmostreed_transaction_connect_download_progress void rpmostreed_transaction_connect_download_progress
(RpmostreedTransaction *transaction, (RpmostreedTransaction *transaction,
OstreeAsyncProgress *progress); OstreeAsyncProgress *progress);