core: Use at-relative lookup for locating objects too

Add new internal API to both fstatat() and write a pathname for the
given object.  Use it in commit, and also wrapped in the old
GFile-based API.

This is more efficient.
This commit is contained in:
Colin Walters 2013-09-07 04:47:40 -04:00
parent a7c0992d94
commit b97249d4f9
3 changed files with 72 additions and 29 deletions

View File

@ -34,20 +34,16 @@
static gboolean static gboolean
commit_loose_object_trusted (OstreeRepo *self, commit_loose_object_trusted (OstreeRepo *self,
const char *checksum, const char *loose_path,
OstreeObjectType objtype,
const char *tempfile_name, const char *tempfile_name,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
char loose_prefix[3]; char loose_prefix[3];
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
_ostree_loose_path (loose_objpath, checksum, objtype, self->mode); loose_prefix[0] = loose_path[0];
loose_prefix[1] = loose_path[1];
loose_prefix[0] = loose_objpath[0];
loose_prefix[1] = loose_objpath[1];
loose_prefix[2] = '\0'; loose_prefix[2] = '\0';
if (G_UNLIKELY (mkdirat (self->objects_dir_fd, loose_prefix, 0777) == -1)) if (G_UNLIKELY (mkdirat (self->objects_dir_fd, loose_prefix, 0777) == -1))
{ {
@ -60,7 +56,7 @@ commit_loose_object_trusted (OstreeRepo *self,
} }
if (G_UNLIKELY (renameat (self->tmp_dir_fd, tempfile_name, if (G_UNLIKELY (renameat (self->tmp_dir_fd, tempfile_name,
self->objects_dir_fd, loose_objpath) < 0)) self->objects_dir_fd, loose_path) == -1))
{ {
if (errno != EEXIST) if (errno != EEXIST)
{ {
@ -155,6 +151,7 @@ write_object (OstreeRepo *self,
GChecksum *checksum = NULL; GChecksum *checksum = NULL;
gboolean temp_file_is_regular; gboolean temp_file_is_regular;
gboolean is_symlink = FALSE; gboolean is_symlink = FALSE;
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
g_return_val_if_fail (self->in_transaction, FALSE); g_return_val_if_fail (self->in_transaction, FALSE);
@ -165,9 +162,15 @@ write_object (OstreeRepo *self,
if (expected_checksum) if (expected_checksum)
{ {
if (!_ostree_repo_find_object (self, objtype, expected_checksum, &stored_path, if (!_ostree_repo_has_loose_object (self, expected_checksum, objtype,
cancellable, error)) &have_obj, loose_objpath,
cancellable, error))
goto out; goto out;
if (have_obj)
{
ret = TRUE;
goto out;
}
} }
repo_mode = ostree_repo_get_mode (self); repo_mode = ostree_repo_get_mode (self);
@ -290,8 +293,9 @@ write_object (OstreeRepo *self,
} }
} }
if (!ostree_repo_has_object (self, objtype, actual_checksum, &have_obj, if (!_ostree_repo_has_loose_object (self, actual_checksum, objtype,
cancellable, error)) &have_obj, loose_objpath,
cancellable, error))
goto out; goto out;
do_commit = !have_obj; do_commit = !have_obj;
@ -358,7 +362,7 @@ write_object (OstreeRepo *self,
(void) close (fd); (void) close (fd);
} }
} }
if (!commit_loose_object_trusted (self, actual_checksum, objtype, temp_filename, if (!commit_loose_object_trusted (self, loose_objpath, temp_filename,
cancellable, error)) cancellable, error))
goto out; goto out;
g_clear_pointer (&temp_filename, g_free); g_clear_pointer (&temp_filename, g_free);

View File

@ -76,6 +76,15 @@ _ostree_repo_find_object (OstreeRepo *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
gboolean
_ostree_repo_has_loose_object (OstreeRepo *self,
const char *checksum,
OstreeObjectType objtype,
gboolean *out_is_stored,
char *loose_path_buf,
GCancellable *cancellable,
GError **error);
gboolean gboolean
_ostree_repo_get_loose_object_dirs (OstreeRepo *self, _ostree_repo_get_loose_object_dirs (OstreeRepo *self,
GPtrArray **out_object_dirs, GPtrArray **out_object_dirs,

View File

@ -989,6 +989,43 @@ ostree_repo_load_object_stream (OstreeRepo *self,
return ret; return ret;
} }
/*
* _ostree_repo_has_loose_object:
* @loose_path_buf: Buffer of size _OSTREE_LOOSE_PATH_MAX
*
* Locate object in repository; if it exists, @out_is_stored will be
* set to TRUE. @loose_path_buf is always set to the loose path.
*/
gboolean
_ostree_repo_has_loose_object (OstreeRepo *self,
const char *checksum,
OstreeObjectType objtype,
gboolean *out_is_stored,
char *loose_path_buf,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
struct stat stbuf;
int res;
_ostree_loose_path (loose_path_buf, checksum, objtype, self->mode);
do
res = fstatat (self->objects_dir_fd, loose_path_buf, &stbuf, AT_SYMLINK_NOFOLLOW);
while (G_UNLIKELY (res == -1 && errno == EINTR));
if (res == -1 && errno != ENOENT)
{
ot_util_set_error_from_errno (error, errno);
goto out;
}
ret = TRUE;
*out_is_stored = (res != -1);
out:
return ret;
}
gboolean gboolean
_ostree_repo_find_object (OstreeRepo *self, _ostree_repo_find_object (OstreeRepo *self,
OstreeObjectType objtype, OstreeObjectType objtype,
@ -998,25 +1035,18 @@ _ostree_repo_find_object (OstreeRepo *self,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
struct stat stbuf; gboolean has_object;
gs_unref_object GFile *object_path = NULL; char loose_path[_OSTREE_LOOSE_PATH_MAX];
gs_unref_object GFile *ret_stored_path = NULL;
object_path = _ostree_repo_get_object_path (self, checksum, objtype); if (!_ostree_repo_has_loose_object (self, checksum, objtype, &has_object, loose_path,
cancellable, error))
if (lstat (gs_file_get_path_cached (object_path), &stbuf) == 0) goto out;
{
ret_stored_path = object_path;
object_path = NULL; /* Transfer ownership */
}
else if (errno != ENOENT)
{
ot_util_set_error_from_errno (error, errno);
goto out;
}
ret = TRUE; ret = TRUE;
ot_transfer_out_value (out_stored_path, &ret_stored_path); if (has_object)
*out_stored_path = g_file_resolve_relative_path (self->objects_dir, loose_path);
else
*out_stored_path = NULL;
out: out:
return ret; return ret;
} }