diff options
author | Colin Walters <walters@verbum.org> | 2013-09-30 08:51:25 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2013-09-30 08:51:25 -0400 |
commit | 7b119370a2ea972965a4a5ad391d4619db6cb121 (patch) | |
tree | 4999bd0bad1a1cb0e77efb348951f99f2c76bfed | |
parent | 8592922c2c377d1b5d96aecf5ef840a0471d528f (diff) | |
download | ostree-7b119370a2ea972965a4a5ad391d4619db6cb121.tar.gz |
repo: Enumerate objects using openat() too, make more efficient
This drops several calls to malloc()/g_object_new() per object
enumeration. Just a followup to using openat() and friends in other
places.
-rw-r--r-- | src/libostree/ostree-repo.c | 103 |
1 files changed, 52 insertions, 51 deletions
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index f8738a88..ebc10f28 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -670,72 +670,59 @@ _ostree_repo_get_loose_object_dirs (OstreeRepo *self, } static gboolean -list_loose_object_dir (OstreeRepo *self, - GFile *dir, +list_loose_objects_at (OstreeRepo *self, GHashTable *inout_objects, + const char *prefix, + int dfd, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; - const char *dirname = NULL; - const char *dot = NULL; - gs_unref_object GFileEnumerator *enumerator = NULL; - GString *checksum = NULL; - - dirname = gs_file_get_basename_cached (dir); + DIR *d = NULL; + struct dirent *dent; - /* We're only querying name */ - enumerator = g_file_enumerate_children (dir, "standard::name,standard::type", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, - error); - if (!enumerator) - goto out; + d = fdopendir (dfd); + if (!d) + { + ot_util_set_error_from_errno (error, errno); + goto out; + } - while (TRUE) + while ((dent = readdir (d)) != NULL) { - GFileInfo *file_info; - const char *name; - guint32 type; + const char *name = dent->d_name; + const char *dot; OstreeObjectType objtype; + char buf[65]; - if (!gs_file_enumerator_iterate (enumerator, &file_info, NULL, - NULL, error)) - goto out; - if (file_info == NULL) - break; - - type = g_file_info_get_attribute_uint32 (file_info, "standard::type"); - - if (type == G_FILE_TYPE_DIRECTORY) + if (strcmp (name, ".") == 0 || + strcmp (name, "..") == 0) continue; - name = g_file_info_get_attribute_byte_string (file_info, "standard::name"); + dot = strrchr (name, '.'); + if (!dot) + continue; - if (g_str_has_suffix (name, ".file")) + if (strcmp (dot, ".file") == 0) objtype = OSTREE_OBJECT_TYPE_FILE; - else if (g_str_has_suffix (name, ".dirtree")) + else if (strcmp (dot, ".dirtree") == 0) objtype = OSTREE_OBJECT_TYPE_DIR_TREE; - else if (g_str_has_suffix (name, ".dirmeta")) + else if (strcmp (dot, ".dirmeta") == 0) objtype = OSTREE_OBJECT_TYPE_DIR_META; - else if (g_str_has_suffix (name, ".commit")) + else if (strcmp (dot, ".commit") == 0) objtype = OSTREE_OBJECT_TYPE_COMMIT; else continue; - dot = strrchr (name, '.'); - g_assert (dot); - if ((dot - name) == 62) { GVariant *key, *value; - if (checksum) - g_string_free (checksum, TRUE); - checksum = g_string_new (dirname); - g_string_append_len (checksum, name, 62); + memcpy (buf, prefix, 2); + memcpy (buf + 2, name, 62); + buf[sizeof(buf)-1] = '\0'; - key = ostree_object_name_serialize (checksum->str, objtype); + key = ostree_object_name_serialize (buf, objtype); value = g_variant_new ("(b@as)", TRUE, g_variant_new_strv (NULL, 0)); /* transfer ownership */ @@ -746,8 +733,8 @@ list_loose_object_dir (OstreeRepo *self, ret = TRUE; out: - if (checksum) - g_string_free (checksum, TRUE); + if (d) + (void) closedir (d); return ret; } @@ -758,16 +745,30 @@ list_loose_objects (OstreeRepo *self, GError **error) { gboolean ret = FALSE; - guint i; - gs_unref_ptrarray GPtrArray *object_dirs = NULL; - - if (!_ostree_repo_get_loose_object_dirs (self, &object_dirs, cancellable, error)) - goto out; + guint c; + int dfd = -1; + static const gchar hexchars[] = "0123456789abcdef"; - for (i = 0; i < object_dirs->len; i++) + for (c = 0; c < 255; c++) { - GFile *objdir = object_dirs->pdata[i]; - if (!list_loose_object_dir (self, objdir, inout_objects, cancellable, error)) + char buf[3]; + buf[0] = hexchars[c >> 4]; + buf[1] = hexchars[c & 0xF]; + buf[2] = '\0'; + dfd = openat (self->objects_dir_fd, buf, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC); + if (dfd == -1) + { + if (errno == ENOENT) + continue; + else + { + ot_util_set_error_from_errno (error, errno); + goto out; + } + } + /* Takes ownership of dfd */ + if (!list_loose_objects_at (self, inout_objects, buf, dfd, + cancellable, error)) goto out; } |