• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include <tracefs.h>
8 
9 #include "trace-local.h"
10 
11 enum action {
12 	ACTION_DEFAULT	= 0,
13 	ACTION_SNAPSHOT	= (1 << 0),
14 	ACTION_TRACE	= (1 << 1),
15 	ACTION_SAVE	= (1 << 2),
16 	ACTION_MAX	= (1 << 3),
17 	ACTION_CHANGE	= (1 << 4),
18 };
19 
20 #define ACTIONS ((ACTION_MAX - 1))
21 
do_sql(const char * instance_name,const char * buffer,const char * name,const char * var,const char * trace_dir,bool execute,int action,char ** save_fields)22 static int do_sql(const char *instance_name,
23 		  const char *buffer, const char *name, const char *var,
24 		  const char *trace_dir, bool execute, int action,
25 		  char **save_fields)
26 {
27 	struct tracefs_synth *synth;
28 	struct tep_handle *tep;
29 	struct trace_seq seq;
30 	enum tracefs_synth_handler handler;
31 	char *err;
32 	int ret;
33 
34 	if ((action & ACTIONS) && !var)
35 		die("Error: -s, -S and -T not supported without -m or -c");
36 
37 	if (!name)
38 		name = "Anonymous";
39 
40 	trace_seq_init(&seq);
41 	tep = tracefs_local_events(trace_dir);
42 	if (!tep)
43 		die("Could not read %s", trace_dir ? trace_dir : "tracefs directory");
44 
45 	synth = tracefs_sql(tep, name, buffer, &err);
46 	if (!synth)
47 		die("Failed creating synthetic event!\n%s", err ? err : "");
48 
49 	if (tracefs_synth_complete(synth)) {
50 		if (var) {
51 			if (action & ACTION_MAX)
52 				handler = TRACEFS_SYNTH_HANDLE_MAX;
53 			else
54 				handler = TRACEFS_SYNTH_HANDLE_CHANGE;
55 
56 			/* Default to trace if other actions are not set */
57 			if (!(action & (ACTION_SAVE | ACTION_SNAPSHOT)))
58 				action |= ACTION_TRACE;
59 
60 			if (action & ACTION_SAVE) {
61 				ret = tracefs_synth_save(synth, handler, var, save_fields);
62 				if (ret < 0) {
63 					err = "adding save";
64 					goto failed_action;
65 				}
66 			}
67 			if (action & ACTION_TRACE) {
68 				/*
69 				 * By doing the trace before snapshot, it will be included
70 				 * in the snapshot.
71 				 */
72 				ret = tracefs_synth_trace(synth, handler, var);
73 				if (ret < 0) {
74 					err = "adding trace";
75 					goto failed_action;
76 				}
77 			}
78 			if (action & ACTION_SNAPSHOT) {
79 				ret = tracefs_synth_snapshot(synth, handler, var);
80 				if (ret < 0) {
81 					err = "adding snapshot";
82  failed_action:
83 					perror(err);
84 					if (errno == ENODEV)
85 						fprintf(stderr, "ERROR: '%s' is not a variable\n",
86 							var);
87 					exit(-1);
88 				}
89 			}
90 		}
91 		tracefs_synth_echo_cmd(&seq, synth);
92 		if (execute) {
93 			ret = tracefs_synth_create(synth);
94 			if (ret < 0)
95 				die("%s\n", tracefs_error_last(NULL));
96 		}
97 	} else {
98 		struct tracefs_instance *instance = NULL;
99 		struct tracefs_hist *hist;
100 
101 		hist = tracefs_synth_get_start_hist(synth);
102 		if (!hist)
103 			die("get_start_hist");
104 
105 		if (instance_name) {
106 			if (execute)
107 				instance = tracefs_instance_create(instance_name);
108 			else
109 				instance = tracefs_instance_alloc(trace_dir,
110 								  instance_name);
111 			if (!instance)
112 				die("Failed to create instance");
113 		}
114 		tracefs_hist_echo_cmd(&seq, instance, hist, 0);
115 		if (execute) {
116 			ret = tracefs_hist_start(instance, hist);
117 			if (ret < 0)
118 				die("%s\n", tracefs_error_last(instance));
119 		}
120 	}
121 
122 	tracefs_synth_free(synth);
123 
124 	trace_seq_do_printf(&seq);
125 	trace_seq_destroy(&seq);
126 	return 0;
127 }
128 
trace_sqlhist(int argc,char ** argv)129 void trace_sqlhist (int argc, char **argv)
130 {
131 	char *trace_dir = NULL;
132 	char *buffer = NULL;
133 	char buf[BUFSIZ];
134 	int buffer_size = 0;
135 	const char *file = NULL;
136 	const char *instance = NULL;
137 	bool execute = false;
138 	char **save_fields = NULL;
139 	const char *name;
140 	const char *var;
141 	char **save_argv;
142 	int action = 0;
143 	char *tok;
144 	FILE *fp;
145 	size_t r;
146 	int c;
147 	int i;
148 
149 	/* Remove 'trace-cmd' */
150 	save_argv = argv;
151 	argc -= 1;
152 	argv += 1;
153 
154 	if (argc < 2)
155 		usage(save_argv);
156 
157 	for (;;) {
158 		c = getopt(argc, argv, "ht:f:en:m:c:sS:TB:");
159 		if (c == -1)
160 			break;
161 
162 		switch(c) {
163 		case 'h':
164 			usage(save_argv);
165 		case 't':
166 			trace_dir = optarg;
167 			break;
168 		case 'f':
169 			file = optarg;
170 			break;
171 		case 'e':
172 			execute = true;
173 			break;
174 		case 'm':
175 			action |= ACTION_MAX;
176 			var = optarg;
177 			break;
178 		case 'c':
179 			action |= ACTION_CHANGE;
180 			var = optarg;
181 			break;
182 		case 's':
183 			action |= ACTION_SNAPSHOT;
184 			break;
185 		case 'S':
186 			action |= ACTION_SAVE;
187 			tok = strtok(optarg, ",");
188 			while (tok) {
189 				save_fields = tracefs_list_add(save_fields, tok);
190 				tok = strtok(NULL, ",");
191 			}
192 			if (!save_fields) {
193 				perror(optarg);
194 				exit(-1);
195 			}
196 			break;
197 		case 'T':
198 			action |= ACTION_TRACE | ACTION_SNAPSHOT;
199 			break;
200 		case 'B':
201 			instance = optarg;
202 			break;
203 		case 'n':
204 			name = optarg;
205 			break;
206 		}
207 	}
208 
209 	if ((action & (ACTION_MAX|ACTION_CHANGE)) == (ACTION_MAX|ACTION_CHANGE)) {
210 		fprintf(stderr, "Can not use both -m and -c together\n");
211 		exit(-1);
212 	}
213 	if (file) {
214 		if (!strcmp(file, "-"))
215 			fp = stdin;
216 		else
217 			fp = fopen(file, "r");
218 		if (!fp) {
219 			perror(file);
220 			exit(-1);
221 		}
222 		while ((r = fread(buf, 1, BUFSIZ, fp)) > 0) {
223 			buffer = realloc(buffer, buffer_size + r + 1);
224 			strncpy(buffer + buffer_size, buf, r);
225 			buffer_size += r;
226 		}
227 		fclose(fp);
228 		if (buffer_size)
229 			buffer[buffer_size] = '\0';
230 	} else if (argc == optind) {
231 		usage(save_argv);
232 	} else {
233 		for (i = optind; i < argc; i++) {
234 			r = strlen(argv[i]);
235 			buffer = realloc(buffer, buffer_size + r + 2);
236 			if (i != optind)
237 				buffer[buffer_size++] = ' ';
238 			strcpy(buffer + buffer_size, argv[i]);
239 			buffer_size += r;
240 		}
241 	}
242 
243 	do_sql(instance, buffer, name, var, trace_dir, execute, action, save_fields);
244 	free(buffer);
245 }
246 
247