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/stats/info.hh"
40 #include "base/stats/mysql.hh"
41 #include "base/stats/mysql_run.hh"
42 #include "base/stats/types.hh"
43 #include "base/str.hh"
44 #include "base/userinfo.hh"
45 #include "sim/host.hh"
52 MySqlRun::connect(const string
&host
, const string
&user
, const string
&passwd
,
53 const string
&db
, const string
&name
, const string
&sample
,
54 const string
&project
)
57 panic("can only get one database connection at this time!");
59 mysql
.connect(host
, user
, passwd
, db
);
61 panic("could not connect to database server\n%s\n", mysql
.error
);
63 if (mysql
.autocommit(false))
64 panic("could not set autocommit\n%s\n", mysql
.error
);
68 setup(name
, sample
, user
, project
);
72 MySqlRun::setup(const string
&name
, const string
&sample
, const string
&user
,
73 const string
&project
)
75 assert(mysql
.connected());
80 "runs(rn_name,rn_sample,rn_user,rn_project,rn_date,rn_expire)"
81 "values(\"%s\", \"%s\", \"%s\", \"%s\", NOW(),"
82 "DATE_ADD(CURDATE(), INTERVAL 31 DAY))",
83 name
, sample
, user
, project
);
87 panic("could not get a run\n%s\n", mysql
.error
);
89 run_id
= mysql
.insert_id();
91 panic("could not commit transaction\n%s\n", mysql
.error
);
95 MySqlRun::remove(const string
&name
)
97 assert(mysql
.connected());
99 ccprintf(sql
, "DELETE FROM runs WHERE rn_name=\"%s\"", name
);
102 panic("could not delete run\n%s\n", mysql
.error
);
104 panic("could not commit transaction\n%s\n", mysql
.error
);
110 assert(mysql
.connected());
112 mysql
.query("DELETE data "
114 "LEFT JOIN runs ON dt_run=rn_id "
115 "WHERE rn_id IS NULL");
118 panic("could not commit transaction\n%s\n", mysql
.error
);
120 mysql
.query("DELETE formula_ref "
122 "LEFT JOIN runs ON fr_run=rn_id "
123 "WHERE rn_id IS NULL");
126 panic("could not commit transaction\n%s\n", mysql
.error
);
128 mysql
.query("DELETE formulas "
130 "LEFT JOIN formula_ref ON fm_stat=fr_stat "
131 "WHERE fr_stat IS NULL");
134 panic("could not commit transaction\n%s\n", mysql
.error
);
136 mysql
.query("DELETE stats "
138 "LEFT JOIN data ON st_id=dt_stat "
139 "WHERE dt_stat IS NULL");
142 panic("could not commit transaction\n%s\n", mysql
.error
);
144 mysql
.query("DELETE subdata "
146 "LEFT JOIN data ON sd_stat=dt_stat "
147 "WHERE dt_stat IS NULL");
150 panic("could not commit transaction\n%s\n", mysql
.error
);
152 mysql
.query("DELETE events"
154 "LEFT JOIN runs ON ev_run=rn_id"
155 "WHERE rn_id IS NULL");
158 panic("could not commit transaction\n%s\n", mysql
.error
);
160 mysql
.query("DELETE event_names"
162 "LEFT JOIN events ON en_id=ev_event"
163 "WHERE ev_event IS NULL");
166 panic("could not commit transaction\n%s\n", mysql
.error
);
190 SetupStat::setup(MySqlRun
*run
)
192 MySQL::Connection
&mysql
= run
->conn();
197 "stats(st_name, st_descr, st_type, st_print, st_prereq, "
198 "st_prec, st_nozero, st_nonan, st_total, st_pdf, st_cdf, "
199 "st_min, st_max, st_bktsize, st_size)"
200 "values(\"%s\",\"%s\",\"%s\","
201 " %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
202 name
, descr
, type
, print
, prereq
, (int)prec
, nozero
, nonan
,
204 min
, max
, bktsize
, size
);
208 int id
= mysql
.insert_id();
210 panic("could not commit transaction\n%s\n", mysql
.error
);
215 ccprintf(select
, "SELECT * FROM stats WHERE st_name=\"%s\"", name
);
218 MySQL::Result result
= mysql
.store_result();
220 panic("could not find stat\n%s\n", mysql
.error
);
222 assert(result
.num_fields() == 16);
223 MySQL::Row row
= result
.fetch_row();
225 panic("could not get stat row\n%s\n", mysql
.error
);
233 if (name
!= (char *)row
[1])
234 panic("failed stat check on %s:name. %s != %s\n",
237 if (descr
!= (char *)row
[2])
238 panic("failed stat check on %s:descr. %s != %s\n",
239 name
, descr
, row
[2]);
241 if (type
!= (char *)row
[3])
242 panic("failed stat check on %s:type. %s != %s\n",
245 if (!to_number(row
[4], tb
) || print
!= tb
)
246 panic("failed stat check on %s:print. %d != %d\n",
249 if (!to_number(row
[6], ti8
) || prec
!= ti8
)
250 panic("failed stat check on %s:prec. %d != %d\n",
253 if (!to_number(row
[7], tb
) || nozero
!= tb
)
254 panic("failed stat check on %s:nozero. %d != %d\n",
257 if (!to_number(row
[8], tb
) || nonan
!= tb
)
258 panic("failed stat check on %s:nonan. %d != %d\n",
261 if (!to_number(row
[9], tb
) || total
!= tb
)
262 panic("failed stat check on %s:total. %d != %d\n",
265 if (!to_number(row
[10], tb
) || pdf
!= tb
)
266 panic("failed stat check on %s:pdf. %d != %d\n",
269 if (!to_number(row
[11], tb
) || cdf
!= tb
)
270 panic("failed stat check on %s:cdf. %d != %d\n",
273 if (!to_number(row
[12], ti64
) || min
!= ti64
)
274 panic("failed stat check on %s:min. %d != %d\n",
277 if (!to_number(row
[13], ti64
) || max
!= ti64
)
278 panic("failed stat check on %s:max. %d != %d\n",
281 if (!to_number(row
[14], tu64
) || bktsize
!= tu64
)
282 panic("failed stat check on %s:bktsize. %d != %d\n",
283 name
, bktsize
, tu64
);
285 if (!to_number(row
[15], tu16
) || size
!= tu16
)
286 panic("failed stat check on %s:size. %d != %d\n",
289 to_number(row
[5], prereq
);
291 to_number(row
[0], statid
);
295 InsertData::InsertData(MySqlRun
*_run
)
298 query
= new char[maxsize
+ 1];
303 InsertData::~InsertData()
312 MySQL::Connection
&mysql
= run
->conn();
313 assert(mysql
.connected());
316 panic("could not insert data\n%s\n", mysql
.error
);
318 panic("could not commit transaction\n%s\n", mysql
.error
);
324 strcpy(query
, "INSERT INTO "
325 "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_data) "
327 size
= strlen(query
);
333 if (size
+ 1024 > maxsize
)
343 size
+= sprintf(query
+ size
, "(%u,%d,%d,%u,%llu,\"%f\")",
344 stat
, x
, y
, run
->run(), (unsigned long long)tick
,
348 InsertEvent::InsertEvent(MySqlRun
*_run
)
351 query
= new char[maxsize
+ 1];
357 InsertEvent::~InsertEvent()
363 InsertEvent::insert(const string
&stat
)
365 MySQL::Connection
&mysql
= run
->conn();
366 assert(mysql
.connected());
368 event_map_t::iterator i
= events
.find(stat
);
370 if (i
== events
.end()) {
372 csprintf("SELECT en_id "
374 "where en_name=\"%s\"",
377 MySQL::Result result
= mysql
.store_result();
379 panic("could not get a run\n%s\n", mysql
.error
);
381 assert(result
.num_fields() == 1);
382 MySQL::Row row
= result
.fetch_row();
384 if (!to_number(row
[0], event
))
385 panic("invalid event id: %s\n", row
[0]);
388 csprintf("INSERT INTO "
389 "event_names(en_name)"
394 panic("could not get a run\n%s\n", mysql
.error
);
396 event
= mysql
.insert_id();
402 if (size
+ 1024 > maxsize
)
412 size
+= sprintf(query
+ size
, "(%u,%u,%llu)",
413 event
, run
->run(), (unsigned long long)curTick
);
419 static const char query_header
[] = "INSERT INTO "
420 "events(ev_event, ev_run, ev_tick)"
423 MySQL::Connection
&mysql
= run
->conn();
424 assert(mysql
.connected());
430 size
= sizeof(query_header
);
432 memcpy(query
, query_header
, size
);
443 void setup(MySqlRun
*run
);
447 InsertSubData::setup(MySqlRun
*run
)
449 MySQL::Connection
&mysql
= run
->conn();
450 assert(mysql
.connected());
453 "INSERT INTO subdata(sd_stat,sd_x,sd_y,sd_name,sd_descr) "
454 "values(%d,%d,%d,\"%s\",\"%s\")",
455 stat
, x
, y
, name
, descr
);
459 // panic("could not insert subdata\n%s\n", mysql.error);
462 panic("could not commit transaction\n%s\n", mysql
.error
);
466 : run(new MySqlRun
), newdata(run
), newevent(run
)
475 MySql::connect(const string
&host
, const string
&user
, const string
&passwd
,
476 const string
&db
, const string
&name
, const string
&sample
,
477 const string
&project
)
479 run
->connect(host
, user
, passwd
, db
, name
, sample
, project
);
483 MySql::connected() const
485 return run
->connected();
494 MySQL::Connection
&mysql
= run
->conn();
496 list
<Info
*>::const_iterator i
, end
= statsList().end();
497 for (i
= statsList().begin(); i
!= end
; ++i
) {
501 for (i
= statsList().begin(); i
!= end
; ++i
) {
504 // update the prerequisite
505 uint16_t stat_id
= find(info
->id
);
506 uint16_t prereq_id
= find(info
->prereq
->id
);
507 assert(stat_id
&& prereq_id
);
510 ccprintf(update
, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
514 panic("could not update prereq\n%s\n", mysql
.error
);
517 panic("could not commit transaction\n%s\n", mysql
.error
);
522 panic("could not commit transaction\n%s\n", mysql
.error
);
528 MySql::configure(const Info
&info
, string type
)
531 stat
.name
= info
.name
;
532 stat
.descr
= info
.desc
;
534 stat
.print
= info
.flags
& print
;
535 stat
.prec
= info
.precision
;
536 stat
.nozero
= info
.flags
& nozero
;
537 stat
.nonan
= info
.flags
& nonan
;
538 stat
.total
= info
.flags
& total
;
539 stat
.pdf
= info
.flags
& pdf
;
540 stat
.cdf
= info
.flags
& cdf
;
546 MySql::configure(const ScalarInfo
&info
)
548 if (!configure(info
, "SCALAR"))
551 insert(info
.id
, stat
.setup(run
));
555 MySql::configure(const VectorInfo
&info
)
557 if (!configure(info
, "VECTOR"))
560 uint16_t statid
= stat
.setup(run
);
562 if (!info
.subnames
.empty()) {
563 InsertSubData subdata
;
564 subdata
.stat
= statid
;
566 for (off_type i
= 0; i
< info
.subnames
.size(); ++i
) {
568 subdata
.name
= info
.subnames
[i
];
569 subdata
.descr
= info
.subdescs
.empty() ? "" : info
.subdescs
[i
];
571 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
576 insert(info
.id
, statid
);
580 MySql::configure(const DistInfo
&info
)
582 if (!configure(info
, "DIST"))
585 const DistParams
*params
=
586 safe_cast
<const DistParams
*>(info
.storageParams
);
587 if (!params
->fancy
) {
588 stat
.size
= params
->buckets
;
589 stat
.min
= params
->min
;
590 stat
.max
= params
->max
;
591 stat
.bktsize
= params
->bucket_size
;
593 insert(info
.id
, stat
.setup(run
));
597 MySql::configure(const VectorDistInfo
&info
)
599 if (!configure(info
, "VECTORDIST"))
602 const DistParams
*params
=
603 safe_cast
<const DistParams
*>(info
.storageParams
);
604 if (!params
->fancy
) {
605 stat
.size
= params
->buckets
;
606 stat
.min
= params
->min
;
607 stat
.max
= params
->max
;
608 stat
.bktsize
= params
->bucket_size
;
611 uint16_t statid
= stat
.setup(run
);
613 if (!info
.subnames
.empty()) {
614 InsertSubData subdata
;
615 subdata
.stat
= statid
;
617 for (off_type i
= 0; i
< info
.subnames
.size(); ++i
) {
619 subdata
.name
= info
.subnames
[i
];
620 subdata
.descr
= info
.subdescs
.empty() ? "" : info
.subdescs
[i
];
621 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
626 insert(info
.id
, statid
);
630 MySql::configure(const Vector2dInfo
&info
)
632 if (!configure(info
, "VECTOR2D"))
635 uint16_t statid
= stat
.setup(run
);
637 if (!info
.subnames
.empty()) {
638 InsertSubData subdata
;
639 subdata
.stat
= statid
;
641 for (off_type i
= 0; i
< info
.subnames
.size(); ++i
) {
643 subdata
.name
= info
.subnames
[i
];
644 subdata
.descr
= info
.subdescs
.empty() ? "" : info
.subdescs
[i
];
645 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
650 if (!info
.y_subnames
.empty()) {
651 InsertSubData subdata
;
652 subdata
.stat
= statid
;
655 for (off_type i
= 0; i
< info
.y_subnames
.size(); ++i
) {
657 subdata
.name
= info
.y_subnames
[i
];
658 if (!subdata
.name
.empty())
663 insert(info
.id
, statid
);
667 MySql::configure(const FormulaInfo
&info
)
669 MySQL::Connection
&mysql
= run
->conn();
670 assert(mysql
.connected());
672 configure(info
, "FORMULA");
673 insert(info
.id
, stat
.setup(run
));
675 uint16_t stat
= find(info
.id
);
676 string formula
= info
.str();
678 stringstream insert_formula
;
679 ccprintf(insert_formula
,
680 "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
683 mysql
.query(insert_formula
);
685 // panic("could not insert formula\n%s\n", mysql.error);
687 stringstream insert_ref
;
689 "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
692 mysql
.query(insert_ref
);
694 // panic("could not insert formula reference\n%s\n", mysql.error);
697 panic("could not commit transaction\n%s\n", mysql
.error
);
703 return run
->connected();
715 newdata
.tick
= curTick
;
717 MySQL::Connection
&mysql
= run
->conn();
719 list
<Info
*>::const_iterator i
, end
= statsList().end();
720 for (i
= statsList().begin(); i
!= end
; ++i
) {
724 panic("could not commit transaction\n%s\n", mysql
.error
);
731 MySql::event(const std::string
&event
)
733 newevent
.insert(event
);
737 MySql::output(const ScalarInfo
&info
)
739 if (!(info
.flags
& print
))
742 newdata
.stat
= find(info
.id
);
745 newdata
.data
= info
.value();
751 MySql::output(const VectorInfo
&info
)
753 if (!(info
.flags
& print
))
756 newdata
.stat
= find(info
.id
);
759 const VCounter
&cvec
= info
.value();
760 size_type size
= info
.size();
761 for (off_type x
= 0; x
< size
; x
++) {
763 newdata
.data
= cvec
[x
];
769 MySql::output(const DistData
&data
, const DistParams
*params
)
771 const int db_sum
= -1;
772 const int db_squares
= -2;
773 const int db_samples
= -3;
774 const int db_min_val
= -4;
775 const int db_max_val
= -5;
776 const int db_underflow
= -6;
777 const int db_overflow
= -7;
780 newdata
.data
= data
.sum
;
783 newdata
.x
= db_squares
;
784 newdata
.data
= data
.squares
;
787 newdata
.x
= db_samples
;
788 newdata
.data
= data
.samples
;
791 if (data
.samples
&& !params
->fancy
) {
792 newdata
.x
= db_min_val
;
793 newdata
.data
= data
.min_val
;
796 newdata
.x
= db_max_val
;
797 newdata
.data
= data
.max_val
;
800 newdata
.x
= db_underflow
;
801 newdata
.data
= data
.underflow
;
804 newdata
.x
= db_overflow
;
805 newdata
.data
= data
.overflow
;
808 size_type size
= data
.cvec
.size();
809 for (off_type x
= 0; x
< size
; x
++) {
811 newdata
.data
= data
.cvec
[x
];
818 MySql::output(const DistInfo
&info
)
820 if (!(info
.flags
& print
))
823 newdata
.stat
= find(info
.id
);
825 output(info
.data
, safe_cast
<const DistParams
*>(info
.storageParams
));
829 MySql::output(const VectorDistInfo
&info
)
831 if (!(info
.flags
& print
))
834 newdata
.stat
= find(info
.id
);
836 size_type size
= info
.data
.size();
837 for (off_type y
= 0; y
< size
; ++y
) {
840 safe_cast
<const DistParams
*>(info
.storageParams
));
845 MySql::output(const Vector2dInfo
&info
)
847 if (!(info
.flags
& print
))
850 newdata
.stat
= find(info
.id
);
853 for (off_type x
= 0; x
< info
.x
; x
++) {
855 for (off_type y
= 0; y
< info
.y
; y
++) {
857 newdata
.data
= info
.cvec
[index
++];
864 MySql::output(const FormulaInfo
&info
)
869 * Implement the visitor
872 MySql::visit(const ScalarInfo
&info
)
881 MySql::visit(const VectorInfo
&info
)
890 MySql::visit(const DistInfo
&info
)
900 MySql::visit(const VectorDistInfo
&info
)
910 MySql::visit(const Vector2dInfo
&info
)
920 MySql::visit(const FormulaInfo
&info
)
929 initMySQL(string host
, string user
, string password
, string database
,
930 string project
, string name
, string sample
)
932 extern list
<Output
*> OutputList
;
935 if (mysql
.connected())
938 mysql
.connect(host
, user
, password
, database
, name
, sample
, project
);
939 OutputList
.push_back(&mysql
);
944 /* end namespace Stats */ }