daemon: Start implementing transaction methods
This commit is contained in:
parent
075d6bdad0
commit
0114507865
@ -30,6 +30,8 @@ librpmostreed_la_SOURCES = \
|
||||
src/daemon/auth.c \
|
||||
src/daemon/deployment-utils.h \
|
||||
src/daemon/deployment-utils.c \
|
||||
src/daemon/transactions.h \
|
||||
src/daemon/transactions.c \
|
||||
src/daemon/rpmostree-package-variants.h \
|
||||
src/daemon/rpmostree-package-variants.c \
|
||||
src/daemon/os.h \
|
||||
|
@ -196,8 +196,6 @@ daemon_constructed (GObject *_object)
|
||||
|
||||
G_OBJECT_CLASS (daemon_parent_class)->constructed (_object);
|
||||
|
||||
g_dbus_connection_start_message_processing (self->connection);
|
||||
|
||||
path = utils_generate_object_path (BASE_DBUS_PATH, "Sysroot", NULL);
|
||||
self->sysroot = g_object_new (TYPE_SYSROOT,
|
||||
"sysroot-path", self->sysroot_path,
|
||||
@ -210,6 +208,8 @@ daemon_constructed (GObject *_object)
|
||||
}
|
||||
|
||||
daemon_publish (self, path, FALSE, self->sysroot);
|
||||
g_dbus_connection_start_message_processing (self->connection);
|
||||
|
||||
g_debug ("daemon constructed");
|
||||
|
||||
out:
|
||||
|
@ -36,6 +36,31 @@ deployment_generate_id (OstreeDeployment *deployment)
|
||||
return g_strdup_printf ("%s_%u", osname, hash);
|
||||
}
|
||||
|
||||
OstreeDeployment *
|
||||
deployment_get_for_id (OstreeSysroot *sysroot,
|
||||
const gchar *deploy_id)
|
||||
{
|
||||
g_autoptr (GPtrArray) deployments = NULL;
|
||||
guint i;
|
||||
|
||||
OstreeDeployment *deployment = NULL;
|
||||
|
||||
deployments = ostree_sysroot_get_deployments (sysroot);
|
||||
if (deployments == NULL)
|
||||
goto out;
|
||||
|
||||
for (i=0; i<deployments->len; i++)
|
||||
{
|
||||
g_autofree gchar *id = deployment_generate_id (deployments->pdata[i]);
|
||||
if (g_strcmp0 (deploy_id, id) == 0) {
|
||||
deployment = g_object_ref (deployments->pdata[i]);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return deployment;
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
deployment_gpg_results (OstreeRepo *repo,
|
||||
const gchar *origin_refspec,
|
||||
@ -180,3 +205,60 @@ deployment_generate_variant (OstreeDeployment *deployment,
|
||||
|
||||
return g_variant_builder_end (&builder);
|
||||
}
|
||||
|
||||
gint
|
||||
rollback_deployment_index (const gchar *name,
|
||||
OstreeSysroot *ot_sysroot,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr (GPtrArray) deployments = NULL;
|
||||
glnx_unref_object OstreeDeployment *merge_deployment = NULL;
|
||||
|
||||
gint index_to_prepend = -1;
|
||||
gint merge_index = -1;
|
||||
gint previous_index = -1;
|
||||
guint i;
|
||||
|
||||
merge_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name);
|
||||
if (merge_deployment == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No deployments found for os %s", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
deployments = ostree_sysroot_get_deployments (ot_sysroot);
|
||||
if (deployments->len < 2)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Found %u deployments, at least 2 required for rollback",
|
||||
deployments->len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_assert (merge_deployment != NULL);
|
||||
for (i = 0; i < deployments->len; i++)
|
||||
{
|
||||
if (deployments->pdata[i] == merge_deployment)
|
||||
merge_index = i;
|
||||
|
||||
if (g_strcmp0 (ostree_deployment_get_osname (deployments->pdata[i]), name) == 0 &&
|
||||
deployments->pdata[i] != merge_deployment &&
|
||||
previous_index < 0)
|
||||
{
|
||||
previous_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (merge_index < deployments->len);
|
||||
g_assert (deployments->pdata[merge_index] == merge_deployment);
|
||||
|
||||
/* If merge deployment is not booted assume we are using it. */
|
||||
if (merge_index == 0 && previous_index > 0)
|
||||
index_to_prepend = previous_index;
|
||||
else
|
||||
index_to_prepend = merge_index;
|
||||
|
||||
out:
|
||||
return index_to_prepend;
|
||||
}
|
||||
|
@ -24,8 +24,16 @@
|
||||
|
||||
char * deployment_generate_id (OstreeDeployment *deployment);
|
||||
|
||||
OstreeDeployment * deployment_get_for_id (OstreeSysroot *sysroot,
|
||||
const gchar *deploy_id);
|
||||
|
||||
char * deployment_get_refspec (OstreeDeployment *deployment);
|
||||
|
||||
GVariant * deployment_generate_blank_variant (void);
|
||||
|
||||
GVariant * deployment_generate_variant (OstreeDeployment *deployment,
|
||||
OstreeRepo *repo);
|
||||
|
||||
gint rollback_deployment_index (const gchar *name,
|
||||
OstreeSysroot *ot_sysroot,
|
||||
GError **error);
|
||||
|
@ -37,6 +37,7 @@
|
||||
<property name="BootedDeployment" type="(ssisstsav)" access="read"/>
|
||||
<property name="DefaultDeployment" type="(ssisstsav)" access="read"/>
|
||||
<property name="RollbackDeployment" type="(ssisstsav)" access="read"/>
|
||||
<property name="UpgradeOrigin" type="s" access="read"/>
|
||||
<property name="HasCachedUpdateRpmDiff" type="b" access="read"/>
|
||||
|
||||
<!-- NONE, DIFF, PREPARE, REBOOT -->
|
||||
@ -50,11 +51,11 @@
|
||||
</method>
|
||||
|
||||
<method name="GetCachedUpdateRpmDiff">
|
||||
<arg type="s" name="deployid"/>
|
||||
<arg type="a(sua{sv})" name="result" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="DownloadUpdateRpmDiff">
|
||||
<arg type="s" name="deployid"/>
|
||||
<arg type="o" name="transaction" direction="out"/>
|
||||
</method>
|
||||
|
||||
@ -74,9 +75,14 @@
|
||||
<arg type="o" name="transaction" direction="out"/>
|
||||
</method>
|
||||
|
||||
<!-- Available options:
|
||||
"skip-purge" (type 'b')
|
||||
-->
|
||||
<method name="Rebase">
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<arg type="s" name="refspec"/>
|
||||
<arg type="as" name="packages"/>
|
||||
<arg type="o" name="transaction" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="GetCachedRebaseRpmDiff">
|
||||
@ -96,17 +102,14 @@
|
||||
<interface name="org.projectatomic.rpmostree1.Transaction">
|
||||
<property name="Method" type="s" access="read"/>
|
||||
<property name="InitiatingOwner" type="s" access="read"/>
|
||||
<property name="Complete" type="b" access="read"/>
|
||||
<property name="Success" type="b" access="read"/>
|
||||
<property name="ResultMessage" type="s" access="read"/>
|
||||
|
||||
<!-- Yes, we can. -->
|
||||
<method name="Cancel">
|
||||
</method>
|
||||
|
||||
<!-- XXX Blindly mimicing UDisks2.Job for now. -->
|
||||
<signal name="Completed">
|
||||
<arg name="success" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<!-- For miscellaneous messages. -->
|
||||
<signal name="Message">
|
||||
<arg name="text" type="s" direction="out"/>
|
||||
|
869
src/daemon/os.c
869
src/daemon/os.c
File diff suppressed because it is too large
Load Diff
@ -86,7 +86,7 @@ static guint64 UPDATED_THROTTLE_SECONDS = 2;
|
||||
static guint sysroot_signals[NUM_SIGNALS] = { 0, };
|
||||
|
||||
static void sysroot_iface_init (RPMOSTreeSysrootIface *iface);
|
||||
|
||||
static gboolean _throttle_refresh (gpointer user_data);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (Sysroot, sysroot, RPMOSTREE_TYPE_SYSROOT_SKELETON,
|
||||
G_IMPLEMENT_INTERFACE (RPMOSTREE_TYPE_SYSROOT,
|
||||
@ -131,6 +131,8 @@ handle_create_osname (RPMOSTreeSysroot *object,
|
||||
GError *error = NULL;
|
||||
g_autofree gchar *dbus_path = NULL;
|
||||
|
||||
gboolean needs_refresh = FALSE;
|
||||
|
||||
Sysroot *self = SYSROOT (object);
|
||||
|
||||
if (!ostree_sysroot_ensure_initialized (self->ot_sysroot,
|
||||
@ -194,7 +196,13 @@ handle_create_osname (RPMOSTreeSysroot *object,
|
||||
|
||||
dbus_path = utils_generate_object_path (BASE_DBUS_PATH,
|
||||
osname, NULL);
|
||||
sysroot_ensure_refresh (SYSROOT (self));
|
||||
g_rw_lock_reader_lock (&self->children_lock);
|
||||
needs_refresh = self->last_monitor_event == 0;
|
||||
g_rw_lock_reader_unlock (&self->children_lock);
|
||||
|
||||
if (needs_refresh)
|
||||
_throttle_refresh (self);
|
||||
|
||||
rpmostree_sysroot_complete_create_osname (RPMOSTREE_SYSROOT (self),
|
||||
invocation,
|
||||
g_strdup (dbus_path));
|
||||
@ -213,6 +221,14 @@ handle_get_os (RPMOSTreeSysroot *object,
|
||||
Sysroot *self = SYSROOT (object);
|
||||
glnx_unref_object GDBusInterfaceSkeleton *os_interface = NULL;
|
||||
|
||||
if (arg_name[0] == '\0')
|
||||
{
|
||||
rpmostree_sysroot_complete_get_os (object,
|
||||
invocation,
|
||||
rpmostree_sysroot_dup_booted (object));
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_rw_lock_reader_lock (&self->children_lock);
|
||||
|
||||
os_interface = g_hash_table_lookup (self->os_interfaces, arg_name);
|
||||
@ -236,6 +252,7 @@ handle_get_os (RPMOSTreeSysroot *object,
|
||||
arg_name);
|
||||
}
|
||||
|
||||
out:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -530,9 +547,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static gboolean _throttle_refresh (gpointer user_data);
|
||||
|
||||
static void
|
||||
_do_reload_data (GTask *task,
|
||||
gpointer object,
|
||||
@ -564,7 +578,7 @@ _reload_callback (GObject *source_object,
|
||||
if (error)
|
||||
{
|
||||
// this was valid once, make sure it is tried again
|
||||
// TODO, should we bail at some point?
|
||||
// TODO: should we bail at some point?
|
||||
g_message ("Error refreshing sysroot data: %s", error->message);
|
||||
g_timeout_add_seconds (UPDATED_THROTTLE_SECONDS,
|
||||
_throttle_refresh,
|
||||
@ -635,22 +649,16 @@ sysroot_iface_init (RPMOSTreeSysrootIface *iface)
|
||||
|
||||
|
||||
/**
|
||||
* sysroot_ensure_refresh:
|
||||
* sysroot_emit_update:
|
||||
*
|
||||
* Ensures that the sysroot will reload it's
|
||||
* internal data.
|
||||
* Emits an sysroot-updated signal
|
||||
* requires a known up to date sysroot
|
||||
*/
|
||||
|
||||
void
|
||||
sysroot_ensure_refresh (Sysroot *self)
|
||||
sysroot_emit_update (Sysroot *self,
|
||||
OstreeSysroot *ot_sysroot)
|
||||
{
|
||||
gboolean needs_run;
|
||||
g_rw_lock_reader_lock (&self->children_lock);
|
||||
needs_run = self->last_monitor_event == 0;
|
||||
g_rw_lock_reader_unlock (&self->children_lock);
|
||||
|
||||
if (needs_run)
|
||||
_throttle_refresh (self);
|
||||
g_signal_emit (self, sysroot_signals[UPDATED], 0, ot_sysroot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define RPM_OSTREED_SYSROOT_H__
|
||||
|
||||
#include "types.h"
|
||||
#include "ostree.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -38,7 +39,9 @@ gchar * sysroot_get_sysroot_path (Sysroot *self);
|
||||
gboolean sysroot_populate (Sysroot *self,
|
||||
GError **error);
|
||||
|
||||
void sysroot_ensure_refresh (Sysroot *self);
|
||||
void sysroot_emit_update (Sysroot *self,
|
||||
OstreeSysroot *ot_sysroot);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* RPM_OSTREED_SYSROOT_H__ */
|
||||
|
267
src/daemon/transactions.c
Normal file
267
src/daemon/transactions.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "transactions.h"
|
||||
#include "errors.h"
|
||||
#include "daemon.h"
|
||||
|
||||
static guint TRANSACTION_KEEP_SECONDS = 300;
|
||||
|
||||
static gboolean
|
||||
ensure_same_caller (RPMOSTreeTransaction *transaction,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
const char *known_sender;
|
||||
const char *sender;
|
||||
|
||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
known_sender = rpmostree_transaction_get_initiating_owner (transaction);
|
||||
|
||||
if (g_strcmp0(sender, known_sender) != 0)
|
||||
{
|
||||
GError *error = g_error_new_literal (RPM_OSTREED_ERROR, RPM_OSTREED_ERROR_FAILED,
|
||||
"You are not allowed to cancel this transaction.");
|
||||
g_dbus_method_invocation_take_error (invocation, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_cancel_cb (RPMOSTreeTransaction *transaction,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GCancellable *method_cancellable)
|
||||
{
|
||||
if (!ensure_same_caller (transaction, invocation))
|
||||
goto out;
|
||||
|
||||
g_cancellable_cancel (method_cancellable);
|
||||
rpmostree_transaction_complete_cancel (transaction, invocation);
|
||||
|
||||
out:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
progress_changed_cb (OstreeAsyncProgress *progress,
|
||||
RPMOSTreeTransaction *transaction)
|
||||
{
|
||||
guint64 start_time = ostree_async_progress_get_uint64 (progress, "start-time");
|
||||
guint64 elapsed_secs = 0;
|
||||
|
||||
guint outstanding_fetches = ostree_async_progress_get_uint (progress, "outstanding-fetches");
|
||||
guint outstanding_writes = ostree_async_progress_get_uint (progress, "outstanding-writes");
|
||||
|
||||
guint n_scanned_metadata = ostree_async_progress_get_uint (progress, "scanned-metadata");
|
||||
guint metadata_fetched = ostree_async_progress_get_uint (progress, "metadata-fetched");
|
||||
guint outstanding_metadata_fetches = ostree_async_progress_get_uint (progress, "outstanding-metadata-fetches");
|
||||
|
||||
guint total_delta_parts = ostree_async_progress_get_uint (progress, "total-delta-parts");
|
||||
guint fetched_delta_parts = ostree_async_progress_get_uint (progress, "fetched-delta-parts");
|
||||
guint total_delta_superblocks = ostree_async_progress_get_uint (progress, "total-delta-superblocks");
|
||||
guint64 total_delta_part_size = ostree_async_progress_get_uint64 (progress, "total-delta-part-size");
|
||||
|
||||
guint fetched = ostree_async_progress_get_uint (progress, "fetched");
|
||||
guint requested = ostree_async_progress_get_uint (progress, "requested");
|
||||
|
||||
guint64 bytes_sec = 0;
|
||||
guint64 bytes_transferred = ostree_async_progress_get_uint64 (progress, "bytes-transferred");
|
||||
|
||||
GVariant *arg_time;
|
||||
GVariant *arg_outstanding;
|
||||
GVariant *arg_metadata;
|
||||
GVariant *arg_delta;
|
||||
GVariant *arg_content;
|
||||
GVariant *arg_transfer;
|
||||
|
||||
g_autofree gchar *status;
|
||||
|
||||
/* If there is a status that is all we output */
|
||||
status = ostree_async_progress_get_status (progress);
|
||||
if (status) {
|
||||
rpmostree_transaction_emit_message (transaction, g_strdup (status));
|
||||
return;
|
||||
}
|
||||
|
||||
if (start_time)
|
||||
{
|
||||
guint64 elapsed_secs = (g_get_monotonic_time () - start_time) / G_USEC_PER_SEC;
|
||||
if (elapsed_secs)
|
||||
bytes_sec = bytes_transferred / elapsed_secs;
|
||||
}
|
||||
|
||||
arg_time = g_variant_new ("(tt)",
|
||||
start_time,
|
||||
elapsed_secs);
|
||||
|
||||
arg_outstanding = g_variant_new ("(uu)",
|
||||
outstanding_fetches,
|
||||
outstanding_writes);
|
||||
|
||||
arg_metadata = g_variant_new ("(uuu)",
|
||||
n_scanned_metadata,
|
||||
metadata_fetched,
|
||||
outstanding_metadata_fetches);
|
||||
|
||||
arg_delta = g_variant_new ("(uuut)",
|
||||
total_delta_parts,
|
||||
fetched_delta_parts,
|
||||
total_delta_superblocks,
|
||||
total_delta_part_size);
|
||||
|
||||
arg_content = g_variant_new ("(uu)",
|
||||
fetched,
|
||||
requested);
|
||||
|
||||
arg_transfer = g_variant_new ("(tt)",
|
||||
bytes_transferred,
|
||||
bytes_sec);
|
||||
|
||||
/* This sinks the floating GVariant refs (I think...). */
|
||||
rpmostree_transaction_emit_download_progress (transaction,
|
||||
arg_time,
|
||||
arg_outstanding,
|
||||
arg_metadata,
|
||||
arg_delta,
|
||||
arg_content,
|
||||
arg_transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
gpg_verify_result_cb (OstreeRepo *repo,
|
||||
const char *checksum,
|
||||
OstreeGpgVerifyResult *result,
|
||||
RPMOSTreeTransaction *transaction)
|
||||
{
|
||||
guint n, i;
|
||||
GVariantBuilder builder;
|
||||
|
||||
if (rpmostree_transaction_get_complete (transaction))
|
||||
return;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
|
||||
|
||||
n = ostree_gpg_verify_result_count_all (result);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
g_variant_builder_add (&builder, "v",
|
||||
ostree_gpg_verify_result_get_all (result, i));
|
||||
}
|
||||
|
||||
rpmostree_transaction_emit_signature_progress (transaction,
|
||||
g_variant_builder_end (&builder),
|
||||
g_strdup (checksum));
|
||||
}
|
||||
|
||||
void
|
||||
transaction_connect_download_progress (RPMOSTreeTransaction *transaction,
|
||||
OstreeAsyncProgress *progress)
|
||||
{
|
||||
g_signal_connect_object (progress,
|
||||
"changed",
|
||||
G_CALLBACK (progress_changed_cb),
|
||||
transaction, 0);
|
||||
}
|
||||
|
||||
void
|
||||
transaction_connect_signature_progress (RPMOSTreeTransaction *transaction,
|
||||
OstreeRepo *repo)
|
||||
{
|
||||
g_signal_connect_object (repo, "gpg-verify-result",
|
||||
G_CALLBACK (gpg_verify_result_cb),
|
||||
transaction, 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
close_transaction (gpointer user_data)
|
||||
{
|
||||
RPMOSTreeTransaction *transaction = RPMOSTREE_TRANSACTION (user_data);
|
||||
const char *object_path;
|
||||
|
||||
object_path = g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON(transaction));
|
||||
|
||||
if (object_path)
|
||||
{
|
||||
daemon_unpublish (daemon_get (),
|
||||
object_path,
|
||||
transaction);
|
||||
}
|
||||
g_clear_object (&transaction);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RPMOSTreeTransaction *
|
||||
new_transaction (GDBusMethodInvocation *invocation,
|
||||
GCancellable *method_cancellable,
|
||||
GError **error)
|
||||
{
|
||||
RPMOSTreeTransaction *transaction;
|
||||
const char *method_name;
|
||||
const char *object_path;
|
||||
const char *sender;
|
||||
g_autofree gchar *child_object_path = NULL;
|
||||
|
||||
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
|
||||
|
||||
method_name = g_dbus_method_invocation_get_method_name (invocation);
|
||||
object_path = g_dbus_method_invocation_get_object_path (invocation);
|
||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
|
||||
child_object_path = g_build_path ("/", object_path, "Transaction", NULL);
|
||||
|
||||
transaction = rpmostree_transaction_skeleton_new ();
|
||||
rpmostree_transaction_set_method (transaction, method_name);
|
||||
rpmostree_transaction_set_initiating_owner (transaction, sender);
|
||||
|
||||
if (G_IS_CANCELLABLE (method_cancellable))
|
||||
{
|
||||
g_signal_connect_object (transaction,
|
||||
"handle-cancel",
|
||||
G_CALLBACK (handle_cancel_cb),
|
||||
method_cancellable, 0);
|
||||
}
|
||||
|
||||
/* Published uniquely */
|
||||
daemon_publish (daemon_get (), child_object_path, TRUE, transaction);
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
void
|
||||
complete_transaction (RPMOSTreeTransaction *transaction,
|
||||
gboolean success,
|
||||
const gchar *message)
|
||||
{
|
||||
if (message != NULL)
|
||||
rpmostree_transaction_set_result_message (transaction, message);
|
||||
|
||||
rpmostree_transaction_set_success (transaction, success);
|
||||
rpmostree_transaction_set_complete (transaction, TRUE);
|
||||
|
||||
g_timeout_add_seconds (TRANSACTION_KEEP_SECONDS,
|
||||
close_transaction,
|
||||
g_object_ref (transaction));
|
||||
}
|
39
src/daemon/transactions.h
Normal file
39
src/daemon/transactions.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostree.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
RPMOSTreeTransaction * new_transaction (GDBusMethodInvocation *invocation,
|
||||
GCancellable *method_cancellable,
|
||||
GError **error);
|
||||
|
||||
void complete_transaction (RPMOSTreeTransaction *transaction,
|
||||
gboolean success,
|
||||
const gchar *message);
|
||||
|
||||
void
|
||||
transaction_connect_download_progress (RPMOSTreeTransaction *transaction,
|
||||
OstreeAsyncProgress *progress);
|
||||
|
||||
void
|
||||
transaction_connect_signature_progress (RPMOSTreeTransaction *transaction,
|
||||
OstreeRepo *repo);
|
@ -36,4 +36,7 @@ typedef struct _Sysroot Sysroot;
|
||||
struct _OSStub;
|
||||
typedef struct _OSStub OSStub;
|
||||
|
||||
struct _Transaction;
|
||||
typedef struct _Transaction Transaction;
|
||||
|
||||
#endif /* RPM_OSTREED_TYPES_H__ */
|
||||
|
@ -18,158 +18,10 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
#include "errors.h"
|
||||
|
||||
#include "libgsystem.h"
|
||||
#include <libglnx.h>
|
||||
|
||||
static gboolean
|
||||
handle_cancel_cb (RPMOSTreeTransaction *transaction,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GCancellable *method_cancellable)
|
||||
{
|
||||
g_cancellable_cancel (method_cancellable);
|
||||
|
||||
rpmostree_transaction_complete_cancel (transaction, invocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
progress_changed_cb (OstreeAsyncProgress *progress,
|
||||
RPMOSTreeTransaction *transaction)
|
||||
{
|
||||
guint64 start_time = ostree_async_progress_get_uint64 (progress, "start-time");
|
||||
guint64 elapsed_secs = 0;
|
||||
|
||||
guint outstanding_fetches = ostree_async_progress_get_uint (progress, "outstanding-fetches");
|
||||
guint outstanding_writes = ostree_async_progress_get_uint (progress, "outstanding-writes");
|
||||
|
||||
guint n_scanned_metadata = ostree_async_progress_get_uint (progress, "scanned-metadata");
|
||||
guint metadata_fetched = ostree_async_progress_get_uint (progress, "metadata-fetched");
|
||||
guint outstanding_metadata_fetches = ostree_async_progress_get_uint (progress, "outstanding-metadata-fetches");
|
||||
|
||||
guint total_delta_parts = ostree_async_progress_get_uint (progress, "total-delta-parts");
|
||||
guint fetched_delta_parts = ostree_async_progress_get_uint (progress, "fetched-delta-parts");
|
||||
guint total_delta_superblocks = ostree_async_progress_get_uint (progress, "total-delta-superblocks");
|
||||
guint64 total_delta_part_size = ostree_async_progress_get_uint64 (progress, "total-delta-part-size");
|
||||
|
||||
guint fetched = ostree_async_progress_get_uint (progress, "fetched");
|
||||
guint requested = ostree_async_progress_get_uint (progress, "requested");
|
||||
|
||||
guint64 bytes_sec = 0;
|
||||
guint64 bytes_transferred = ostree_async_progress_get_uint64 (progress, "bytes-transferred");
|
||||
|
||||
GVariant *arg_time;
|
||||
GVariant *arg_outstanding;
|
||||
GVariant *arg_metadata;
|
||||
GVariant *arg_delta;
|
||||
GVariant *arg_content;
|
||||
GVariant *arg_transfer;
|
||||
|
||||
if (start_time)
|
||||
{
|
||||
guint64 elapsed_secs = (g_get_monotonic_time () - start_time) / G_USEC_PER_SEC;
|
||||
if (elapsed_secs)
|
||||
bytes_sec = bytes_transferred / elapsed_secs;
|
||||
}
|
||||
|
||||
arg_time = g_variant_new ("(tt)",
|
||||
start_time,
|
||||
elapsed_secs);
|
||||
|
||||
arg_outstanding = g_variant_new ("(uu)",
|
||||
outstanding_fetches,
|
||||
outstanding_writes);
|
||||
|
||||
arg_metadata = g_variant_new ("(uuu)",
|
||||
n_scanned_metadata,
|
||||
metadata_fetched,
|
||||
outstanding_metadata_fetches);
|
||||
|
||||
arg_delta = g_variant_new ("(uuut)",
|
||||
total_delta_parts,
|
||||
fetched_delta_parts,
|
||||
total_delta_superblocks,
|
||||
total_delta_part_size);
|
||||
|
||||
arg_content = g_variant_new ("(uu)",
|
||||
fetched,
|
||||
requested);
|
||||
|
||||
arg_transfer = g_variant_new ("(tt)",
|
||||
bytes_transferred,
|
||||
bytes_sec);
|
||||
|
||||
/* This sinks the floating GVariant refs (I think...). */
|
||||
rpmostree_transaction_emit_download_progress (transaction,
|
||||
arg_time,
|
||||
arg_outstanding,
|
||||
arg_metadata,
|
||||
arg_delta,
|
||||
arg_content,
|
||||
arg_transfer);
|
||||
}
|
||||
|
||||
RPMOSTreeTransaction *
|
||||
new_transaction (GDBusMethodInvocation *invocation,
|
||||
GCancellable *method_cancellable,
|
||||
OstreeAsyncProgress **out_progress,
|
||||
GError **error)
|
||||
{
|
||||
RPMOSTreeTransaction *transaction;
|
||||
GDBusConnection *connection;
|
||||
const char *method_name;
|
||||
const char *object_path;
|
||||
const char *sender;
|
||||
g_autofree gchar *child_object_path = NULL;
|
||||
|
||||
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
|
||||
|
||||
connection = g_dbus_method_invocation_get_connection (invocation);
|
||||
method_name = g_dbus_method_invocation_get_method_name (invocation);
|
||||
object_path = g_dbus_method_invocation_get_object_path (invocation);
|
||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
|
||||
child_object_path = g_build_path ("/", object_path, "Transaction", NULL);
|
||||
|
||||
transaction = rpmostree_transaction_skeleton_new ();
|
||||
rpmostree_transaction_set_method (transaction, method_name);
|
||||
rpmostree_transaction_set_initiating_owner (transaction, sender);
|
||||
|
||||
if (G_IS_CANCELLABLE (method_cancellable))
|
||||
{
|
||||
g_signal_connect_object (transaction,
|
||||
"handle-cancel",
|
||||
G_CALLBACK (handle_cancel_cb),
|
||||
method_cancellable, 0);
|
||||
}
|
||||
|
||||
if (out_progress != NULL)
|
||||
{
|
||||
OstreeAsyncProgress *progress;
|
||||
|
||||
progress = ostree_async_progress_new ();
|
||||
|
||||
g_signal_connect_object (progress,
|
||||
"changed",
|
||||
G_CALLBACK (progress_changed_cb),
|
||||
transaction, 0);
|
||||
|
||||
*out_progress = g_steal_pointer (&progress);
|
||||
}
|
||||
|
||||
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (transaction),
|
||||
connection,
|
||||
child_object_path,
|
||||
error))
|
||||
{
|
||||
g_clear_object (&transaction);
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
append_to_object_path (GString *str,
|
||||
const gchar *s)
|
||||
@ -298,7 +150,111 @@ utils_load_sysroot_and_repo (gchar *path,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
gs_transfer_out_value (out_sysroot, &ot_sysroot);
|
||||
if (out_sysroot != NULL)
|
||||
*out_sysroot = g_steal_pointer (&ot_sysroot);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* refspec_parse_partial:
|
||||
* @new_provided_refspec: The provided refspec
|
||||
* @base_refspec: The refspec string to base on.
|
||||
* @out_refspec: Pointer to the new refspec
|
||||
* @error: Pointer to an error pointer.
|
||||
*
|
||||
* Takes a refspec string and adds any missing bits based on the
|
||||
* base_refspec argument. Errors if a full valid refspec can't
|
||||
* be derived.
|
||||
*
|
||||
* Returns: True on sucess.
|
||||
*/
|
||||
gboolean
|
||||
refspec_parse_partial (const gchar *new_provided_refspec,
|
||||
gchar *base_refspec,
|
||||
gchar **out_refspec,
|
||||
GError **error)
|
||||
{
|
||||
|
||||
g_autofree gchar *ref = NULL;
|
||||
g_autofree gchar *remote = NULL;
|
||||
g_autofree gchar *origin_ref = NULL;
|
||||
g_autofree gchar *origin_remote = NULL;
|
||||
GError *parse_error = NULL;
|
||||
|
||||
gboolean ret = FALSE;
|
||||
|
||||
/* Allow just switching remotes */
|
||||
if (g_str_has_suffix (new_provided_refspec, ":"))
|
||||
{
|
||||
remote = g_strdup (new_provided_refspec);
|
||||
remote[strlen (remote) - 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ostree_parse_refspec (new_provided_refspec, &remote,
|
||||
&ref, &parse_error))
|
||||
{
|
||||
g_set_error_literal (error, RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
parse_error->message);
|
||||
g_clear_error (&parse_error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (base_refspec != NULL)
|
||||
{
|
||||
if (!ostree_parse_refspec (base_refspec, &origin_remote,
|
||||
&origin_ref, &parse_error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ref == NULL)
|
||||
{
|
||||
if (origin_ref)
|
||||
{
|
||||
ref = g_strdup (origin_ref);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
g_set_error (error, RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
"Could not determine default ref to pull.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
}
|
||||
else if (remote == NULL)
|
||||
{
|
||||
if (origin_remote)
|
||||
{
|
||||
remote = g_strdup (origin_remote);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error, RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
"Could not determine default remote to pull.");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_strcmp0 (origin_remote, remote) == 0 &&
|
||||
g_strcmp0 (origin_ref, ref) == 0)
|
||||
{
|
||||
g_set_error (error, RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
"Old and new refs are equal: %s:%s",
|
||||
remote, ref);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*out_refspec = g_strconcat (remote, ":", ref, NULL);
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
|
@ -22,11 +22,6 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
RPMOSTreeTransaction * new_transaction (GDBusMethodInvocation *invocation,
|
||||
GCancellable *method_cancellable,
|
||||
OstreeAsyncProgress **out_progress,
|
||||
GError **error);
|
||||
|
||||
gchar * utils_generate_object_path (const gchar *base,
|
||||
const gchar *part,
|
||||
...);
|
||||
@ -40,3 +35,8 @@ gboolean utils_load_sysroot_and_repo (gchar *path,
|
||||
OstreeSysroot **out_sysroot,
|
||||
OstreeRepo **out_repo,
|
||||
GError **error);
|
||||
|
||||
gboolean refspec_parse_partial (const gchar *new_provided_refspec,
|
||||
gchar *base_refspec,
|
||||
gchar **out_refspec,
|
||||
GError **error);
|
||||
|
Loading…
Reference in New Issue
Block a user