diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2023-02-03 14:00:00 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-02-04 12:27:10 +0100 |
commit | 1ec59cc52a426bcc283645fa46e490c7fe23eef5 (patch) | |
tree | 27ed124333c4e4563a01f1c646427029f53e4e67 /Userland/Applications/SpaceAnalyzer | |
parent | 98e9ee07e38fa8395a9f253a082d37b60fc36104 (diff) | |
download | serenity-1ec59cc52a426bcc283645fa46e490c7fe23eef5.zip |
SpaceAnalyzer: Make TreeMapWidget responsible for filesystem analysis
Also, the Tree object was only ever used by the TreeMapWidget, so its
creation can happen inside `analyze()`, fixing the memory leak issue.
Plus, it doesn't have to be RefCounted.
Diffstat (limited to 'Userland/Applications/SpaceAnalyzer')
-rw-r--r-- | Userland/Applications/SpaceAnalyzer/Tree.h | 12 | ||||
-rw-r--r-- | Userland/Applications/SpaceAnalyzer/TreeMapWidget.cpp | 72 | ||||
-rw-r--r-- | Userland/Applications/SpaceAnalyzer/TreeMapWidget.h | 4 | ||||
-rw-r--r-- | Userland/Applications/SpaceAnalyzer/main.cpp | 87 |
4 files changed, 82 insertions, 93 deletions
diff --git a/Userland/Applications/SpaceAnalyzer/Tree.h b/Userland/Applications/SpaceAnalyzer/Tree.h index 377bb4fb1f..f37ff8075b 100644 --- a/Userland/Applications/SpaceAnalyzer/Tree.h +++ b/Userland/Applications/SpaceAnalyzer/Tree.h @@ -9,7 +9,6 @@ #include <AK/DeprecatedString.h> #include <AK/Forward.h> #include <AK/OwnPtr.h> -#include <AK/RefCounted.h> #include <AK/Vector.h> struct MountInfo { @@ -44,16 +43,21 @@ private: OwnPtr<Vector<TreeNode>> m_children; }; -class Tree : public RefCounted<Tree> { +class Tree { public: - Tree(DeprecatedString root_name) - : m_root(move(root_name)) {}; + static ErrorOr<NonnullOwnPtr<Tree>> create(DeprecatedString root_name) + { + return adopt_nonnull_own_or_enomem(new (nothrow) Tree(move(root_name))); + } ~Tree() {}; + TreeNode& root() { return m_root; }; private: + Tree(DeprecatedString root_name) + : m_root(move(root_name)) {}; TreeNode m_root; }; diff --git a/Userland/Applications/SpaceAnalyzer/TreeMapWidget.cpp b/Userland/Applications/SpaceAnalyzer/TreeMapWidget.cpp index 87505d06d4..921386f457 100644 --- a/Userland/Applications/SpaceAnalyzer/TreeMapWidget.cpp +++ b/Userland/Applications/SpaceAnalyzer/TreeMapWidget.cpp @@ -1,17 +1,19 @@ /* * Copyright (c) 2021-2022, the SerenityOS developers. - * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> + * Copyright (c) 2022-2023, Sam Atkins <atkinssj@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ #include "TreeMapWidget.h" +#include "ProgressWindow.h" #include "Tree.h" #include <AK/Array.h> #include <AK/DeprecatedString.h> #include <AK/NumberFormat.h> #include <LibGUI/ConnectionToWindowServer.h> #include <LibGUI/Painter.h> +#include <LibGUI/Statusbar.h> #include <LibGfx/Font/Font.h> #include <WindowServer/WindowManager.h> @@ -373,15 +375,79 @@ void TreeMapWidget::recalculate_path_for_new_tree() m_viewpoint = new_path_length - 1; } -void TreeMapWidget::set_tree(RefPtr<Tree> tree) +static ErrorOr<void> fill_mounts(Vector<MountInfo>& output) { - m_tree = tree; + // Output info about currently mounted filesystems. + auto file = TRY(Core::Stream::File::open("/sys/kernel/df"sv, Core::Stream::OpenMode::Read)); + + auto content = TRY(file->read_until_eof()); + auto json = TRY(JsonValue::from_string(content)); + + TRY(json.as_array().try_for_each([&output](JsonValue const& value) -> ErrorOr<void> { + auto& filesystem_object = value.as_object(); + MountInfo mount_info; + mount_info.mount_point = filesystem_object.get_deprecated_string("mount_point"sv).value_or({}); + mount_info.source = filesystem_object.get_deprecated_string("source"sv).value_or("none"); + TRY(output.try_append(mount_info)); + return {}; + })); + + return {}; +} + +ErrorOr<void> TreeMapWidget::analyze(GUI::Statusbar& statusbar) +{ + statusbar.set_text(""); + auto progress_window = TRY(ProgressWindow::try_create("Space Analyzer"sv)); + progress_window->show(); + + // Build an in-memory tree mirroring the filesystem and for each node + // calculate the sum of the file size for all its descendants. + auto tree = TRY(Tree::create("")); + Vector<MountInfo> mounts; + TRY(fill_mounts(mounts)); + auto errors = tree->root().populate_filesize_tree(mounts, [&](size_t processed_file_count) { + progress_window->update_progress_label(processed_file_count); + }); + + progress_window->close(); + + // Display an error summary in the statusbar. + if (!errors.is_empty()) { + StringBuilder builder; + bool first = true; + builder.append("Some directories were not analyzed: "sv); + for (auto& key : errors.keys()) { + if (!first) { + builder.append(", "sv); + } + auto const* error = strerror(key); + builder.append({ error, strlen(error) }); + builder.append(" ("sv); + int value = errors.get(key).value(); + builder.append(DeprecatedString::number(value)); + if (value == 1) { + builder.append(" time"sv); + } else { + builder.append(" times"sv); + } + builder.append(')'); + first = false; + } + statusbar.set_text(builder.to_deprecated_string()); + } else { + statusbar.set_text("No errors"); + } + + m_tree = move(tree); recalculate_path_for_new_tree(); if (on_path_change) { on_path_change(); } update(); + + return {}; } void TreeMapWidget::set_viewpoint(size_t viewpoint) diff --git a/Userland/Applications/SpaceAnalyzer/TreeMapWidget.h b/Userland/Applications/SpaceAnalyzer/TreeMapWidget.h index 4c0424aa67..f02743f735 100644 --- a/Userland/Applications/SpaceAnalyzer/TreeMapWidget.h +++ b/Userland/Applications/SpaceAnalyzer/TreeMapWidget.h @@ -24,7 +24,7 @@ public: TreeNode const* path_node(size_t n) const; size_t viewpoint() const; void set_viewpoint(size_t); - void set_tree(RefPtr<Tree> tree); + ErrorOr<void> analyze(GUI::Statusbar&); private: TreeMapWidget() = default; @@ -53,7 +53,7 @@ private: Vector<DeprecatedString> path_to_position(Gfx::IntPoint); void recalculate_path_for_new_tree(); - RefPtr<Tree> m_tree; + OwnPtr<Tree> m_tree; Vector<DeprecatedString> m_path; size_t m_viewpoint { 0 }; void const* m_selected_node_cache; diff --git a/Userland/Applications/SpaceAnalyzer/main.cpp b/Userland/Applications/SpaceAnalyzer/main.cpp index 984e145233..2cd91bfa2f 100644 --- a/Userland/Applications/SpaceAnalyzer/main.cpp +++ b/Userland/Applications/SpaceAnalyzer/main.cpp @@ -5,20 +5,13 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include "ProgressWindow.h" #include "Tree.h" #include "TreeMapWidget.h" -#include <AK/Error.h> #include <AK/LexicalPath.h> -#include <AK/Queue.h> -#include <AK/QuickSort.h> #include <AK/String.h> -#include <AK/StringView.h> #include <AK/URL.h> #include <Applications/SpaceAnalyzer/SpaceAnalyzerGML.h> #include <LibCore/File.h> -#include <LibCore/IODevice.h> -#include <LibCore/Stream.h> #include <LibDesktop/Launcher.h> #include <LibGUI/Application.h> #include <LibGUI/BoxLayout.h> @@ -26,7 +19,6 @@ #include <LibGUI/Clipboard.h> #include <LibGUI/FileIconProvider.h> #include <LibGUI/Icon.h> -#include <LibGUI/Label.h> #include <LibGUI/Menu.h> #include <LibGUI/Menubar.h> #include <LibGUI/MessageBox.h> @@ -36,73 +28,6 @@ static constexpr auto APP_NAME = "Space Analyzer"sv; -static ErrorOr<void> fill_mounts(Vector<MountInfo>& output) -{ - // Output info about currently mounted filesystems. - auto file = TRY(Core::Stream::File::open("/sys/kernel/df"sv, Core::Stream::OpenMode::Read)); - - auto content = TRY(file->read_until_eof()); - auto json = TRY(JsonValue::from_string(content)); - - TRY(json.as_array().try_for_each([&output](JsonValue const& value) -> ErrorOr<void> { - auto& filesystem_object = value.as_object(); - MountInfo mount_info; - mount_info.mount_point = filesystem_object.get_deprecated_string("mount_point"sv).value_or({}); - mount_info.source = filesystem_object.get_deprecated_string("source"sv).value_or("none"); - TRY(output.try_append(mount_info)); - return {}; - })); - - return {}; -} - -static ErrorOr<void> analyze(RefPtr<Tree> tree, SpaceAnalyzer::TreeMapWidget& treemapwidget, GUI::Statusbar& statusbar) -{ - statusbar.set_text(""); - auto progress_window = TRY(ProgressWindow::try_create(APP_NAME)); - progress_window->show(); - - // Build an in-memory tree mirroring the filesystem and for each node - // calculate the sum of the file size for all its descendants. - Vector<MountInfo> mounts; - TRY(fill_mounts(mounts)); - auto errors = tree->root().populate_filesize_tree(mounts, [&](size_t processed_file_count) { - progress_window->update_progress_label(processed_file_count); - }); - - progress_window->close(); - - // Display an error summary in the statusbar. - if (!errors.is_empty()) { - StringBuilder builder; - bool first = true; - builder.append("Some directories were not analyzed: "sv); - for (auto& key : errors.keys()) { - if (!first) { - builder.append(", "sv); - } - auto const* error = strerror(key); - builder.append({ error, strlen(error) }); - builder.append(" ("sv); - int value = errors.get(key).value(); - builder.append(DeprecatedString::number(value)); - if (value == 1) { - builder.append(" time"sv); - } else { - builder.append(" times"sv); - } - builder.append(')'); - first = false; - } - statusbar.set_text(builder.to_deprecated_string()); - } else { - statusbar.set_text("No errors"); - } - treemapwidget.set_tree(tree); - - return {}; -} - static DeprecatedString get_absolute_path_to_selected_node(SpaceAnalyzer::TreeMapWidget const& treemapwidget, bool include_last_node = true) { StringBuilder path_builder; @@ -120,8 +45,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) { auto app = TRY(GUI::Application::try_create(arguments)); - RefPtr<Tree> tree = adopt_ref(*new Tree("")); - // Configure application window. auto app_icon = GUI::Icon::default_icon("app-space-analyzer"sv); auto window = TRY(GUI::Window::try_create()); @@ -141,9 +64,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) auto file_menu = TRY(window->try_add_menu("&File")); TRY(file_menu->try_add_action(GUI::Action::create("&Analyze", [&](auto&) { // FIXME: Just modify the tree in memory instead of traversing the entire file system - // FIXME: Dispose of the old tree - auto new_tree = adopt_ref(*new Tree("")); - if (auto result = analyze(new_tree, treemapwidget, statusbar); result.is_error()) { + if (auto result = treemapwidget.analyze(statusbar); result.is_error()) { GUI::MessageBox::show_error(window, DeprecatedString::formatted("{}", result.error())); } }))); @@ -197,9 +118,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) } } - // FIXME: Dispose of the old tree - auto new_tree = adopt_ref(*new Tree("")); - if (auto result = analyze(new_tree, treemapwidget, statusbar); result.is_error()) { + if (auto result = treemapwidget.analyze(statusbar); result.is_error()) { GUI::MessageBox::show_error(window, DeprecatedString::formatted("{}", result.error())); } }); @@ -257,7 +176,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) }; // At startup automatically do an analysis of root. - TRY(analyze(tree, treemapwidget, statusbar)); + TRY(treemapwidget.analyze(statusbar)); window->show(); return app->exec(); |