[rtems-tools commit] record: Add Client base class

Sebastian Huber sebh at rtems.org
Tue Sep 3 13:03:18 UTC 2019


Module:    rtems-tools
Branch:    master
Commit:    a124bdb8513615a4be3c9a2cd1e46ee3fd93c7d9
Changeset: http://git.rtems.org/rtems-tools/commit/?id=a124bdb8513615a4be3c9a2cd1e46ee3fd93c7d9

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Aug 30 06:30:28 2019 +0200

record: Add Client base class

Update #3665.

---

 trace/record/client.h              |  70 ++++++++
 trace/record/record-client-base.cc |  90 ++++++++++
 trace/record/record-main-lttng.cc  | 334 ++++++++++++++++---------------------
 trace/wscript                      |   4 +-
 4 files changed, 309 insertions(+), 189 deletions(-)

diff --git a/trace/record/client.h b/trace/record/client.h
new file mode 100644
index 0000000..2d55052
--- /dev/null
+++ b/trace/record/client.h
@@ -0,0 +1,70 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2018, 2019 embedded brains GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RTEMS_TOOLS_TRACE_RECORD_CLIENT_H_
+#define RTEMS_TOOLS_TRACE_RECORD_CLIENT_H_
+
+#include <rtems/recordclient.h>
+#include <rtems/recorddata.h>
+
+#include <sys/types.h>
+
+#include <csignal>
+
+class Client {
+ public:
+  Client() = default;
+
+  Client(const Client&) = delete;
+
+  Client& operator=(const Client&) = delete;
+
+  void Open(const char* file);
+
+  void Connect(const char* host, uint16_t port);
+
+  void Run();
+
+  void RequestStop() { stop_ = 1; }
+
+  void Destroy();
+
+ protected:
+  void Initialize(rtems_record_client_handler handler) {
+    rtems_record_client_init(&base_, handler, this);
+  }
+
+  size_t data_size() const { return base_.data_size; };
+
+ private:
+  rtems_record_client_context base_;
+  int fd_ = -1;
+  ssize_t (*reader_)(int fd, void* buf, size_t n) = nullptr;
+  sig_atomic_t stop_ = 0;
+};
+
+#endif  // RTEMS_TOOLS_TRACE_RECORD_CLIENT_H_
diff --git a/trace/record/record-client-base.cc b/trace/record/record-client-base.cc
new file mode 100644
index 0000000..e56608c
--- /dev/null
+++ b/trace/record/record-client-base.cc
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2018, 2019 embedded brains GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "client.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <cstring>
+
+static ssize_t ReadFile(int fd, void* buf, size_t n) {
+  return read(fd, buf, n);
+}
+
+static ssize_t ReadSocket(int fd, void* buf, size_t n) {
+  return recv(fd, buf, n, 0);
+}
+
+void Client::Open(const char* file) {
+  assert(fd_ == -1);
+  fd_ = open(file, O_RDONLY);
+  assert(fd_ >= 0);
+  reader_ = ReadFile;
+}
+
+void Client::Connect(const char* host, uint16_t port) {
+  assert(fd_ == -1);
+  fd_ = socket(PF_INET, SOCK_STREAM, 0);
+  assert(fd_ >= 0);
+
+  struct sockaddr_in in_addr;
+  memset(&in_addr, 0, sizeof(in_addr));
+  in_addr.sin_family = AF_INET;
+  in_addr.sin_port = htons(port);
+  in_addr.sin_addr.s_addr = inet_addr(host);
+
+  int rv = connect(fd_, (struct sockaddr*)&in_addr, sizeof(in_addr));
+  assert(rv == 0);
+
+  reader_ = ReadSocket;
+}
+
+void Client::Run() {
+  while (stop_ == 0) {
+    int buf[8192];
+    ssize_t n = (*reader_)(fd_, buf, sizeof(buf));
+
+    if (n > 0) {
+      rtems_record_client_run(&base_, buf, static_cast<size_t>(n));
+    } else {
+      break;
+    }
+  }
+}
+
+void Client::Destroy() {
+  int rv = close(fd_);
+  assert(rv == 0);
+
+  rtems_record_client_destroy(&base_);
+}
diff --git a/trace/record/record-main-lttng.cc b/trace/record/record-main-lttng.cc
index 9e10c5e..51d4f0e 100644
--- a/trace/record/record-main-lttng.cc
+++ b/trace/record/record-main-lttng.cc
@@ -26,20 +26,13 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <rtems/recordclient.h>
-#include <rtems/recorddata.h>
+#include "client.h"
 
-#include <arpa/inet.h>
 #include <assert.h>
