[ostree] lib: Add ostree_sysroot_load_if_changed() API



commit fea786cb2d086865d83797c842d89b7352b27527
Author: Colin Walters <walters verbum org>
Date:   Thu Mar 3 13:49:54 2016 -0500

    lib: Add ostree_sysroot_load_if_changed() API
    
    This will allow daemons like rpm-ostree to detect if there are any new
    deployments efficiently, in combination with using inotify.  If there
    are any changes, rpm-ostree wants publish them on DBus.
    
    While we're here, add some changes to start doing unit C testing of
    the sysroot API.

 Makefile-tests.am                      |    5 ++-
 apidoc/ostree-sections.txt             |    1 +
 src/libostree/libostree.sym            |    1 +
 src/libostree/ostree-sysroot-private.h |    1 +
 src/libostree/ostree-sysroot.c         |   40 ++++++++++++--
 src/libostree/ostree-sysroot.h         |    6 ++
 tests/libostreetest.c                  |   34 ++++++++++--
 tests/libostreetest.h                  |   12 ++---
 tests/test-basic-c.c                   |   11 ++--
 tests/test-sysroot-c.c                 |   92 ++++++++++++++++++++++++++++++++
 10 files changed, 179 insertions(+), 24 deletions(-)
---
diff --git a/Makefile-tests.am b/Makefile-tests.am
index 61b9b66..34bbb44 100644
--- a/Makefile-tests.am
+++ b/Makefile-tests.am
@@ -122,7 +122,7 @@ libreaddir_rand_la_LDFLAGS = -avoid-version
 test_programs = tests/test-varint tests/test-ot-unix-utils tests/test-bsdiff tests/test-mutable-tree \
        tests/test-keyfile-utils tests/test-ot-opt-utils tests/test-ot-tool-util \
        tests/test-gpg-verify-result tests/test-checksum tests/test-lzma tests/test-rollsum \
-       tests/test-basic-c
+       tests/test-basic-c tests/test-sysroot-c
 
 # An interactive tool
 noinst_PROGRAMS += tests/test-rollsum-cli
@@ -156,6 +156,9 @@ tests_test_mutable_tree_LDADD = $(TESTS_LDADD)
 tests_test_basic_c_CFLAGS = $(TESTS_CFLAGS)
 tests_test_basic_c_LDADD = $(TESTS_LDADD)
 
+tests_test_sysroot_c_CFLAGS = $(TESTS_CFLAGS)
+tests_test_sysroot_c_LDADD = $(TESTS_LDADD)
+
 tests_test_ot_unix_utils_CFLAGS = $(TESTS_CFLAGS)
 tests_test_ot_unix_utils_LDADD = $(TESTS_LDADD)
 
diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt
index ee4ba1c..87c138d 100644
--- a/apidoc/ostree-sections.txt
+++ b/apidoc/ostree-sections.txt
@@ -381,6 +381,7 @@ ostree_sysroot_new
 ostree_sysroot_new_default
 ostree_sysroot_get_path
 ostree_sysroot_load
+ostree_sysroot_load_if_changed
 ostree_sysroot_lock
 ostree_sysroot_try_lock
 ostree_sysroot_lock_async
diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym
index 0335017..a85f0db 100644
--- a/src/libostree/libostree.sym
+++ b/src/libostree/libostree.sym
@@ -317,4 +317,5 @@ global:
         ostree_repo_get_dfd;
         ostree_repo_list_refs_ext;
         ostree_sysroot_init_osname;
+        ostree_sysroot_load_if_changed;
 } LIBOSTREE_2016.3;
diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h
index 356509a..229893d 100644
--- a/src/libostree/ostree-sysroot-private.h
+++ b/src/libostree/ostree-sysroot-private.h
@@ -49,6 +49,7 @@ struct OstreeSysroot {
   int bootversion;
   int subbootversion;
   OstreeDeployment *booted_deployment;
+  struct timespec loaded_ts;
 
   /* Only access through ostree_sysroot_get_repo() */
   OstreeRepo *repo;
diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c
index eb2b353..b122040 100644
--- a/src/libostree/ostree-sysroot.c
+++ b/src/libostree/ostree-sysroot.c
@@ -794,18 +794,23 @@ ostree_sysroot_load (OstreeSysroot  *self,
                      GCancellable   *cancellable,
                      GError        **error)
 {
+  return ostree_sysroot_load_if_changed (self, NULL, cancellable, error);
+}
+
+gboolean
+ostree_sysroot_load_if_changed (OstreeSysroot  *self,
+                                gboolean       *out_changed,
+                                GCancellable   *cancellable,
+                                GError        **error)
+{
   gboolean ret = FALSE;
   guint i;
   int bootversion = 0;
   int subbootversion = 0;
+  struct stat stbuf;
   g_autoptr(GPtrArray) boot_loader_configs = NULL;
   g_autoptr(GPtrArray) deployments = NULL;
 
-  g_clear_pointer (&self->deployments, g_ptr_array_unref);
-  g_clear_pointer (&self->booted_deployment, g_object_unref);
-  self->bootversion = -1;
-  self->subbootversion = -1;
-
   if (!ensure_sysroot_fd (self, error))
     goto out;
 
@@ -816,6 +821,28 @@ ostree_sysroot_load (OstreeSysroot  *self,
                                                     cancellable, error))
     goto out;
 
+  if (fstatat (self->sysroot_fd, "ostree/deploy", &stbuf, 0) < 0)
+    {
+      glnx_set_error_from_errno (error);
+      goto out;
+    }
+
+  if (out_changed)
+    {
+      if (self->loaded_ts.tv_sec == stbuf.st_mtim.tv_sec &&
+          self->loaded_ts.tv_nsec == stbuf.st_mtim.tv_nsec)
+        {
+          *out_changed = FALSE;
+          ret = TRUE;
+          goto out;
+        }
+    }
+
+  g_clear_pointer (&self->deployments, g_ptr_array_unref);
+  g_clear_pointer (&self->booted_deployment, g_object_unref);
+  self->bootversion = -1;
+  self->subbootversion = -1;
+
   if (!_ostree_sysroot_read_boot_loader_configs (self, bootversion, &boot_loader_configs,
                                                  cancellable, error))
     goto out;
@@ -847,8 +874,11 @@ ostree_sysroot_load (OstreeSysroot  *self,
   self->deployments = deployments;
   deployments = NULL; /* Transfer ownership */
   self->loaded = TRUE;
+  self->loaded_ts = stbuf.st_mtim;
 
   ret = TRUE;
+  if (out_changed)
+    *out_changed = TRUE;
  out:
   return ret;
 }
diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h
index cab59d0..077862a 100644
--- a/src/libostree/ostree-sysroot.h
+++ b/src/libostree/ostree-sysroot.h
@@ -52,6 +52,12 @@ gboolean ostree_sysroot_load (OstreeSysroot  *self,
                               GError        **error);
 
 _OSTREE_PUBLIC
+gboolean ostree_sysroot_load_if_changed (OstreeSysroot  *self,
+                                         gboolean       *out_changed,
+                                         GCancellable   *cancellable,
+                                         GError        **error);
+
+_OSTREE_PUBLIC
 void ostree_sysroot_unload (OstreeSysroot  *self);
 
 _OSTREE_PUBLIC
diff --git a/tests/libostreetest.c b/tests/libostreetest.c
index 9ebebde..5828336 100644
--- a/tests/libostreetest.c
+++ b/tests/libostreetest.c
@@ -60,23 +60,45 @@ run_libtest (const char *cmd, GError **error)
   return ret;
 }
 
