示例#1
0
class RunController(threading.Thread):
    
    def __init__(self, log_level = logging.INFO, log_name = "MetLab"):
        super(RunController, self).__init__()
        self.log_name = log_name
        self.log = logging.getLogger( log_name )
        self.log.setLevel( log_level )
        self._stop = threading.Event()
        self.current = None
        self.state = 'idle'
        self.run_queue = {}
        self.retval = {}
        self.process_counter = 0
        self.wd = None
        self._init_db()
    
    def _init_db(self):
        for table in DATABASE_SCHEMA:
            self._query( table )
    
    def _query(self, query, *args):
        con = None
        data = None
        
        try:
            con = sqlite3.connect( DATABASE )
            cur = con.cursor()
            cur.execute(query, tuple(args))
            data = cur.fetchall()
            if not data:
                con.commit()
        except sqlite3.Error as e:
            self.log.error("Database error: %s" % e)
        except Exception as e:
            self.log.error("Exception in _query: %s" % e)
        finally:
            if con:
                con.close()
        return data
    
    def get_paths(self):
        return self._query("SELECT `name`,`path` FROM paths")
    
    def get_retval(self, pid):
        if int(pid) in self.retval:
            return self.retval[int(pid)]
        return None
    
    def queue(self, cmd):
        pid = self.process_counter
        if cmd[0][0] == '.':
            cmd[0] = os.path.abspath(cmd[0])
        self.run_queue[pid] = cmd
        self.log.info("adding step: %s" % cmd)
        if hasattr(self, "project_id"):
            self._query("INSERT INTO steps(project_id, command) VALUES (?, ?)", str(self.project_id), " ".join(cmd))
        self.process_counter += 1
        return pid
    
    def clear(self):
        self.run_queue = {}
    
    def run(self, wd = None):
        self.log.info("Starting RunController")
        try:
            while True:
                time.sleep(0.2)
                if self._stop.isSet():
                    break
                if self.current and self.current.status == 'completed':
                    if self.current.retval:
                        self.retval[self.current.pid] = self.current.retval
                        self.log.info("Retval: %s" % self.current.retval)
                    self.current_process = None
                    self.current.join()
                    self.current = None
                if self.current and self.current.status in ['failed', 'aborted']:
                    self.log.error("%s %s" % (self.current.name, self.current.status))
                    self.current_process = None
                    self.current.join()
                    self.current = None
                    self.run_queue.clear()
                if self.run_queue and not self.current:
                    pid = sorted(self.run_queue.keys())[0]
                    cmd = self.run_queue[pid]
                    if cmd[0] == 'mkdir':
                        try:
                            os.stat(cmd[1])
                        except:
                            os.makedirs(cmd[1])
                    elif cmd[0] == 'cd':
                        os.chdir(cmd[1])
                    else:
                        cwd = os.getcwd()
                        os.chdir(self.wd)
                        self.current = External(cmd[0], cmd[1:], pid = pid, log_name = self.log_name, wd=self.wd)
                        self.current.start()
                        while not self.current.started:
                            time.sleep(0.1)
                        os.chdir(cwd)
                    del self.run_queue[pid]
                    self.state = 'running'
                if not self.run_queue and not self.current and self.state == 'running':
                    self.state = 'finished'
            if self.current:
                self.current.stop()
                self.current.join()
        except Exception as e:
            print "RunController: %s" % e
        self.log.info("RunController finishing")
    
    def set_wd(self, dir_name):
        self.log.info("Setting new WD to %s" % dir_name)
        if dir_name[0] == ".":
            self.wd = "%s%s" % (os.getcwd(), dir_name[1:])
        elif dir_name[0] != "/":
            self.wd = "%s/%s" % (os.getcwd(), dir_name)
        else:
            self.wd = dir_name
    
    def stop(self):
        self._stop.set()
    
    def stop_current(self):
        if self.current:
            self.current.stop()
    
    def start_project(self, name):
        self.queue(["mkdir", name])
        self._query("INSERT INTO projects (name, directory, started) VALUES ('%s', '%s', %i)" % (name, self.wd, time.time()))
        self.project_id = self._query("SELECT id FROM projects ORDER BY id DESC LIMIT 1")[0][0]
        self.log.info("Settings project_id = %i" % self.project_id)
示例#2
0
class RunController(threading.Thread):
    def __init__(self, log_level=logging.INFO, log_name="MetLab"):
        super(RunController, self).__init__()
        self.log_name = log_name
        self.log = logging.getLogger(log_name)
        self.log.setLevel(log_level)
        self._stop = threading.Event()
        self.current = None
        self.state = 'idle'
        self.run_queue = {}
        self.retval = {}
        self.process_counter = 0
        self.wd = None
        self._init_db()

    def _init_db(self):
        for table in DATABASE_SCHEMA:
            self._query(table)

    def _query(self, query, *args):
        con = None
        data = None

        try:
            con = sqlite3.connect(DATABASE)
            cur = con.cursor()
            cur.execute(query, tuple(args))
            data = cur.fetchall()
            if not data:
                con.commit()
        except sqlite3.Error as e:
            self.log.error("Database error: %s" % e)
        except Exception as e:
            self.log.error("Exception in _query: %s" % e)
        finally:
            if con:
                con.close()
        return data

    def get_paths(self):
        return self._query("SELECT `name`,`path` FROM paths")

    def get_retval(self, pid):
        if int(pid) in self.retval:
            return self.retval[int(pid)]
        return None

    def queue(self, cmd):
        pid = self.process_counter
        if cmd[0][0] == '.':
            cmd[0] = os.path.abspath(cmd[0])
        self.run_queue[pid] = cmd
        self.log.info("adding step: %s" % cmd)
        if hasattr(self, "project_id"):
            self._query("INSERT INTO steps(project_id, command) VALUES (?, ?)",
                        str(self.project_id), " ".join(cmd))
        self.process_counter += 1
        return pid

    def clear(self):
        self.run_queue = {}

    def run(self, wd=None):
        self.log.info("Starting RunController")
        try:
            while True:
                time.sleep(0.2)
                if self._stop.isSet():
                    break
                if self.current and self.current.status == 'completed':
                    if self.current.retval:
                        self.retval[self.current.pid] = self.current.retval
                        self.log.info("Retval: %s" % self.current.retval)
                    self.current_process = None
                    self.current.join()
                    self.current = None
                if self.current and self.current.status == 'aborted':
                    self.log.warning("%s aborted without finishing" %
                                     self.current.name)
                if self.run_queue and not self.current:
                    pid = sorted(self.run_queue.keys())[0]
                    cmd = self.run_queue[pid]
                    if cmd[0] == 'mkdir':
                        try:
                            os.stat(cmd[1])
                        except:
                            os.makedirs(cmd[1])
                    elif cmd[0] == 'cd':
                        os.chdir(cmd[1])
                    else:
                        self.current = External(cmd[0],
                                                cmd[1:],
                                                pid=pid,
                                                log_name=self.log_name)
                        cwd = os.getcwd()
                        if self.wd:
                            os.chdir(self.wd)
                        self.current.start()
                        while not self.current.started:
                            time.sleep(0.1)
                        os.chdir(cwd)
                    del self.run_queue[pid]
                    self.state = 'running'
                if not self.run_queue and not self.current and self.state == 'running':
                    self.state = 'finished'
            if self.current:
                self.current.stop()
                self.current.join()
        except Exception as e:
            print "RunController: %s" % e
        self.log.info("RunController finishing")

    def set_wd(self, dir_name):
        if dir_name[0] == ".":
            self.wd = "%s%s" % (os.getcwd(), dir_name[1:])
        elif dir_name[0] != "/":
            self.wd = "%s/%s" % (os.getcwd(), dir_name)
        else:
            self.wd = dir_name

    def stop(self):
        self._stop.set()

    def stop_current(self):
        if self.current:
            self.current.stop()

    def start_project(self, name):
        self.queue(["mkdir", name])
        self._query(
            "INSERT INTO projects (name, directory, started) VALUES ('%s', '%s', %i)"
            % (name, self.wd, time.time()))
        self.project_id = self._query(
            "SELECT id FROM projects ORDER BY id DESC LIMIT 1")[0][0]
        self.log.info("Settings project_id = %i" % self.project_id)