diff --git a/source/src/commands/help.cpp b/source/src/commands/help.cpp index d32414d..4c8238d 100644 --- a/source/src/commands/help.cpp +++ b/source/src/commands/help.cpp @@ -146,6 +146,9 @@ int help_handler(const CommandContext& ctx) { show_command("start"); show_command("stop"); info << std::endl; + show_command("disable"); + show_command("enable"); + info << std::endl; show_command("ssh"); info << std::endl; show_command("create-server"); diff --git a/source/src/commands/list.cpp b/source/src/commands/list.cpp index b73fc1c..b5a82d0 100644 --- a/source/src/commands/list.cpp +++ b/source/src/commands/list.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace dropshell { @@ -96,6 +97,8 @@ void list_servers() { // mutex for the tableprint std::mutex tp_mutex; + // mutex for server status maps + std::mutex status_mutex; info << "Checking "< server_online_status; + // Pre-compute disabled status to avoid threading issues with config access + std::set disabled_servers; + for (const auto& disabled : gConfig().get_disabled_servers()) { + disabled_servers.insert(disabled); + } transwarp::parallel exec{server_user_pairs.size()}; auto task = transwarp::for_each(exec, server_user_pairs.begin(), server_user_pairs.end(), [&](const server_user_pair& sup) { @@ -118,21 +126,42 @@ void list_servers() { std::string ports_used_str = ""; std::set ports_used; - // Check if server is disabled - bool is_disabled = gConfig().is_server_disabled(sup.server.get_server_name()); + // Check if server is disabled (from pre-computed set, thread-safe read) + bool is_disabled = (disabled_servers.find(sup.server.get_server_name()) != disabled_servers.end()); // Check if server is online (with caching to avoid redundant checks for multiple users) bool is_online = false; if (!is_disabled) { - auto it = server_online_status.find(sup.server.get_server_name()); - if (it != server_online_status.end()) { - is_online = it->second; - } else { + // First check if we already know the status + bool already_checked = false; + { + std::lock_guard lock(status_mutex); + auto it = server_online_status.find(sup.server.get_server_name()); + if (it != server_online_status.end()) { + is_online = it->second; + already_checked = true; + } + } + + // If not already checked, do the SSH check outside the lock + if (!already_checked) { // Quick connectivity check sSSHInfo sshinfo = server_env.get_SSH_INFO(sup.user.user); std::string test_cmd = "true"; - is_online = execute_ssh_command(sshinfo, sCommand("", test_cmd, {}), cMode::Silent); - server_online_status[sup.server.get_server_name()] = is_online; + bool check_result = execute_ssh_command(sshinfo, sCommand("", test_cmd, {}), cMode::Silent); + + // Store the result with lock + { + std::lock_guard lock(status_mutex); + // Check again in case another thread checked it while we were waiting + auto it = server_online_status.find(sup.server.get_server_name()); + if (it == server_online_status.end()) { + server_online_status[sup.server.get_server_name()] = check_result; + is_online = check_result; + } else { + is_online = it->second; + } + } } } @@ -149,18 +178,22 @@ void list_servers() { ports_used_str += std::to_string(port) + " "; } - // Add red cross to address if server is offline or disabled + // Add red cross to address if server is offline std::string address_display = sup.server.get_SSH_HOST(); - if (is_disabled) { - address_display += " :disabled:"; - } else if (!is_online) { + if (!is_online && !is_disabled) { address_display += " :cross:"; } + // Add disabled marker to server name (invisible, used for row coloring) + std::string server_name_display = sup.server.get_server_name(); + if (is_disabled) { + server_name_display += ":disabled:"; + } + // critical section { std::lock_guard lock(tp_mutex); - tp.add_row({sup.server.get_server_name(), address_display, sup.user.user, serviceticks, ports_used_str}); + tp.add_row({server_name_display, address_display, sup.user.user, serviceticks, ports_used_str}); ++checked; } // print out a tick character for each server checked. diff --git a/source/src/utils/tableprint.cpp b/source/src/utils/tableprint.cpp index 2d8ad19..eec432e 100644 --- a/source/src/utils/tableprint.cpp +++ b/source/src/utils/tableprint.cpp @@ -40,7 +40,8 @@ const std::map kReplacements = { {":error:", {"!", kTextColor_Red}}, {":question:", {"?", kTextColor_DarkGrey}}, {":greytick:", {"+", kTextColor_LightGrey}}, - {":greycross:", {"x", kTextColor_LightGrey}} + {":greycross:", {"x", kTextColor_LightGrey}}, + {":disabled:", {"", kTextColor_DarkGrey}} // Special marker for disabled rows }; // Helper function to get ANSI color code @@ -285,11 +286,26 @@ void tableprint::print() { // Print rows for (size_t row_idx = 1; row_idx < rows.size(); ++row_idx) { const auto& row = rows[row_idx]; + + // Check if this row contains :disabled: marker + bool is_disabled = false; + for (const auto& cell : row) { + if (cell.find(":disabled:") != std::string::npos) { + is_disabled = true; + break; + } + } + dropshell::info << "\033[90m"; // Dark grey color for borders dropshell::info << "|"; for (size_t i = 0; i < row.size(); ++i) { // Set the appropriate color for the row - std::string rowcolor = (row_idx % 2 == 1) ? "\033[38;5;142m" : "\033[38;5;250m"; + std::string rowcolor; + if (is_disabled) { + rowcolor = "\033[90m"; // Dark grey for disabled servers + } else { + rowcolor = (row_idx % 2 == 1) ? "\033[38;5;142m" : "\033[38;5;250m"; + } dropshell::info << width_print_left(row[i],col_widths[i]+2,rowcolor); dropshell::info << "\033[90m" << "|"; }