Ejemplo n.º 1
0
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]))
Ejemplo n.º 2
0
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]))
Ejemplo n.º 3
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
Ejemplo n.º 4
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