class MysqlReporter(BenchmarkReport): def __init__(self): BenchmarkReport.__init__(self) # use this to print out what is happening self._stdout = StdoutReporter() self.run_id = int(time()) self.tool_params = '{0}'.format(configs.configs['params']) # replace apostrophes in tool_params self.tool_params = self.tool_params.replace('\'', '\\\'') from database import DatabaseConnection self._db = DatabaseConnection() ver = self._db.query('SELECT VERSION()')[0][0] satt_log('Connected to database: MySQL version {0}'.format(ver)) self._rating_methods = RatingMethod(self._db.query) def progress(self, progress): # we must redirect progress to stdout self._stdout.progress(progress) def _commit(self): self._db.commit() def _updateDb(self, rb): def choose_tag(): if configs.configs.has_key('tool-tag'): return configs.configs['tool-tag'] else: return configs.configs['tool'] ver = rb.versions.strip() q = """ SELECT id FROM years WHERE year = '{0}'; """.format(configs.configs['year']); res = self._db.query(q) if not res: err('Do not have year {0}. If this is not typo, ' 'update the database and benchmarks'.format(configs.configs['year'])) year_id = res[0][0] # If tool that runs in this run is not known to database, add it q = """ SELECT id FROM tools WHERE name = '{0}' and version = '{1}' and params = '{2}' and year_id = '{3}'; """.format(configs.configs['tool'], ver, self.tool_params, year_id) res = self._db.query(q) if not res: q2 = """ INSERT INTO tools (name, year_id, version, params, tag, note) VALUES('{0}', '{1}', '{2}', '{3}', '{4}', {5}); """.format(configs.configs['tool'], year_id, ver, self.tool_params, choose_tag(), Empty2Null(configs.configs['note'])) self._db.query(q2) # get new tool_id res = self._db.query(q) assert len(res) == 1 tool_id = res[0][0] return tool_id, year_id def save_task(self, rb, cat_id): """ Save unknown task into the database """ name = get_name(rb.name) cr = self._get_correct_result(name, rb) if cr is None: msg = 'Couldn\'t infer if the result is correct or not, setting unkown' satt_log(msg) rb.output += msg rb.result = 'unknown ({0})'.format(rb.result) # create new task q = """ INSERT INTO tasks (name, category_id, correct_result, property) VALUES('{0}', '{1}', '{2}', '{3}'); """.format(name, cat_id, cr, None) self._db.query(q) q = """ SELECT id, correct_result FROM tasks WHERE name = '{0}' and category_id = '{1}'; """.format(name, cat_id) return self._db.query(q) def update_category(self, year_id, name): """ Create new category in the database """ # create the a category in the database q = """ INSERT INTO categories (year_id, name) VALUES ('{0}', '{1}'); """.format(year_id, name) self._db.query(q) # return the new result q = """ SELECT id, name FROM categories WHERE year_id = '{0}' and name = '{1}'; """.format(year_id, name) return self._db.query(q) def done(self, rb): # print it after saving if not self._stdout.done(rb): # if there is a problem, the benchmark will run again, so do not # proceed further return False tool_id, year_id = self._updateDb(rb) q = """ SELECT id, name FROM categories WHERE year_id = '{0}' and name = '{1}'; """.format(year_id, rb.category) res = self._db.query(q) if not res: if configs.configs['save-new-tasks'] == 'yes': res = self.update_category(year_id, rb.category) else: rb.dumpToFile('Do not have given category') satt_log('^^ dumped to file (unknown category)') return True assert len(res) == 1 if not len(res[0]) == 2: print(res[0]) assert len(res[0]) == 2 cat_id = res[0][0] cat_name = res[0][1] q = """ SELECT id, correct_result FROM tasks WHERE name = '{0}' and category_id = '{1}'; """.format(get_name(rb.name), cat_id) res = self._db.query(q) # we do not have such a task?? if not res: if configs.configs['save-new-tasks'] == 'yes': res = self.save_task(rb, cat_id) else: rb.dumpToFile('Do not have given task') satt_log('^^ dumped to file (unknown task)') return True assert len(res) == 1 task_id = res[0][0] correct_result = res[0][1] # replace ' by \' in output rb.output = rb.output.replace('\'', '\\\'') ic = is_correct(correct_result, rb.result) result= rb.result.lower() if rb.witness != '': wtns = rb.witness.strip() # replace ' even in witness, because it can contain # arbitrary text wtns = wtns.replace('\'', '\\\'') else: wtns = None if rb.witness_output != '': # FIXME we should limit the wintess_output size, otherwise we # get get some performance issues rb.witness_output = rb.witness_output.strip() rb.witness_output = rb.witness_output.replace('\'', '\\\'') q = """ INSERT INTO task_results (tool_id, task_id, result, witness, is_correct, points, cpu_time, memory_usage, output, witness_output, run_id) VALUES('{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', {8}, '{9}', '{10}') """.format(tool_id, task_id, result, wtns, ic, self._rating_methods.points(ic, rb.result, wtns, cat_name), None2Zero(rb.time), None2Zero(rb.memory), Empty2Null(rb.output), rb.witness_output, self.run_id) def _exception_handler(args, data): q, tool_id, task_id = data if (args[1].startswith('Duplicate entry')): if configs.configs['ignore-duplicates'] == 'yes': satt_log('Already has this result for this tool, ignoring.') else: err('Already has result of this benchmark for this tool.\n' 'It is only supported to have one result for each ' 'benchmark and particular tool\n' 'If want ignore this behaviour use --ignore-duplicates.\n' '(tool + version + params). You can delete the old result:\n' ' $ ./db-cli \'DELETE from task_results WHERE tool_id={0}' ' and task_id={1}\'\n' 'or you can delete all results for this tool:\n' ' $ ./db-cli \'DELETE from tools WHERE id={0}\'\n' .format(tool_id, task_id, tool_id)) else: err('Failed querying db: {0}\n\n{1}'.format(args[1], q)) self._db.query_with_exception_handler(q, _exception_handler, (q, tool_id, task_id)) self._commit() return True def sendEmail(self, server, from_addr, to_addrs): import smtplib from email.mime.text import MIMEText time_format = '%Y-%m-%d-%H-%S' raw_started_at = strptime(configs.configs['started_at'], time_format) started_at = strftime('%a %b %d %H:%M:%S %Y', raw_started_at) finished_at = strftime('%a %b %d %H:%M:%S %Y') text = """ This is automatically generated message. Do not answer. ======================================================= Satt on tool {0} started at {1}, finished {2} with parameters: {3} on benchmarks from year {4} Note: {5} Results: """.format(configs.configs['tool'], started_at, finished_at, configs.configs['params'], configs.configs['year'], configs.configs['note']) q = """ SELECT result, is_correct, witness, count(*) FROM task_results WHERE run_id = {0} GROUP BY result, is_correct, witness""".format(self.run_id) res = self._db.query(q) if not res: err('No results stored to db after this run?') total = 0 for row in res: result = row[0] if result == 'true' or result == 'false': if row[1] == 0: result += ' incorrect' else: result += ' correct' if not row[2] is None: text += '{0:<15} (witness {1}): {2}\n'.format(result, row[2], row[3]) else: text += '{0:<15}: {1}\n'.format(result, row[3]) total += row[3] text += '\nTotal number of benchmarks: {0}'.format(total) q = """SELECT tool_id FROM task_results WHERE run_id = {0}""".format(self.run_id) res = self._db.query(q) if not res: err('Failed querying db for tool\'s id') tool_id = res[0][0] text += '\n\nYou can check the results here:\n' text += 'http://macdui.fi.muni.cz:3000/tools/{0}'.format(tool_id) text += '\n\nHave a nice day!\n' msg = MIMEText(text) msg['Subject'] = 'Satt results from {0}'.format(started_at) msg['From'] = from_addr msg['To'] = '*****@*****.**' s = smtplib.SMTP(server) ret = s.sendmail(from_addr, to_addrs, msg.as_string()) s.quit() for r in ret: dbg('Failed sending e-mail to {0},' 'err: {1}'.format(r[0], r[1]))
class MysqlReporter(BenchmarkReport): def __init__(self): BenchmarkReport.__init__(self) # use this to print out what is happening self._stdout = StdoutReporter() self.run_id = int(time()) self.tool_params = '{0}'.format(configs.configs['params']) # replace apostrophes in tool_params self.tool_params = self.tool_params.replace('\'', '\\\'') from database import DatabaseConnection self._db = DatabaseConnection() ver = self._db.query('SELECT VERSION()')[0][0] satt_log('Connected to database: MySQL version {0}'.format(ver)) self._rating_methods = RatingMethod(self._db.query) def progress(self, progress): # we must redirect progress to stdout self._stdout.progress(progress) def _commit(self): self._db.commit() def _updateDb(self, rb): def choose_tag(): if configs.configs.has_key('tool-tag'): return configs.configs['tool-tag'] else: return configs.configs['tool'] ver = rb.versions.strip() q = """ SELECT id FROM years WHERE year = '{0}'; """.format(configs.configs['year']) res = self._db.query(q) if not res: err('Do not have year {0}. If this is not typo, ' 'update the database and benchmarks'.format( configs.configs['year'])) year_id = res[0][0] # If tool that runs in this run is not known to database, add it q = """ SELECT id FROM tools WHERE name = '{0}' and version = '{1}' and params = '{2}' and year_id = '{3}'; """.format(configs.configs['tool'], ver, self.tool_params, year_id) res = self._db.query(q) if not res: q2 = """ INSERT INTO tools (name, year_id, version, params, tag, note) VALUES('{0}', '{1}', '{2}', '{3}', '{4}', {5}); """.format(configs.configs['tool'], year_id, ver, self.tool_params, choose_tag(), Empty2Null(configs.configs['note'])) self._db.query(q2) # get new tool_id res = self._db.query(q) assert len(res) == 1 tool_id = res[0][0] return tool_id, year_id def save_task(self, rb, cat_id): """ Save unknown task into the database """ name = get_name(rb.name) cr = self._get_correct_result(name, rb) if cr is None: msg = 'Couldn\'t infer if the result is correct or not, setting unkown' satt_log(msg) rb.output += msg rb.result = 'unknown ({0})'.format(rb.result) # create new task q = """ INSERT INTO tasks (name, category_id, correct_result, property) VALUES('{0}', '{1}', '{2}', '{3}'); """.format(name, cat_id, cr, None) self._db.query(q) q = """ SELECT id, correct_result FROM tasks WHERE name = '{0}' and category_id = '{1}'; """.format(name, cat_id) return self._db.query(q) def update_category(self, year_id, name): """ Create new category in the database """ # create the a category in the database q = """ INSERT INTO categories (year_id, name) VALUES ('{0}', '{1}'); """.format(year_id, name) self._db.query(q) # return the new result q = """ SELECT id, name FROM categories WHERE year_id = '{0}' and name = '{1}'; """.format(year_id, name) return self._db.query(q) def done(self, rb): # print it after saving if not self._stdout.done(rb): # if there is a problem, the benchmark will run again, so do not # proceed further return False tool_id, year_id = self._updateDb(rb) q = """ SELECT id, name FROM categories WHERE year_id = '{0}' and name = '{1}'; """.format(year_id, rb.category) res = self._db.query(q) if not res: if configs.configs['save-new-tasks'] == 'yes': res = self.update_category(year_id, rb.category) else: rb.dumpToFile('Do not have given category') satt_log('^^ dumped to file (unknown category)') return True assert len(res) == 1 if not len(res[0]) == 2: print(res[0]) assert len(res[0]) == 2 cat_id = res[0][0] cat_name = res[0][1] q = """ SELECT id, correct_result FROM tasks WHERE name = '{0}' and category_id = '{1}'; """.format(get_name(rb.name), cat_id) res = self._db.query(q) # we do not have such a task?? if not res: if configs.configs['save-new-tasks'] == 'yes': res = self.save_task(rb, cat_id) else: rb.dumpToFile('Do not have given task') satt_log('^^ dumped to file (unknown task)') return True assert len(res) == 1 task_id = res[0][0] correct_result = res[0][1] # replace ' by \' in output rb.output = rb.output.replace('\'', '\\\'') ic = is_correct(correct_result, rb.result) result = rb.result.lower() if rb.witness != '': wtns = rb.witness.strip() # replace ' even in witness, because it can contain # arbitrary text wtns = wtns.replace('\'', '\\\'') else: wtns = None if rb.witness_output != '': # FIXME we should limit the wintess_output size, otherwise we # get get some performance issues rb.witness_output = rb.witness_output.strip() rb.witness_output = rb.witness_output.replace('\'', '\\\'') q = """ INSERT INTO task_results (tool_id, task_id, result, witness, is_correct, points, cpu_time, memory_usage, output, witness_output, run_id) VALUES('{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', {8}, '{9}', '{10}') """.format(tool_id, task_id, result, wtns, ic, self._rating_methods.points(ic, rb.result, wtns, cat_name), None2Zero(rb.time), None2Zero(rb.memory), Empty2Null(rb.output), rb.witness_output, self.run_id) def _exception_handler(args, data): q, tool_id, task_id = data if (args[1].startswith('Duplicate entry')): if configs.configs['ignore-duplicates'] == 'yes': satt_log( 'Already has this result for this tool, ignoring.') else: err('Already has result of this benchmark for this tool.\n' 'It is only supported to have one result for each ' 'benchmark and particular tool\n' 'If want ignore this behaviour use --ignore-duplicates.\n' '(tool + version + params). You can delete the old result:\n' ' $ ./db-cli \'DELETE from task_results WHERE tool_id={0}' ' and task_id={1}\'\n' 'or you can delete all results for this tool:\n' ' $ ./db-cli \'DELETE from tools WHERE id={0}\'\n'. format(tool_id, task_id, tool_id)) else: err('Failed querying db: {0}\n\n{1}'.format(args[1], q)) self._db.query_with_exception_handler(q, _exception_handler, (q, tool_id, task_id)) self._commit() return True def sendEmail(self, server, from_addr, to_addrs): import smtplib from email.mime.text import MIMEText time_format = '%Y-%m-%d-%H-%S' raw_started_at = strptime(configs.configs['started_at'], time_format) started_at = strftime('%a %b %d %H:%M:%S %Y', raw_started_at) finished_at = strftime('%a %b %d %H:%M:%S %Y') text = """ This is automatically generated message. Do not answer. ======================================================= Satt on tool {0} started at {1}, finished {2} with parameters: {3} on benchmarks from year {4} Note: {5} Results: """.format(configs.configs['tool'], started_at, finished_at, configs.configs['params'], configs.configs['year'], configs.configs['note']) q = """ SELECT result, is_correct, witness, count(*) FROM task_results WHERE run_id = {0} GROUP BY result, is_correct, witness""".format(self.run_id) res = self._db.query(q) if not res: err('No results stored to db after this run?') total = 0 for row in res: result = row[0] if result == 'true' or result == 'false': if row[1] == 0: result += ' incorrect' else: result += ' correct' if not row[2] is None: text += '{0:<15} (witness {1}): {2}\n'.format( result, row[2], row[3]) else: text += '{0:<15}: {1}\n'.format(result, row[3]) total += row[3] text += '\nTotal number of benchmarks: {0}'.format(total) q = """SELECT tool_id FROM task_results WHERE run_id = {0}""".format(self.run_id) res = self._db.query(q) if not res: err('Failed querying db for tool\'s id') tool_id = res[0][0] text += '\n\nYou can check the results here:\n' text += 'http://macdui.fi.muni.cz:3000/tools/{0}'.format(tool_id) text += '\n\nHave a nice day!\n' msg = MIMEText(text) msg['Subject'] = 'Satt results from {0}'.format(started_at) msg['From'] = from_addr msg['To'] = '*****@*****.**' s = smtplib.SMTP(server) ret = s.sendmail(from_addr, to_addrs, msg.as_string()) s.quit() for r in ret: dbg('Failed sending e-mail to {0},' 'err: {1}'.format(r[0], r[1]))
class DatabaseProxy(object): def __init__(self, conffile = None): self._db = DatabaseConnection(conffile) # self check ver = self._db.query('SELECT VERSION()')[0][0] satt_log('Connected to database: MySQL version {0}'.format(ver)) self._rating_methods = RatingMethod(self._db.query) def connection(self): return self._db def commit(self): self._db.commit() def getYearID(self, year): q = """ SELECT id FROM years WHERE year = '{0}'; """.format(year); res = self._db.query(q) if not res: return None return res[0][0] def getToolID(self, tool, version, tool_params, year_id): q = """ SELECT id FROM tools WHERE name = '{0}' and version = '{1}' and params = '{2}' and year_id = '{3}'; """.format(tool, version, tool_params, year_id) res = self._db.query(q) if not res: return None assert len(res) == 1 return res[0][0] def getCategoryID(self, year_id, category_name): q = """ SELECT id FROM categories WHERE year_id = '{0}' and name = '{1}'; """.format(year_id, category_name) res = self._db.query(q) if not res: return None return res[0][0] def getTaskID(self, category_id, name): q = """ SELECT id FROM tasks WHERE name = '{0}' and category_id = '{1}'; """.format(get_name(name), category_id) res = self._db.query(q) if not res: return None return res[0][0] def getTaskWithCorrectResult(self, category_id, name): q = """ SELECT id, correct_result FROM tasks WHERE name = '{0}' and category_id = '{1}'; """.format(get_name(rb.name), cat_id) res = self._db.query(q) if not res: return None return (res[0][0], res[0][1]) def hasTaskResult(self, task_id, tool_id): q = """ SELECT count(*) FROM task_results WHERE task_id = '{0}' and tool_id = '{1}'; """.format(task_id, tool_id) res = self._db.query(q) if not res: return False return res[0][0] != 0
class DatabaseProxy(object): def __init__(self, conffile=None): self._db = DatabaseConnection(conffile) # self check ver = self._db.query('SELECT VERSION()')[0][0] satt_log('Connected to database: MySQL version {0}'.format(ver)) self._rating_methods = RatingMethod(self._db.query) def connection(self): return self._db def commit(self): self._db.commit() def getYearID(self, year): q = """ SELECT id FROM years WHERE year = '{0}'; """.format(year) res = self._db.query(q) if not res: return None return res[0][0] def getToolID(self, tool, version, tool_params, year_id): q = """ SELECT id FROM tools WHERE name = '{0}' and version = '{1}' and params = '{2}' and year_id = '{3}'; """.format(tool, version, tool_params, year_id) res = self._db.query(q) if not res: return None assert len(res) == 1 return res[0][0] def getCategoryID(self, year_id, category_name): q = """ SELECT id FROM categories WHERE year_id = '{0}' and name = '{1}'; """.format(year_id, category_name) res = self._db.query(q) if not res: return None return res[0][0] def getTaskID(self, category_id, name): q = """ SELECT id FROM tasks WHERE name = '{0}' and category_id = '{1}'; """.format(get_name(name), category_id) res = self._db.query(q) if not res: return None return res[0][0] def getTaskWithCorrectResult(self, category_id, name): q = """ SELECT id, correct_result FROM tasks WHERE name = '{0}' and category_id = '{1}'; """.format(get_name(rb.name), cat_id) res = self._db.query(q) if not res: return None return (res[0][0], res[0][1]) def hasTaskResult(self, task_id, tool_id): q = """ SELECT count(*) FROM task_results WHERE task_id = '{0}' and tool_id = '{1}'; """.format(task_id, tool_id) res = self._db.query(q) if not res: return False return res[0][0] != 0