[ostree] main: Clean up fsck code: honor --quiet, warn (but continue) on missing objects



commit c8801ae48915d23117096757fffcad73f4279115
Author: Colin Walters <walters verbum org>
Date:   Thu Jul 18 09:05:58 2013 -0400

    main: Clean up fsck code: honor --quiet, warn (but continue) on missing objects
    
    When we make fsck --delete work again, it will be convenient to
    continue on missing objects.

 src/ostree/ot-builtin-fsck.c |  197 +++++++++++++++++++++++++-----------------
 1 files changed, 119 insertions(+), 78 deletions(-)
---
diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c
index 77fe795..7610729 100644
--- a/src/ostree/ot-builtin-fsck.c
+++ b/src/ostree/ot-builtin-fsck.c
@@ -25,79 +25,50 @@
 #include "ot-builtins.h"
 #include "ostree.h"
 
-static gboolean quiet;
-static gboolean delete;
+static gboolean opt_quiet;
+static gboolean opt_delete;
 
 static GOptionEntry options[] = {
-  { "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet, "Don't display informational messages", NULL },
-  { "delete", 0, 0, G_OPTION_ARG_NONE, &delete, "Remove corrupted objects", NULL },
+  { "quiet", 'q', 0, G_OPTION_ARG_NONE, &opt_quiet, "Only print error messages", NULL },
+  { "delete", 0, 0, G_OPTION_ARG_NONE, &opt_delete, "Remove corrupted objects", NULL },
   { NULL }
 };
 
-typedef struct {
-  OstreeRepo *repo;
-} OtFsckData;
-
 static gboolean
-fsck_reachable_objects_from_commits (OtFsckData            *data,
-                                     GHashTable            *commits,
-                                     GCancellable          *cancellable,
-                                     GError               **error)
+load_and_fsck_one_object (OstreeRepo            *repo,
+                          const char            *checksum,
+                          OstreeObjectType       objtype,
+                          GCancellable          *cancellable,
+                          GError               **error)
 {
   gboolean ret = FALSE;
-  GHashTableIter hash_iter;
-  gpointer key, value;
-  gs_unref_hashtable GHashTable *reachable_objects = NULL;
+  gboolean missing = FALSE;
+  gs_unref_variant GVariant *metadata = NULL;
   gs_unref_object GInputStream *input = NULL;
   gs_unref_object GFileInfo *file_info = NULL;
   gs_unref_variant GVariant *xattrs = NULL;
-  gs_unref_variant GVariant *metadata = NULL;
-  gs_free guchar *computed_csum = NULL;
-  gs_free char *tmp_checksum = NULL;
+  GError *temp_error = NULL;
 
-  reachable_objects = ostree_repo_traverse_new_reachable ();
-
-  g_hash_table_iter_init (&hash_iter, commits);
-  while (g_hash_table_iter_next (&hash_iter, &key, &value))
+  if (OSTREE_OBJECT_TYPE_IS_META (objtype))
     {
-      GVariant *serialized_key = key;
-      const char *checksum;
-      OstreeObjectType objtype;
-
-      ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
-
-      g_assert (objtype == OSTREE_OBJECT_TYPE_COMMIT);
-
-      if (!ostree_repo_traverse_commit (data->repo, checksum, 0, reachable_objects,
-                                        cancellable, error))
-        goto out;
-    }
-
-  g_hash_table_iter_init (&hash_iter, reachable_objects);
-  while (g_hash_table_iter_next (&hash_iter, &key, &value))
-    {
-      GVariant *serialized_key = key;
-      const char *checksum;
-      OstreeObjectType objtype;
-
-      ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
-
-      g_clear_object (&input);
-      g_clear_object (&file_info);
-      g_clear_pointer (&xattrs, (GDestroyNotify) g_variant_unref);
-
-      if (objtype == OSTREE_OBJECT_TYPE_COMMIT
-          || objtype == OSTREE_OBJECT_TYPE_DIR_TREE 
-          || objtype == OSTREE_OBJECT_TYPE_DIR_META)
+      if (!ostree_repo_load_variant (repo, objtype,
+                                     checksum, &metadata, &temp_error))
         {
-          g_clear_pointer (&metadata, (GDestroyNotify) g_variant_unref);
-          if (!ostree_repo_load_variant (data->repo, objtype,
-                                         checksum, &metadata, error))
+          if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+            {
+              g_clear_error (&temp_error);
+              g_printerr ("Object missing: %s.%s\n", checksum,
+                          ostree_object_type_to_string (objtype));
+              missing = TRUE;
+            }
+          else
             {
               g_prefix_error (error, "Loading metadata object %s: ", checksum);
               goto out;
             }
-
+        }
+      else
+        {
           if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
             {
               if (!ostree_validate_structureof_commit (metadata, error))
@@ -122,23 +93,35 @@ fsck_reachable_objects_from_commits (OtFsckData            *data,
                   goto out;
                 }
             }
-          else
-            g_assert_not_reached ();
-          
+      
           input = g_memory_input_stream_new_from_data (g_variant_get_data (metadata),
                                                        g_variant_get_size (metadata),
                                                        NULL);
+
         }
-      else if (objtype == OSTREE_OBJECT_TYPE_FILE)
+    }
+  else
+    {
+      guint32 mode;
+      g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
+      if (!ostree_repo_load_file (repo, checksum, &input, &file_info,
+                                  &xattrs, cancellable, &temp_error))
         {
-          guint32 mode;
-          if (!ostree_repo_load_file (data->repo, checksum, &input, &file_info,
-                                      &xattrs, cancellable, error))
+          if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+            {
+              g_clear_error (&temp_error);
+              g_printerr ("Object missing: %s.%s\n", checksum,
+                          ostree_object_type_to_string (objtype));
+              missing = TRUE;
+            }
+          else
             {
               g_prefix_error (error, "Loading file object %s: ", checksum);
               goto out;
             }
-
+        }
+      else
+        {
           mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
           if (!ostree_validate_structureof_file_mode (mode, error))
             {
@@ -146,18 +129,18 @@ fsck_reachable_objects_from_commits (OtFsckData            *data,
               goto out;
             }
         }
-      else
-        {
-          g_assert_not_reached ();
-        }
+    }
+
+  if (!missing)
+    {
+      gs_free guchar *computed_csum = NULL;
+      gs_free char *tmp_checksum = NULL;
 
-      g_free (computed_csum);
       if (!ostree_checksum_file_from_input (file_info, xattrs, input,
                                             objtype, &computed_csum,
                                             cancellable, error))
         goto out;
-
-      g_free (tmp_checksum);
+      
       tmp_checksum = ostree_checksum_from_bytes (computed_csum);
       if (strcmp (checksum, tmp_checksum) != 0)
         {
@@ -174,12 +157,71 @@ fsck_reachable_objects_from_commits (OtFsckData            *data,
   return ret;
 }
 
+static gboolean
+fsck_reachable_objects_from_commits (OstreeRepo            *repo,
+                                     GHashTable            *commits,
+                                     GCancellable          *cancellable,
+                                     GError               **error)
+{
+  gboolean ret = FALSE;
+  GHashTableIter hash_iter;
+  gpointer key, value;
+  gs_unref_hashtable GHashTable *reachable_objects = NULL;
+  gs_unref_variant GVariant *metadata = NULL;
+  gs_free guchar *computed_csum = NULL;
+  guint i;
+  guint mod;
+  guint count;
+
+  reachable_objects = ostree_repo_traverse_new_reachable ();
+
+  g_hash_table_iter_init (&hash_iter, commits);
+  while (g_hash_table_iter_next (&hash_iter, &key, &value))
+    {
+      GVariant *serialized_key = key;
+      const char *checksum;
+      OstreeObjectType objtype;
+
+      ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
+
+      g_assert (objtype == OSTREE_OBJECT_TYPE_COMMIT);
+
+      if (!ostree_repo_traverse_commit (repo, checksum, 0, reachable_objects,
+                                        cancellable, error))
+        goto out;
+    }
+
+  count = g_hash_table_size (reachable_objects);
+  mod = count / 10;
+  i = 0;
+  g_hash_table_iter_init (&hash_iter, reachable_objects);
+  while (g_hash_table_iter_next (&hash_iter, &key, &value))
+    {
+      GVariant *serialized_key = key;
+      const char *checksum;
+      OstreeObjectType objtype;
+
+      ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
+
+      if (!load_and_fsck_one_object (repo, checksum, objtype,
+                                     cancellable, error))
+        goto out;
+
+      if (i % mod == 0)
+        g_print ("%u/%u objects\n", i, count);
+      i++;
+    }
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
 gboolean
 ostree_builtin_fsck (int argc, char **argv, GFile *repo_path, GCancellable *cancellable, GError **error)
 {
   gboolean ret = FALSE;
   GOptionContext *context;
-  OtFsckData data;
   GHashTableIter hash_iter;
   gpointer key, value;
   gs_unref_object OstreeRepo *repo = NULL;
@@ -196,10 +238,8 @@ ostree_builtin_fsck (int argc, char **argv, GFile *repo_path, GCancellable *canc
   if (!ostree_repo_check (repo, error))
     goto out;
 
-  memset (&data, 0, sizeof (data));
-  data.repo = repo;
-
-  g_print ("Enumerating objects...\n");
+  if (!opt_quiet)
+    g_print ("Enumerating objects...\n");
 
   if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL,
                                  &objects, cancellable, error))
@@ -224,10 +264,11 @@ ostree_builtin_fsck (int argc, char **argv, GFile *repo_path, GCancellable *canc
 
   g_clear_pointer (&objects, (GDestroyNotify) g_hash_table_unref);
 
-  g_print ("Verifying content integrity of %u commit objects...\n",
-           (guint)g_hash_table_size (commits));
+  if (!opt_quiet)
+    g_print ("Verifying content integrity of %u commit objects...\n",
+             (guint)g_hash_table_size (commits));
 
-  if (!fsck_reachable_objects_from_commits (&data, commits, cancellable, error))
+  if (!fsck_reachable_objects_from_commits (repo, commits, cancellable, error))
     goto out;
 
   ret = TRUE;


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