summaryrefslogtreecommitdiffstats
path: root/trace/record/record-main-lttng.c
diff options
context:
space:
mode:
Diffstat (limited to 'trace/record/record-main-lttng.c')
-rw-r--r--trace/record/record-main-lttng.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/trace/record/record-main-lttng.c b/trace/record/record-main-lttng.c
new file mode 100644
index 0000000..570e748
--- /dev/null
+++ b/trace/record/record-main-lttng.c
@@ -0,0 +1,198 @@
+/*
+ * 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 <rtems/recorddata.h>
+#include <rtems/recordclient.h>
+
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+static const struct option longopts[] = {
+ { "help", 0, NULL, 'h' },
+ { "host", 1, NULL, 'H' },
+ { "port", 1, NULL, 'p' },
+ { NULL, 0, NULL, 0 }
+};
+
+typedef struct client_item {
+ uint64_t ns;
+ uint32_t cpu;
+ rtems_record_event event;
+ uint64_t data;
+} client_item;
+
+typedef struct client_context {
+ int dummy;
+} client_context;
+
+static void usage( char **argv )
+{
+ printf(
+ "%s [--host=HOST] [--port=PORT]\n"
+ "\n"
+ "Mandatory arguments to long options are mandatory for short options too.\n"
+ " -h, --help print this help text\n"
+ " -H, --host=HOST the host IPv4 address of the record server\n"
+ " -p, --port=PORT the TCP port of the record server\n"
+ argv[ 0 ]
+ );
+}
+
+static int connect_client( const char *host, uint16_t port )
+{
+ struct sockaddr_in in_addr;
+ int fd;
+ int rv;
+
+ fd = 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 );
+ rv = connect( fd, (struct sockaddr *) &in_addr, sizeof( in_addr ) );
+ assert( rv == 0 );
+
+ return fd;
+}
+
+static void print_item( FILE *f, const client_item *item )
+{
+ if ( item->ns != 0 ) {
+ uint32_t seconds;
+ uint32_t nanoseconds;
+
+ seconds = (uint32_t) ( item->ns / 1000000000 );
+ nanoseconds = (uint32_t) ( item->ns % 1000000000 );
+ fprintf( f, "%" PRIu32 ".%09" PRIu32 ":", seconds, nanoseconds );
+ } else {
+ fprintf( f, "*:" );
+ }
+
+ fprintf(
+ f,
+ "%" PRIu32 ":%s:%" PRIx64 "\n",
+ item->cpu,
+ rtems_record_event_text( item->event ),
+ item->data
+ );
+}
+
+static rtems_record_client_status handler(
+ uint64_t bt,
+ uint32_t cpu,
+ rtems_record_event event,
+ uint64_t data,
+ void *arg
+)
+{
+ client_context *cctx;
+ client_item item;
+
+ cctx = arg;
+ (void) cctx;
+
+ item.ns = rtems_record_client_bintime_to_nanoseconds( bt );
+ item.cpu = cpu;
+ item.event = event;
+ item.data = data;
+
+ print_item( stdout, &item );
+
+ return RTEMS_RECORD_CLIENT_SUCCESS;
+}
+
+int main( int argc, char **argv )
+{
+ rtems_record_client_context ctx;
+ client_context cctx;
+ const char *host;
+ uint16_t port;
+ int fd;
+ int rv;
+ int opt;
+ int longindex;
+
+ host = "127.0.0.1";
+ port = 1234;
+
+ while (
+ ( opt = getopt_long( argc, argv, "hH:p:", &longopts[0], &longindex ) )
+ != -1
+ ) {
+ switch ( opt ) {
+ case 'h':
+ usage( argv );
+ exit( EXIT_SUCCESS );
+ break;
+ case 'H':
+ host = optarg;
+ break;
+ case 'p':
+ port = (uint16_t) strtoul( optarg, NULL, 10 );
+ break;
+ default:
+ exit( EXIT_FAILURE );
+ break;
+ }
+ }
+
+ memset( &cctx, 0, sizeof( cctx ) );
+
+ fd = connect_client( host, port );
+ rtems_record_client_init( &ctx, handler, &cctx );
+
+ while ( true ) {
+ int buf[ 8192 ];
+ ssize_t n;
+
+ n = recv( fd, buf, sizeof( buf ), 0 );
+ if ( n >= 0 ) {
+ rtems_record_client_run( &ctx, buf, (size_t) n );
+ } else {
+ break;
+ }
+ }
+
+ rv = close( fd );
+ assert( rv == 0 );
+
+ return 0;
+}