-gboolean
-ot_test_setup_repo (OtTest *self,
-                    GCancellable *cancellable,
+OstreeRepo *
+ot_test_setup_repo (GCancellable *cancellable,
                     GError **error)
 {
   gboolean ret = FALSE;
   g_autoptr(GFile) repo_path = g_file_new_for_path ("repo");
+  glnx_unref_object OstreeRepo* ret_repo = NULL;
 
   if (!run_libtest ("setup_test_repository", error))
     goto out;
 
-  self->repo = ostree_repo_new (repo_path);
+  ret_repo = ostree_repo_new (repo_path);
 
-  if (!ostree_repo_open (self->repo, cancellable, error))
+  if (!ostree_repo_open (ret_repo, cancellable, error))
     goto out;
 
   ret = TRUE;
  out:
-  return ret;
+  if (ret)
+    return g_steal_pointer (&ret_repo);
+  return NULL;
+}
+
+OstreeSysroot *
+ot_test_setup_sysroot (GCancellable *cancellable,
+                       GError **error)
+{
+  gboolean ret = FALSE;
+  g_autoptr(GFile) sysroot_path = g_file_new_for_path ("sysroot");
+  glnx_unref_object OstreeSysroot *ret_sysroot = NULL;
+
+  if (!run_libtest ("setup_os_repository \"archive-z2\" \"syslinux\"", error))
+    goto out;
+
+  ret_sysroot = ostree_sysroot_new (sysroot_path);
+
+  ret = TRUE;
+ out:
+  if (ret)
+    return g_steal_pointer (&ret_sysroot);
+  return NULL;
 }
diff --git a/tests/libostreetest.h b/tests/libostreetest.h
index 2ab9348..eb9bb0b 100644
--- a/tests/libostreetest.h
+++ b/tests/libostreetest.h
@@ -27,13 +27,11 @@
 
 G_BEGIN_DECLS
 
-typedef struct {
-  OstreeRepo *repo;
-  GSubprocess *shell;
-} OtTest;
 
-gboolean ot_test_setup_repo (OtTest *self,
-                             GCancellable *cancellable,
-                             GError **error);
+OstreeRepo *ot_test_setup_repo (GCancellable *cancellable,
+                                GError **error);
+
+OstreeSysroot *ot_test_setup_sysroot (GCancellable *cancellable,
+                                      GError **error);
 
 G_END_DECLS
diff --git a/tests/test-basic-c.c b/tests/test-basic-c.c
index e0bcf9f..d5dcc81 100644
--- a/tests/test-basic-c.c
+++ b/tests/test-basic-c.c
@@ -30,21 +30,22 @@
 static void
 test_repo_is_not_system (gconstpointer data)
 {
-  OtTest *self = (void*)data;
-  g_assert (!ostree_repo_is_system (self->repo));
+  OstreeRepo *repo = (void*)data;
+  g_assert (!ostree_repo_is_system (repo));
 }
 
 int main (int argc, char **argv)
 {
   g_autoptr(GError) error = NULL;
-  OtTest selfd = {NULL,};
+  glnx_unref_object OstreeRepo *repo = NULL;
 
   g_test_init (&argc, &argv, NULL);
 
-  if (!ot_test_setup_repo (&selfd, NULL, &error))
+  repo = ot_test_setup_repo (NULL, &error); 
+  if (!repo)
     goto out;
   
-  g_test_add_data_func ("/repo-not-system", &selfd, test_repo_is_not_system);
+  g_test_add_data_func ("/repo-not-system", repo, test_repo_is_not_system);
 
   return g_test_run();
  out:
diff --git a/tests/test-sysroot-c.c b/tests/test-sysroot-c.c
new file mode 100644
index 0000000..9c07faf
--- /dev/null
+++ b/tests/test-sysroot-c.c
@@ -0,0 +1,92 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <gio/gio.h>
+#include <string.h>
+
+#include "libglnx.h"
+#include "libostreetest.h"
+
+static gboolean
+run_sync (const char *cmdline, GError **error)
+{
+  int estatus;
+  if (!g_spawn_command_line_sync (cmdline, NULL, NULL, &estatus, error))
+    return FALSE;
+  if (!g_spawn_check_exit_status (estatus, error))
+    return FALSE;
+  return TRUE;
+}
+
+static void
+test_sysroot_reload (gconstpointer data)
+{
+  OstreeSysroot *sysroot = (void*)data;
+  g_autoptr(GError) error = NULL;
+  gboolean changed;
+
+  if (!ostree_sysroot_load (sysroot, NULL, &error))
+    goto out;
+
+  if (!ostree_sysroot_load_if_changed (sysroot, &changed, NULL, &error))
+    goto out;
+  g_assert (!changed);
+
+  if (!run_sync ("ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo 
testos/buildmaster/x86_64-runtime", &error))
+    goto out;
+
+  if (!run_sync ("ostree admin --sysroot=sysroot deploy --karg=root=LABEL=MOO --karg=quiet --os=testos 
testos:testos/buildmaster/x86_64-runtime", &error))
+    goto out;
+
+  if (!ostree_sysroot_load_if_changed (sysroot, &changed, NULL, &error))
+    goto out;
+  g_assert (changed);
+
+  if (!ostree_sysroot_load_if_changed (sysroot, &changed, NULL, &error))
+    goto out;
+  g_assert (!changed);
+
+ out:
+  if (error)
+    g_error ("%s", error->message);
+}
+
+int main (int argc, char **argv)
+{
+  g_autoptr(GError) error = NULL;
+  glnx_unref_object OstreeSysroot *sysroot = NULL;
+
+  g_test_init (&argc, &argv, NULL);
+
+  sysroot = ot_test_setup_sysroot (NULL, &error); 
+  if (!sysroot)
+    goto out;
+  
+  g_test_add_data_func ("/sysroot-reload", sysroot, test_sysroot_reload);
+
+  return g_test_run();
+ out:
+  if (error)
+    g_error ("%s", error->message);
+  return 1;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]