mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 08:00:53 +00:00
libsysprof-analyze: automatically handle compressed streams
If we want /proc/kallsyms and we discover /proc/kallsyms.gz, then use the /proc/kallsyms.gz instead and transparently decompress it. Also, list the file in sysprof_document_list_files() as /proc/kallsyms instead of /proc/kallsyms.gz as that is really the intention (but mark the compressed bit for decoding the chunks).
This commit is contained in:
@ -25,6 +25,7 @@
|
|||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
SysprofDocumentFile *_sysprof_document_file_new (const char *path,
|
SysprofDocumentFile *_sysprof_document_file_new (const char *path,
|
||||||
GPtrArray *file_chunks);
|
GPtrArray *file_chunks,
|
||||||
|
gboolean compressed);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@ -26,9 +26,10 @@
|
|||||||
|
|
||||||
struct _SysprofDocumentFile
|
struct _SysprofDocumentFile
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
char *path;
|
char *path;
|
||||||
GPtrArray *file_chunks;
|
GPtrArray *file_chunks;
|
||||||
|
guint compressed : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -104,7 +105,8 @@ sysprof_document_file_init (SysprofDocumentFile *self)
|
|||||||
|
|
||||||
SysprofDocumentFile *
|
SysprofDocumentFile *
|
||||||
_sysprof_document_file_new (const char *path,
|
_sysprof_document_file_new (const char *path,
|
||||||
GPtrArray *file_chunks)
|
GPtrArray *file_chunks,
|
||||||
|
gboolean compressed)
|
||||||
{
|
{
|
||||||
SysprofDocumentFile *self;
|
SysprofDocumentFile *self;
|
||||||
|
|
||||||
@ -114,6 +116,7 @@ _sysprof_document_file_new (const char *path,
|
|||||||
self = g_object_new (SYSPROF_TYPE_DOCUMENT_FILE, NULL);
|
self = g_object_new (SYSPROF_TYPE_DOCUMENT_FILE, NULL);
|
||||||
self->path = g_strdup (path);
|
self->path = g_strdup (path);
|
||||||
self->file_chunks = file_chunks;
|
self->file_chunks = file_chunks;
|
||||||
|
self->compressed = !!compressed;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -169,7 +172,7 @@ sysprof_document_file_dup_bytes (SysprofDocumentFile *self)
|
|||||||
GInputStream *
|
GInputStream *
|
||||||
sysprof_document_file_read (SysprofDocumentFile *self)
|
sysprof_document_file_read (SysprofDocumentFile *self)
|
||||||
{
|
{
|
||||||
GInputStream *input;
|
g_autoptr(GInputStream) input = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (SYSPROF_IS_DOCUMENT_FILE (self), NULL);
|
g_return_val_if_fail (SYSPROF_IS_DOCUMENT_FILE (self), NULL);
|
||||||
|
|
||||||
@ -193,6 +196,13 @@ sysprof_document_file_read (SysprofDocumentFile *self)
|
|||||||
g_memory_input_stream_add_bytes (G_MEMORY_INPUT_STREAM (input), bytes);
|
g_memory_input_stream_add_bytes (G_MEMORY_INPUT_STREAM (input), bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->compressed)
|
||||||
|
{
|
||||||
|
g_autoptr(GZlibDecompressor) zlib = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
|
||||||
|
|
||||||
|
return g_converter_input_stream_new (input, G_CONVERTER (zlib));
|
||||||
|
}
|
||||||
|
|
||||||
return g_steal_pointer (&input);
|
return g_steal_pointer (&input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -895,14 +895,19 @@ SysprofDocumentFile *
|
|||||||
sysprof_document_lookup_file (SysprofDocument *self,
|
sysprof_document_lookup_file (SysprofDocument *self,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
|
g_autofree char *gz_path = NULL;
|
||||||
gpointer key, value;
|
gpointer key, value;
|
||||||
|
|
||||||
g_return_val_if_fail (SYSPROF_IS_DOCUMENT (self), NULL);
|
g_return_val_if_fail (SYSPROF_IS_DOCUMENT (self), NULL);
|
||||||
g_return_val_if_fail (path != NULL, NULL);
|
g_return_val_if_fail (path != NULL, NULL);
|
||||||
|
|
||||||
if (g_hash_table_lookup_extended (self->files_first_position, path, &key, &value))
|
gz_path = g_strdup_printf ("%s.gz", path);
|
||||||
|
|
||||||
|
if (g_hash_table_lookup_extended (self->files_first_position, path, &key, &value) ||
|
||||||
|
g_hash_table_lookup_extended (self->files_first_position, gz_path, &key, &value))
|
||||||
{
|
{
|
||||||
g_autoptr(GPtrArray) file_chunks = g_ptr_array_new_with_free_func (g_object_unref);
|
g_autoptr(GPtrArray) file_chunks = g_ptr_array_new_with_free_func (g_object_unref);
|
||||||
|
const char *real_path = key;
|
||||||
EggBitsetIter iter;
|
EggBitsetIter iter;
|
||||||
guint target = GPOINTER_TO_SIZE (value);
|
guint target = GPOINTER_TO_SIZE (value);
|
||||||
guint i;
|
guint i;
|
||||||
@ -913,7 +918,7 @@ sysprof_document_lookup_file (SysprofDocument *self,
|
|||||||
{
|
{
|
||||||
g_autoptr(SysprofDocumentFileChunk) file_chunk = sysprof_document_get_item ((GListModel *)self, i);
|
g_autoptr(SysprofDocumentFileChunk) file_chunk = sysprof_document_get_item ((GListModel *)self, i);
|
||||||
|
|
||||||
if (g_strcmp0 (path, sysprof_document_file_chunk_get_path (file_chunk)) == 0)
|
if (g_strcmp0 (real_path, sysprof_document_file_chunk_get_path (file_chunk)) == 0)
|
||||||
{
|
{
|
||||||
gboolean is_last = sysprof_document_file_chunk_get_is_last (file_chunk);
|
gboolean is_last = sysprof_document_file_chunk_get_is_last (file_chunk);
|
||||||
|
|
||||||
@ -926,7 +931,9 @@ sysprof_document_lookup_file (SysprofDocument *self,
|
|||||||
while (egg_bitset_iter_next (&iter, &i));
|
while (egg_bitset_iter_next (&iter, &i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return _sysprof_document_file_new (path, g_steal_pointer (&file_chunks));
|
return _sysprof_document_file_new (path,
|
||||||
|
g_steal_pointer (&file_chunks),
|
||||||
|
g_strcmp0 (real_path, gz_path) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -957,6 +964,7 @@ sysprof_document_list_files (SysprofDocument *self)
|
|||||||
{
|
{
|
||||||
g_autoptr(SysprofDocumentFile) file = NULL;
|
g_autoptr(SysprofDocumentFile) file = NULL;
|
||||||
g_autoptr(GPtrArray) file_chunks = g_ptr_array_new_with_free_func (g_object_unref);
|
g_autoptr(GPtrArray) file_chunks = g_ptr_array_new_with_free_func (g_object_unref);
|
||||||
|
g_autofree char *no_gz_path = NULL;
|
||||||
const char *path = key;
|
const char *path = key;
|
||||||
guint target = GPOINTER_TO_SIZE (value);
|
guint target = GPOINTER_TO_SIZE (value);
|
||||||
guint i;
|
guint i;
|
||||||
@ -980,7 +988,12 @@ sysprof_document_list_files (SysprofDocument *self)
|
|||||||
while (egg_bitset_iter_next (&iter, &i));
|
while (egg_bitset_iter_next (&iter, &i));
|
||||||
}
|
}
|
||||||
|
|
||||||
file = _sysprof_document_file_new (path, g_steal_pointer (&file_chunks));
|
if (g_str_has_suffix (path, ".gz"))
|
||||||
|
path = no_gz_path = g_strndup (path, strlen (path) - 3);
|
||||||
|
|
||||||
|
file = _sysprof_document_file_new (path,
|
||||||
|
g_steal_pointer (&file_chunks),
|
||||||
|
no_gz_path != NULL);
|
||||||
|
|
||||||
g_list_store_append (model, file);
|
g_list_store_append (model, file);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -191,10 +191,9 @@ sysprof_kallsyms_symbolizer_prepare_async (SysprofSymbolizer *symbolizer,
|
|||||||
{
|
{
|
||||||
SysprofKallsymsSymbolizer *self = (SysprofKallsymsSymbolizer *)symbolizer;
|
SysprofKallsymsSymbolizer *self = (SysprofKallsymsSymbolizer *)symbolizer;
|
||||||
g_autoptr(SysprofDocumentFile) file = NULL;
|
g_autoptr(SysprofDocumentFile) file = NULL;
|
||||||
g_autoptr(GZlibDecompressor) decompressor = NULL;
|
|
||||||
g_autoptr(GInputStream) input_gz = NULL;
|
|
||||||
g_autoptr(GInputStream) input = NULL;
|
g_autoptr(GInputStream) input = NULL;
|
||||||
g_autoptr(GTask) task = NULL;
|
g_autoptr(GTask) task = NULL;
|
||||||
|
GInputStream *base_stream;
|
||||||
|
|
||||||
g_assert (SYSPROF_IS_KALLSYMS_SYMBOLIZER (self));
|
g_assert (SYSPROF_IS_KALLSYMS_SYMBOLIZER (self));
|
||||||
g_assert (SYSPROF_IS_DOCUMENT (document));
|
g_assert (SYSPROF_IS_DOCUMENT (document));
|
||||||
@ -203,9 +202,12 @@ sysprof_kallsyms_symbolizer_prepare_async (SysprofSymbolizer *symbolizer,
|
|||||||
task = g_task_new (self, cancellable, callback, user_data);
|
task = g_task_new (self, cancellable, callback, user_data);
|
||||||
g_task_set_source_tag (task, sysprof_kallsyms_symbolizer_prepare_async);
|
g_task_set_source_tag (task, sysprof_kallsyms_symbolizer_prepare_async);
|
||||||
|
|
||||||
if (self->stream == NULL)
|
base_stream = self->stream;
|
||||||
|
|
||||||
|
if (base_stream == NULL)
|
||||||
{
|
{
|
||||||
if (!(file = sysprof_document_lookup_file (document, "/proc/kallsyms.gz")))
|
|
||||||
|
if (!(file = sysprof_document_lookup_file (document, "/proc/kallsyms")))
|
||||||
{
|
{
|
||||||
g_task_return_new_error (task,
|
g_task_return_new_error (task,
|
||||||
G_IO_ERROR,
|
G_IO_ERROR,
|
||||||
@ -214,20 +216,15 @@ sysprof_kallsyms_symbolizer_prepare_async (SysprofSymbolizer *symbolizer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
|
base_stream = input = sysprof_document_file_read (file);
|
||||||
input_gz = sysprof_document_file_read (file);
|
}
|
||||||
input = g_converter_input_stream_new (input_gz, G_CONVERTER (decompressor));
|
|
||||||
|
|
||||||
g_task_set_task_data (task,
|
g_assert (base_stream != NULL);
|
||||||
g_data_input_stream_new (input),
|
g_assert (G_IS_INPUT_STREAM (base_stream));
|
||||||
g_object_unref);
|
|
||||||
}
|
g_task_set_task_data (task,
|
||||||
else
|
g_data_input_stream_new (base_stream),
|
||||||
{
|
g_object_unref);
|
||||||
g_task_set_task_data (task,
|
|
||||||
g_steal_pointer (&self->stream),
|
|
||||||
g_object_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_task_run_in_thread (task, sysprof_kallsyms_symbolizer_prepare_worker);
|
g_task_run_in_thread (task, sysprof_kallsyms_symbolizer_prepare_worker);
|
||||||
}
|
}
|
||||||
@ -364,9 +361,7 @@ sysprof_kallsyms_symbolizer_new_for_symbols (GInputStream *symbols)
|
|||||||
g_return_val_if_fail (G_IS_INPUT_STREAM (symbols), NULL);
|
g_return_val_if_fail (G_IS_INPUT_STREAM (symbols), NULL);
|
||||||
|
|
||||||
self = g_object_new (SYSPROF_TYPE_KALLSYMS_SYMBOLIZER, NULL);
|
self = g_object_new (SYSPROF_TYPE_KALLSYMS_SYMBOLIZER, NULL);
|
||||||
self->stream = G_INPUT_STREAM (g_data_input_stream_new (symbols));
|
self->stream = symbols;
|
||||||
|
|
||||||
g_object_unref (symbols);
|
|
||||||
|
|
||||||
return SYSPROF_SYMBOLIZER (self);
|
return SYSPROF_SYMBOLIZER (self);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user