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