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