From 8ec7d6322fe004a93a1b391c279020c5411996c0 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 23 Oct 2019 09:12:08 -0600 Subject: [PATCH] lib/commit: Fix object sizes metadata for multiple commits The object sizes hash table was only being cleared when the repo was finalized. That means that performing multiple commits while the repo was open would reuse all the object sizes metadata for each commit. Clear the hash table when the sizes metadata is setup and when it's added to a commit. This still does not fix the issue all the way since it does nothing to prevent the program from constructing multiple commits simultaneously. To handle that, the object sizes hash table should be attached to the MutableTree since that has the commit state. However, the MutableTree is gone when the commit is actually created. The hash table would have to be transferred to the root file when writing the MutableTree. That would be an awkward addition to OstreeRepoFile, though. Add a FIXME to capture that. --- src/libostree/ostree-repo-commit.c | 11 ++++++++++- src/libostree/ostree-repo-private.h | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 8f059e11..752a01be 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -352,7 +352,13 @@ repo_setup_generate_sizes (OstreeRepo *self, if (modifier && modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES) { if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE) - self->generate_sizes = TRUE; + { + self->generate_sizes = TRUE; + + /* Clear any stale data in the object sizes hash table */ + if (self->object_sizes != NULL) + g_hash_table_remove_all (self->object_sizes); + } else g_debug ("Not generating sizes for non-archive repo"); } @@ -428,6 +434,9 @@ add_size_index_to_metadata (OstreeRepo *self, g_variant_builder_add (builder, "{sv}", "ostree.sizes", g_variant_builder_end (&index_builder)); + + /* Clear the object sizes hash table for a subsequent commit. */ + g_hash_table_remove_all (self->object_sizes); } return g_variant_ref_sink (g_variant_builder_end (builder)); diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index b57ad799..bc2325e5 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -143,6 +143,14 @@ struct OstreeRepo { guint zlib_compression_level; GHashTable *loose_object_devino_hash; GHashTable *updated_uncompressed_dirs; + + /* FIXME: The object sizes hash table is really per-commit state, not repo + * state. Using a single table for the repo means that commits cannot be + * built simultaneously if they're adding size information. This data should + * probably be in OstreeMutableTree, but that's gone by the time the actual + * commit is constructed. At that point the only commit state is in the root + * OstreeRepoFile. + */ GHashTable *object_sizes; /* Cache the repo's device/inode to use for comparisons elsewhere */