Hi Vu,

No problem, I hope users will get the meaning of "clean-up job" :).

Thanks

Minh

On 1/10/19 8:46 pm, Nguyen Minh Vu wrote:
Hi Minh,

I put that note in the usage of max-idle option. See below:

+          "--max-idle=NUM        Set the maximum number of idle time to NUM\n" +          "                      minutes. If a stream has not been used for\n" +          "                      NUM minutes, the stream will be closed.\n" +          "                      The default value is zero (disable the\n"
+          "                      clean-up job)\n",

Regards, Vu

On 10/1/19 5:38 PM, Minh Hon Chau wrote:
Hi Vu,

Ok, then the value '0' needs to be written somewhere (README?) for this special purpose I guess, to avoid a confusion later on.

Thanks

Minh

On 1/10/19 8:27 pm, Nguyen Minh Vu wrote:
Hi Minh,

Thanks for your comment.

When passing zero to max-idle, the server will disable 'close unused log streams' functionality. It may be useful when user has previously set max-idle to a specific value, and want to disable it later.

If the range starts from 1, there is no chance to disable it.

Regards, Vu

On 10/1/19 5:17 PM, Minh Hon Chau wrote:
Hi Vu,

ack for minor comment.

The range of --max-idle, I think, should be starting from 1, as the log_server ignores the tv_sec=0. From user's perspective, if allowing max-idle=0, the meaning seems that the stream must be constantly writing traces, or the stream will be deleted.

Thanks

Minh

On 24/9/19 12:57 pm, Vu Minh Nguyen wrote:
Providing a new option '--max-idle' to configure the maximum idle time of logtrace streams. If a stream has not been used for such time, logtrace
server will close the stream from its database.

This patch also corrects wrong indentation in osaflog.cc file.
---
  src/dtm/Makefile                  |   2 +-
  src/dtm/common/osaflog_protocol.h |   2 +
  src/dtm/tools/Makefile            |  18 ++++
  src/dtm/tools/osaflog.cc          | 132 ++++++++++++++++++------------
  src/dtm/transport/log_server.cc   |  57 ++++++++++++-
  src/dtm/transport/log_server.h    |   7 +-
  src/dtm/transport/transportd.conf |   6 ++
  7 files changed, 168 insertions(+), 56 deletions(-)
  create mode 100644 src/dtm/tools/Makefile

diff --git a/src/dtm/Makefile b/src/dtm/Makefile
index 533b0f273..fb0221075 100644
--- a/src/dtm/Makefile
+++ b/src/dtm/Makefile
@@ -15,7 +15,7 @@
  #
    all:
-    $(MAKE) -C ../.. bin/osafdtmd bin/osaftransportd
+    $(MAKE) -C ../.. bin/osafdtmd bin/osaftransportd bin/osaflog
    check:
      $(MAKE) -C ../.. bin/transport_test
