core: Optimize commits to raw repositories

Avoid creating a temporary intermediate file in the case where we have
the total object length available.
This commit is contained in:
Colin Walters committed 2012-05-04 06:15:47 -04:00
1 parent 67f61976f4
commit 7ce587da30
7 files changed
+208 -75

No files matched your search

+65 -27
View File
@@ -340,6 +340,7 @@ ostree_raw_file_to_content_stream (GInputStream *input,
GFileInfo *file_info,
GVariant *xattrs,
GInputStream **out_input,
guint64 *out_length,
GCancellable *cancellable,
GError **error)
{
@@ -377,21 +378,23 @@ ostree_raw_file_to_content_stream (GInputStream *input,
ret = TRUE;
ot_transfer_out_value (out_input, &ret_input);
if (out_length)
*out_length = header_size + g_file_info_get_size (file_info);
out:
return ret;
}
gboolean
ostree_content_file_parse (GFile *content_path,
gboolean trusted,
GInputStream **out_input,
GFileInfo **out_file_info,
GVariant **out_xattrs,
GCancellable *cancellable,
GError **error)
ostree_content_stream_parse (GInputStream *input,
guint64 input_length,
gboolean trusted,
GInputStream **out_input,
GFileInfo **out_file_info,
GVariant **out_xattrs,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
guint64 length;
guint32 archive_header_size;
guchar dummy[4];
gsize bytes_read;
@@ -402,39 +405,27 @@ ostree_content_file_parse (GFile *content_path,
ot_lvariant GVariant *file_header = NULL;
ot_lfree guchar *buf = NULL;
ret_input = (GInputStream*)g_file_read (content_path, cancellable, error);
if (!ret_input)
goto out;
content_file_info = g_file_input_stream_query_info ((GFileInputStream*)ret_input,
OSTREE_GIO_FAST_QUERYINFO,
cancellable, error);
if (!content_file_info)
goto out;
length = g_file_info_get_size (content_file_info);
if (!g_input_stream_read_all (ret_input,
if (!g_input_stream_read_all (input,
&archive_header_size, 4, &bytes_read,
cancellable, error))
goto out;
archive_header_size = GUINT32_FROM_BE (archive_header_size);
if (archive_header_size > length)
if (archive_header_size > input_length)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"File header size %u exceeds size %" G_GUINT64_FORMAT,
(guint)archive_header_size, length);
(guint)archive_header_size, input_length);
goto out;
}
/* Skip over padding */
if (!g_input_stream_read_all (ret_input,
if (!g_input_stream_read_all (input,
dummy, 4, &bytes_read,
cancellable, error))
goto out;
buf = g_malloc (archive_header_size);
if (!g_input_stream_read_all (ret_input, buf, archive_header_size, &bytes_read,
if (!g_input_stream_read_all (input, buf, archive_header_size, &bytes_read,
cancellable, error))
goto out;
file_header = g_variant_new_from_data (OSTREE_FILE_HEADER_GVARIANT_FORMAT,
@@ -448,14 +439,61 @@ ostree_content_file_parse (GFile *content_path,
error))
goto out;
if (ret_file_info)
g_file_info_set_size (ret_file_info, length - archive_header_size - 8);
g_file_info_set_size (ret_file_info, input_length - archive_header_size - 8);
if (g_file_info_get_file_type (ret_file_info) != G_FILE_TYPE_REGULAR)
{
g_clear_object (&ret_input);
}
/* Now give the input stream at its current position as return value */
ret = TRUE;
/* Give the input stream at its current position as return value;
* assuming the caller doesn't seek, this should be fine. We might
* want to wrap it though in a non-seekable stream.
**/
g_object_ref (input);
ot_transfer_out_value (out_input, &input);
ot_transfer_out_value (out_file_info, &ret_file_info);
ot_transfer_out_value (out_xattrs, &ret_xattrs);
out:
return ret;
}
gboolean
ostree_content_file_parse (GFile *content_path,
gboolean trusted,
GInputStream **out_input,
GFileInfo **out_file_info,
GVariant **out_xattrs,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
guint64 length;
ot_lobj GInputStream *file_input = NULL;
ot_lobj GInputStream *ret_input = NULL;
ot_lobj GFileInfo *content_file_info = NULL;
ot_lobj GFileInfo *ret_file_info = NULL;
ot_lvariant GVariant *ret_xattrs = NULL;
file_input = (GInputStream*)g_file_read (content_path, cancellable, error);
if (!file_input)
goto out;
content_file_info = g_file_input_stream_query_info ((GFileInputStream*)file_input,
OSTREE_GIO_FAST_QUERYINFO,
cancellable, error);
if (!content_file_info)
goto out;
length = g_file_info_get_size (content_file_info);
if (!ostree_content_stream_parse (file_input, length, trusted,
out_input ? &ret_input : NULL,
&ret_file_info, &ret_xattrs,
cancellable, error))
goto out;
ret = TRUE;
ot_transfer_out_value (out_input, &ret_input);