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.
This commit is contained in:
Colin Walters 2013-09-30 08:51:25 -04:00
parent 8592922c2c
commit 7b119370a2
1 changed files with 59 additions and 58 deletions

View File

@ -670,72 +670,59 @@ _ostree_repo_get_loose_object_dirs (OstreeRepo *self,
} }
static gboolean static gboolean
list_loose_object_dir (OstreeRepo *self, list_loose_objects_at (OstreeRepo *self,
GFile *dir,
GHashTable *inout_objects, GHashTable *inout_objects,
const char *prefix,
int dfd,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
const char *dirname = NULL; DIR *d = NULL;
const char *dot = NULL; struct dirent *dent;
gs_unref_object GFileEnumerator *enumerator = NULL;
GString *checksum = NULL;
dirname = gs_file_get_basename_cached (dir); d = fdopendir (dfd);
if (!d)
/* 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;
while (TRUE)
{ {
GFileInfo *file_info; ot_util_set_error_from_errno (error, errno);
const char *name; goto out;
guint32 type; }
while ((dent = readdir (d)) != NULL)
{
const char *name = dent->d_name;
const char *dot;
OstreeObjectType objtype; OstreeObjectType objtype;
char buf[65];
if (!gs_file_enumerator_iterate (enumerator, &file_info, NULL, if (strcmp (name, ".") == 0 ||
NULL, error)) strcmp (name, "..") == 0)
goto out;
if (file_info == NULL)
break;
type = g_file_info_get_attribute_uint32 (file_info, "standard::type");
if (type == G_FILE_TYPE_DIRECTORY)
continue;
name = g_file_info_get_attribute_byte_string (file_info, "standard::name");
if (g_str_has_suffix (name, ".file"))
objtype = OSTREE_OBJECT_TYPE_FILE;
else if (g_str_has_suffix (name, ".dirtree"))
objtype = OSTREE_OBJECT_TYPE_DIR_TREE;
else if (g_str_has_suffix (name, ".dirmeta"))
objtype = OSTREE_OBJECT_TYPE_DIR_META;
else if (g_str_has_suffix (name, ".commit"))
objtype = OSTREE_OBJECT_TYPE_COMMIT;
else
continue; continue;
dot = strrchr (name, '.'); dot = strrchr (name, '.');
g_assert (dot); if (!dot)
continue;
if (strcmp (dot, ".file") == 0)
objtype = OSTREE_OBJECT_TYPE_FILE;
else if (strcmp (dot, ".dirtree") == 0)
objtype = OSTREE_OBJECT_TYPE_DIR_TREE;
else if (strcmp (dot, ".dirmeta") == 0)
objtype = OSTREE_OBJECT_TYPE_DIR_META;
else if (strcmp (dot, ".commit") == 0)
objtype = OSTREE_OBJECT_TYPE_COMMIT;
else
continue;
if ((dot - name) == 62) if ((dot - name) == 62)
{ {
GVariant *key, *value; GVariant *key, *value;
if (checksum) memcpy (buf, prefix, 2);
g_string_free (checksum, TRUE); memcpy (buf + 2, name, 62);
checksum = g_string_new (dirname); buf[sizeof(buf)-1] = '\0';
g_string_append_len (checksum, name, 62);
key = ostree_object_name_serialize (checksum->str, objtype); key = ostree_object_name_serialize (buf, objtype);
value = g_variant_new ("(b@as)", value = g_variant_new ("(b@as)",
TRUE, g_variant_new_strv (NULL, 0)); TRUE, g_variant_new_strv (NULL, 0));
/* transfer ownership */ /* transfer ownership */
@ -746,8 +733,8 @@ list_loose_object_dir (OstreeRepo *self,
ret = TRUE; ret = TRUE;
out: out:
if (checksum) if (d)
g_string_free (checksum, TRUE); (void) closedir (d);
return ret; return ret;
} }
@ -758,16 +745,30 @@ list_loose_objects (OstreeRepo *self,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
guint i; guint c;
gs_unref_ptrarray GPtrArray *object_dirs = NULL; int dfd = -1;
static const gchar hexchars[] = "0123456789abcdef";
if (!_ostree_repo_get_loose_object_dirs (self, &object_dirs, cancellable, error)) for (c = 0; c < 255; c++)
goto out;
for (i = 0; i < object_dirs->len; i++)
{ {
GFile *objdir = object_dirs->pdata[i]; char buf[3];
if (!list_loose_object_dir (self, objdir, inout_objects, cancellable, error)) 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; goto out;
} }