aboutsummaryrefslogtreecommitdiffstats
path: root/trace-listen.c
diff options
context:
space:
mode:
authorYoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>2014-07-11 00:58:26 +0000
committerSteven Rostedt <rostedt@goodmis.org>2016-03-21 17:18:44 -0400
commit7ea7f9846352f4b607bb1cc7e7b680eca61c12e4 (patch)
tree041e6d0807a5bf830f1f1b65503488d037c6e38d /trace-listen.c
parent8bbbaaaf78ecd479d149fc84ab7d50be90c3540d (diff)
downloadtrace-cmd-7ea7f9846352f4b607bb1cc7e7b680eca61c12e4.tar.gz
trace-cmd/listen: Apply the trace-msg protocol for communication between a server and clients
Apply trace-msg protocol for communication between a server and clients. Currently, trace-listen(server) and trace-record -N(client) operate as follows: <server> <client> listen to socket fd connect to socket fd accept the client send "tracecmd" +------------> receive "tracecmd" check "tracecmd" send cpus receive cpus <------------+ print "cpus=XXX" send pagesize | receive pagesize <--------+ print "pagesize=XXX" send option | receive option <----------+ understand option send port_array +------------> receive port_array understand port_array send meta data receive meta data <-------+ record meta data (snip) read block --- start sending trace data on child processes --- --- When client finishes sending trace data --- close(socket fd) read size = 0 close(socket fd) All messages are unstructured character strings, so server(client) using the protocol must parse the unstructured messages. Since it is hard to add complex contents in the protocol, structured binary message trace-msg is introduced as the communication protocol. By applying this patch, server and client operate as follows: <server> <client> listen to socket fd connect to socket fd accept the client send "tracecmd" +------------> receive "tracecmd" check "tracecmd" send "V2\0<MAGIC_NUMBER>\00" as the v2 protocol receive "V2" <------------+ check "V2" read "<MAGIC_NUMBER>\00" send "V2" +---------------> receive "V2" check "V2" send cpus,pagesize,option(MSG_TINIT) receive MSG_TINIT <-------+ print "cpus=XXX" print "pagesize=XXX" understand option send port_array +--MSG_RINIT-> receive MSG_RINIT understand port_array send meta data(MSG_SENDMETA) receive MSG_SENDMETA <----+ record meta data (snip) send a message to finish sending meta data | (MSG_FINMETA) receive MSG_FINMETA <-----+ read block --- start sending trace data on child processes --- --- When client finishes sending trace data --- send MSG_CLOSE receive MSG_CLOSE <-------+ close(socket fd) close(socket fd) By introducing the v2 protocol, after the client checks "tracecmd", the client will send "V2\0<MAGIC_NUMBER>\00\0". This complex message is used when the new client tries to connect to the old server. The new client wants to check whether the reply message from the server is "V2" or not. However, the old server does not respond to the client before receiving cpu numbers, page size, and options. Each message is separated with "\0" in the old server, so the client send "V2" as cpu numbers, "<MAGIC_NUMBER>" as page size, and "0" as no options. On the other hands, the old server will understand the messages as cpus=0, pagesize=<MAGIC_NUMBER>, and options=0, and then the server will send the message "\0" as port numbers. Then, the message which the client receives is not "V2" but "\0", so the client will reconnect to the old server as the v1 protocol. <How to test> [1] Backward compatability checks We need to test backward compatability of this patch for old trace-cmds(client/server). So, this patch was tested for [2] command checks in following 3 types: <client> <server> new old old new new new [2] Command checks - server (common) # trace-cmd listen -p 12345 1) record - client # trace-cmd record -e sched -N <server IP>:12345 ^C 2) record + multiple buffers - client # trace-cmd record -B foo -e sched -N <server IP>:12345 ^C 3) extract - client # ./trace-cmd start -e sched # sleep 5 # ./trace-cmd extract -N <server IP>:12345 4) extract + snapshot - client # ./trace-cmd start -e sched # sleep 5 # ./trace-cmd snapshot -s # ./trace-cmd extract -N <server IP>:12345 -s Changes in V4: Fix some typos, cleanups and rebase for current trace-cmd-v2.4 Change the argument of tracecmd_msg_recv() Changes in V3: Change the license of trace-msg.c to LGPL v2.1 Changes in V2: Regacy porotocol support in order to keep backward compatibility Link: http://lkml.kernel.org/r/20140711005826.25516.77711.stgit@yuno-kbuild.novalocal Signed-off-by: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'trace-listen.c')
-rw-r--r--trace-listen.c137
1 files changed, 84 insertions, 53 deletions
diff --git a/trace-listen.c b/trace-listen.c
index 1e38edac..77df7c3d 100644
--- a/trace-listen.c
+++ b/trace-listen.c
@@ -33,6 +33,7 @@
#include <errno.h>
#include "trace-local.h"
+#include "trace-msg.h"
#define MAX_OPTION_SIZE 4096
@@ -45,10 +46,10 @@ static FILE *logfp;
static int debug;
-static int use_tcp;
-
static int backlog = 5;
+static int proto_ver;
+
#define TEMP_FILE_STR "%s.%s:%s.cpu%d", output_file, host, port, cpu
static char *get_temp_file(const char *host, const char *port, int cpu)
{
@@ -114,10 +115,9 @@ static int process_option(char *option)
return 0;
}
-static int done;
static void finish(int sig)
{
- done = 1;
+ done = true;
}
#define LOG_BUF_SIZE 1024
@@ -146,7 +146,7 @@ static void __plog(const char *prefix, const char *fmt, va_list ap,
fprintf(fp, "%.*s", r, buf);
}
-static void plog(const char *fmt, ...)
+void plog(const char *fmt, ...)
{
va_list ap;
@@ -155,7 +155,7 @@ static void plog(const char *fmt, ...)
va_end(ap);
}
-static void pdie(const char *fmt, ...)
+void pdie(const char *fmt, ...)
{
va_list ap;
char *str = "";
@@ -334,58 +334,80 @@ static int communicate_with_client(int fd, int *cpus, int *pagesize)
*cpus = atoi(buf);
- plog("cpus=%d\n", *cpus);
- if (*cpus < 0)
- return -EINVAL;
+ /* Is the client using the new protocol? */
+ if (!*cpus) {
+ if (memcmp(buf, "V2", 2) != 0) {
+ plog("Cannot handle the protocol %s", buf);
+ return -EINVAL;
+ }
- /* next read the page size */
- n = read_string(fd, buf, BUFSIZ);
- if (n == BUFSIZ)
- /** ERROR **/
- return -EINVAL;
+ /* read the rest of dummy data, but not use */
+ read(fd, buf, sizeof(V2_MAGIC)+1);
- *pagesize = atoi(buf);
+ proto_ver = V2_PROTOCOL;
- plog("pagesize=%d\n", *pagesize);
- if (*pagesize <= 0)
- return -EINVAL;
+ /* Let the client know we use v2 protocol */
+ write(fd, "V2", 2);
- /* Now the number of options */
- n = read_string(fd, buf, BUFSIZ);
- if (n == BUFSIZ)
- /** ERROR **/
- return -EINVAL;
+ /* read the CPU count, the page size, and options */
+ if (tracecmd_msg_initial_setting(fd, cpus, pagesize) < 0)
+ return -EINVAL;
+ } else {
+ /* The client is using the v1 protocol */
- options = atoi(buf);
+ plog("cpus=%d\n", *cpus);
+ if (*cpus < 0)
+ return -EINVAL;
- for (i = 0; i < options; i++) {
- /* next is the size of the options */
+ /* next read the page size */
n = read_string(fd, buf, BUFSIZ);
if (n == BUFSIZ)
/** ERROR **/
return -EINVAL;
- size = atoi(buf);
- /* prevent a client from killing us */
- if (size > MAX_OPTION_SIZE)
+
+ *pagesize = atoi(buf);
+
+ plog("pagesize=%d\n", *pagesize);
+ if (*pagesize <= 0)
return -EINVAL;
- option = malloc(size);
- if (!option)
- return -ENOMEM;
- do {
- t = size;
- s = 0;
- s = read(fd, option+s, t);
- if (s <= 0)
- return -EIO;
- t -= s;
- s = size - t;
- } while (t);
- s = process_option(option);
- free(option);
- /* do we understand this option? */
- if (!s)
+ /* Now the number of options */
+ n = read_string(fd, buf, BUFSIZ);
+ if (n == BUFSIZ)
+ /** ERROR **/
return -EINVAL;
+
+ options = atoi(buf);
+
+ for (i = 0; i < options; i++) {
+ /* next is the size of the options */
+ n = read_string(fd, buf, BUFSIZ);
+ if (n == BUFSIZ)
+ /** ERROR **/
+ return -EINVAL;
+ size = atoi(buf);
+ /* prevent a client from killing us */
+ if (size > MAX_OPTION_SIZE)
+ return -EINVAL;
+ option = malloc(size);
+ if (!option)
+ return -ENOMEM;
+ do {
+ t = size;
+ s = 0;
+ s = read(fd, option+s, t);
+ if (s <= 0)
+ return -EIO;
+ t -= s;
+ s = size - t;
+ } while (t);
+
+ s = process_option(option);
+ free(option);
+ /* do we understand this option? */
+ if (!s)
+ return -EINVAL;
+ }
}
if (use_tcp)
@@ -462,14 +484,20 @@ static int *create_all_readers(int cpus, const char *node, const char *port,
start_port = udp_port + 1;
}
- /* send the client a comma deliminated set of port numbers */
- for (cpu = 0; cpu < cpus; cpu++) {
- snprintf(buf, BUFSIZ, "%s%d",
- cpu ? "," : "", port_array[cpu]);
- write(fd, buf, strlen(buf));
+ if (proto_ver == V2_PROTOCOL) {
+ /* send set of port numbers to the client */
+ if (tracecmd_msg_send_port_array(fd, cpus, port_array) < 0)
+ goto out_free;
+ } else {
+ /* send the client a comma deliminated set of port numbers */
+ for (cpu = 0; cpu < cpus; cpu++) {
+ snprintf(buf, BUFSIZ, "%s%d",
+ cpu ? "," : "", port_array[cpu]);
+ write(fd, buf, strlen(buf));
+ }
+ /* end with null terminator */
+ write(fd, "\0", 1);
}
- /* end with null terminator */
- write(fd, "\0", 1);
return pid_array;
@@ -563,7 +591,10 @@ static int process_client(const char *node, const char *port, int fd)
return -ENOMEM;
/* Now we are ready to start reading data from the client */
- collect_metadata_from_client(fd, ofd);
+ if (proto_ver == V2_PROTOCOL)
+ tracecmd_msg_collect_metadata(fd, ofd);
+ else
+ collect_metadata_from_client(fd, ofd);
/* wait a little to let our readers finish reading */
sleep(1);