From 131ebc5f3643cfe50106b060f6a10213f1013f94 Mon Sep 17 00:00:00 2001
From: Michael Davis <michael.davis@cern.ch>
Date: Wed, 19 Jun 2019 16:11:58 +0200
Subject: [PATCH] [cta-admin] Implements streaming version of "cta-admin admin
 ls"

---
 cmdline/CtaAdminCmd.cpp                   |  5 +++-
 cmdline/CtaAdminTextFormatter.cpp         | 35 +++++++++++++++++++++++
 cmdline/CtaAdminTextFormatter.hpp         |  2 ++
 xroot_plugins/XrdSsiCtaRequestMessage.cpp | 35 +++++++----------------
 xroot_plugins/XrdSsiCtaRequestMessage.hpp |  2 +-
 5 files changed, 53 insertions(+), 26 deletions(-)

diff --git a/cmdline/CtaAdminCmd.cpp b/cmdline/CtaAdminCmd.cpp
index 631ceaa758..78932e112f 100644
--- a/cmdline/CtaAdminCmd.cpp
+++ b/cmdline/CtaAdminCmd.cpp
@@ -71,6 +71,7 @@ void IStreamBuffer<cta::xrd::Data>::DataCallback(cta::xrd::Data record) const
       std::cout << CtaAdminCmd::jsonDelim();
 
       switch(record.data_case()) {
+         case Data::kAdlsItem:      std::cout << Log::DumpProtobuf(&record.adls_item());    break;
          case Data::kAflsItem:      std::cout << Log::DumpProtobuf(&record.afls_item());    break;
          case Data::kAflsSummary:   std::cout << Log::DumpProtobuf(&record.afls_summary()); break;
          case Data::kFrlsItem:      std::cout << Log::DumpProtobuf(&record.frls_item());    break;
@@ -88,7 +89,8 @@ void IStreamBuffer<cta::xrd::Data>::DataCallback(cta::xrd::Data record) const
    }
    // Format results in a tabular format for a human
    else switch(record.data_case()) {
-         case Data::kAflsItem:      formattedText.print(record.afls_item());     break;
+         case Data::kAdlsItem:      formattedText.print(record.adls_item());    break;
+         case Data::kAflsItem:      formattedText.print(record.afls_item());    break;
          case Data::kAflsSummary:   formattedText.print(record.afls_summary()); break;
          case Data::kFrlsItem:      formattedText.print(record.frls_item());    break;
          case Data::kFrlsSummary:   formattedText.print(record.frls_summary()); break;
@@ -232,6 +234,7 @@ void CtaAdminCmd::send() const
          std::cout << response.message_txt();
          // Print streaming response header
          if(!isJson()) switch(response.show_header()) {
+            case HeaderType::ADMIN_LS:                     formattedText.printAdLsHeader(); break;
             case HeaderType::ARCHIVEFILE_LS:               formattedText.printAfLsHeader(); break;
             case HeaderType::ARCHIVEFILE_LS_SUMMARY:       formattedText.printAfLsSummaryHeader(); break;
             case HeaderType::FAILEDREQUEST_LS:             formattedText.printFrLsHeader(); break;
diff --git a/cmdline/CtaAdminTextFormatter.cpp b/cmdline/CtaAdminTextFormatter.cpp
index fe579e5aad..7d05b40499 100644
--- a/cmdline/CtaAdminTextFormatter.cpp
+++ b/cmdline/CtaAdminTextFormatter.cpp
@@ -24,6 +24,10 @@
 
 namespace cta { namespace admin {
 
+/**
+ ** Generic utility methods
+ **/
+
 std::string TextFormatter::doubleToStr(double value, char unit) {
   std::stringstream ss;
   ss << std::fixed << std::setprecision(1) << value << unit;
@@ -101,6 +105,37 @@ void TextFormatter::flush() {
 }
 
 
+/**
+ ** Output for specific commands
+ **/
+
+void TextFormatter::printAdLsHeader() {
+  push_back("HEADER");
+  push_back(
+    "user",
+    "c.user",
+    "c.host", 
+    "c.time",
+    "m.user",
+    "m.host",
+    "m.time",
+    "comment"
+  );
+}
+
+void TextFormatter::print(const cta::admin::AdminLsItem &adls_item) {
+  push_back(
+    adls_item.user(),
+    adls_item.creation_log().username(),
+    adls_item.creation_log().host(),
+    timeToStr(adls_item.creation_log().time()),
+    adls_item.last_modification_log().username(),
+    adls_item.last_modification_log().host(),
+    timeToStr(adls_item.last_modification_log().time()),
+    adls_item.comment()
+  );
+}
+
 void TextFormatter::printAfLsHeader() {
   push_back("HEADER");
   push_back(
diff --git a/cmdline/CtaAdminTextFormatter.hpp b/cmdline/CtaAdminTextFormatter.hpp
index 4024128764..808c87b896 100644
--- a/cmdline/CtaAdminTextFormatter.hpp
+++ b/cmdline/CtaAdminTextFormatter.hpp
@@ -44,6 +44,7 @@ public:
   }
 
   // Output headers
+  void printAdLsHeader();
   void printAfLsHeader();
   void printAfLsSummaryHeader();
   void printFrLsHeader();
@@ -57,6 +58,7 @@ public:
   void printRepackLsHeader();
    
   // Output records
+  void print(const AdminLsItem &adls_item);
   void print(const ArchiveFileLsItem &afls_item);
   void print(const ArchiveFileLsSummary &afls_summary);
   void print(const FailedRequestLsItem &frls_item);
diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.cpp b/xroot_plugins/XrdSsiCtaRequestMessage.cpp
index 5b73e2aa9d..1f4b5775ed 100644
--- a/xroot_plugins/XrdSsiCtaRequestMessage.cpp
+++ b/xroot_plugins/XrdSsiCtaRequestMessage.cpp
@@ -25,6 +25,7 @@
 using XrdSsiPb::PbException;
 
 #include <cmdline/CtaAdminCmdParse.hpp>
+#include "XrdCtaAdminLs.hpp"
 #include "XrdCtaArchiveFileLs.hpp"
 #include "XrdCtaFailedRequestLs.hpp"
 #include "XrdCtaListPendingQueue.hpp"
@@ -112,7 +113,7 @@ void RequestMessage::process(const cta::xrd::Request &request, cta::xrd::Respons
                processAdmin_Rm(response);
                break;
             case cmd_pair(AdminCmd::CMD_ADMIN, AdminCmd::SUBCMD_LS):
-               processAdmin_Ls(response);
+               processAdmin_Ls(response, stream);
                break;
             case cmd_pair(AdminCmd::CMD_ARCHIVEFILE, AdminCmd::SUBCMD_LS):
                processArchiveFile_Ls(response, stream);
@@ -679,33 +680,19 @@ void RequestMessage::processAdmin_Rm(cta::xrd::Response &response)
 
 
 
-void RequestMessage::processAdmin_Ls(cta::xrd::Response &response)
+void RequestMessage::processAdmin_Ls(cta::xrd::Response &response, XrdSsiStream* &stream)
 {
-   using namespace cta::admin;
-
-   std::stringstream cmdlineOutput;
+  using namespace cta::admin;
 
-   std::list<cta::common::dataStructures::AdminUser> list= m_catalogue.getAdminUsers();
+  // Create a XrdSsi stream object to return the results
+  stream = new AdminLsStream(*this, m_catalogue, m_scheduler);
 
-   if(!list.empty())
-   {
-      std::vector<std::vector<std::string>> responseTable;
-      std::vector<std::string> header = {
-         "user","c.user","c.host","c.time","m.user","m.host","m.time","comment"
-      };
-      if(has_flag(OptionBoolean::SHOW_HEADER)) responseTable.push_back(header);    
-      for(auto it = list.cbegin(); it != list.cend(); it++) {
-         std::vector<std::string> currentRow;
-         currentRow.push_back(it->name);
-         addLogInfoToResponseRow(currentRow, it->creationLog, it->lastModificationLog);
-         currentRow.push_back(it->comment);
-         responseTable.push_back(currentRow);
-      }
-      cmdlineOutput << formatResponse(responseTable);
-   }
+  // Should the client display column headers?
+  if(has_flag(OptionBoolean::SHOW_HEADER)) {
+    response.set_show_header(HeaderType::ADMIN_LS);
+  }
 
-   response.set_message_txt(cmdlineOutput.str());
-   response.set_type(cta::xrd::Response::RSP_SUCCESS);
+  response.set_type(cta::xrd::Response::RSP_SUCCESS);
 }
 
 
diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.hpp b/xroot_plugins/XrdSsiCtaRequestMessage.hpp
index 0f690ab4a4..7d660c4e83 100644
--- a/xroot_plugins/XrdSsiCtaRequestMessage.hpp
+++ b/xroot_plugins/XrdSsiCtaRequestMessage.hpp
@@ -153,7 +153,6 @@ private:
    void processAdmin_Add             (cta::xrd::Response &response);
    void processAdmin_Ch              (cta::xrd::Response &response);
    void processAdmin_Rm              (cta::xrd::Response &response);
-   void processAdmin_Ls              (cta::xrd::Response &response);
    void processArchiveRoute_Add      (cta::xrd::Response &response);
    void processArchiveRoute_Ch       (cta::xrd::Response &response);
    void processArchiveRoute_Rm       (cta::xrd::Response &response);
@@ -205,6 +204,7 @@ private:
     */
    typedef void admincmdstream_t(cta::xrd::Response &response, XrdSsiStream* &stream);
 
+   admincmdstream_t processAdmin_Ls;
    admincmdstream_t processArchiveFile_Ls;
    admincmdstream_t processFailedRequest_Ls;
    admincmdstream_t processListPendingArchives;
-- 
GitLab