diff --git a/src/dtm/common/osaflog_protocol.h b/src/dtm/common/osaflog_protocol.h
index 61e9f6f39..d35e5f345 100644
--- a/src/dtm/common/osaflog_protocol.h
+++ b/src/dtm/common/osaflog_protocol.h
@@ -27,6 +27,8 @@ namespace Osaflog {
  static constexpr const char* kServerSocketPath =
      PKGLOCALSTATEDIR "/osaf_log.sock";
  +static constexpr const uint64_t kOneDayInMinute = 24*60;
+
  struct __attribute__((__packed__)) ClientAddressConstantPrefix {
    sa_family_t family = AF_UNIX;
    char abstract = '\0';
diff --git a/src/dtm/tools/Makefile b/src/dtm/tools/Makefile
new file mode 100644
index 000000000..8c48b70a5
--- /dev/null
+++ b/src/dtm/tools/Makefile
@@ -0,0 +1,18 @@
+#      -*- OpenSAF  -*-
+#
+# (C) Copyright 2019 The OpenSAF Foundation
+#
+# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed +# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson AB
+#
+
+all:
+    $(MAKE) -C ../../.. bin/osaflog
diff --git a/src/dtm/tools/osaflog.cc b/src/dtm/tools/osaflog.cc
index 64be253e9..abbf0b164 100644
--- a/src/dtm/tools/osaflog.cc
+++ b/src/dtm/tools/osaflog.cc
@@ -47,6 +47,7 @@ namespace {
  void PrintUsage(const char* program_name);
  bool SendCommand(const std::string& command);
  bool MaxTraceFileSize(uint64_t max_file_size);
+bool SetMaxIdleTime(uint64_t max_idle);
  bool NoOfBackupFiles(uint64_t number_of_backups);
  bool Flush();
  base::UnixServerSocket* CreateSocket();
@@ -70,10 +71,12 @@ int main(int argc, char** argv) {
                                    {"print", no_argument, nullptr, 'p'},                                     {"delete", no_argument, nullptr, 'd'},                                     {"extract-trace", required_argument, 0, 'e'}, +                                  {"max-idle", required_argument, 0, 'i'},
                                    {0, 0, 0, 0}};
      uint64_t max_file_size = 0;
    uint64_t max_backups = 0;
+  uint64_t max_idle = 0;
    int option = 0;
      int long_index = 0;
@@ -82,71 +85,81 @@ int main(int argc, char** argv) {
    bool delete_result =  true;
    bool max_file_size_result = true;
    bool number_of_backups_result = true;
+  bool max_idle_result = true;
    bool flush_set = false;
    bool pretty_print_set = false;
    bool delete_set = false;
    bool max_file_size_set = false;
    bool max_backups_set = false;
+  bool max_idle_set = false;
    bool thread_trace = false;
    std::string input_core = "";
    std::string output_trace = "";
      if (argc == 1) {
-     PrintUsage(argv[0]);
-     exit(EXIT_FAILURE);
+    PrintUsage(argv[0]);
+    exit(EXIT_FAILURE);
    }
      while ((option = getopt_long(argc, argv, "m:b:p:f:e:",
-                   long_options, &long_index)) != -1) {
-        switch (option) {
-             case 'p':
-                   pretty_print_set = true;
-                   flush_set = true;
-                 break;
-             case 'd':
-                   delete_set = true;
-                 break;
-             case 'f':
-                   flush_set = true;
-                 break;
-             case 'm':
-                   max_file_size = base::StrToUint64(optarg,
- &max_file_size_set);
-                   if (!max_file_size_set || max_file_size > SIZE_MAX) { -                     fprintf(stderr, "Illegal max-file-size argument\n");
-                     exit(EXIT_FAILURE);
-                   }
-                 break;
-             case 'b':
-                   max_backups = base::StrToUint64(optarg, &max_backups_set);
-                   if (!max_backups_set || max_backups > SIZE_MAX) {
-                     fprintf(stderr, "Illegal max-backups argument\n");
-                     exit(EXIT_FAILURE);
-                   }
-                 break;
-             case 'e':
-                   if (argv[optind] == nullptr || optarg == nullptr) { -                     fprintf(stderr, "Coredump file or output trace file is "
-                         "not specified in arguments\n");
-                     exit(EXIT_FAILURE);
-                   }
-                   input_core = std::string(optarg);
-                   output_trace = std::string(argv[optind]);
-                   struct stat statbuf;
-                   if (stat(input_core.c_str(), &statbuf) != 0) {
-                    fprintf(stderr, "Core dump file does not exist\n");
-                    exit(EXIT_FAILURE);
-                   }
-
-                   if (stat(output_trace.c_str(), &statbuf) == 0) {
-                     fprintf(stderr, "Output trace file already exists\n");
-                     exit(EXIT_FAILURE);
-                   }
-                   thread_trace = true;
-                   break;
-             default: PrintUsage(argv[0]);
-                 exit(EXIT_FAILURE);
+                               long_options, &long_index)) != -1) {
+    switch (option) {
+      case 'p':
+        pretty_print_set = true;
+        flush_set = true;
+        break;
+      case 'd':
+        delete_set = true;
+        break;
+      case 'f':
+        flush_set = true;
+        break;
+      case 'm':
+        max_file_size = base::StrToUint64(optarg,
+ &max_file_size_set);
+        if (!max_file_size_set || max_file_size > SIZE_MAX) {
+          fprintf(stderr, "Illegal max-file-size argument\n");
+          exit(EXIT_FAILURE);
+        }
+        break;
+      case 'b':
+        max_backups = base::StrToUint64(optarg, &max_backups_set);
+        if (!max_backups_set || max_backups > SIZE_MAX) {
+          fprintf(stderr, "Illegal max-backups argument\n");
+          exit(EXIT_FAILURE);
+        }
+        break;
+      case 'i':
+        max_idle = base::StrToUint64(optarg, &max_idle_set);
+        if (!max_idle_set || max_idle > Osaflog::kOneDayInMinute) {
+          fprintf(stderr, "Illegal max-idle argument."
+                  " Valid value is in the range [0-24*60]\n");
+          exit(EXIT_FAILURE);
+        }
+        break;
+      case 'e':
+        if (argv[optind] == nullptr || optarg == nullptr) {
+          fprintf(stderr, "Coredump file or output trace file is "
+                  "not specified in arguments\n");
+          exit(EXIT_FAILURE);
+        }
+        input_core = std::string(optarg);
+        output_trace = std::string(argv[optind]);
+        struct stat statbuf;
+        if (stat(input_core.c_str(), &statbuf) != 0) {
+          fprintf(stderr, "Core dump file does not exist\n");
+          exit(EXIT_FAILURE);
          }
+
+        if (stat(output_trace.c_str(), &statbuf) == 0) {
+          fprintf(stderr, "Output trace file already exists\n");
+          exit(EXIT_FAILURE);
+        }
+        thread_trace = true;
+        break;
+      default: PrintUsage(argv[0]);
+        exit(EXIT_FAILURE);
+    }
    }
      if (thread_trace) exit(ExtractTrace(input_core, output_trace));
@@ -181,8 +194,11 @@ int main(int argc, char** argv) {
    if (max_file_size_set == true) {
       max_file_size_result = MaxTraceFileSize(max_file_size);
    }
+  if (max_idle_set == true) {
+    max_idle_result = SetMaxIdleTime(max_idle);
+  }
    if (flush_result && print_result && max_file_size_result &&
-      delete_result && number_of_backups_result)
+      delete_result && number_of_backups_result && max_idle_result)
       exit(EXIT_SUCCESS);
    exit(EXIT_FAILURE);
  }
@@ -220,7 +236,12 @@ void PrintUsage(const char* program_name) {
            "                      THREAD_TRACE_BUFFER enabled, this option\n"             "                      reads the <corefile> to extract the trace\n"             "                      strings in all threads and writes them to\n"
-          "                      the <tracefile> file.\n",
+          "                      the <tracefile> file.\n"
+          "--max-idle=NUM        Set the maximum number of idle time to NUM\n" +          "                      minutes. If a stream has not been used for\n" +          "                      NUM minutes, the stream will be closed.\n" +          "                      The default value is zero (disable the\n"
+          "                      clean-up job)\n",
            program_name);
  }
  @@ -297,6 +318,11 @@ bool NoOfBackupFiles(uint64_t max_backups) {
    return SendCommand(std::string("max-backups ") + std::to_string(max_backups));
  }
  +bool SetMaxIdleTime(uint64_t max_idle) {
+  return SendCommand(std::string("max-idle-time ") +
+                     std::to_string(max_idle));
+}
+
  bool Flush() {
    return SendCommand(std::string{"flush"});
  }
diff --git a/src/dtm/transport/log_server.cc b/src/dtm/transport/log_server.cc
index 43fa86a89..51a0a582c 100644
--- a/src/dtm/transport/log_server.cc
+++ b/src/dtm/transport/log_server.cc
@@ -44,6 +44,7 @@ LogServer::LogServer(int term_fd)
    LogServer::~LogServer() {
    for (const auto& s : log_streams_) delete s.second;
+  log_streams_.clear();
  }
    void LogServer::Run() {
@@ -77,6 +78,9 @@ void LogServer::Run() {
          ExecuteCommand(buffer, result, src_addr, addrlen);
        }
      }
+
+    CloseIdleStreams();
+
      struct timespec current = base::ReadMonotonicClock();
      struct timespec last_flush = current;
      bool empty = true;
@@ -91,11 +95,40 @@ void LogServer::Run() {
        if (!stream->empty()) empty = false;
      }
      struct timespec timeout = (last_flush + base::kFifteenSeconds) - current;
+    struct timespec* poll_timeout = &timeout;
+    if (empty && log_streams_.size() > 1) {
+      uint64_t max_idle = max_idle_time_.tv_sec;
+      poll_timeout = (max_idle) ? &max_idle_time_ : nullptr;
+    }
      pfd[1].fd = log_socket_.fd();
-    osaf_ppoll(pfd, 2, empty ? nullptr : &timeout, nullptr);
+    osaf_ppoll(pfd, 2, poll_timeout, nullptr);
    } while ((pfd[0].revents & POLLIN) == 0);
  }
  +void LogServer::CloseIdleStreams() {
+  if (max_idle_time_.tv_sec == 0) return;
+
+  struct timespec current = base::ReadMonotonicClock();
+  auto it = log_streams_.begin();
+  while (it != log_streams_.end()) {
+    LogStream* stream = it->second;
+    struct timespec last_write = stream->last_write();
+    std::string name = stream->name();
+    if ((current - last_write) >= max_idle_time_
+        && name != kMdsLogStreamName) {
+      syslog(LOG_NOTICE, "Deleted the idle stream: %s", name.c_str());
+      if (current_stream_ == stream) {
+        current_stream_ = log_streams_.begin()->second;
+      }
+      it = log_streams_.erase(it);
+      delete stream;
+      no_of_log_streams_--;
+    } else {
+      it++;
+    }
+  }
+}
+
  LogServer::LogStream* LogServer::GetStream(const char* msg_id,
                                             size_t msg_id_size) {
    if (msg_id_size == current_stream_->log_name_size() &&
@@ -176,6 +209,19 @@ bool LogServer::ReadConfig(const char *transport_config_file) {
                 "has illegal value '%s'", &line[tag_len]);
        }
      }
