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
|
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,
|
||||||
|
&have_obj, loose_objpath,
|
||||||
cancellable, error))
|
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,7 +293,8 @@ 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,
|
||||||
|
&have_obj, loose_objpath,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
{
|
|
||||||
ret_stored_path = object_path;
|
|
||||||
object_path = NULL; /* Transfer ownership */
|
|
||||||
}
|
|
||||||
else if (errno != ENOENT)
|
|
||||||
{
|
|
||||||
ot_util_set_error_from_errno (error, errno);
|
|
||||||
goto out;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue