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
38 #include "base/stats/info.hh"
39 #include "base/stats/mysql.hh"
40 #include "base/stats/mysql_run.hh"
41 #include "base/stats/types.hh"
42 #include "base/misc.hh"
43 #include "base/mysql.hh"
44 #include "base/statistics.hh"
45 #include "base/str.hh"
46 #include "base/types.hh"
47 #include "base/userinfo.hh"
48 #include "sim/core.hh"
55 MySqlRun::connect(const string
&host
, const string
&user
, const string
&passwd
,
56 const string
&db
, const string
&name
, const string
&sample
,
57 const string
&project
)
60 panic("can only get one database connection at this time!");
62 mysql
.connect(host
, user
, passwd
, db
);
64 panic("could not connect to database server\n%s\n", mysql
.error
);
66 if (mysql
.autocommit(false))
67 panic("could not set autocommit\n%s\n", mysql
.error
);
71 setup(name
, sample
, user
, project
);
75 MySqlRun::setup(const string
&name
, const string
&sample
, const string
&user
,
76 const string
&project
)
78 assert(mysql
.connected());
83 "runs(rn_name,rn_sample,rn_user,rn_project,rn_date,rn_expire)"
84 "values(\"%s\", \"%s\", \"%s\", \"%s\", NOW(),"
85 "DATE_ADD(CURDATE(), INTERVAL 31 DAY))",
86 name
, sample
, user
, project
);
90 panic("could not get a run\n%s\n", mysql
.error
);
92 run_id
= mysql
.insert_id();
94 panic("could not commit transaction\n%s\n", mysql
.error
);
98 MySqlRun::remove(const string
&name
)
100 assert(mysql
.connected());
102 ccprintf(sql
, "DELETE FROM runs WHERE rn_name=\"%s\"", name
);
105 panic("could not delete run\n%s\n", mysql
.error
);
107 panic("could not commit transaction\n%s\n", mysql
.error
);
113 assert(mysql
.connected());
115 mysql
.query("DELETE data "
117 "LEFT JOIN runs ON dt_run=rn_id "
118 "WHERE rn_id IS NULL");
121 panic("could not commit transaction\n%s\n", mysql
.error
);
123 mysql
.query("DELETE formula_ref "
125 "LEFT JOIN runs ON fr_run=rn_id "
126 "WHERE rn_id IS NULL");
129 panic("could not commit transaction\n%s\n", mysql
.error
);
131 mysql
.query("DELETE formulas "
133 "LEFT JOIN formula_ref ON fm_stat=fr_stat "
134 "WHERE fr_stat IS NULL");
137 panic("could not commit transaction\n%s\n", mysql
.error
);
139 mysql
.query("DELETE stats "
141 "LEFT JOIN data ON st_id=dt_stat "
142 "WHERE dt_stat IS NULL");
145 panic("could not commit transaction\n%s\n", mysql
.error
);
147 mysql
.query("DELETE subdata "
149 "LEFT JOIN data ON sd_stat=dt_stat "
150 "WHERE dt_stat IS NULL");
153 panic("could not commit transaction\n%s\n", mysql
.error
);
177 SetupStat::setup(MySqlRun
*run
)
179 MySQL::Connection
&mysql
= run
->conn();
184 "stats(st_name, st_descr, st_type, st_print, st_prereq, "
185 "st_prec, st_nozero, st_nonan, st_total, st_pdf, st_cdf, "
186 "st_min, st_max, st_bktsize, st_size)"
187 "values(\"%s\",\"%s\",\"%s\","
188 " %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
189 name
, descr
, type
, print
, prereq
, (int)prec
, nozero
, nonan
,
191 min
, max
, bktsize
, size
);
195 int id
= mysql
.insert_id();
197 panic("could not commit transaction\n%s\n", mysql
.error
);
202 ccprintf(select
, "SELECT * FROM stats WHERE st_name=\"%s\"", name
);
205 MySQL::Result result
= mysql
.store_result();
207 panic("could not find stat\n%s\n", mysql
.error
);
209 assert(result
.num_fields() == 16);
210 MySQL::Row row
= result
.fetch_row();
212 panic("could not get stat row\n%s\n", mysql
.error
);
220 if (name
!= (char *)row
[1])
221 panic("failed stat check on %s:name. %s != %s\n",
224 if (descr
!= (char *)row
[2])
225 panic("failed stat check on %s:descr. %s != %s\n",
226 name
, descr
, row
[2]);
228 if (type
!= (char *)row
[3])
229 panic("failed stat check on %s:type. %s != %s\n",
232 if (!to_number(row
[4], tb
) || print
!= tb
)
233 panic("failed stat check on %s:print. %d != %d\n",
236 if (!to_number(row
[6], ti8
) || prec
!= ti8
)
237 panic("failed stat check on %s:prec. %d != %d\n",
240 if (!to_number(row
[7], tb
) || nozero
!= tb
)
241 panic("failed stat check on %s:nozero. %d != %d\n",
244 if (!to_number(row
[8], tb
) || nonan
!= tb
)
245 panic("failed stat check on %s:nonan. %d != %d\n",
248 if (!to_number(row
[9], tb
) || total
!= tb
)
249 panic("failed stat check on %s:total. %d != %d\n",
252 if (!to_number(row
[10], tb
) || pdf
!= tb
)
253 panic("failed stat check on %s:pdf. %d != %d\n",
256 if (!to_number(row
[11], tb
) || cdf
!= tb
)
257 panic("failed stat check on %s:cdf. %d != %d\n",
260 if (!to_number(row
[12], ti64
) || min
!= ti64
)
261 panic("failed stat check on %s:min. %d != %d\n",
264 if (!to_number(row
[13], ti64
) || max
!= ti64
)
265 panic("failed stat check on %s:max. %d != %d\n",
268 if (!to_number(row
[14], tu64
) || bktsize
!= tu64
)
269 panic("failed stat check on %s:bktsize. %d != %d\n",
270 name
, bktsize
, tu64
);
272 if (!to_number(row
[15], tu16
) || size
!= tu16
)
273 panic("failed stat check on %s:size. %d != %d\n",
276 to_number(row
[5], prereq
);
278 to_number(row
[0], statid
);
282 InsertData::InsertData(MySqlRun
*_run
)
285 query
= new char[maxsize
+ 1];
290 InsertData::~InsertData()
299 MySQL::Connection
&mysql
= run
->conn();
300 assert(mysql
.connected());
303 panic("could not insert data\n%s\n", mysql
.error
);
305 panic("could not commit transaction\n%s\n", mysql
.error
);
311 strcpy(query
, "INSERT INTO "
312 "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_data) "
314 size
= strlen(query
);
320 if (size
+ 1024 > maxsize
)
330 size
+= sprintf(query
+ size
, "(%u,%d,%d,%u,%llu,\"%f\")",
331 stat
, x
, y
, run
->run(), (unsigned long long)tick
,
343 void setup(MySqlRun
*run
);
347 InsertSubData::setup(MySqlRun
*run
)
349 MySQL::Connection
&mysql
= run
->conn();
350 assert(mysql
.connected());
353 "INSERT INTO subdata(sd_stat,sd_x,sd_y,sd_name,sd_descr) "
354 "values(%d,%d,%d,\"%s\",\"%s\")",
355 stat
, x
, y
, name
, descr
);
359 // panic("could not insert subdata\n%s\n", mysql.error);
362 panic("could not commit transaction\n%s\n", mysql
.error
);
366 : run(new MySqlRun
), newdata(run
)
375 MySql::connect(const string
&host
, const string
&user
, const string
&passwd
,
376 const string
&db
, const string
&name
, const string
&sample
,
377 const string
&project
)
379 run
->connect(host
, user
, passwd
, db
, name
, sample
, project
);
383 MySql::connected() const
385 return run
->connected();
394 MySQL::Connection
&mysql
= run
->conn();
396 list
<Info
*>::const_iterator i
, end
= statsList().end();
397 for (i
= statsList().begin(); i
!= end
; ++i
) {
401 for (i
= statsList().begin(); i
!= end
; ++i
) {
404 // update the prerequisite
405 uint16_t stat_id
= find(info
->id
);
406 uint16_t prereq_id
= find(info
->prereq
->id
);
407 assert(stat_id
&& prereq_id
);
410 ccprintf(update
, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
414 panic("could not update prereq\n%s\n", mysql
.error
);
417 panic("could not commit transaction\n%s\n", mysql
.error
);
422 panic("could not commit transaction\n%s\n", mysql
.error
);
428 MySql::configure(const Info
&info
, string type
)
431 stat
.name
= info
.name
;
432 stat
.descr
= info
.desc
;
434 stat
.print
= info
.flags
& display
;
435 stat
.prec
= info
.precision
;
436 stat
.nozero
= info
.flags
& nozero
;
437 stat
.nonan
= info
.flags
& nonan
;
438 stat
.total
= info
.flags
& total
;
439 stat
.pdf
= info
.flags
& pdf
;
440 stat
.cdf
= info
.flags
& cdf
;
446 MySql::configure(const ScalarInfo
&info
)
448 if (!configure(info
, "SCALAR"))
451 insert(info
.id
, stat
.setup(run
));
455 MySql::configure(const VectorInfo
&info
)
457 if (!configure(info
, "VECTOR"))
460 uint16_t statid
= stat
.setup(run
);
462 if (!info
.subnames
.empty()) {
463 InsertSubData subdata
;
464 subdata
.stat
= statid
;
466 for (off_type i
= 0; i
< info
.subnames
.size(); ++i
) {
468 subdata
.name
= info
.subnames
[i
];
469 subdata
.descr
= info
.subdescs
.empty() ? "" : info
.subdescs
[i
];
471 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
476 insert(info
.id
, statid
);
480 MySql::configure(const DistInfo
&info
)
482 if (!configure(info
, "DIST"))
485 const DistStor::Params
*params
=
486 dynamic_cast<const DistStor::Params
*>(info
.storageParams
);
488 assert(params
->type
== Dist
);
489 stat
.size
= params
->buckets
;
490 stat
.min
= params
->min
;
491 stat
.max
= params
->max
;
492 stat
.bktsize
= params
->bucket_size
;
494 insert(info
.id
, stat
.setup(run
));
498 MySql::configure(const VectorDistInfo
&info
)
500 if (!configure(info
, "VECTORDIST"))
503 const DistStor::Params
*params
=
504 dynamic_cast<const DistStor::Params
*>(info
.storageParams
);
506 assert(params
->type
== Dist
);
507 stat
.size
= params
->buckets
;
508 stat
.min
= params
->min
;
509 stat
.max
= params
->max
;
510 stat
.bktsize
= params
->bucket_size
;
513 uint16_t statid
= stat
.setup(run
);
515 if (!info
.subnames
.empty()) {
516 InsertSubData subdata
;
517 subdata
.stat
= statid
;
519 for (off_type i
= 0; i
< info
.subnames
.size(); ++i
) {
521 subdata
.name
= info
.subnames
[i
];
522 subdata
.descr
= info
.subdescs
.empty() ? "" : info
.subdescs
[i
];
523 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
528 insert(info
.id
, statid
);
532 MySql::configure(const Vector2dInfo
&info
)
534 if (!configure(info
, "VECTOR2D"))
537 uint16_t statid
= stat
.setup(run
);
539 if (!info
.subnames
.empty()) {
540 InsertSubData subdata
;
541 subdata
.stat
= statid
;
543 for (off_type i
= 0; i
< info
.subnames
.size(); ++i
) {
545 subdata
.name
= info
.subnames
[i
];
546 subdata
.descr
= info
.subdescs
.empty() ? "" : info
.subdescs
[i
];
547 if (!subdata
.name
.empty() || !subdata
.descr
.empty())
552 if (!info
.y_subnames
.empty()) {
553 InsertSubData subdata
;
554 subdata
.stat
= statid
;
557 for (off_type i
= 0; i
< info
.y_subnames
.size(); ++i
) {
559 subdata
.name
= info
.y_subnames
[i
];
560 if (!subdata
.name
.empty())
565 insert(info
.id
, statid
);
569 MySql::configure(const FormulaInfo
&info
)
571 MySQL::Connection
&mysql
= run
->conn();
572 assert(mysql
.connected());
574 configure(info
, "FORMULA");
575 insert(info
.id
, stat
.setup(run
));
577 uint16_t stat
= find(info
.id
);
578 string formula
= info
.str();
580 stringstream insert_formula
;
581 ccprintf(insert_formula
,
582 "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
585 mysql
.query(insert_formula
);
587 // panic("could not insert formula\n%s\n", mysql.error);
589 stringstream insert_ref
;
591 "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
594 mysql
.query(insert_ref
);
596 // panic("could not insert formula reference\n%s\n", mysql.error);
599 panic("could not commit transaction\n%s\n", mysql
.error
);
605 return run
->connected();
617 newdata
.tick
= curTick();
619 MySQL::Connection
&mysql
= run
->conn();
621 list
<Info
*>::const_iterator i
, end
= statsList().end();
622 for (i
= statsList().begin(); i
!= end
; ++i
) {
626 panic("could not commit transaction\n%s\n", mysql
.error
);
633 MySql::output(const ScalarInfo
&info
)
635 if (!(info
.flags
& display
))
638 newdata
.stat
= find(info
.id
);
641 newdata
.data
= info
.value();
647 MySql::output(const VectorInfo
&info
)
649 if (!(info
.flags
& display
))
652 newdata
.stat
= find(info
.id
);
655 const VCounter
&cvec
= info
.value();
656 size_type size
= info
.size();
657 for (off_type x
= 0; x
< size
; x
++) {
659 newdata
.data
= cvec
[x
];
665 MySql::output(const DistData
&data
, const DistParams
*params
)
667 const int db_sum
= -1;
668 const int db_squares
= -2;
669 const int db_samples
= -3;
670 const int db_min_val
= -4;
671 const int db_max_val
= -5;
672 const int db_underflow
= -6;
673 const int db_overflow
= -7;
676 newdata
.data
= data
.sum
;
679 newdata
.x
= db_squares
;
680 newdata
.data
= data
.squares
;
683 newdata
.x
= db_samples
;
684 newdata
.data
= data
.samples
;
687 if (data
.samples
&& params
->type
== Dist
) {
688 newdata
.x
= db_min_val
;
689 newdata
.data
= data
.min_val
;
692 newdata
.x
= db_max_val
;
693 newdata
.data
= data
.max_val
;
696 newdata
.x
= db_underflow
;
697 newdata
.data
= data
.underflow
;
700 newdata
.x
= db_overflow
;
701 newdata
.data
= data
.overflow
;
704 size_type size
= data
.cvec
.size();
705 for (off_type x
= 0; x
< size
; x
++) {
707 newdata
.data
= data
.cvec
[x
];
714 MySql::output(const DistInfo
&info
)
716 if (!(info
.flags
& display
))
719 newdata
.stat
= find(info
.id
);
721 output(info
.data
, safe_cast
<const DistParams
*>(info
.storageParams
));
725 MySql::output(const VectorDistInfo
&info
)
727 if (!(info
.flags
& display
))
730 newdata
.stat
= find(info
.id
);
732 size_type size
= info
.data
.size();
733 for (off_type y
= 0; y
< size
; ++y
) {
736 safe_cast
<const DistParams
*>(info
.storageParams
));
741 MySql::output(const Vector2dInfo
&info
)
743 if (!(info
.flags
& display
))
746 newdata
.stat
= find(info
.id
);
749 for (off_type x
= 0; x
< info
.x
; x
++) {
751 for (off_type y
= 0; y
< info
.y
; y
++) {
753 newdata
.data
= info
.cvec
[index
++];
760 MySql::output(const FormulaInfo
&info
)
765 * Implement the visitor
768 MySql::visit(const ScalarInfo
&info
)
777 MySql::visit(const VectorInfo
&info
)
786 MySql::visit(const DistInfo
&info
)
796 MySql::visit(const VectorDistInfo
&info
)
806 MySql::visit(const Vector2dInfo
&info
)
816 MySql::visit(const FormulaInfo
&info
)
825 initMySQL(string host
, string user
, string password
, string database
,
826 string project
, string name
, string sample
)
828 extern list
<Output
*> OutputList
;
831 if (mysql
.connected())
834 mysql
.connect(host
, user
, password
, database
, name
, sample
, project
);
835 OutputList
.push_back(&mysql
);