+
+    if (strncmp(line, "TRANSPORT_MAX_IDLE_TIME=",
+                strlen("TRANSPORT_MAX_IDLE_TIME=")) == 0) {
+      tag_len = strlen("TRANSPORT_MAX_IDLE_TIME=");
+      bool success;
+      uint64_t max_idle_time = base::StrToUint64(&line[tag_len], &success);
+      if (success && max_idle_time <= Osaflog::kOneDayInMinute) {
+        max_idle_time_.tv_sec = max_idle_time;
+      } else {
+        syslog(LOG_ERR, "TRANSPORT_MAX_IDLE_TIME "
+               "has illegal value '%s'", &line[tag_len]);
+      }
+    }
    }
      /* Close file. */
@@ -258,6 +304,13 @@ std::string LogServer::ExecuteCommand(const std::string& command,
        stream->Flush();
      }
      return std::string{"!flush"};
+  } else if (command == "?max-idle-time") {
+      bool success = false;
+      uint64_t max_idle_time = base::StrToUint64(argument.c_str(), &success);
+      if (success && max_idle_time <= Osaflog::kOneDayInMinute) {
+        max_idle_time_.tv_sec = max_idle_time*60;
+      }
+      return std::string{"!max-idle-time " + std::to_string(max_idle_time)};
    } else {
      return std::string{"!not_supported"};
    }
@@ -268,11 +321,13 @@ LogServer::LogStream::LogStream(const std::string& log_name,       : log_name_{log_name}, last_flush_{}, log_writer_{log_name, max_backups,
max_file_size} {
    if (log_name.size() > kMaxLogNameSize) osaf_abort(log_name.size());
+  last_write_ = base::ReadMonotonicClock();
  }
    void LogServer::LogStream::Write(size_t size) {
    if (log_writer_.empty()) last_flush_ = base::ReadMonotonicClock();
    log_writer_.Write(size);
+  last_write_ = base::ReadMonotonicClock();
  }
    void LogServer::LogStream::Flush() {
diff --git a/src/dtm/transport/log_server.h b/src/dtm/transport/log_server.h
index 283509cc7..65b95b9b0 100644
--- a/src/dtm/transport/log_server.h
+++ b/src/dtm/transport/log_server.h
@@ -46,6 +46,7 @@ class LogServer {
    // process has received the SIGTERM signal, which is indicated by the caller
    // by making the term_fd (provided in the constructor) readable.
    void Run();
+  void CloseIdleStreams();
    // To read Transportd.conf
    bool ReadConfig(const char *transport_config_file);
  @@ -55,7 +56,7 @@ class LogServer {
      static constexpr size_t kMaxLogNameSize = 32;
      LogStream(const std::string& log_name, size_t max_backups,
                                                   size_t max_file_size);
-
+    ~LogStream() { Flush(); }
      size_t log_name_size() const { return log_name_.size(); }
      const char* log_name_data() const { return log_name_.data(); }
      char* current_buffer_position() {
@@ -68,6 +69,8 @@ class LogServer {
      // I/O.
      void Write(size_t size);
      void Flush();
+    const char* name() const { return log_name_.c_str(); }
+    struct timespec last_write() const { return last_write_; }
      struct timespec last_flush() const {
        return last_flush_;
      }
@@ -75,6 +78,7 @@ class LogServer {
     private:
      const std::string log_name_;
      struct timespec last_flush_;
+    struct timespec last_write_;
      LogWriter log_writer_;
    };
    LogStream* GetStream(const char* msg_id, size_t msg_id_size);
@@ -95,6 +99,7 @@ class LogServer {
    // Configuration for LogServer
    size_t max_backups_;
    size_t max_file_size_;
+  struct timespec max_idle_time_{0, 0};
      base::UnixServerSocket log_socket_;
    std::map<std::string, LogStream*> log_streams_;
diff --git a/src/dtm/transport/transportd.conf b/src/dtm/transport/transportd.conf
index 23e87a0a1..0746c1775 100644
--- a/src/dtm/transport/transportd.conf
+++ b/src/dtm/transport/transportd.conf
@@ -11,3 +11,9 @@
  # be done based on this value. Default value will be 9
  # i.e totally 10 log files will be maintain.
  #TRANSPORT_MAX_BACKUPS=9
+
+#
+# TRANSPORT_MAX_IDLE_TIME: Number of idle time. If a stream has not been used +# for this number minutes (e.g: trace was disabled using SIGUSR2), the stream
+# will be closed. A valid value is in the range [0-24*60].
+#TRANSPORT_MAX_IDLE_TIME=0






_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to