diff --git a/cmdline/CtaAdminTextFormatter.cpp b/cmdline/CtaAdminTextFormatter.cpp index 9168b51b3db0228f2ed0079d36acb5456f75f290..14d5cdbe266001c388da718d5737f16c7a8d107a 100644 --- a/cmdline/CtaAdminTextFormatter.cpp +++ b/cmdline/CtaAdminTextFormatter.cpp @@ -37,6 +37,26 @@ std::string timeToString(const time_t &time) } +std::string TextFormatter::getDataSize(uint64_t value) { + const std::vector<char> suffix = { 'E', 'P', 'T', 'G', 'M', 'K' }; + + // Simple case, values less than 1000 bytes don't take a suffix + if(value < 1000) return std::to_string(value); + + // Find the correct scaling, starting at 1 EB and working down. I'm assuming we won't have + // zettabytes or yottabytes of data in a tapepool anytime soon. + uint64_t divisor; + int unit; + for(unit = 0, divisor = 1'000'000'000'000'000'000; value < divisor; divisor /= 1000, ++unit) ; + + // Convert to format like "3.1G" + std::stringstream ss; + double val_d = static_cast<double>(value) / static_cast<double>(divisor); + ss << std::fixed << std::setprecision(1) << val_d << suffix[unit]; + + return ss.str(); +} + void TextFormatter::flush() { if(m_outputBuffer.empty()) return; @@ -176,11 +196,8 @@ void TextFormatter::print(const cta::admin::FailedRequestLsItem &frls_item) { frls_item.af().df().path() ); - for(auto &errLogMsg : frls_item.failurelogs()) { - push_back( - "", "", "", "", "", errLogMsg - ); - } + // Note: failure log messages are available in frls_item.failurelogs(). These are not currently + // displayed in the text output, only in JSON. } void TextFormatter::printFrLsSummaryHeader() { @@ -427,9 +444,6 @@ void TextFormatter::printTapePoolLsHeader() { void TextFormatter::print(const cta::admin::TapePoolLsItem &tpls_item) { - auto capacity_str = std::to_string(tpls_item.capacity_bytes() / 1000000000) + "G"; - auto data_str = std::to_string(tpls_item.data_bytes() / 1000000000) + "G"; - uint64_t avail = tpls_item.capacity_bytes() > tpls_item.data_bytes() ? tpls_item.capacity_bytes()-tpls_item.data_bytes() : 0; auto avail_str = std::to_string(avail / 1000000000) + "G"; @@ -445,8 +459,8 @@ void TextFormatter::print(const cta::admin::TapePoolLsItem &tpls_item) tpls_item.num_tapes(), tpls_item.num_partial_tapes(), tpls_item.num_physical_files(), - capacity_str, - data_str, + getDataSize(tpls_item.capacity_bytes()), + getDataSize(tpls_item.data_bytes()), avail_str, use_percent_ss.str(), tpls_item.encrypt(), diff --git a/cmdline/CtaAdminTextFormatter.hpp b/cmdline/CtaAdminTextFormatter.hpp index 58284cf42c601054573088a3dbe3bafab6472091..b454d88bb43e14bf1b5024d0edd7d503624d82e0 100644 --- a/cmdline/CtaAdminTextFormatter.hpp +++ b/cmdline/CtaAdminTextFormatter.hpp @@ -81,23 +81,23 @@ private: //! Recursive variadic method to build a log string from an arbitrary number of items of arbitrary type template<typename T, typename... Args> - void buildVector(std::vector<std::string> &line, const T &item, Args... args) { + static void buildVector(std::vector<std::string> &line, const T &item, Args... args) { buildVector(line, item); buildVector(line, args...); } //! Base case method to add one item to the log - void buildVector(std::vector<std::string> &line, const std::string &item) { + static void buildVector(std::vector<std::string> &line, const std::string &item) { line.push_back(item); } //! Base case method to add one item to the log, overloaded for char* - void buildVector(std::vector<std::string> &line, const char *item) { + static void buildVector(std::vector<std::string> &line, const char *item) { line.push_back(std::string(item)); } //! Base case method to add one item to the log, overloaded for bool - void buildVector(std::vector<std::string> &line, bool item) { + static void buildVector(std::vector<std::string> &line, bool item) { line.push_back(item ? "true" : "false"); } @@ -106,10 +106,13 @@ private: * (works for all integer and floating-point types) */ template<typename T> - void buildVector(std::vector<std::string> &line, const T &item) { + static void buildVector(std::vector<std::string> &line, const T &item) { line.push_back(std::to_string(item)); } + //! Convert data size in bytes to abbreviated string with appropriate size suffix (K/M/G/T/P/E) + static std::string getDataSize(uint64_t value); + //! Flush buffer to stdout void flush();