-#include <fcntl.h>
 #include <getopt.h>
 #include <inttypes.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-#include <unistd.h>
 
+#include <cstring>
 #include <iostream>
 
 #define CTF_MAGIC 0xC1FC1FC1
@@ -82,6 +75,8 @@ struct PacketContext {
   uint32_t cpu_id;
 } __attribute__((__packed__));
 
+static const size_t kPacketContextBits = sizeof(PacketContext) * BITS_PER_CHAR;
+
 struct EventHeaderCompact {
   uint8_t id;
   uint32_t event_id;
@@ -99,6 +94,9 @@ struct EventSchedSwitch {
   int32_t next_prio;
 } __attribute__((__packed__));
 
+static const size_t kEventSchedSwitchBits =
+    sizeof(EventSchedSwitch) * BITS_PER_CHAR;
+
 struct PerCPUContext {
   FILE* event_stream;
   uint64_t timestamp_begin;
@@ -111,8 +109,21 @@ struct PerCPUContext {
   EventSchedSwitch sched_switch;
 };
 
-struct LTTNGClient {
-  rtems_record_client_context base;
+class LTTNGClient : public Client {
+ public:
+  LTTNGClient() {
+    Initialize(LTTNGClient::HandlerCaller);
+
+    memset(&pkt_ctx_, 0, sizeof(pkt_ctx_));
+    memcpy(pkt_ctx_.header.uuid, kUUID, sizeof(pkt_ctx_.header.uuid));
+    pkt_ctx_.header.ctf_magic = CTF_MAGIC;
+  }
+
+  void OpenStreamFiles();
+
+  void CloseStreamFiles();
+
+ private:
   PerCPUContext per_cpu_[RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT];
 
   /*
@@ -122,32 +133,33 @@ struct LTTNGClient {
    * POSIX API.
    */
   uint8_t thread_names_[THREAD_API_COUNT][THREAD_ID_COUNT][THREAD_NAME_SIZE];
-};
 
-static int ConnectClient(const char* host,
-                         uint16_t port,
-                         const char* input_file,
-                         bool input_file_flag) {
-  struct sockaddr_in in_addr;
-  int fd;
-  int rv;
-
-  fd = (input_file_flag) ? open(input_file, O_RDONLY)
-                         : socket(PF_INET, SOCK_STREAM, 0);
-  assert(fd >= 0);
-
-  memset(&in_addr, 0, sizeof(in_addr));
-  in_addr.sin_family = AF_INET;
-  in_addr.sin_port = htons(port);
-  in_addr.sin_addr.s_addr = inet_addr(host);
-
-  if (!input_file_flag) {
-    rv = connect(fd, (struct sockaddr*)&in_addr, sizeof(in_addr));
-    assert(rv == 0);
+  PacketContext pkt_ctx_;
+
+  static rtems_record_client_status HandlerCaller(uint64_t bt,
+                                                  uint32_t cpu,
+                                                  rtems_record_event event,
+                                                  uint64_t data,
+                                                  void* arg) {
+    LTTNGClient& self = *static_cast<LTTNGClient*>(arg);
+    return self.Handler(bt, cpu, event, data);
   }
 
-  return fd;
-}
+  rtems_record_client_status Handler(uint64_t bt,
+                                     uint32_t cpu,
+                                     rtems_record_event event,
+                                     uint64_t data);
+
+  void CopyThreadName(const ClientItem& item,
+                      size_t api_index,
+                      uint8_t* dst) const;
+
+  void WriteSchedSwitch(PerCPUContext* pcpu, const ClientItem& item);
+
+  void AddThreadName(PerCPUContext* pcpu, const ClientItem& item);
+
+  void PrintItem(const ClientItem& item);
+};
 
 static uint32_t GetAPIIndexOfID(uint32_t id) {
   return ((id >> 24) & 0x7) - 1;
@@ -161,14 +173,13 @@ static bool IsIdleTaskByAPIIndex(uint32_t api_index) {
   return api_index == 0;
 }
 
-static void CopyThreadName(const LTTNGClient* ctx,
-                           const ClientItem* item,
-                           size_t api_index,
-                           uint8_t* dst) {
+void LTTNGClient::CopyThreadName(const ClientItem& item,
+                                 size_t api_index,
+                                 uint8_t* dst) const {
   const uint8_t* name;
 
   if (api_index < THREAD_API_COUNT) {
-    name = ctx->thread_names_[api_index][GetObjIndexOfID(item->data)];
+    name = thread_names_[api_index][GetObjIndexOfID(item.data)];
   } else {
     name = kEmptyThreadName;
   }
@@ -181,115 +192,96 @@ static void CopyThreadName(const LTTNGClient* ctx,
      * RTEMS, the idle threads can move around, so mimic this Linux behaviour.
      */
     snprintf(reinterpret_cast<char*>(dst) + 4, THREAD_NAME_SIZE - 4,
-             "/%" PRIu32, item->cpu);
+             "/%" PRIu32, item.cpu);
   }
 }
 
-static void WriteSchedSwitch(LTTNGClient* ctx,
-                             PerCPUContext* pcpu,
-                             const ClientItem* item) {
-  size_t se_size;
-  EventSchedSwitch* se;
-  uint32_t api_index;
-
-  se_size = sizeof(*se) * BITS_PER_CHAR;
-  pcpu->content_size += se_size;
-  pcpu->packet_size += se_size;
+void LTTNGClient::WriteSchedSwitch(PerCPUContext* pcpu,
+                                   const ClientItem& item) {
+  pcpu->content_size += kEventSchedSwitchBits;
+  pcpu->packet_size += kEventSchedSwitchBits;
 
-  api_index = GetAPIIndexOfID(item->data);
-  se = &pcpu->sched_switch;
+  EventSchedSwitch& ss = pcpu->sched_switch;
+  ss.header.id = COMPACT_HEADER_ID;
+  ss.header.event_id = 0;
+  ss.header.ns = item.ns;
 
-  se->header.id = COMPACT_HEADER_ID;
-  se->header.event_id = 0;
-  se->header.ns = item->ns;
-  se->next_tid = IsIdleTaskByAPIIndex(api_index) ? 0 : item->data;
+  uint32_t api_index = GetAPIIndexOfID(item.data);
+  ss.next_tid = IsIdleTaskByAPIIndex(api_index) ? 0 : item.data;
 
-  CopyThreadName(ctx, item, api_index, se->next_comm);
-  fwrite(se, sizeof(*se), 1, pcpu->event_stream);
+  CopyThreadName(item, api_index, ss.next_comm);
+  fwrite(&ss, sizeof(ss), 1, pcpu->event_stream);
 }
 
-static void AddThreadName(LTTNGClient* ctx,
-                          PerCPUContext* pcpu,
-                          const ClientItem* item) {
-  uint64_t name;
-  uint32_t api_index;
-  uint32_t obj_index;
-  size_t i;
-
+void LTTNGClient::AddThreadName(PerCPUContext* pcpu, const ClientItem& item) {
   if (pcpu->thread_name_index >= THREAD_NAME_SIZE) {
     return;
   }
 
-  api_index = GetAPIIndexOfID(pcpu->thread_id);
-
+  uint32_t api_index = GetAPIIndexOfID(pcpu->thread_id);
   if (api_index >= THREAD_API_COUNT) {
     return;
   }
 
-  obj_index = GetObjIndexOfID(pcpu->thread_id);
-  name = item->data;
-
-  for (i = pcpu->thread_name_index;
-       i < pcpu->thread_name_index + ctx->base.data_size; ++i) {
-    ctx->thread_names_[api_index][obj_index][i] = static_cast<uint8_t>(name);
+  uint32_t obj_index = GetObjIndexOfID(pcpu->thread_id);
+  uint64_t name = item.data;
+  size_t i;
+  for (i = pcpu->thread_name_index; i < pcpu->thread_name_index + data_size();
+       ++i) {
+    thread_names_[api_index][obj_index][i] = static_cast<uint8_t>(name);
     name >>= BITS_PER_CHAR;
   }
 
   pcpu->thread_name_index = i;
 }
 
-static void PrintItem(LTTNGClient* ctx, const ClientItem* item) {
-  PerCPUContext* pcpu;
-  EventSchedSwitch* se;
-  uint32_t api_index;
-
-  pcpu = &ctx->per_cpu_[item->cpu];
-  se = &pcpu->sched_switch;
-
-  if (pcpu->timestamp_begin == 0) {
-    pcpu->timestamp_begin = item->ns;
+void LTTNGClient::PrintItem(const ClientItem& item) {
+  PerCPUContext& pcpu = per_cpu_[item.cpu];
+  if (pcpu.timestamp_begin == 0) {
+    pcpu.timestamp_begin = item.ns;
   }
 
-  pcpu->timestamp_end = item->ns;
+  pcpu.timestamp_end = item.ns;
 
-  switch (item->event) {
-    case RTEMS_RECORD_THREAD_SWITCH_OUT:
-      api_index = GetAPIIndexOfID(item->data);
-      se->header.ns = item->ns;
+  EventSchedSwitch& ss = pcpu.sched_switch;
+  switch (item.event) {
+    case RTEMS_RECORD_THREAD_SWITCH_OUT: {
+      uint32_t api_index = GetAPIIndexOfID(item.data);
+      ss.header.ns = item.ns;
 
       if (IsIdleTaskByAPIIndex(api_index)) {
-        se->prev_tid = 0;
-        se->prev_state = TASK_IDLE;
+        ss.prev_tid = 0;
+        ss.prev_state = TASK_IDLE;
       } else {
-        se->prev_tid = item->data;
-        se->prev_state = TASK_RUNNING;
+        ss.prev_tid = item.data;
+        ss.prev_state = TASK_RUNNING;
       }
 
-      CopyThreadName(ctx, item, api_index, se->prev_comm);
+      CopyThreadName(item, api_index, ss.prev_comm);
       break;
+    }
     case RTEMS_RECORD_THREAD_SWITCH_IN:
-      if (item->ns == se->header.ns) {
-        WriteSchedSwitch(ctx, pcpu, item);
+      if (item.ns == ss.header.ns) {
+        WriteSchedSwitch(&pcpu, item);
       }
       break;
     case RTEMS_RECORD_THREAD_ID:
-      pcpu->thread_id = item->data;
-      pcpu->thread_ns = item->ns;
-      pcpu->thread_name_index = 0;
+      pcpu.thread_id = item.data;
+      pcpu.thread_ns = item.ns;
+      pcpu.thread_name_index = 0;
       break;
     case RTEMS_RECORD_THREAD_NAME:
-      AddThreadName(ctx, pcpu, item);
+      AddThreadName(&pcpu, item);
       break;
     default:
       break;
   }
 }
 
-static rtems_record_client_status Handler(uint64_t bt,
-                                          uint32_t cpu,
-                                          rtems_record_event event,
-                                          uint64_t data,
-                                          void* arg) {
+rtems_record_client_status LTTNGClient::Handler(uint64_t bt,
+                                                uint32_t cpu,
+                                                rtems_record_event event,
+                                                uint64_t data) {
   ClientItem item;
 
   item.ns = rtems_record_client_bintime_to_nanoseconds(bt);
@@ -297,11 +289,39 @@ static rtems_record_client_status Handler(uint64_t bt,
   item.event = event;
   item.data = data;
 
-  PrintItem(static_cast<LTTNGClient*>(arg), &item);
+  PrintItem(item);
 
   return RTEMS_RECORD_CLIENT_SUCCESS;
 }
 
+void LTTNGClient::OpenStreamFiles() {
+  for (size_t i = 0; i < RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT; ++i) {
+    char filename[256];
+    snprintf(filename, sizeof(filename), "event_%zu", i);
+    FILE* f = fopen(filename, "wb");
+    assert(f != NULL);
+    per_cpu_[i].event_stream = f;
+    fwrite(&pkt_ctx_, sizeof(pkt_ctx_), 1, f);
+  }
+}
+
+void LTTNGClient::CloseStreamFiles() {
+  for (size_t i = 0; i < RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT; ++i) {
+    PerCPUContext* pcpu = &per_cpu_[i];
+    fseek(pcpu->event_stream, 0, SEEK_SET);
+
+    pkt_ctx_.header.stream_instance_id = i;
+    pkt_ctx_.timestamp_begin = pcpu->timestamp_begin;
+    pkt_ctx_.timestamp_end = pcpu->timestamp_end;
+    pkt_ctx_.content_size = pcpu->content_size + kPacketContextBits;
+    pkt_ctx_.packet_size = pcpu->packet_size + kPacketContextBits;
+    pkt_ctx_.cpu_id = i;
+
+    fwrite(&pkt_ctx_, sizeof(pkt_ctx_), 1, pcpu->event_stream);
+    fclose(pcpu->event_stream);
+  }
+}
+
 static const char kMetadata[] =
     "/* CTF 1.8 */\n"
     "\n"
@@ -411,6 +431,13 @@ static void GenerateMetadata() {
   fclose(file);
 }
 
+static LTTNGClient client;
+
+static void SignalHandler(int s) {
+  client.RequestStop();
+  signal(s, SIG_DFL);
+}
+
 static const struct option kLongOpts[] = {{"help", 0, NULL, 'h'},
                                           {"host", 1, NULL, 'H'},
                                           {"port", 1, NULL, 'p'},
@@ -434,28 +461,11 @@ static void Usage(char** argv) {
 }
 
 int main(int argc, char** argv) {
-  LTTNGClient ctx;
-  PacketContext pkt_ctx;
-  size_t pkt_ctx_size;
-  const char* host;
-  uint16_t port;
-  const char* input_file;
-  bool input_file_flag;
-  bool input_TCP_host;
-  bool input_TCP_port;
-  int fd;
-  int rv;
+  const char* host = "127.0.0.1";
+  uint16_t port = 1234;
+  const char* file = nullptr;
   int opt;
   int longindex;
-  size_t i;
-  char filename[256];
-
-  host = "127.0.0.1";
-  port = 1234;
-  input_file = "raw_data";
-  input_file_flag = false;
-  input_TCP_host = false;
-  input_TCP_port = false;
 
   while ((opt = getopt_long(argc, argv, "hH:p:i:", &kLongOpts[0],
                             &longindex)) != -1) {
@@ -465,83 +475,31 @@ int main(int argc, char** argv) {
         return 0;
       case 'H':
         host = optarg;
-        input_TCP_host = true;
         break;
       case 'p':
         port = (uint16_t)strtoul(optarg, NULL, 10);
-        input_TCP_port = true;
         break;
       case 'i':
-        input_file = optarg;
-        assert(input_file != NULL);
-        input_file_flag = true;
+        file = optarg;
         break;
       default:
         return 1;
     }
   }
 
-  if (input_file_flag && (input_TCP_host || input_TCP_port)) {
-    printf("There should be one input medium\n");
-    exit(EXIT_SUCCESS);
-  }
-
-  memset(&ctx, 0, sizeof(ctx));
-
   GenerateMetadata();
+  client.OpenStreamFiles();
 
-  memset(&pkt_ctx, 0, sizeof(pkt_ctx));
-  memcpy(pkt_ctx.header.uuid, kUUID, sizeof(pkt_ctx.header.uuid));
-  pkt_ctx.header.ctf_magic = CTF_MAGIC;
-
-  for (i = 0; i < RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT; ++i) {
-    FILE* f;
-
-    snprintf(filename, sizeof(filename), "event_%zu", i);
-    f = fopen(filename, "wb");
-    assert(f != NULL);
-    ctx.per_cpu_[i].event_stream = f;
-    fwrite(&pkt_ctx, sizeof(pkt_ctx), 1, f);
-  }
-
-  fd = ConnectClient(host, port, input_file, input_file_flag);
-  rtems_record_client_init(&ctx.base, Handler, &ctx);
-
-  while (true) {
-    int buf[8192];
-    ssize_t n;
-
-    n = (input_file_flag) ? read(fd, buf, sizeof(buf))
-                          : recv(fd, buf, sizeof(buf), 0);
-    if (n > 0) {
-      rtems_record_client_run(&ctx.base, buf, (size_t)n);
-    } else {
-      break;
-    }
-  }
-
-  rtems_record_client_destroy(&ctx.base);
-  pkt_ctx_size = sizeof(pkt_ctx) * BITS_PER_CHAR;
-
-  for (i = 0; i < RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT; ++i) {
-    PerCPUContext* pcpu;
-
-    pcpu = &ctx.per_cpu_[i];
-    fseek(pcpu->event_stream, 0, SEEK_SET);
-
-    pkt_ctx.header.stream_instance_id = i;
-    pkt_ctx.timestamp_begin = pcpu->timestamp_begin;
-    pkt_ctx.timestamp_end = pcpu->timestamp_end;
-    pkt_ctx.content_size = pcpu->content_size + pkt_ctx_size;
-    pkt_ctx.packet_size = pcpu->packet_size + pkt_ctx_size;
-    pkt_ctx.cpu_id = i;
-
-    fwrite(&pkt_ctx, sizeof(pkt_ctx), 1, pcpu->event_stream);
-    fclose(pcpu->event_stream);
+  if (file != nullptr) {
+    client.Open(file);
+  } else {
+    client.Connect(host, port);
   }
 
-  rv = close(fd);
-  assert(rv == 0);
+  signal(SIGINT, SignalHandler);
+  client.Run();
+  client.Destroy();
+  client.CloseStreamFiles();
 
   return 0;
 }
diff --git a/trace/wscript b/trace/wscript
index bc28e85..d2b5625 100644
--- a/trace/wscript
+++ b/trace/wscript
@@ -59,7 +59,9 @@ def build(bld):
     # Build rtems-record-lttng
     #
     bld.program(target = 'rtems-record-lttng',
-                source = ['record/record-client.c', 'record/record-main-lttng.cc'],
+                source = ['record/record-client.c',
+                          'record/record-client-base.cc',
+                          'record/record-main-lttng.cc'],
                 includes = ['record'],
                 defines = defines,
                 cflags = conf['cflags'] + conf['warningflags'],



More information about the vc mailing list