6 Commits
v1.0 ... v1.0.1

Author SHA1 Message Date
bfd6a55f58 Fail* v1.0.1
This is a maintenance release primarily fixing docker demo builds.

Change-Id: I4f71ae9c50d29f36a9b6fd2ff11067b39f99c39d
2014-11-14 11:13:26 +01:00
96ead7df84 scripts/docker: use ac++ 1.2 instead of daily build
Since the AspectC++ daily builds switched to the clang frontend, Fail*
doesn't build anymore.  Unless that changes, use the 1.2 release.

Change-Id: Ia7817c396dfabd3a10f0cf0ea6a8d4c1fb95365d
2014-11-14 11:08:47 +01:00
6e6148f701 client.sh: exit on any error status
This prevents the client script from continuously invoking
the fail-client when it is not executable, e.g., in the case
of missing libraries.

Change-Id: I2746eaf1980507dbd7c95fb5a6a1cc018a33aa67
2014-11-10 15:45:38 +01:00
36d9e77c96 import-trace: extend sanity checks to time1/2
Up to now, the sanity checks only tested equivalence classes
determined by dynamic instructions (instr1/instr2), although the
actual timing boundaries (time1/time2) have been the really relevant
information for quite some time now.  This change extends the checks
to time1/time2.

Change-Id: I53d1ed10684ff09f6b9f1245ef842dd0d85f2655
2014-11-07 11:40:53 +01:00
569dd3328b import-trace: sanity-check speedup
The sanity check testing whether the fault space is rectangular is
unnecessarily slow, as it joins the "trace" table without any reason,
and includes all variants instead of the currently imported one.

Change-Id: Icfe948290ec595209868952fc1639c979bd78d83
2014-11-07 11:37:49 +01:00
d30ffdd3e5 import-trace: sanity-check code deduplication
Change-Id: I098981dfe93d760e3a423a374be05dbad3ee9cc1
2014-11-07 11:29:50 +01:00
5 changed files with 115 additions and 52 deletions

View File

@ -9,7 +9,7 @@ ENABLE_TESTING()
PROJECT(Fail*) PROJECT(Fail*)
set(PROJECT_VERSION "1.0" CACHE STRING "Fail* version number") set(PROJECT_VERSION "1.0.1" CACHE STRING "Fail* version number")
#### Put all resulting library files in <your_build_dir>/lib #### #### Put all resulting library files in <your_build_dir>/lib ####
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)

View File

@ -51,7 +51,7 @@ do
#nice -n 19 ./bochs -q 2>&1 | tee log.$$.txt | fgrep Result #nice -n 19 ./bochs -q 2>&1 | tee log.$$.txt | fgrep Result
#nice -n 18 ./bochs -q 2>&1 | fgrep Result #nice -n 18 ./bochs -q 2>&1 | fgrep Result
nice -n 18 ./fail-client -q >/dev/null 2>&1 nice -n 18 ./fail-client -q >/dev/null 2>&1
if [ $? -eq 1 ] if [ $? -gt 0 ] # exit on any error
then then
break break
fi fi

View File

@ -45,9 +45,9 @@ USER fail
ENV HOME /home/fail ENV HOME /home/fail
WORKDIR /home/fail WORKDIR /home/fail
# Get the latest version of AspectC++ for 64 Bit # Get AspectC++ v1.2 for 64 Bit
RUN wget http://aspectc.org:8080/job/Build_Binaries/Platform=linux_x86_64/lastBuild/artifact/binaries.tar.bz2 RUN wget http://www.aspectc.org/releases/1.2/ac-bin-linux-x86-64bit-1.2.tar.gz
RUN tar xvjf binaries.tar.bz2; mv AspectC++/bin/linux-release bin; rm -rf 'AspectC++' RUN tar xvzf ac-bin-linux-x86-64bit-1.2.tar.gz; mkdir bin; mv aspectc++/ac++ aspectc++/ag++ bin/; rm -rf aspectc++
ENV PATH /home/fail/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ENV PATH /home/fail/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Clone FAIL* # Clone FAIL*

View File

@ -59,6 +59,20 @@ bool Importer::clear_database() {
return ret; return ret;
} }
bool Importer::sanitycheck(std::string check_name, std::string fail_msg, std::string sql)
{
LOG << "Sanity check: " << check_name << " ..." << std::flush;
MYSQL_RES *res = db->query(sql.c_str(), true);
if (res && mysql_num_rows(res) == 0) {
std::cout << " OK" << std::endl;
return true;
} else {
std::cout << " FAILED: " << fail_msg << std::endl;
return false;
}
}
bool Importer::copy_to_database(fail::ProtoIStream &ps) { bool Importer::copy_to_database(fail::ProtoIStream &ps) {
// For now we just use the min/max occuring timestamp; for "sparse" traces // For now we just use the min/max occuring timestamp; for "sparse" traces
// (e.g., only mem accesses, only a subset of the address space) it might // (e.g., only mem accesses, only a subset of the address space) it might
@ -149,14 +163,13 @@ bool Importer::copy_to_database(fail::ProtoIStream &ps) {
if (m_sanitychecks) { if (m_sanitychecks) {
std::stringstream ss; std::stringstream ss;
bool all_ok = true; bool all_ok = true;
MYSQL_RES *res;
// PC-based fault space rectangular, covered, and non-overlapping? // PC- and timing-based fault space non-overlapping, covered, and
// (same for timing-based fault space?) // rectangular?
LOG << "Sanity check: EC overlaps ..." << std::flush; // non-overlapping (instr1/2)?
ss << ss <<
"SELECT t1.variant_id\n" //, v.variant, v.benchmark, t1.instr1, t1.instr2, t1.data_address, t2.instr1, t2.instr2 "SELECT t1.variant_id\n"
"FROM trace t1\n" "FROM trace t1\n"
"JOIN variant v\n" "JOIN variant v\n"
" ON v.id = t1.variant_id\n" " ON v.id = t1.variant_id\n"
@ -167,19 +180,32 @@ bool Importer::copy_to_database(fail::ProtoIStream &ps) {
" OR (t1.instr2 >= t2.instr1 AND t1.instr2 <= t2.instr2)\n" " OR (t1.instr2 >= t2.instr1 AND t1.instr2 <= t2.instr2)\n"
" OR (t1.instr1 < t2.instr1 AND t1.instr2 > t2.instr2))\n" " OR (t1.instr1 < t2.instr1 AND t1.instr2 > t2.instr2))\n"
"WHERE t1.variant_id = " << m_variant_id; "WHERE t1.variant_id = " << m_variant_id;
if (!sanitycheck("EC overlaps (instr1/2)",
res = db->query(ss.str().c_str(), true); "not all ECs are disjoint", ss.str())) {
ss.str("");
ss.clear();
if (res && mysql_num_rows(res) == 0) {
std::cout << " OK" << std::endl;
} else {
std::cout << " FAILED: not all ECs are disjoint" << std::endl;
// TODO: show a list of overlapping ECs?
all_ok = false; all_ok = false;
} }
ss.str("");
LOG << "Sanity check: FS row sum = total width ..." << std::flush; // non-overlapping (time1/2)?
ss <<
"SELECT t1.variant_id\n"
"FROM trace t1\n"
"JOIN variant v\n"
" ON v.id = t1.variant_id\n"
"JOIN trace t2\n"
" ON t1.variant_id = t2.variant_id AND t1.data_address = t2.data_address\n"
" AND (t1.time1 != t2.time1 OR t2.time2 != t2.time2)\n"
" AND ((t1.time1 >= t2.time1 AND t1.time1 <= t2.time2)\n"
" OR (t1.time2 >= t2.time1 AND t1.time2 <= t2.time2)\n"
" OR (t1.time1 < t2.time1 AND t1.time2 > t2.time2))\n"
"WHERE t1.variant_id = " << m_variant_id;
if (!sanitycheck("EC overlaps (time1/2)",
"not all ECs are disjoint", ss.str())) {
all_ok = false;
}
ss.str("");
// covered (instr1/2)?
ss << ss <<
"SELECT t.variant_id, t.data_address,\n" "SELECT t.variant_id, t.data_address,\n"
" (SELECT (MAX(t2.instr2) - MIN(t2.instr1) + 1)\n" " (SELECT (MAX(t2.instr2) - MIN(t2.instr1) + 1)\n"
@ -195,47 +221,79 @@ bool Importer::copy_to_database(fail::ProtoIStream &ps) {
"GROUP BY t.variant_id, t.data_address\n" "GROUP BY t.variant_id, t.data_address\n"
"HAVING diff != 0\n" "HAVING diff != 0\n"
"ORDER BY t.data_address\n"; "ORDER BY t.data_address\n";
if (!sanitycheck("FS row sum = total width (instr1/2)",
res = db->query(ss.str().c_str(), true); "MAX(instr2)-MIN(instr1)+1 == SUM(instr2-instr1+1) not true for all fault-space rows",
ss.str(""); ss.str())) {
ss.clear();
if (res && mysql_num_rows(res) == 0) {
std::cout << " OK" << std::endl;
} else {
std::cout << " FAILED: MAX(instr2)-MIN(instr1)+1 == SUM(instr2-instr1+1) not true for all fault-space rows" << std::endl;
// TODO: show a list of failing data_addresses?
all_ok = false; all_ok = false;
} }
ss.str("");
LOG << "Sanity check: Global min/max = FS row local min/max ..." << std::flush; // covered (time1/2)?
ss << ss <<
"SELECT t.variant_id, local.data_address, global.min_instr, global.max_instr, local.min_instr, local.max_instr\n" "SELECT t.variant_id, t.data_address,\n"
"FROM trace t\n" " (SELECT (MAX(t2.time2) - MIN(t2.time1) + 1)\n"
"JOIN\n"
" (SELECT t2.variant_id, MIN(instr1) AS min_instr, MAX(instr2) AS max_instr\n"
" FROM trace t2\n" " FROM trace t2\n"
" GROUP BY t2.variant_id) AS global\n" " WHERE t2.variant_id = t.variant_id)\n"
" ON global.variant_id = t.variant_id\n" " -\n"
"JOIN\n" " (SELECT SUM(t3.time2 - t3.time1 + 1)\n"
" (SELECT variant_id, data_address, MIN(instr1) AS min_instr, MAX(instr2) AS max_instr\n"
" FROM trace t3\n" " FROM trace t3\n"
" GROUP BY t3.variant_id, t3.data_address) AS local\n" " WHERE t3.variant_id = t.variant_id AND t3.data_address = t.data_address)\n"
" ON local.variant_id = t.variant_id\n" " AS diff\n"
"AND (local.min_instr != global.min_instr\n" "FROM trace t\n"
" OR local.max_instr != global.max_instr)\n"
"WHERE t.variant_id = " << m_variant_id << "\n" "WHERE t.variant_id = " << m_variant_id << "\n"
"GROUP BY t.variant_id, local.data_address\n"; "GROUP BY t.variant_id, t.data_address\n"
"HAVING diff != 0\n"
res = db->query(ss.str().c_str(), true); "ORDER BY t.data_address\n";
ss.str(""); if (!sanitycheck("FS row sum = total width (time1/2)",
ss.clear(); "MAX(time2)-MIN(time1)+1 == SUM(time2-time1+1) not true for all fault-space rows",
if (res && mysql_num_rows(res) == 0) { ss.str())) {
std::cout << " OK" << std::endl;
} else {
std::cout << " FAILED: global MIN(instr1)/MAX(instr2) != row-local MIN(instr1)/MAX(instr2)" << std::endl;
// TODO: show a list of failing data_addresses and global min/max?
all_ok = false; all_ok = false;
} }
ss.str("");
// rectangular (instr1/2)?
ss <<
"SELECT local.data_address, global.min_instr, global.max_instr, local.min_instr, local.max_instr\n"
"FROM\n"
" (SELECT MIN(instr1) AS min_instr, MAX(instr2) AS max_instr\n"
" FROM trace t2\n"
" WHERE variant_id = " << m_variant_id << "\n"
" GROUP BY t2.variant_id) AS global\n"
"JOIN\n"
" (SELECT data_address, MIN(instr1) AS min_instr, MAX(instr2) AS max_instr\n"
" FROM trace t3\n"
" WHERE variant_id = " << m_variant_id << "\n"
" GROUP BY t3.variant_id, t3.data_address) AS local\n"
" ON (local.min_instr != global.min_instr\n"
" OR local.max_instr != global.max_instr)";
if (!sanitycheck("Global min/max = FS row local min/max (instr1/2)",
"global MIN(instr1)/MAX(instr2) != row-local MIN(instr1)/MAX(instr2)",
ss.str())) {
all_ok = false;
}
ss.str("");
// rectangular (time1/2)?
ss <<
"SELECT local.data_address, global.min_time, global.max_time, local.min_time, local.max_time\n"
"FROM\n"
" (SELECT MIN(time1) AS min_time, MAX(time2) AS max_time\n"
" FROM trace t2\n"
" WHERE variant_id = " << m_variant_id << "\n"
" GROUP BY t2.variant_id) AS global\n"
"JOIN\n"
" (SELECT data_address, MIN(time1) AS min_time, MAX(time2) AS max_time\n"
" FROM trace t3\n"
" WHERE variant_id = " << m_variant_id << "\n"
" GROUP BY t3.variant_id, t3.data_address) AS local\n"
" ON (local.min_time != global.min_time\n"
" OR local.max_time != global.max_time)";
if (!sanitycheck("Global min/max = FS row local min/max (time1/2)",
"global MIN(time1)/MAX(time2) != row-local MIN(time1)/MAX(time2)",
ss.str())) {
all_ok = false;
}
ss.str("");
if (!all_ok) { if (!all_ok) {
return false; return false;

View File

@ -113,6 +113,11 @@ protected:
*/ */
virtual bool trace_end_reached() { return true; } virtual bool trace_end_reached() { return true; }
/**
* Executes an SQL statement, assumes a sanity check failure if it returns
* any result rows, and provides some diagnostics.
*/
bool sanitycheck(std::string check_name, std::string fail_msg, std::string sql);
public: public:
Importer() : m_sanitychecks(false), m_import_write_ecs(true), m_extended_trace(false), m_row_count(0), m_time_trace_start(0) {} Importer() : m_sanitychecks(false), m_import_write_ecs(true), m_extended_trace(false), m_row_count(0), m_time_trace_start(0) {}
bool init(const std::string &variant, const std::string &benchmark, fail::Database *db); bool init(const std::string &variant, const std::string &benchmark, fail::Database *db);