]>
Commit | Line | Data |
---|---|---|
c3a3c0c9 WC |
1 | // coveragedb.cxx |
2 | // Copyright (C) 2007 Red Hat Inc. | |
3 | // | |
4 | // This file is part of systemtap, and is free software. You can | |
5 | // redistribute it and/or modify it under the terms of the GNU General | |
6 | // Public License (GPL); either version 2, or (at your option) any | |
7 | // later version. | |
8 | ||
9 | #include "parse.h" | |
10 | #include "coveragedb.h" | |
11 | #include "config.h" | |
12 | #include "elaborate.h" | |
13 | #include "tapsets.h" | |
14 | #include "session.h" | |
15 | #include "util.h" | |
16 | ||
1c0b94ef FCE |
17 | #ifdef HAVE_LIBSQLITE3 |
18 | ||
c3a3c0c9 WC |
19 | #include <iostream> |
20 | #include <sqlite3.h> | |
ed7742ee | 21 | #include <cstdlib> |
c3a3c0c9 WC |
22 | |
23 | using namespace std; | |
24 | ||
25 | void print_coverage_info(systemtap_session &s) | |
26 | { | |
c3a3c0c9 | 27 | // print out used probes |
19211404 | 28 | clog << _("---- used probes-----") << endl; |
c3a3c0c9 WC |
29 | for (unsigned i=0; i<s.probes.size(); i++) { |
30 | // walk through the chain of probes | |
2c5a19c6 | 31 | vector<probe*> used_probe_list; |
c3a3c0c9 WC |
32 | s.probes[i]->collect_derivation_chain(used_probe_list); |
33 | for (unsigned j=0; j<used_probe_list.size(); ++j) { | |
34 | for (unsigned k=0; k< used_probe_list[j]->locations.size(); ++k) | |
19211404 | 35 | clog << _("probe: ") |
f94baaee | 36 | << used_probe_list[j]->locations[k]->components.front()->tok->location << endl; |
c3a3c0c9 | 37 | } |
dff50e09 | 38 | |
c3a3c0c9 WC |
39 | clog << "----" << endl; |
40 | // for each probe print used and unused variables | |
41 | for (unsigned j=0; j<s.probes[i]->locals.size(); ++j) { | |
19211404 | 42 | clog << _("local: ") << s.probes[i]->locals[j]->tok->location << endl; |
c3a3c0c9 WC |
43 | } |
44 | for (unsigned j=0; j<s.probes[i]->unused_locals.size(); ++j) { | |
19211404 | 45 | clog << _("unused_local: ") |
c3a3c0c9 WC |
46 | << s.probes[i]->unused_locals[j]->tok->location |
47 | << endl; | |
48 | } | |
49 | } | |
50 | // print out unused probes | |
19211404 | 51 | clog << _("---- unused probes----- ") << endl; |
c3a3c0c9 WC |
52 | for (unsigned i=0; i<s.unused_probes.size(); i++) { |
53 | // walk through the chain of probes | |
2c5a19c6 | 54 | vector<probe*> unused_probe_list; |
5657c32c | 55 | s.unused_probes[i]->collect_derivation_chain(unused_probe_list); |
c3a3c0c9 WC |
56 | for (unsigned j=0; j<unused_probe_list.size(); ++j) { |
57 | for (unsigned k=0; k< unused_probe_list[j]->locations.size(); ++k) | |
19211404 | 58 | clog << _("probe: ") |
f94baaee | 59 | << unused_probe_list[j]->locations[k]->components.front()->tok->location << endl; |
c3a3c0c9 WC |
60 | } |
61 | ||
62 | } | |
63 | // print out used functions | |
19211404 | 64 | clog << _("---- used functions----- ") << endl; |
f76427a2 FCE |
65 | for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) |
66 | { | |
67 | clog << "function: " << it->second->tok->location | |
68 | << " " << it->second->name | |
69 | << endl; | |
70 | } | |
c3a3c0c9 | 71 | // print out unused functions |
19211404 | 72 | clog << _("---- unused functions----- ") << endl; |
c3a3c0c9 | 73 | for (unsigned i=0; i<s.unused_functions.size(); i++) { |
19211404 | 74 | clog << _("unused_function: ") << s.unused_functions[i]->tok->location |
c3a3c0c9 WC |
75 | << " " << s.unused_functions[i]->name |
76 | << endl; | |
77 | } | |
78 | // print out used globals | |
19211404 | 79 | clog << _("---- used globals----- ") << endl; |
c3a3c0c9 | 80 | for (unsigned i=0; i<s.globals.size(); i++) { |
19211404 | 81 | clog << _("globals: ") << s.globals[i]->tok->location |
c3a3c0c9 WC |
82 | << " " << s.globals[i]->name |
83 | << endl; | |
84 | } | |
85 | // print out unused globals | |
19211404 | 86 | clog << _("---- unused globals----- ") << endl; |
c3a3c0c9 | 87 | for (unsigned i=0; i<s.unused_globals.size(); i++) { |
19211404 | 88 | clog << _("globals: ") << s.unused_globals[i]->tok->location |
c3a3c0c9 WC |
89 | << " " << s.unused_globals[i]->name |
90 | << endl; | |
91 | } | |
92 | } | |
93 | ||
94 | ||
b34237a1 WC |
95 | bool |
96 | has_table(sqlite3 *db, const char * table) | |
97 | { | |
98 | int rc, rows, columns; | |
99 | char *errmsg; | |
100 | char **results = NULL; | |
101 | ||
102 | ostringstream command; | |
103 | command << "SELECT name FROM sqlite_master " | |
104 | << "WHERE type='table' AND name='" << table << "'"; | |
105 | ||
106 | rc = sqlite3_get_table(db, command.str().c_str(), | |
107 | &results, &rows, &columns, &errmsg); | |
108 | ||
109 | if(rc != SQLITE_OK) { | |
1b6156ad | 110 | cerr << _("Error in statement: ") << command.str() << " [" << errmsg << "]." |
b34237a1 WC |
111 | << endl; |
112 | } | |
113 | sqlite3_free_table(results); | |
114 | return (rows !=0); | |
115 | } | |
116 | ||
117 | ||
118 | bool | |
119 | has_index(sqlite3 *db, const char * index) | |
120 | { | |
121 | int rc, rows, columns; | |
122 | char *errmsg; | |
123 | char **results = NULL; | |
124 | ||
125 | ostringstream command; | |
126 | command << "SELECT name FROM sqlite_master " | |
127 | << "WHERE type='index' AND name='" << index << "'"; | |
128 | ||
129 | rc = sqlite3_get_table(db, command.str().c_str(), | |
130 | &results, &rows, &columns, &errmsg); | |
131 | ||
132 | if(rc != SQLITE_OK) { | |
1b6156ad | 133 | cerr << _("Error in statement: ") << command.str() << " [" << errmsg << "]." |
b34237a1 WC |
134 | << endl; |
135 | } | |
136 | sqlite3_free_table(results); | |
137 | return (rows !=0); | |
138 | } | |
139 | ||
140 | ||
c3a3c0c9 WC |
141 | void sql_stmt(sqlite3 *db, const char* stmt) |
142 | { | |
143 | char *errmsg; | |
144 | int ret; | |
145 | ||
146 | // cerr << "sqlite: " << stmt << endl; | |
147 | ||
148 | ret = sqlite3_exec(db, stmt, 0, 0, &errmsg); | |
149 | ||
150 | if(ret != SQLITE_OK) { | |
19211404 | 151 | cerr << _("Error in statement: ") << stmt << " [" << errmsg << "]." |
c3a3c0c9 WC |
152 | << endl; |
153 | } | |
154 | } | |
155 | ||
156 | void enter_element(sqlite3 *db, coverage_element &x) | |
157 | { | |
158 | ostringstream command; | |
1e41115c | 159 | command << "insert or ignore into counts values ('" |
c3a3c0c9 WC |
160 | << x.file << "', '" |
161 | << x.line << "', '" | |
162 | << x.col << "', '" | |
163 | << x.type << "','" | |
164 | << x.name << "', '" | |
165 | << x.parent <<"'," | |
b34237a1 | 166 | << "'0', '0')"; |
c3a3c0c9 WC |
167 | sql_stmt(db, command.str().c_str()); |
168 | } | |
169 | ||
b34237a1 | 170 | |
c3a3c0c9 WC |
171 | void increment_element(sqlite3 *db, coverage_element &x) |
172 | { | |
b34237a1 | 173 | ostringstream command; |
c3a3c0c9 | 174 | // make sure value in table |
1e41115c | 175 | command << "insert or ignore into counts values ('" |
b34237a1 WC |
176 | << x.file << "', '" |
177 | << x.line << "', '" | |
178 | << x.col << "', '" | |
179 | << x.type << "','" | |
180 | << x.name << "', '" | |
181 | << x.parent <<"'," | |
182 | << "'0', '0'); " | |
6b1a0274 | 183 | // increment appropriate value |
b34237a1 WC |
184 | << "update counts set compiled=compiled+" |
185 | << x.compiled << " where (" | |
186 | << "file=='" << x.file << "' and " | |
187 | << "line=='" << x.line << "' and " | |
188 | << "col=='" << x.col << "' and " | |
189 | << "type=='" << x.type << "' and " | |
190 | << "name=='" << x.name << "')"; | |
191 | sql_stmt(db, command.str().c_str()); | |
c3a3c0c9 WC |
192 | } |
193 | ||
194 | ||
195 | void | |
196 | sql_update_used_probes(sqlite3 *db, systemtap_session &s) | |
197 | { | |
c3a3c0c9 WC |
198 | // update database used probes |
199 | for (unsigned i=0; i<s.probes.size(); i++) { | |
200 | // walk through the chain of probes | |
2c5a19c6 | 201 | vector<probe*> used_probe_list; |
c3a3c0c9 WC |
202 | s.probes[i]->collect_derivation_chain(used_probe_list); |
203 | for (unsigned j=0; j<used_probe_list.size(); ++j) { | |
204 | for (unsigned k=0; k< used_probe_list[j]->locations.size(); ++k){ | |
f94baaee | 205 | struct source_loc place = used_probe_list[j]->locations[k]->components.front()->tok->location; |
c3a3c0c9 WC |
206 | coverage_element x(place); |
207 | ||
b34237a1 | 208 | x.type = db_type_probe; |
c3a3c0c9 WC |
209 | x.name = used_probe_list[j]->locations[k]->str(); |
210 | x.compiled = 1; | |
211 | increment_element(db, x); | |
212 | } | |
213 | } | |
dff50e09 | 214 | |
c3a3c0c9 WC |
215 | // for each probe update used and unused variables |
216 | for (unsigned j=0; j<s.probes[i]->locals.size(); ++j) { | |
217 | struct source_loc place = s.probes[i]->locals[j]->tok->location; | |
218 | coverage_element x(place); | |
219 | ||
b34237a1 | 220 | x.type = db_type_local; |
47d349b1 | 221 | x.name = s.probes[i]->locals[j]->tok->content; |
c3a3c0c9 WC |
222 | x.compiled = 1; |
223 | increment_element(db, x); | |
224 | } | |
225 | for (unsigned j=0; j<s.probes[i]->unused_locals.size(); ++j) { | |
226 | struct source_loc place = s.probes[i]->unused_locals[j]->tok->location; | |
227 | coverage_element x(place); | |
228 | ||
b34237a1 | 229 | x.type = db_type_local; |
47d349b1 | 230 | x.name = s.probes[i]->unused_locals[j]->tok->content; |
b34237a1 | 231 | x.compiled = 0; |
c3a3c0c9 WC |
232 | increment_element(db, x); |
233 | } | |
234 | } | |
235 | } | |
236 | ||
237 | ||
238 | void | |
239 | sql_update_unused_probes(sqlite3 *db, systemtap_session &s) | |
240 | { | |
c3a3c0c9 WC |
241 | // update database unused probes |
242 | for (unsigned i=0; i<s.unused_probes.size(); i++) { | |
243 | // walk through the chain of probes | |
2c5a19c6 | 244 | vector<probe*> unused_probe_list; |
5657c32c | 245 | s.unused_probes[i]->collect_derivation_chain(unused_probe_list); |
c3a3c0c9 WC |
246 | for (unsigned j=0; j<unused_probe_list.size(); ++j) { |
247 | for (unsigned k=0; k< unused_probe_list[j]->locations.size(); ++k) { | |
248 | ||
f94baaee | 249 | struct source_loc place = unused_probe_list[j]->locations[k]->components.front()->tok->location; |
c3a3c0c9 WC |
250 | coverage_element x(place); |
251 | ||
b34237a1 | 252 | x.type = db_type_probe; |
c3a3c0c9 | 253 | x.name = unused_probe_list[j]->locations[k]->str(); |
b34237a1 | 254 | x.compiled = 0; |
c3a3c0c9 WC |
255 | increment_element(db, x); |
256 | } | |
257 | } | |
258 | } | |
259 | } | |
260 | ||
261 | ||
262 | void | |
263 | sql_update_used_functions(sqlite3 *db, systemtap_session &s) | |
264 | { | |
265 | // update db used functions | |
f76427a2 FCE |
266 | for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) |
267 | { | |
268 | struct source_loc place = it->second->tok->location; | |
269 | coverage_element x(place); | |
270 | ||
271 | x.type = db_type_function; | |
272 | x.name = it->second->name; | |
273 | x.compiled = 1; | |
274 | increment_element(db, x); | |
275 | } | |
c3a3c0c9 WC |
276 | } |
277 | ||
278 | ||
279 | void | |
280 | sql_update_unused_functions(sqlite3 *db, systemtap_session &s) | |
281 | { | |
282 | // update db unused functions | |
283 | for (unsigned i=0; i<s.unused_functions.size(); i++) { | |
284 | struct source_loc place = s.unused_functions[i]->tok->location; | |
285 | coverage_element x(place); | |
286 | ||
b34237a1 | 287 | x.type = db_type_function; |
c3a3c0c9 | 288 | x.name = s.unused_functions[i]->name; |
b34237a1 | 289 | x.compiled = 0; |
c3a3c0c9 WC |
290 | increment_element(db, x); |
291 | } | |
292 | } | |
293 | ||
294 | ||
295 | void | |
296 | sql_update_used_globals(sqlite3 *db, systemtap_session &s) | |
297 | { | |
298 | // update db used globals | |
299 | for (unsigned i=0; i<s.globals.size(); i++) { | |
c3a3c0c9 WC |
300 | struct source_loc place = s.globals[i]->tok->location; |
301 | coverage_element x(place); | |
302 | ||
b34237a1 | 303 | x.type = db_type_global; |
c3a3c0c9 WC |
304 | x.name = s.globals[i]->name; |
305 | x.compiled = 1; | |
306 | increment_element(db, x); | |
307 | } | |
308 | } | |
309 | ||
310 | ||
311 | void | |
312 | sql_update_unused_globals(sqlite3 *db, systemtap_session &s) | |
313 | { | |
314 | // update db unused globals | |
315 | for (unsigned i=0; i<s.unused_globals.size(); i++) { | |
316 | struct source_loc place = s.unused_globals[i]->tok->location; | |
317 | coverage_element x(place); | |
318 | ||
b34237a1 | 319 | x.type = db_type_global; |
c3a3c0c9 | 320 | x.name = s.unused_globals[i]->name; |
b34237a1 | 321 | x.compiled = 0; |
c3a3c0c9 WC |
322 | increment_element(db, x); |
323 | } | |
324 | } | |
325 | ||
c3a3c0c9 WC |
326 | void update_coverage_db(systemtap_session &s) |
327 | { | |
328 | sqlite3 *db; | |
329 | int rc; | |
330 | ||
331 | string filename(s.data_path + "/" + s.kernel_release + ".db"); | |
332 | ||
333 | rc = sqlite3_open(filename.c_str(), &db); | |
334 | if( rc ){ | |
335 | cerr << "Can't open database: " << sqlite3_errmsg(db) << endl; | |
336 | sqlite3_close(db); | |
504d2b61 | 337 | return; |
c3a3c0c9 WC |
338 | } |
339 | ||
b34237a1 WC |
340 | // lock the database |
341 | sql_stmt(db, "begin"); | |
342 | ||
343 | string create_table("create table counts (" | |
c3a3c0c9 WC |
344 | "file text, line integer, col integer, " |
345 | "type text, name text, parent text, " | |
b34237a1 | 346 | "compiled integer, executed integer)"); |
8a2b19ab | 347 | string create_index("create unique index tokens on counts (file, line, col, " |
b34237a1 | 348 | "type, name)"); |
c3a3c0c9 | 349 | |
b34237a1 WC |
350 | // make sure the table is there |
351 | if (!has_table(db, "counts")) | |
352 | sql_stmt(db, create_table.c_str()); | |
c3a3c0c9 | 353 | |
b34237a1 WC |
354 | // make sure the index is there |
355 | if (!has_index(db, "tokens")) | |
356 | sql_stmt(db, create_index.c_str()); | |
c3a3c0c9 | 357 | |
c3a3c0c9 WC |
358 | sql_update_used_probes(db, s); |
359 | sql_update_unused_probes(db, s); | |
360 | sql_update_used_functions(db, s); | |
361 | sql_update_unused_functions(db, s); | |
362 | sql_update_used_globals(db, s); | |
363 | sql_update_unused_globals(db, s); | |
364 | ||
365 | // unlock the database and close database | |
366 | sql_stmt(db, "commit"); | |
367 | ||
368 | sqlite3_close(db); | |
369 | } | |
1c0b94ef FCE |
370 | |
371 | #endif /* HAVE_LIBSQLITE3 */ | |
73267b89 JS |
372 | |
373 | /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ |