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 "base/userinfo.hh"
47 #include "sim/host.hh"
54 MySqlRun::connect(const string
&host
, const string
&user
, const string
&passwd
,
55 const string
&db
, const string
&name
, const string
&sample
,
56 const string
&project
)
59 panic("can only get one database connection at this time!");
61 mysql
.connect(host
, user
, passwd
, db
);
63 panic("could not connect to database server\n%s\n", mysql
.error
);
65 if (mysql
.autocommit(false))
66 panic("could not set autocommit\n%s\n", mysql
.error
);
70 setup(name
, sample
, user
, project
);
74 MySqlRun::setup(const string
&name
, const string
&sample
, const string
&user
,
75 const string
&project
)
77 assert(mysql
.connected());
82 "runs(rn_name,rn_sample,rn_user,rn_project,rn_date,rn_expire)"
83 "values(\"%s\", \"%s\", \"%s\", \"%s\", NOW(),"
84 "DATE_ADD(CURDATE(), INTERVAL 31 DAY))",
85 name
, sample
, user
, project
);
89 panic("could not get a run\n%s\n", mysql
.error
);
91 run_id
= mysql
.insert_id();
93 panic("could not commit transaction\n%s\n", mysql
.error
);
97 MySqlRun::remove(const string
&name
)
99 assert(mysql
.connected());
101 ccprintf(sql
, "DELETE FROM runs WHERE rn_name=\"%s\"", name
);
104 panic("could not delete run\n%s\n", mysql
.error
);
106 panic("could not commit transaction\n%s\n", mysql
.error
);
112 assert(mysql
.connected());
114 mysql
.query("DELETE data "
116 "LEFT JOIN runs ON dt_run=rn_id "
117 "WHERE rn_id IS NULL");
120 panic("could not commit transaction\n%s\n", mysql
.error
);
122 mysql
.query("DELETE formula_ref "
124 "LEFT JOIN runs ON fr_run=rn_id "
125 "WHERE rn_id IS NULL");
128 panic("could not commit transaction\n%s\n", mysql
.error
);
130 mysql
.query("DELETE formulas "
132 "LEFT JOIN formula_ref ON fm_stat=fr_stat "
133 "WHERE fr_stat IS NULL");
136 panic("could not commit transaction\n%s\n", mysql
.error
);
138 mysql
.query("DELETE stats "
140 "LEFT JOIN data ON st_id=dt_stat "
141 "WHERE dt_stat IS NULL");
144 panic("could not commit transaction\n%s\n", mysql
.error
);
146 mysql
.query("DELETE subdata "
148 "LEFT JOIN data ON sd_stat=dt_stat "
149 "WHERE dt_stat IS NULL");
152 panic("could not commit transaction\n%s\n", mysql
.error
);
154 mysql
.query("DELETE events"
156 "LEFT JOIN runs ON ev_run=rn_id"
157 "WHERE rn_id IS NULL");
160 panic("could not commit transaction\n%s\n", mysql
.error
);
162 mysql
.query("DELETE event_names"
164 "LEFT JOIN events ON en_id=ev_event"
165 "WHERE ev_event IS NULL");
168 panic("could not commit transaction\n%s\n", mysql
.error
);
192 SetupStat::setup(MySqlRun
*run
)
194 MySQL::Connection
&mysql
= run
->conn();
199 "stats(st_name, st_descr, st_type, st_print, st_prereq, "
200 "st_prec, st_nozero, st_nonan, st_total, st_pdf, st_cdf, "
201 "st_min, st_max, st_bktsize, st_size)"
202 "values(\"%s\",\"%s\",\"%s\","
203 " %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
204 name
, descr
, type
, print
, prereq
, (int)prec
, nozero
, nonan
,
206 min
, max
, bktsize
, size
);
210 int id
= mysql
.insert_id();
212 panic("could not commit transaction\n%s\n", mysql
.error
);
217 ccprintf(select
, "SELECT * FROM stats WHERE st_name=\"%s\"", name
);
220 MySQL::Result result
= mysql
.store_result();
222 panic("could not find stat\n%s\n", mysql
.error
);
224 assert(result
.num_fields() == 16);
225 MySQL::Row row
= result
.fetch_row();
227 panic("could not get stat row\n%s\n", mysql
.error
);
235 if (name
!= (char *)row
[1])
236 panic("failed stat check on %s:name. %s != %s\n",
239 if (descr
!= (char *)row
[2])
240 panic("failed stat check on %s:descr. %s != %s\n",
241 name
, descr
, row
[2]);
243 if (type
!= (char *)row
[3])
244 panic("failed stat check on %s:type. %s != %s\n",
247 if (!to_number(row
[4], tb
) || print
!= tb
)
248 panic("failed stat check on %s:print. %d != %d\n",
251 if (!to_number(row
[6], ti8
) || prec
!= ti8
)
252 panic("failed stat check on %s:prec. %d != %d\n",
255 if (!to_number(row
[7], tb
) || nozero
!= tb
)
256 panic("failed stat check on %s:nozero. %d != %d\n",
259 if (!to_number(row
[8], tb
) || nonan
!= tb
)
260 panic("failed stat check on %s:nonan. %d != %d\n",
263 if (!to_number(row
[9], tb
) || total
!= tb
)
264 panic("failed stat check on %s:total. %d != %d\n",
267 if (!to_number(row
[10], tb
) || pdf
!= tb
)
268 panic("failed stat check on %s:pdf. %d != %d\n",
271 if (!to_number(row
[11], tb
) || cdf
!= tb
)
272 panic("failed stat check on %s:cdf. %d != %d\n",
275 if (!to_number(row
[12], ti64
) || min
!= ti64
)
276 panic("failed stat check on %s:min. %d != %d\n",
279 if (!to_number(row
[13], ti64
) || max
!= ti64
)
280 panic("failed stat check on %s:max. %d != %d\n",
283 if (!to_number(row
[14], tu64
) || bktsize
!= tu64
)
284 panic("failed stat check on %s:bktsize. %d != %d\n",
285 name
, bktsize
, tu64
);
287 if (!to_number(row
[15], tu16
) || size
!= tu16
)
288 panic("failed stat check on %s:size. %d != %d\n",
291 to_number(row
[5], prereq
);
293 to_number(row
[0], statid
);
297 InsertData::InsertData(MySqlRun
*_run
)
300 query
= new char[maxsize
+ 1];
305 InsertData::~InsertData()
314 MySQL::Connection
&mysql
= run
->conn();
315 assert(mysql
.connected());
318 panic("could not insert data\n%s\n", mysql
.error
);
320 panic("could not commit transaction\n%s\n", mysql
.error
);
326 strcpy(query
, "INSERT INTO "
327 "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_data) "
329 size
= strlen(query
);
335 if (size
+ 1024 > maxsize
)
345 size
+= sprintf(query
+ size
, "(%u,%d,%d,%u,%llu,\"%f\")",
346 stat
, x
, y
, run
->run(), (unsigned long long)tick
,
350 InsertEvent::InsertEvent(MySqlRun
*_run
)
353 query
= new char[maxsize
+ 1];
359 InsertEvent::~InsertEvent()
365 InsertEvent::insert(const string
&stat
)
367 MySQL::Connection
&mysql
= run
->conn();
368 assert(mysql
.connected());
370 event_map_t::iterator i
= events
.find(stat
);
372 if (i
== events
.end()) {
374 csprintf("SELECT en_id "
376 "where en_name=\"%s\"",
379 MySQL::Result result
= mysql
.store_result();
381 panic("could not get a run\n%s\n", mysql
.error
);
383 assert(result
.num_fields() == 1);
384 MySQL::Row row
= result
.fetch_row();
386 if (!to_number(row
[0], event
))
387 panic("invalid event id: %s\n", row
[0]);
390 csprintf("INSERT INTO "
391 "event_names(en_name)"
396 panic("could not get a run\n%s\n", mysql
.error
);
398 event
= mysql
.insert_id();
404 if (size
+ 1024 > maxsize
)
414 size
+= sprintf(query
+ size
, "(%u,%u,%llu)",
415 event
, run
->run(), (unsigned long long)curTick
);
421 static const char query_header
[] = "INSERT INTO "
422 "events(ev_event, ev_run, ev_tick)"
425 MySQL::Connection
&mysql
= run
->conn();
426 assert(mysql
.connected());
432 size
= sizeof(query_header
);
434 memcpy(query
, query_header
, size
);
445 void setup(MySqlRun
*run
);
449 InsertSubData::setup(MySqlRun
*run
)
451 MySQL::Connection
&mysql
= run
->conn();
452 assert(mysql
.connected());
455 "INSERT INTO subdata(sd_stat,sd_x,sd_y,sd_name,sd_descr) "
456 "values(%d,%d,%d,\"%s\",\"%s\")",
457 stat
, x
, y
, name
, descr
);
461 // panic("could not insert subdata\n%s\n", mysql.error);
464 panic("could not commit transaction\n%s\n", mysql
.error
);
468 : run(new MySqlRun
), newdata(run
), newevent(run
)
477 MySql::connect(const string
&host
, const string
&user
, const string
&passwd
,
478 const string
&db
, const string
&name
, const string
&sample
,
479 const string
&project
)
481 run
->connect(host
, user
, passwd
, db
, name
, sample
, project
);
485 MySql::connected() const
487 return run
->connected();
496 using namespace Database
;
498 MySQL::Connection
&mysql
= run
->conn();
500 stat_list_t::const_iterator i
, end
= stats().end();
501 for (i
= stats().begin(); i
!= end
; ++i
) {
505 for (i
= stats().begin(); i
!= end
; ++i
) {
508 // update the prerequisite
509 uint16_t stat_id
= find(data
->id
);
510 uint16_t prereq_id
= find(data
->prereq
->id
);
511 assert(stat_id
&& prereq_id
);
514 ccprintf(update
, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
518 panic("could not update prereq\n%s\n", mysql
.error
);
521 panic("could not commit transaction\n%s\n", mysql
.error
);
526 panic("could not commit transaction\n%s\n", mysql
.error
);
533 MySql::configure(const StatData
&data
, string type
)
536 stat
.name
= data
.name
;
537 stat
.descr
= data
.desc
;
539 stat
.print
= data
.flags
& print
;
540 stat
.prec
= data
.precision
;
541 stat
.nozero
= data
.flags
& nozero
;
542 stat
.nonan
= data
.flags
& nonan
;
543 stat
.total
= data
.flags
& total
;
544 stat
.pdf
= data
.flags
& pdf
;
545 stat
.cdf
= data
.flags
& cdf
;
551 MySql::configure(const ScalarData
&data
)
553 if (!configure(data
, "SCALAR"))
556 insert(data
.id
, stat
.setup(run
));
560 MySql::configure(const VectorData
&data
)
562 if (!configure(data
, "VECTOR"))
565 uint16_t statid
= stat
.setup(run
);
567 if (!data
.subnames
.empty()) {
568 InsertSubData subdata
;
569 subdata
.stat
= statid
;
571 for (off_type i
= 0; i
< data
.subnames
.size(); ++i
) {
573 subdata
.name
= data
.subnames
[i
];
574 subdata
.descr
= data
.subdescs
.empty() ? "" : data
.subdescs
[i
];
576 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
581 insert(data
.id
, statid
);
585 MySql::configure(const DistData
&data
)
587 if (!configure(data
, "DIST"))
590 if (!data
.data
.fancy
) {
591 stat
.size
= data
.data
.size
;
592 stat
.min
= data
.data
.min
;
593 stat
.max
= data
.data
.max
;
594 stat
.bktsize
= data
.data
.bucket_size
;
596 insert(data
.id
, stat
.setup(run
));
600 MySql::configure(const VectorDistData
&data
)
602 if (!configure(data
, "VECTORDIST"))
605 if (!data
.data
[0].fancy
) {
606 stat
.size
= data
.data
[0].size
;
607 stat
.min
= data
.data
[0].min
;
608 stat
.max
= data
.data
[0].max
;
609 stat
.bktsize
= data
.data
[0].bucket_size
;
612 uint16_t statid
= stat
.setup(run
);
614 if (!data
.subnames
.empty()) {
615 InsertSubData subdata
;
616 subdata
.stat
= statid
;
618 for (off_type i
= 0; i
< data
.subnames
.size(); ++i
) {
620 subdata
.name
= data
.subnames
[i
];
621 subdata
.descr
= data
.subdescs
.empty() ? "" : data
.subdescs
[i
];
622 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
627 insert(data
.id
, statid
);
631 MySql::configure(const Vector2dData
&data
)
633 if (!configure(data
, "VECTOR2D"))
636 uint16_t statid
= stat
.setup(run
);
638 if (!data
.subnames
.empty()) {
639 InsertSubData subdata
;
640 subdata
.stat
= statid
;
642 for (off_type i
= 0; i
< data
.subnames
.size(); ++i
) {
644 subdata
.name
= data
.subnames
[i
];
645 subdata
.descr
= data
.subdescs
.empty() ? "" : data
.subdescs
[i
];
646 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
651 if (!data
.y_subnames
.empty()) {
652 InsertSubData subdata
;
653 subdata
.stat
= statid
;
656 for (off_type i
= 0; i
< data
.y_subnames
.size(); ++i
) {
658 subdata
.name
= data
.y_subnames
[i
];
659 if (!subdata
.name
.empty())
664 insert(data
.id
, statid
);
668 MySql::configure(const FormulaData
&data
)
670 MySQL::Connection
&mysql
= run
->conn();
671 assert(mysql
.connected());
673 configure(data
, "FORMULA");
674 insert(data
.id
, stat
.setup(run
));
676 uint16_t stat
= find(data
.id
);
677 string formula
= data
.str();
679 stringstream insert_formula
;
680 ccprintf(insert_formula
,
681 "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
684 mysql
.query(insert_formula
);
686 // panic("could not insert formula\n%s\n", mysql.error);
688 stringstream insert_ref
;
690 "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
693 mysql
.query(insert_ref
);
695 // panic("could not insert formula reference\n%s\n", mysql.error);
698 panic("could not commit transaction\n%s\n", mysql
.error
);
704 return run
->connected();
710 using namespace Database
;
717 newdata
.tick
= curTick
;
719 MySQL::Connection
&mysql
= run
->conn();
721 Database::stat_list_t::const_iterator i
, end
= Database::stats().end();
722 for (i
= Database::stats().begin(); i
!= end
; ++i
) {
726 panic("could not commit transaction\n%s\n", mysql
.error
);
733 MySql::event(const std::string
&event
)
735 newevent
.insert(event
);
740 MySql::output(const ScalarData
&data
)
742 if (!(data
.flags
& print
))
745 newdata
.stat
= find(data
.id
);
748 newdata
.data
= data
.value();
754 MySql::output(const VectorData
&data
)
756 if (!(data
.flags
& print
))
759 newdata
.stat
= find(data
.id
);
762 const VCounter
&cvec
= data
.value();
763 size_type size
= data
.size();
764 for (off_type x
= 0; x
< size
; x
++) {
766 newdata
.data
= cvec
[x
];
772 MySql::output(const DistDataData
&data
)
774 const int db_sum
= -1;
775 const int db_squares
= -2;
776 const int db_samples
= -3;
777 const int db_min_val
= -4;
778 const int db_max_val
= -5;
779 const int db_underflow
= -6;
780 const int db_overflow
= -7;
783 newdata
.data
= data
.sum
;
786 newdata
.x
= db_squares
;
787 newdata
.data
= data
.squares
;
790 newdata
.x
= db_samples
;
791 newdata
.data
= data
.samples
;
794 if (data
.samples
&& !data
.fancy
) {
795 newdata
.x
= db_min_val
;
796 newdata
.data
= data
.min_val
;
799 newdata
.x
= db_max_val
;
800 newdata
.data
= data
.max_val
;
803 newdata
.x
= db_underflow
;
804 newdata
.data
= data
.underflow
;
807 newdata
.x
= db_overflow
;
808 newdata
.data
= data
.overflow
;
811 size_type size
= data
.cvec
.size();
812 for (off_type x
= 0; x
< size
; x
++) {
814 newdata
.data
= data
.cvec
[x
];
822 MySql::output(const DistData
&data
)
824 if (!(data
.flags
& print
))
827 newdata
.stat
= find(data
.id
);
833 MySql::output(const VectorDistData
&data
)
835 if (!(data
.flags
& print
))
838 newdata
.stat
= find(data
.id
);
840 size_type size
= data
.data
.size();
841 for (off_type y
= 0; y
< size
; ++y
) {
843 output(data
.data
[y
]);
848 MySql::output(const Vector2dData
&data
)
850 if (!(data
.flags
& print
))
853 newdata
.stat
= find(data
.id
);
856 for (off_type x
= 0; x
< data
.x
; x
++) {
858 for (off_type y
= 0; y
< data
.y
; y
++) {
860 newdata
.data
= data
.cvec
[index
++];
867 MySql::output(const FormulaData
&data
)
872 * Implement the visitor
875 MySql::visit(const ScalarData
&data
)
884 MySql::visit(const VectorData
&data
)
893 MySql::visit(const DistData
&data
)
903 MySql::visit(const VectorDistData
&data
)
913 MySql::visit(const Vector2dData
&data
)
923 MySql::visit(const FormulaData
&data
)
932 initMySQL(string host
, string user
, string password
, string database
,
933 string project
, string name
, string sample
)
935 extern list
<Output
*> OutputList
;
938 if (mysql
.connected())
941 mysql
.connect(host
, user
, password
, database
, name
, sample
, project
);
942 OutputList
.push_back(&mysql
);
947 /* end namespace Stats */ }