aboutsummaryrefslogtreecommitdiffstats
path: root/trace-cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'trace-cmd.c')
-rw-r--r--trace-cmd.c196
1 files changed, 186 insertions, 10 deletions
diff --git a/trace-cmd.c b/trace-cmd.c
index e89362d..cdd78f4 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -27,6 +27,8 @@
27#include <sys/types.h> 27#include <sys/types.h>
28#include <sys/stat.h> 28#include <sys/stat.h>
29#include <sys/wait.h> 29#include <sys/wait.h>
30#include <sys/socket.h>
31#include <netdb.h>
30#include <pthread.h> 32#include <pthread.h>
31#include <fcntl.h> 33#include <fcntl.h>
32#include <unistd.h> 34#include <unistd.h>
@@ -48,7 +50,7 @@
48#define ITER_CTRL "trace_options" 50#define ITER_CTRL "trace_options"
49#define MAX_LATENCY "tracing_max_latency" 51#define MAX_LATENCY "tracing_max_latency"
50 52
51unsigned int page_size; 53static unsigned int page_size;
52 54
53static const char *output_file = "trace.dat"; 55static const char *output_file = "trace.dat";
54 56
@@ -57,6 +59,10 @@ static int sleep_time = 1000;
57static int cpu_count; 59static int cpu_count;
58static int *pids; 60static int *pids;
59 61
62static char *host;
63static int *client_ports;
64static int sfd;
65
60static int filter_task; 66static int filter_task;
61static int filter_pid = -1; 67static int filter_pid = -1;
62 68
@@ -116,7 +122,7 @@ static void kill_threads(void)
116{ 122{
117 int i; 123 int i;
118 124
119 if (!cpu_count) 125 if (!cpu_count || !pids)
120 return; 126 return;
121 127
122 for (i = 0; i < cpu_count; i++) { 128 for (i = 0; i < cpu_count; i++) {
@@ -895,6 +901,41 @@ static void flush(int sig)
895 tracecmd_stop_recording(recorder); 901 tracecmd_stop_recording(recorder);
896} 902}
897 903
904static void connect_port(int cpu)
905{
906 struct addrinfo hints;
907 struct addrinfo *results, *rp;
908 int s;
909 char buf[BUFSIZ];
910
911 snprintf(buf, BUFSIZ, "%d", client_ports[cpu]);
912
913 memset(&hints, 0, sizeof(hints));
914 hints.ai_family = AF_UNSPEC;
915 hints.ai_socktype = SOCK_DGRAM;
916
917 s = getaddrinfo(host, buf, &hints, &results);
918 if (s != 0)
919 die("connecting to UDP server %s:%s", host, buf);
920
921 for (rp = results; rp != NULL; rp = rp->ai_next) {
922 sfd = socket(rp->ai_family, rp->ai_socktype,
923 rp->ai_protocol);
924 if (sfd == -1)
925 continue;
926 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != 1)
927 break;
928 close(sfd);
929 }
930
931 if (rp == NULL)
932 die("Can not connect to UDP server %s:%s", host, buf);
933
934 freeaddrinfo(results);
935
936 client_ports[cpu] = sfd;
937}
938
898static int create_recorder(int cpu) 939static int create_recorder(int cpu)
899{ 940{
900 char *file; 941 char *file;
@@ -913,10 +954,14 @@ static int create_recorder(int cpu)
913 /* do not kill tasks on error */ 954 /* do not kill tasks on error */
914 cpu_count = 0; 955 cpu_count = 0;
915 956
916 file = get_temp_file(cpu); 957 if (client_ports) {
917 958 connect_port(cpu);
918 recorder = tracecmd_create_recorder(file, cpu); 959 recorder = tracecmd_create_recorder_fd(client_ports[cpu], cpu);
919 put_temp_file(file); 960 } else {
961 file = get_temp_file(cpu);
962 recorder = tracecmd_create_recorder(file, cpu);
963 put_temp_file(file);
964 }
920 965
921 if (!recorder) 966 if (!recorder)
922 die ("can't create recorder"); 967 die ("can't create recorder");
@@ -927,18 +972,125 @@ static int create_recorder(int cpu)
927 exit(0); 972 exit(0);
928} 973}
929 974
975static void setup_network(void)
976{
977 struct tracecmd_output *handle;
978 struct addrinfo hints;
979 struct addrinfo *result, *rp;
980 int sfd, s;
981 ssize_t n;
982 char buf[BUFSIZ];
983 char *server;
984 char *port;
985 char *p;
986 int cpu;
987 int i;
988
989 if (!strchr(host, ':')) {
990 server = strdup("localhost");
991 if (!server)
992 die("alloctating server");
993 port = host;
994 host = server;
995 } else {
996 host = strdup(host);
997 if (!host)
998 die("alloctating server");
999 server = strtok_r(host, ":", &p);
1000 port = strtok_r(NULL, ":", &p);
1001 }
1002
1003 memset(&hints, 0, sizeof(hints));
1004 hints.ai_family = AF_UNSPEC;
1005 hints.ai_socktype = SOCK_STREAM;
1006
1007 s = getaddrinfo(server, port, &hints, &result);
1008 if (s != 0)
1009 die("getaddrinfo: %s", gai_strerror(s));
1010
1011 for (rp = result; rp != NULL; rp = rp->ai_next) {
1012 sfd = socket(rp->ai_family, rp->ai_socktype,
1013 rp->ai_protocol);
1014 if (sfd == -1)
1015 continue;
1016
1017 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
1018 break;
1019 close(sfd);
1020 }
1021
1022 if (!rp)
1023 die("Can not connect to %s:%d", server, port);
1024
1025 freeaddrinfo(result);
1026
1027 n = read(sfd, buf, 8);
1028
1029 /* Make sure the server is the tracecmd server */
1030 if (memcmp(buf, "tracecmd", 8) != 0)
1031 die("server not tracecmd server");
1032
1033 /* write the number of CPUs we have (in ASCII) */
1034
1035 sprintf(buf, "%d", cpu_count);
1036
1037 /* include \0 */
1038 write(sfd, buf, strlen(buf)+1);
1039
1040 /* write the pagesize (in ASCII) */
1041
1042 page_size = getpagesize();
1043 sprintf(buf, "%d", page_size);
1044
1045 /* include \0 */
1046 write(sfd, buf, strlen(buf)+1);
1047
1048 client_ports = malloc_or_die(sizeof(int) * cpu_count);
1049
1050 /*
1051 * Now we will receive back a comma deliminated list
1052 * of client ports to connect to.
1053 */
1054 for (cpu = 0; cpu < cpu_count; cpu++) {
1055 for (i = 0; i < BUFSIZ; i++) {
1056 n = read(sfd, buf+i, 1);
1057 if (n != 1)
1058 die("Error, reading server ports");
1059 if (!buf[i] || buf[i] == ',')
1060 break;
1061 }
1062 if (i == BUFSIZ)
1063 die("read bad port number");
1064 buf[i] = 0;
1065 client_ports[cpu] = atoi(buf);
1066 }
1067
1068 /* Now create the handle through this socket */
1069 handle = tracecmd_create_init_fd(sfd, cpu_count);
1070
1071 /* OK, we are all set, let'r rip! */
1072}
1073
1074static void finish_network(void)
1075{
1076 close(sfd);
1077 free(host);
1078}
1079
930static void start_threads(void) 1080static void start_threads(void)
931{ 1081{
932 int i; 1082 int i;
933 1083
934 cpu_count = count_cpus(); 1084 cpu_count = count_cpus();
935 1085
1086 if (host)
1087 setup_network();
1088
936 /* make a thread for every CPU we have */ 1089 /* make a thread for every CPU we have */
937 pids = malloc_or_die(sizeof(*pids) * cpu_count); 1090 pids = malloc_or_die(sizeof(*pids) * cpu_count);
938 1091
939 memset(pids, 0, sizeof(*pids) * cpu_count); 1092 memset(pids, 0, sizeof(*pids) * cpu_count);
940 1093
941
942 for (i = 0; i < cpu_count; i++) { 1094 for (i = 0; i < cpu_count; i++) {
943 pids[i] = create_recorder(i); 1095 pids[i] = create_recorder(i);
944 } 1096 }
@@ -950,6 +1102,11 @@ static void record_data(void)
950 char **temp_files; 1102 char **temp_files;
951 int i; 1103 int i;
952 1104
1105 if (host) {
1106 finish_network();
1107 return;
1108 }
1109
953 if (latency) 1110 if (latency)
954 handle = tracecmd_create_file_latency(output_file, cpu_count); 1111 handle = tracecmd_create_file_latency(output_file, cpu_count);
955 else { 1112 else {
@@ -1066,7 +1223,7 @@ void usage(char **argv)
1066 "usage:\n" 1223 "usage:\n"
1067 " %s record [-v][-e event [-f filter]][-p plugin][-F][-d][-o file] \\\n" 1224 " %s record [-v][-e event [-f filter]][-p plugin][-F][-d][-o file] \\\n"
1068 " [-s usecs][-O option ][-l func][-g func][-n func]\n" 1225 " [-s usecs][-O option ][-l func][-g func][-n func]\n"
1069 " [-P pid][command ...]\n" 1226 " [-P pid][-N host:port][command ...]\n"
1070 " -e run command with event enabled\n" 1227 " -e run command with event enabled\n"
1071 " -f filter for previous -e event\n" 1228 " -f filter for previous -e event\n"
1072 " -p run command with plugin enabled\n" 1229 " -p run command with plugin enabled\n"
@@ -1080,6 +1237,7 @@ void usage(char **argv)
1080 " -o data output file [default trace.dat]\n" 1237 " -o data output file [default trace.dat]\n"
1081 " -O option to enable (or disable)\n" 1238 " -O option to enable (or disable)\n"
1082 " -s sleep interval between recording (in usecs) [default: 1000]\n" 1239 " -s sleep interval between recording (in usecs) [default: 1000]\n"
1240 " -N host:port to connect to (see listen)\n"
1083 "\n" 1241 "\n"
1084 " %s start [-e event][-p plugin][-d][-O option ][-P pid]\n" 1242 " %s start [-e event][-p plugin][-d][-O option ][-P pid]\n"
1085 " Uses same options as record, but does not run a command.\n" 1243 " Uses same options as record, but does not run a command.\n"
@@ -1122,11 +1280,17 @@ void usage(char **argv)
1122 " if left out, will start at beginning of file\n" 1280 " if left out, will start at beginning of file\n"
1123 " end - decimal end time in seconds\n" 1281 " end - decimal end time in seconds\n"
1124 "\n" 1282 "\n"
1283 " %s listen -p port[-D][-o file][-d dir]\n"
1284 " Creates a socket to listen for clients.\n"
1285 " -D create it in daemon mode.\n"
1286 " -o file name to use for clients.\n"
1287 " -d diretory to store client files.\n"
1288 "\n"
1125 " %s list [-e][-p]\n" 1289 " %s list [-e][-p]\n"
1126 " -e list available events\n" 1290 " -e list available events\n"
1127 " -p list available plugins\n" 1291 " -p list available plugins\n"
1128 " -o list available options\n" 1292 " -o list available options\n"
1129 "\n", p, VERSION_STRING, p, p, p, p, p, p, p, p); 1293 "\n", p, VERSION_STRING, p, p, p, p, p, p, p, p, p);
1130 exit(-1); 1294 exit(-1);
1131} 1295}
1132 1296
@@ -1159,6 +1323,9 @@ int main (int argc, char **argv)
1159 if (strcmp(argv[1], "report") == 0) { 1323 if (strcmp(argv[1], "report") == 0) {
1160 trace_report(argc, argv); 1324 trace_report(argc, argv);
1161 exit(0); 1325 exit(0);
1326 } else if (strcmp(argv[1], "listen") == 0) {
1327 trace_listen(argc, argv);
1328 exit(0);
1162 } else if (strcmp(argv[1], "split") == 0) { 1329 } else if (strcmp(argv[1], "split") == 0) {
1163 trace_split(argc, argv); 1330 trace_split(argc, argv);
1164 exit(0); 1331 exit(0);
@@ -1166,7 +1333,7 @@ int main (int argc, char **argv)
1166 (strcmp(argv[1], "start") == 0) || 1333 (strcmp(argv[1], "start") == 0) ||
1167 ((extract = strcmp(argv[1], "extract") == 0))) { 1334 ((extract = strcmp(argv[1], "extract") == 0))) {
1168 1335
1169 while ((c = getopt(argc-1, argv+1, "+he:f:Fp:do:O:s:vg:l:n:P:")) >= 0) { 1336 while ((c = getopt(argc-1, argv+1, "+he:f:Fp:do:O:s:vg:l:n:P:N:")) >= 0) {
1170 switch (c) { 1337 switch (c) {
1171 case 'h': 1338 case 'h':
1172 usage(argv); 1339 usage(argv);
@@ -1241,6 +1408,8 @@ int main (int argc, char **argv)
1241 disable = 1; 1408 disable = 1;
1242 break; 1409 break;
1243 case 'o': 1410 case 'o':
1411 if (host)
1412 die("-o incompatible with -N");
1244 if (!record && !extract) 1413 if (!record && !extract)
1245 die("start does not take output\n" 1414 die("start does not take output\n"
1246 "Did you mean 'record'?"); 1415 "Did you mean 'record'?");
@@ -1257,6 +1426,13 @@ int main (int argc, char **argv)
1257 usage(argv); 1426 usage(argv);
1258 sleep_time = atoi(optarg); 1427 sleep_time = atoi(optarg);
1259 break; 1428 break;
1429 case 'N':
1430 if (!record)
1431 die("-N only available with record");
1432 if (output)
1433 die("-N incompatible with -o");
1434 host = optarg;
1435 break;
1260 } 1436 }
1261 } 1437 }
1262 1438