Пример #1
0
static gboolean
fsck_reachable_objects_from_commits (OstreeRepo            *repo,
                                     GHashTable            *commits,
                                     gboolean              *out_found_corruption,
                                     GCancellable          *cancellable,
                                     GError               **error)
{
  gboolean ret = FALSE;
  GHashTableIter hash_iter;
  gpointer key, value;
  gs_unref_hashtable GHashTable *reachable_objects = 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_union (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, out_found_corruption,
                                     cancellable, error))
        goto out;

      if (mod == 0 || (i % mod == 0))
        g_print ("%u/%u objects\n", i, count);
      i++;
    }

  ret = TRUE;
 out:
  return ret;
}
Пример #2
0
static gboolean
fsck_reachable_objects_from_commits (OstreeRepo            *repo,
                                     GHashTable            *commits,
                                     gboolean              *out_found_corruption,
                                     GCancellable          *cancellable,
                                     GError               **error)
{
  g_autoptr(GHashTable) reachable_objects = ostree_repo_traverse_new_reachable ();
  g_autoptr(GHashTable) object_parents = ostree_repo_traverse_new_parents ();

  GHashTableIter hash_iter;
  gpointer key, value;
  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_union_with_parents (repo, checksum, 0, reachable_objects, object_parents,
                                                           cancellable, error))
        return FALSE;
    }

  g_auto(GLnxConsoleRef) console = { 0, };
  glnx_console_lock (&console);

  const guint count = g_hash_table_size (reachable_objects);
  guint 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 (!fsck_one_object (repo, checksum, objtype,
                            object_parents, serialized_key,
                            out_found_corruption, cancellable, error))
        return FALSE;

      i++;
      glnx_console_progress_n_items ("fsck objects", i, count);
    }

  return TRUE;
}
Пример #3
0
static GHashTable *
reachable_set_intersect (GHashTable *a, GHashTable *b)
{
  GHashTable *ret = ostree_repo_traverse_new_reachable ();
  GHashTableIter hashiter;
  gpointer key, value;

  g_hash_table_iter_init (&hashiter, a);
  while (g_hash_table_iter_next (&hashiter, &key, &value))
    {
      GVariant *v = key;
      if (g_hash_table_contains (b, v))
        g_hash_table_insert (ret, g_variant_ref (v), v);
    }

  return ret;
}
Пример #4
0
/**
 * ostree_repo_traverse_commit:
 * @repo: Repo
 * @commit_checksum: ASCII SHA256 checksum
 * @maxdepth: Traverse this many parent commits, -1 for unlimited
 * @out_reachable: (out) (transfer container) (element-type GVariant GVariant): Set of reachable objects
 * @cancellable: Cancellable
 * @error: Error
 *
 * Create a new set @out_reachable containing all objects reachable
 * from @commit_checksum, traversing @maxdepth parent commits.
 */
gboolean
ostree_repo_traverse_commit (OstreeRepo      *repo,
                             const char      *commit_checksum,
                             int              maxdepth,
                             GHashTable     **out_reachable,
                             GCancellable    *cancellable,
                             GError         **error)
{
  gboolean ret = FALSE;
  g_autoptr(GHashTable) ret_reachable =
    ostree_repo_traverse_new_reachable ();

  if (!ostree_repo_traverse_commit_union (repo, commit_checksum, maxdepth,
                                          ret_reachable, cancellable, error))
    goto out;

  ret = TRUE;
  gs_transfer_out_value (out_reachable, &ret_reachable);
 out:
  return ret;
}
Пример #5
0
/**
 * ostree_repo_prune:
 * @self: Repo
 * @flags: Options controlling prune process
 * @depth: Stop traversal after this many iterations (-1 for unlimited)
 * @out_objects_total: (out): Number of objects found
 * @out_objects_pruned: (out): Number of objects deleted
 * @out_pruned_object_size_total: (out): Storage size in bytes of objects deleted
 * @cancellable: Cancellable
 * @error: Error
 *
 * Delete content from the repository.  By default, this function will
 * only delete "orphaned" objects not referred to by any commit.  This
 * can happen during a local commit operation, when we have written
 * content objects but not saved the commit referencing them.
 *
 * However, if %OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY is provided, instead
 * of traversing all commits, only refs will be used.  Particularly
 * when combined with @depth, this is a convenient way to delete
 * history from the repository.
 * 
 * Use the %OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE to just determine
 * statistics on objects that would be deleted, without actually
 * deleting them.
 */
gboolean
ostree_repo_prune (OstreeRepo        *self,
                   OstreeRepoPruneFlags   flags,
                   gint               depth,
                   gint              *out_objects_total,
                   gint              *out_objects_pruned,
                   guint64           *out_pruned_object_size_total,
                   GCancellable      *cancellable,
                   GError           **error)
{
  GHashTableIter hash_iter;
  gpointer key, value;
  g_autoptr(GHashTable) objects = NULL;
  g_autoptr(GHashTable) all_refs = NULL;
  g_autoptr(GHashTable) reachable = NULL;
  gboolean refs_only = flags & OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY;

  reachable = ostree_repo_traverse_new_reachable ();

  /* This original prune API has fixed logic for traversing refs or all commits
   * combined with actually deleting content. The newer backend API just does
   * the deletion.
   */

  if (refs_only)
    {
      if (!ostree_repo_list_refs (self, NULL, &all_refs,
                                  cancellable, error))
        return FALSE;

      g_hash_table_iter_init (&hash_iter, all_refs);

      while (g_hash_table_iter_next (&hash_iter, &key, &value))
        {
          const char *checksum = value;

          g_debug ("Finding objects to keep for commit %s", checksum);
          if (!ostree_repo_traverse_commit_union (self, checksum, depth, reachable,
                                                  cancellable, error))
            return FALSE;
        }
    }

  if (!ostree_repo_list_objects (self, OSTREE_REPO_LIST_OBJECTS_ALL | OSTREE_REPO_LIST_OBJECTS_NO_PARENTS,
                                 &objects, cancellable, error))
    return FALSE;

  if (!refs_only)
    {
      g_hash_table_iter_init (&hash_iter, 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 (objtype != OSTREE_OBJECT_TYPE_COMMIT)
            continue;

          g_debug ("Finding objects to keep for commit %s", checksum);
          if (!ostree_repo_traverse_commit_union (self, checksum, depth, reachable,
                                                  cancellable, error))
            return FALSE;
        }
    }

  { OstreeRepoPruneOptions opts = { flags, reachable };
    return repo_prune_internal (self, objects, &opts,
                                out_objects_total, out_objects_pruned,
                                out_pruned_object_size_total, cancellable, error);
  }
}