2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Nathan Binkert
37 #include "base/misc.hh"
38 #include "base/mysql.hh"
39 #include "base/statistics.hh"
40 #include "base/stats/flags.hh"
41 #include "base/stats/mysql.hh"
42 #include "base/stats/mysql_run.hh"
43 #include "base/stats/statdb.hh"
44 #include "base/stats/types.hh"
45 #include "base/str.hh"
46 #include "sim/host.hh"
57 return MySqlDB
.connected();
61 MySqlRun::connect(const string
&host
, const string
&user
, const string
&passwd
,
62 const string
&db
, const string
&name
, const string
&sample
,
63 const string
&project
)
66 panic("can only get one database connection at this time!");
68 mysql
.connect(host
, user
, passwd
, db
);
70 panic("could not connect to database server\n%s\n", mysql
.error
);
72 if (mysql
.autocommit(false))
73 panic("could not set autocommit\n%s\n", mysql
.error
);
77 setup(name
, sample
, user
, project
);
81 MySqlRun::setup(const string
&name
, const string
&sample
, const string
&user
,
82 const string
&project
)
84 assert(mysql
.connected());
89 "runs(rn_name,rn_sample,rn_user,rn_project,rn_date,rn_expire)"
90 "values(\"%s\", \"%s\", \"%s\", \"%s\", NOW(),"
91 "DATE_ADD(CURDATE(), INTERVAL 31 DAY))",
92 name
, sample
, user
, project
);
96 panic("could not get a run\n%s\n", mysql
.error
);
98 run_id
= mysql
.insert_id();
100 panic("could not commit transaction\n%s\n", mysql
.error
);
104 MySqlRun::remove(const string
&name
)
106 assert(mysql
.connected());
108 ccprintf(sql
, "DELETE FROM runs WHERE rn_name=\"%s\"", name
);
111 panic("could not delete run\n%s\n", mysql
.error
);
113 panic("could not commit transaction\n%s\n", mysql
.error
);
119 assert(mysql
.connected());
121 mysql
.query("DELETE data "
123 "LEFT JOIN runs ON dt_run=rn_id "
124 "WHERE rn_id IS NULL");
127 panic("could not commit transaction\n%s\n", mysql
.error
);
129 mysql
.query("DELETE formula_ref "
131 "LEFT JOIN runs ON fr_run=rn_id "
132 "WHERE rn_id IS NULL");
135 panic("could not commit transaction\n%s\n", mysql
.error
);
137 mysql
.query("DELETE formulas "
139 "LEFT JOIN formula_ref ON fm_stat=fr_stat "
140 "WHERE fr_stat IS NULL");
143 panic("could not commit transaction\n%s\n", mysql
.error
);
145 mysql
.query("DELETE stats "
147 "LEFT JOIN data ON st_id=dt_stat "
148 "WHERE dt_stat IS NULL");
151 panic("could not commit transaction\n%s\n", mysql
.error
);
153 mysql
.query("DELETE subdata "
155 "LEFT JOIN data ON sd_stat=dt_stat "
156 "WHERE dt_stat IS NULL");
159 panic("could not commit transaction\n%s\n", mysql
.error
);
161 mysql
.query("DELETE bins "
163 "LEFT JOIN data ON bn_id=dt_bin "
164 "WHERE dt_bin IS NULL");
167 panic("could not commit transaction\n%s\n", mysql
.error
);
169 mysql
.query("DELETE events"
171 "LEFT JOIN runs ON ev_run=rn_id"
172 "WHERE rn_id IS NULL");
175 panic("could not commit transaction\n%s\n", mysql
.error
);
177 mysql
.query("DELETE event_names"
179 "LEFT JOIN events ON en_id=ev_event"
180 "WHERE ev_event IS NULL");
183 panic("could not commit transaction\n%s\n", mysql
.error
);
209 MySQL::Connection
&mysql
= MySqlDB
.conn();
214 "stats(st_name, st_descr, st_type, st_print, st_prereq, "
215 "st_prec, st_nozero, st_nonan, st_total, st_pdf, st_cdf, "
216 "st_min, st_max, st_bktsize, st_size)"
217 "values(\"%s\",\"%s\",\"%s\","
218 " %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
219 name
, descr
, type
, print
, prereq
, (int)prec
, nozero
, nonan
,
221 min
, max
, bktsize
, size
);
225 int id
= mysql
.insert_id();
227 panic("could not commit transaction\n%s\n", mysql
.error
);
232 ccprintf(select
, "SELECT * FROM stats WHERE st_name=\"%s\"", name
);
235 MySQL::Result result
= mysql
.store_result();
237 panic("could not find stat\n%s\n", mysql
.error
);
239 assert(result
.num_fields() == 16);
240 MySQL::Row row
= result
.fetch_row();
242 panic("could not get stat row\n%s\n", mysql
.error
);
250 if (name
!= (char *)row
[1])
251 panic("failed stat check on %s:name. %s != %s\n",
254 if (descr
!= (char *)row
[2])
255 panic("failed stat check on %s:descr. %s != %s\n",
256 name
, descr
, row
[2]);
258 if (type
!= (char *)row
[3])
259 panic("failed stat check on %s:type. %s != %s\n",
262 if (!to_number(row
[4], tb
) || print
!= tb
)
263 panic("failed stat check on %s:print. %d != %d\n",
266 if (!to_number(row
[6], ti8
) || prec
!= ti8
)
267 panic("failed stat check on %s:prec. %d != %d\n",
270 if (!to_number(row
[7], tb
) || nozero
!= tb
)
271 panic("failed stat check on %s:nozero. %d != %d\n",
274 if (!to_number(row
[8], tb
) || nonan
!= tb
)
275 panic("failed stat check on %s:nonan. %d != %d\n",
278 if (!to_number(row
[9], tb
) || total
!= tb
)
279 panic("failed stat check on %s:total. %d != %d\n",
282 if (!to_number(row
[10], tb
) || pdf
!= tb
)
283 panic("failed stat check on %s:pdf. %d != %d\n",
286 if (!to_number(row
[11], tb
) || cdf
!= tb
)
287 panic("failed stat check on %s:cdf. %d != %d\n",
290 if (!to_number(row
[12], ti64
) || min
!= ti64
)
291 panic("failed stat check on %s:min. %d != %d\n",
294 if (!to_number(row
[13], ti64
) || max
!= ti64
)
295 panic("failed stat check on %s:max. %d != %d\n",
298 if (!to_number(row
[14], tu64
) || bktsize
!= tu64
)
299 panic("failed stat check on %s:bktsize. %d != %d\n",
300 name
, bktsize
, tu64
);
302 if (!to_number(row
[15], tu16
) || size
!= tu16
)
303 panic("failed stat check on %s:size. %d != %d\n",
306 to_number(row
[5], prereq
);
308 to_number(row
[0], statid
);
313 SetupBin(const string
&bin
)
315 static map
<string
, int> binmap
;
317 using namespace MySQL
;
318 map
<string
,int>::const_iterator i
= binmap
.find(bin
);
319 if (i
!= binmap
.end())
322 Connection
&mysql
= MySqlDB
.conn();
323 assert(mysql
.connected());
329 ccprintf(select
, "SELECT bn_id FROM bins WHERE bn_name=\"%s\"", bin
);
332 MySQL::Result result
= mysql
.store_result();
334 assert(result
.num_fields() == 1);
335 MySQL::Row row
= result
.fetch_row();
337 to_number(row
[0], bin_id
);
342 ccprintf(insert
, "INSERT INTO bins(bn_name) values(\"%s\")", bin
);
346 panic("could not get a bin\n%s\n", mysql
.error
);
348 bin_id
= mysql
.insert_id();
350 panic("could not commit transaction\n%s\n", mysql
.error
);
352 binmap
.insert(make_pair(bin
, bin_id
));
358 InsertData::InsertData()
360 query
= new char[maxsize
+ 1];
365 InsertData::~InsertData()
374 MySQL::Connection
&mysql
= MySqlDB
.conn();
375 assert(mysql
.connected());
378 panic("could not insert data\n%s\n", mysql
.error
);
380 panic("could not commit transaction\n%s\n", mysql
.error
);
386 strcpy(query
, "INSERT INTO "
387 "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_bin,dt_data) "
389 size
= strlen(query
);
395 if (size
+ 1024 > maxsize
)
405 size
+= sprintf(query
+ size
, "(%u,%d,%d,%u,%llu,%u,\"%f\")",
406 stat
, x
, y
, MySqlDB
.run(), (unsigned long long)tick
,
422 InsertSubData::setup()
424 MySQL::Connection
&mysql
= MySqlDB
.conn();
425 assert(mysql
.connected());
428 "INSERT INTO subdata(sd_stat,sd_x,sd_y,sd_name,sd_descr) "
429 "values(%d,%d,%d,\"%s\",\"%s\")",
430 stat
, x
, y
, name
, descr
);
434 // panic("could not insert subdata\n%s\n", mysql.error);
437 panic("could not commit transaction\n%s\n", mysql
.error
);
441 InsertFormula(uint16_t stat
, const string
&formula
)
443 MySQL::Connection
&mysql
= MySqlDB
.conn();
444 assert(mysql
.connected());
445 stringstream insert_formula
;
446 ccprintf(insert_formula
,
447 "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
450 mysql
.query(insert_formula
);
452 // panic("could not insert formula\n%s\n", mysql.error);
454 stringstream insert_ref
;
456 "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
457 stat
, MySqlDB
.run());
459 mysql
.query(insert_ref
);
461 // panic("could not insert formula reference\n%s\n", mysql.error);
464 panic("could not commit transaction\n%s\n", mysql
.error
);
468 UpdatePrereq(uint16_t stat
, uint16_t prereq
)
470 MySQL::Connection
&mysql
= MySqlDB
.conn();
471 assert(mysql
.connected());
473 ccprintf(update
, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
477 panic("could not update prereq\n%s\n", mysql
.error
);
480 panic("could not commit transaction\n%s\n", mysql
.error
);
489 using namespace Database
;
491 MySQL::Connection
&mysql
= MySqlDB
.conn();
493 stat_list_t::const_iterator i
, end
= stats().end();
494 for (i
= stats().begin(); i
!= end
; ++i
) {
498 for (i
= stats().begin(); i
!= end
; ++i
) {
501 uint16_t stat_id
= find(data
->id
);
502 uint16_t prereq_id
= find(data
->prereq
->id
);
503 assert(stat_id
&& prereq_id
);
505 UpdatePrereq(stat_id
, prereq_id
);
510 panic("could not commit transaction\n%s\n", mysql
.error
);
517 MySql::configure(const StatData
&data
, string type
)
520 stat
.name
= data
.name
;
521 stat
.descr
= data
.desc
;
523 stat
.print
= data
.flags
& print
;
524 stat
.prec
= data
.precision
;
525 stat
.nozero
= data
.flags
& nozero
;
526 stat
.nonan
= data
.flags
& nonan
;
527 stat
.total
= data
.flags
& total
;
528 stat
.pdf
= data
.flags
& pdf
;
529 stat
.cdf
= data
.flags
& cdf
;
535 MySql::configure(const ScalarData
&data
)
537 if (!configure(data
, "SCALAR"))
540 insert(data
.id
, stat
.setup());
544 MySql::configure(const VectorData
&data
)
546 if (!configure(data
, "VECTOR"))
549 uint16_t statid
= stat
.setup();
551 if (!data
.subnames
.empty()) {
552 InsertSubData subdata
;
553 subdata
.stat
= statid
;
555 for (int i
= 0; i
< data
.subnames
.size(); ++i
) {
557 subdata
.name
= data
.subnames
[i
];
558 subdata
.descr
= data
.subdescs
.empty() ? "" : data
.subdescs
[i
];
560 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
565 insert(data
.id
, statid
);
569 MySql::configure(const DistData
&data
)
571 if (!configure(data
, "DIST"))
574 if (!data
.data
.fancy
) {
575 stat
.size
= data
.data
.size
;
576 stat
.min
= data
.data
.min
;
577 stat
.max
= data
.data
.max
;
578 stat
.bktsize
= data
.data
.bucket_size
;
580 insert(data
.id
, stat
.setup());
584 MySql::configure(const VectorDistData
&data
)
586 if (!configure(data
, "VECTORDIST"))
589 if (!data
.data
[0].fancy
) {
590 stat
.size
= data
.data
[0].size
;
591 stat
.min
= data
.data
[0].min
;
592 stat
.max
= data
.data
[0].max
;
593 stat
.bktsize
= data
.data
[0].bucket_size
;
596 uint16_t statid
= stat
.setup();
598 if (!data
.subnames
.empty()) {
599 InsertSubData subdata
;
600 subdata
.stat
= statid
;
602 for (int i
= 0; i
< data
.subnames
.size(); ++i
) {
604 subdata
.name
= data
.subnames
[i
];
605 subdata
.descr
= data
.subdescs
.empty() ? "" : data
.subdescs
[i
];
606 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
611 insert(data
.id
, statid
);
615 MySql::configure(const Vector2dData
&data
)
617 if (!configure(data
, "VECTOR2D"))
620 uint16_t statid
= stat
.setup();
622 if (!data
.subnames
.empty()) {
623 InsertSubData subdata
;
624 subdata
.stat
= statid
;
626 for (int i
= 0; i
< data
.subnames
.size(); ++i
) {
628 subdata
.name
= data
.subnames
[i
];
629 subdata
.descr
= data
.subdescs
.empty() ? "" : data
.subdescs
[i
];
630 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
635 if (!data
.y_subnames
.empty()) {
636 InsertSubData subdata
;
637 subdata
.stat
= statid
;
640 for (int i
= 0; i
< data
.y_subnames
.size(); ++i
) {
642 subdata
.name
= data
.y_subnames
[i
];
643 if (!subdata
.name
.empty())
648 insert(data
.id
, statid
);
652 MySql::configure(const FormulaData
&data
)
654 configure(data
, "FORMULA");
655 insert(data
.id
, stat
.setup());
656 InsertFormula(find(data
.id
), data
.str());
660 MySql::output(MainBin
*bin
)
662 MySQL::Connection
&mysql
= MySqlDB
.conn();
666 newdata
.bin
= SetupBin(bin
->name());
671 Database::stat_list_t::const_iterator i
, end
= Database::stats().end();
672 for (i
= Database::stats().begin(); i
!= end
; ++i
) {
674 if (bin
&& stat
->binned() || !bin
&& !stat
->binned()) {
677 panic("could not commit transaction\n%s\n", mysql
.error
);
685 return MySqlDB
.connected();
691 using namespace Database
;
698 newdata
.tick
= curTick
;
701 if (!bins().empty()) {
702 bin_list_t::iterator i
, end
= bins().end();
703 for (i
= bins().begin(); i
!= end
; ++i
)
711 MySql::output(const ScalarData
&data
)
713 if (!(data
.flags
& print
))
716 newdata
.stat
= find(data
.id
);
719 newdata
.data
= data
.value();
725 MySql::output(const VectorData
&data
)
727 if (!(data
.flags
& print
))
730 newdata
.stat
= find(data
.id
);
733 const VCounter
&cvec
= data
.value();
734 int size
= data
.size();
735 for (int x
= 0; x
< size
; x
++) {
737 newdata
.data
= cvec
[x
];
743 MySql::output(const DistDataData
&data
)
745 const int db_sum
= -1;
746 const int db_squares
= -2;
747 const int db_samples
= -3;
748 const int db_min_val
= -4;
749 const int db_max_val
= -5;
750 const int db_underflow
= -6;
751 const int db_overflow
= -7;
754 newdata
.data
= data
.sum
;
757 newdata
.x
= db_squares
;
758 newdata
.data
= data
.squares
;
761 newdata
.x
= db_samples
;
762 newdata
.data
= data
.samples
;
765 if (data
.samples
&& !data
.fancy
) {
766 newdata
.x
= db_min_val
;
767 newdata
.data
= data
.min_val
;
770 newdata
.x
= db_max_val
;
771 newdata
.data
= data
.max_val
;
774 newdata
.x
= db_underflow
;
775 newdata
.data
= data
.underflow
;
778 newdata
.x
= db_overflow
;
779 newdata
.data
= data
.overflow
;
782 int size
= data
.cvec
.size();
783 for (int x
= 0; x
< size
; x
++) {
785 newdata
.data
= data
.cvec
[x
];
793 MySql::output(const DistData
&data
)
795 if (!(data
.flags
& print
))
798 newdata
.stat
= find(data
.id
);
804 MySql::output(const VectorDistData
&data
)
806 if (!(data
.flags
& print
))
809 newdata
.stat
= find(data
.id
);
811 int size
= data
.data
.size();
812 for (int y
= 0; y
< size
; ++y
) {
814 output(data
.data
[y
]);
819 MySql::output(const Vector2dData
&data
)
821 if (!(data
.flags
& print
))
824 newdata
.stat
= find(data
.id
);
827 for (int x
= 0; x
< data
.x
; x
++) {
829 for (int y
= 0; y
< data
.y
; y
++) {
831 newdata
.data
= data
.cvec
[index
++];
838 MySql::output(const FormulaData
&data
)
843 * Implement the visitor
846 MySql::visit(const ScalarData
&data
)
855 MySql::visit(const VectorData
&data
)
864 MySql::visit(const DistData
&data
)
874 MySql::visit(const VectorDistData
&data
)
884 MySql::visit(const Vector2dData
&data
)
894 MySql::visit(const FormulaData
&data
)
902 /* namespace Stats */ }