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:
parent
a7c0992d94
commit
b97249d4f9
|
|
@ -34,20 +34,16 @@
|
|||
|
||||
static gboolean
|
||||
commit_loose_object_trusted (OstreeRepo *self,
|
||||
const char *checksum,
|
||||
OstreeObjectType objtype,
|
||||
const char *loose_path,
|
||||
const char *tempfile_name,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
char loose_prefix[3];
|
||||
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
|
||||
|
||||
_ostree_loose_path (loose_objpath, checksum, objtype, self->mode);
|
||||
|
||||
loose_prefix[0] = loose_objpath[0];
|
||||
loose_prefix[1] = loose_objpath[1];
|
||||
loose_prefix[0] = loose_path[0];
|
||||
loose_prefix[1] = loose_path[1];
|
||||
loose_prefix[2] = '\0';
|
||||
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,
|
||||
self->objects_dir_fd, loose_objpath) < 0))
|
||||
self->objects_dir_fd, loose_path) == -1))
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
|
|
@ -155,6 +151,7 @@ write_object (OstreeRepo *self,
|
|||
GChecksum *checksum = NULL;
|
||||
gboolean temp_file_is_regular;
|
||||
gboolean is_symlink = FALSE;
|
||||
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
|
||||
|
||||
g_return_val_if_fail (self->in_transaction, FALSE);
|
||||
|
||||
|
|
@ -165,9 +162,15 @@ write_object (OstreeRepo *self,
|
|||
|
||||
if (expected_checksum)
|
||||
{
|
||||
if (!_ostree_repo_find_object (self, objtype, expected_checksum, &stored_path,
|
||||
cancellable, error))
|
||||
if (!_ostree_repo_has_loose_object (self, expected_checksum, objtype,
|
||||
&have_obj, loose_objpath,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
if (have_obj)
|
||||
{
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
cancellable, error))
|
||||
if (!_ostree_repo_has_loose_object (self, actual_checksum, objtype,
|
||||
&have_obj, loose_objpath,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
do_commit = !have_obj;
|
||||
|
|
@ -358,7 +362,7 @@ write_object (OstreeRepo *self,
|
|||
(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))
|
||||
goto out;
|
||||
g_clear_pointer (&temp_filename, g_free);
|
||||
|
|
|
|||
|
|
@ -76,6 +76,15 @@ _ostree_repo_find_object (OstreeRepo *self,
|
|||
GCancellable *cancellable,
|
||||
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
|
||||
_ostree_repo_get_loose_object_dirs (OstreeRepo *self,
|
||||
GPtrArray **out_object_dirs,
|
||||
|
|
|
|||
|
|
@ -989,6 +989,43 @@ ostree_repo_load_object_stream (OstreeRepo *self,
|
|||
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
|
||||
_ostree_repo_find_object (OstreeRepo *self,
|
||||
OstreeObjectType objtype,
|
||||
|
|
@ -998,25 +1035,18 @@ _ostree_repo_find_object (OstreeRepo *self,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
struct stat stbuf;
|
||||
gs_unref_object GFile *object_path = NULL;
|
||||
gs_unref_object GFile *ret_stored_path = NULL;
|
||||
gboolean has_object;
|
||||
char loose_path[_OSTREE_LOOSE_PATH_MAX];
|
||||
|
||||
object_path = _ostree_repo_get_object_path (self, checksum, objtype);
|
||||
|
||||
if (lstat (gs_file_get_path_cached (object_path), &stbuf) == 0)
|
||||
{
|
||||
ret_stored_path = object_path;
|
||||
object_path = NULL; /* Transfer ownership */
|
||||
}
|
||||
else if (errno != ENOENT)
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
if (!_ostree_repo_has_loose_object (self, checksum, objtype, &has_object, loose_path,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
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:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue