Hi Minh

ack (review only). Perhaps std::getline() could have been used, but it doesn't really matter.


Thanks

Gary


On 24/07/18 08:59, Minh Hon Chau wrote:
Hi,

I would like to push the patch by tomorrow if there's no comment on it.

Thanks

Minh


On 20/07/18 13:33, Minh Chau wrote:
If a process produces a core dump file that has THREAD_TRACE_BUFFER
enabled, this option reads the core dump file to extract the trace
strings in all threads and writes them to the trace file.
---
  src/base/log_writer.h    |   3 +-
  src/dtm/tools/osaflog.cc | 100 +++++++++++++++++++++++++++++++++++++++++++++--
  2 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/src/base/log_writer.h b/src/base/log_writer.h
index a7c5000..0a03e92 100644
--- a/src/base/log_writer.h
+++ b/src/base/log_writer.h
@@ -45,6 +45,7 @@ class LogWriter {
    void Write(size_t size);
    void Write(const char* bytes, size_t size);
    void Flush();
+  void SetLogFile(const std::string& log_file) { log_file_ = log_file; }
     private:
    constexpr static const size_t kBufferSize = 128 * size_t{1024};
@@ -54,7 +55,7 @@ class LogWriter {
      std::string log_file(size_t backup) const;
  -  const std::string log_file_;
+  std::string log_file_;
    int fd_;
    size_t current_file_size_;
    size_t current_buffer_size_;
diff --git a/src/dtm/tools/osaflog.cc b/src/dtm/tools/osaflog.cc
index c5946ee..87deecb 100644
--- a/src/dtm/tools/osaflog.cc
+++ b/src/dtm/tools/osaflog.cc
@@ -27,10 +27,15 @@
  #include <cstdio>
  #include <cstdlib>
  #include <cstring>
+#include <algorithm>
+#include <fstream>
  #include <list>
  #include <memory>
  #include <random>
  #include <string>
+#include <vector>
+#include "base/logtrace_buffer.h"
+#include "base/log_writer.h"
  #include "base/string_parse.h"
  #include "base/time.h"
  #include "base/unix_server_socket.h"
@@ -53,7 +58,7 @@ std::string PathName(const std::string& log_stream, int suffix);
  uint64_t GetInode(int fd);
  bool PrettyPrint(FILE* stream);
  bool PrettyPrint(const char* line, size_t size);
-
+int ExtractTrace(const std::string& core_file, const std::string& trace_file);
  char buf[65 * 1024];
    }  // namespace
@@ -64,6 +69,7 @@ int main(int argc, char** argv) {
                                    {"flush", no_argument, 0, 'f'},
                                    {"print", no_argument, nullptr, 'p'},                                     {"delete", no_argument, nullptr, 'd'}, +                                  {"extract-trace", required_argument, 0, 'e'},
                                    {0, 0, 0, 0}};
      uint64_t max_file_size = 0;
@@ -81,13 +87,16 @@ int main(int argc, char** argv) {
    bool delete_set = false;
    bool max_file_size_set = false;
    bool max_backups_set = false;
+  bool thread_trace = false;
+  std::string input_core = "";
+  std::string output_trace = "";
      if (argc == 1) {
       PrintUsage(argv[0]);
       exit(EXIT_FAILURE);
    }
  -  while ((option = getopt_long(argc, argv, "m:b:p:f",
+  while ((option = getopt_long(argc, argv, "m:b:p:f:e:",
                     long_options, &long_index)) != -1) {
          switch (option) {
               case 'p':
@@ -115,11 +124,33 @@ int main(int argc, char** argv) {
                       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));
+
    if (argc > optind && !pretty_print_set && !delete_set) {
      pretty_print_set = true;
      flush_set = true;
@@ -183,7 +214,13 @@ void PrintUsage(const char* program_name) {
            "                      G can be used for kilo-, mega- and\n"
            "                      gigabytes.\n"
            "--max-backups=NUM     Set the maximum number of backup files to\n"
-          "                      retain during log rotation to NUM.\n",
+          "                      retain during log rotation to NUM.\n"
+          "--extract-trace <corefile> <tracefile>\n"
+          "                      If a process produces a core dump file has\n" +          "                      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",
            program_name);
  }
  @@ -386,4 +423,61 @@ bool PrettyPrint(const char* line, size_t size) {
    return true;
  }
  +int SearchStringInFile(std::ifstream& stream, const char* str) {
+  int rc = 0;
+  int len = strlen(str);
+  int i;
+  while (!stream.eof() && rc == 0) {
+    for (i = 0; i < len; i++) {
+      char c;
+      if (!stream.get(c) || str[i] != c) break;
+    }
+    if (i == len) rc = 1;
+  }
+  return rc;
+}
+
+int ExtractTrace(const std::string& core_file,
+    const std::string& trace_file) {
+  std::vector<std::string> v_str{};
+  std::ifstream corefile_stream {core_file, std::ifstream::binary};
+  // extract
+  if (!corefile_stream.fail()) {
+    while (!corefile_stream.eof()) {
+      int s = SearchStringInFile(corefile_stream,
+          LogTraceBuffer::kLogTraceString);
+      if (s == 1) {
+        char ch = '\0';
+        std::string str;
+        while (corefile_stream.get(ch) && ch != '\n') str += ch;
+        str += '\n';
+        v_str.push_back(str);
+      }
+    }
+    corefile_stream.close();
+  } else {
+    fprintf(stderr, "Failed to open coredump file\n");
+    return EXIT_FAILURE;
+  }
+  if (v_str.size() == 0) {
+    fprintf(stderr, "No trace string is found in coredump file\n");
+    return EXIT_FAILURE;
+  }
+  // sort by sequenceId
+  std::sort(v_str.begin(), v_str.end(),
+            [](const std::string a, const std::string b) -> bool {
+            int seqa, seqb;
+            std::sscanf(a.c_str(),"%*s %*s %*s %*s %*s %*s %*s "
+                "sequenceId=\"%d\"]", &seqa);
+            std::sscanf(b.c_str(),"%*s %*s %*s %*s %*s %*s %*s "
+                "sequenceId=\"%d\"]", &seqb);
+            return a < b;
+            });
+  // write
+  LogWriter log_writer{"", 1, LogWriter::kMaxFileSize_10MB};
+  log_writer.SetLogFile(trace_file);
+  for (auto str : v_str) log_writer.Write(str.c_str(), str.length());
+  log_writer.Flush();
+  return EXIT_SUCCESS;
+}
  }  // namespace



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to