Esempio n. 1
0
class WebsocketServer(PyThread):
    def __init__(self,
                 port,
                 app,
                 max_connections=10,
                 max_queued=30,
                 **ws_args):
        PyThread.__init__(self)
        self.Port = port
        self.HandlerQueue = TaskQueue(max_connections, capacity=max_queued)
        self.App = app
        self.WSArgs = ws_args

    def run(self):
        srv_sock = socket(AF_INET, SOCK_STREAM)
        srv_sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        srv_sock.bind(("", self.Port))
        srv_sock.listen(5)

        while True:
            sock, address = srv_sock.accept()
            receiver = WebsocketClientConnection(self.App, sock, address,
                                                 self.WSArgs)
            try:
                self.HandlerQueue.addTask(receiver)
            except:
                # ws response here !
                sock.close()
Esempio n. 2
0
class ReplicationManager(Primitive, Logged):
    def __init__(self, cfg):
        Primitive.__init__(self)
        self.Replicators = TaskQueue(cfg.get('max_rep', 2), stagger=0.5)
        self.DClient = DataClient((cfg["broadcast"], cfg["listen_port"]),
                                  cfg["farm_name"])

    def replicate(self, nfrep, lfn, lpath, info):
        if nfrep > 2:
            # make 2 replicators
            n1 = nfrep // 2
            n2 = nfrep - n1
            r = Replicator(lfn, lpath, info, n1, self.DClient, self)
            self.debug('replicator created: %s *%d' % (lpath, n1))
            self.Replicators.addTask(r)
            r = Replicator(lfn, lpath, info, n2, self.DClient, self)
            self.debug('replicator created: %s *%d' % (lpath, n2))
            self.Replicators.addTask(r)
        elif nfrep > 0:
            r = Replicator(lfn, lpath, info, nfrep, self.DClient, self)
            self.Replicators.addTask(r)
            self.debug('replicator created: %s *%d' % (lpath, nfrep))

    def done(self, rep):
        pass

    def retry(self, rep):
        rep.reinit()
        t = threading.Timer(0.1 + random.random(),
                            self.Replicators.addTask,
                            args=(rep, ))
        t.start()

    def statTxns(self):
        pending, active = self.Replocators.tasks()
        stats = ["RP * %s" % (x.LogPath, ) for x in active
                 ] + ["RP I %s" % (x.LogPath, ) for x in pending]

        return '\n'.join(stats) + ".\n"
Esempio n. 3
0
class QueuedApplication(Primitive, Logged):
    
    def __init__(self, config, logger=None):
        self.Instance = config["instance"]
        Primitive.__init__(self, name=f"[app {self.Instance}]")        
        Logged.__init__(self, f"[app {self.Instance}]", logger, debug=True)
        self.configure(config)

    @synchronized
    def configure(self, config=None):
        config = config or self.Config
        self.Config = config

        reload_files = config.get("touch_reload", [])
        if isinstance(reload_files, str):
            reload_files = [reload_files]

        self.ReloadFileTimestamps = {path: self.mtime(path) for path in reload_files}

        self.Prefix = config.get("prefix", "/")
        self.ReplacePrefix = config.get("replace_prefix")
        self.Timeout = config.get("timeout", 10)

        saved_path = sys.path[:]
        saved_modules = set(sys.modules.keys())
        saved_environ = os.environ.copy()
        try:
            args = None
            fname = config["file"]
            g = {}

            extra_path = config.get("python_path")
            if extra_path is not None:
                if isinstance(extra_path, str):
                    extra_path = [extra_path]
                sys.path = extra_path + sys.path

            if "env" in config:
                os.environ.update(config["env"])
                
            exec(open(fname, "r").read(), g)
            if "create" in config:
                args = config.get("args")
                app = g[config["create"]](args)
            else:
                app = g[config.get("application", "application")]
            self.AppArgs = args
            self.WSGIApp = app

            max_workers = config.get("max_workers", 5)
            queue_capacity = config.get("queue_capacity", 10)
            self.RequestQueue = TaskQueue(max_workers, capacity = queue_capacity,
                delegate=self)
            self.log("(re)configured")

        finally:
            sys.path = saved_path
            extra_modules = set(sys.modules.keys()) - set(saved_modules)
            #print("loadApp: removing modules:", sorted(list(extra_modules)))
            for m in extra_modules:
                del sys.modules[m]
            for n in set(os.environ.keys()) - set(saved_environ.keys()):
                del os.environ[n]
            os.environ.update(saved_environ)
            
    def taskFailed(self, queue, task, exc_type, exc_value, tb):
        self.log_error("request failed:", "\n".join(traceback.format_exception(exc_type, exc_value, tb)))

    def accept(self, request):
        header = request.HTTPHeader
        uri = header.URI
        self.debug("accept: uri:", uri, " prefix:", self.Prefix)
        if uri.startswith(self.Prefix):
            uri = uri[len(self.Prefix):]
            if not uri.startswith("/"):     uri = "/" + uri
            if self.ReplacePrefix:
                uri = self.ReplacePrefix + uri
            header.replaceURI(uri)
            request.AppName = self.Instance
            self.RequestQueue.addTask(RequestTask(self.WSGIApp, request, self.Logger))
            return True
        else:
            return False
            
    def mtime(self, path):
        try:    return os.path.getmtime(path)
        except: return None

    def reloadIfNeeded(self):
        for path, old_timestamp in self.ReloadFileTimestamps.items():
            mt = self.mtime(path)
            if mt is not None and mt != old_timestamp:
                ct = time.ctime(mt)
                self.log(f"file {path} was modified at {ct}")
                break
        else:
            return False
        self.configure()
Esempio n. 4
0
class Service(Primitive, Logged):
    def __init__(self, config, logger=None):
        name = config["name"]
        #print("Service(): config:", config)
        self.ServiceName = name
        Primitive.__init__(self, name=f"[service {name}]")
        Logged.__init__(self, f"[app {name}]", logger, debug=True)
        self.Config = None
        self.Initialized = self.initialize(config)

    @synchronized
    def initialize(self, config=None):
        config = config or self.Config
        self.Config = config

        reload_files = config.get("touch_reload", [])
        if isinstance(reload_files, str):
            reload_files = [reload_files]

        self.ReloadFileTimestamps = {
            path: self.mtime(path)
            for path in reload_files
        }

        self.Prefix = config.get("prefix", "/")
        self.ReplacePrefix = config.get("replace_prefix")
        self.Timeout = config.get("timeout", 10)

        saved_path = sys.path[:]
        saved_modules = set(sys.modules.keys())
        saved_environ = os.environ.copy()
        try:
            args = None
            if "file" in config:
                print(
                    '*** Use of "file" parameter is deprecated. Use "module" instead'
                )
            self.ScriptFileName = fname = config.get("module",
                                                     config.get("file"))
            g = {}

            extra_path = config.get("python_path")
            if extra_path is not None:
                if isinstance(extra_path, str):
                    extra_path = [extra_path]
                sys.path = extra_path + sys.path

            if "env" in config:
                os.environ.update(config["env"])

            try:
                exec(open(fname, "r").read(), g)
            except:
                tb = traceback.format_exc()
                self.log_error(f"Error importing module {fname}:\n{tb}")
                return False

            if "create" in config:
                # deprecated
                print(
                    '*** Use of "create" parameter is deprecated. Use "application: function()" instead'
                )
                application = config["create"] + "()"
            else:
                application = config.get("application", "application")
            if application.endswith("()"):
                args = config.get("args")
                fcn_name = application[:-2]
                fcn = g.get(fcn_name)
                if fcn is None:
                    self.log_error(
                        f"Application creation function {fcn_name} not found in module {fname}"
                    )
                    return False

                try:
                    if isinstance(args, dict):
                        app = fcn(**args)
                    elif isinstance(args, (list, tuple)):
                        app = fcn(*args)
                    elif args is None:
                        app = fcn()
                    else:
                        app = fcn(args)
                except:
                    tb = traceback.format_exc()
                    self.log_error(
                        f"Error calling the application initialization function:\n{tb}"
                    )
                    return False

                if app is None:
                    self.log_error(
                        f'Application creation function {fcn_name} returned None'
                    )
                    return False

            else:
                app = g.get(application)
                if app is None:
                    self.log_error(
                        f'Application object "{application}" not found in {fname}'
                    )
                    return False

            self.AppArgs = args
            self.WSGIApp = app

            max_workers = config.get("max_workers", 5)
            queue_capacity = config.get("queue_capacity", 10)
            self.RequestQueue = TaskQueue(max_workers,
                                          capacity=queue_capacity,
                                          delegate=self)
            self.log("initiaized")

        except:
            tb = traceback.format_exc()
            self.log_error(f"Error initializing application:\n{tb}")
            return False

        finally:
            sys.path = saved_path
            extra_modules = set(sys.modules.keys()) - set(saved_modules)
            #print("loadApp: removing modules:", sorted(list(extra_modules)))
            for m in extra_modules:
                del sys.modules[m]
            for n in set(os.environ.keys()) - set(saved_environ.keys()):
                del os.environ[n]
            os.environ.update(saved_environ)

        return True

    def taskFailed(self, queue, task, exc_type, exc_value, tb):
        self.log_error(
            "request failed:",
            "".join(traceback.format_exception(exc_type, exc_value, tb)))
        try:
            task.Request.close()
        except:
            pass

    def accept(self, request):
        #print(f"Service {self}: accept()")
        if not self.Initialized:
            return False
        header = request.HTTPHeader
        uri = header.URI
        self.debug("accept: uri:", uri, " prefix:", self.Prefix)
        #print("Sevice", self,"   accept: uri:", uri, " prefix:", self.Prefix)
        if uri.startswith(self.Prefix):
            uri = uri[len(self.Prefix):]
            if not uri.startswith("/"): uri = "/" + uri
            if self.ReplacePrefix:
                uri = self.ReplacePrefix + uri
            header.replaceURI(uri)
            request.AppName = self.ServiceName
            script_path = self.Prefix
            while script_path and script_path.endswith("/"):
                script_path = script_path[:-1]
            request.Environ["SCRIPT_NAME"] = script_path
            request.Environ["SCRIPT_FILENAME"] = self.ScriptFileName
            self.RequestQueue.addTask(
                RequestTask(self.WSGIApp, request, self.Logger))
            #print("Service", self, "   accepted")
            return True
        else:
            #print("Service", self, "   rejected")
            return False

    def close(self):
        self.RequestQueue.hold()

    def join(self):
        self.RequestQueue.join()

    def mtime(self, path):
        try:
            return os.path.getmtime(path)
        except:
            return None

    def reloadIfNeeded(self):
        for path, old_timestamp in self.ReloadFileTimestamps.items():
            mt = self.mtime(path)
            if mt is not None and mt != old_timestamp:
                ct = time.ctime(mt)
                self.log(f"file {path} was modified at {ct}")
                break
        else:
            return False
        self.Initialized = self.initialize()
 def purgeEmptyDirs(self):
     if self.EmptyDirs:
         queue = TaskQueue(self.MaxScanners)
         for path in self.EmptyDirs:
             queue.addTask(RMDir(self.Server, path))
         queue.waitUntilEmpty()
class ScannerMaster(PyThread):
    
    MAX_RECURSION_FAILED_COUNT = 5
    REPORT_INTERVAL = 10.0
    
    def __init__(self, server, root, recursive_threshold, max_scanners, timeout, quiet, display_progress, max_files = None,
                include_sizes=True, ignore_subdirs=[]):
        PyThread.__init__(self)
        self.RecursiveThreshold = recursive_threshold
        self.Server = server
        self.Root = canonic_path(root)
        self.MaxScanners = max_scanners
        self.Results = DEQueue()
        self.ScannerQueue = TaskQueue(max_scanners)
        self.Timeout = timeout
        self.Done = False
        self.Error = None
        self.Failed = False
        self.RootFailed = False
        self.Directories = set()
        self.RecursiveFailed = {}       # parent path -> count
        self.Errors = {}                # location -> count
        self.GaveUp = {}
        self.LastReport = time.time()
        self.EmptyDirs = set()
        self.NScanned = 0
        self.NToScan = 1 
        self.Quiet = quiet
        self.DisplayProgress = display_progress and Use_tqdm and not quiet
        if self.DisplayProgress:
            self.TQ = tqdm.tqdm(total=self.NToScan, unit="dir")
            self.LastV = 0
        self.NFiles = self.NDirectories = 0
        self.MaxFiles = max_files       # will stop after number of files found exceeds this number. Used for debugging
        self.IgnoreSubdirs = ignore_subdirs
        self.IgnoredFiles = self.IgnoredDirs = 0
        self.IncludeSizes = include_sizes
        self.TotalSize = 0.0 if include_sizes else None                  # Megabytes

    def run(self):
        #
        # scan Root non-recursovely first, if failed, return immediarely
        #
        #server, location, recursive, timeout
        scanner_task = Scanner(self, self.Server, self.Root, self.RecursiveThreshold == 0, self.Timeout, include_sizes=self.IncludeSizes)
        self.ScannerQueue.addTask(scanner_task)
        
        self.ScannerQueue.waitUntilEmpty()
        self.Results.close()
        self.ScannerQueue.Delegate = None       # detach for garbage collection
        self.ScannerQueue = None
        
    def dir_ignored(self, path):
        # path is expected to be canonic here
        relpath = relative_path(self.Root, path)
        ignore =  any((relpath == subdir or relpath.startswith(subdir+"/")) for subdir in self.IgnoreSubdirs)
        return ignore

    def file_ignored(self, path):
        # path is expected to be canonic here
        relpath = relative_path(self.Root, path)
        return any(relpath.startswith(subdir+"/") for subdir in self.IgnoreSubdirs)

    @synchronized
    def addFiles(self, files):
        if not self.Failed:
            self.Results.append(('f', files))
            self.NFiles += len(files)

    def parent(self, path):
        parts = path.rsplit("/", 1)
        if len(parts) < 2:
            return "/"
        else:
            return parts[0]
            
    def addDirectory(self, path, scan, allow_recursive):
        if scan and not self.Failed:
                assert path.startswith(self.Root)
                relpath = path[len(self.Root):]
                while relpath and relpath[0] == '/':
                    relpath = relpath[1:]
                while relpath and relpath[-1] == '/':
                    relpath = relpath[:-1]
                reldepth = 0 if not relpath else len(relpath.split('/'))
                
                parent = self.parent(path)

                allow_recursive = allow_recursive and (self.RecursiveThreshold is not None 
                    and reldepth >= self.RecursiveThreshold 
                )

                if self.MaxFiles is None or self.NFiles < self.MaxFiles:
                    self.ScannerQueue.addTask(
                        Scanner(self, self.Server, path, allow_recursive, self.Timeout, include_sizes=self.IncludeSizes)
                    )
                    self.NToScan += 1

    def addDirectories(self, dirs, scan=True, allow_recursive=True):
        if not self.Failed:
            self.Results.append(('d', dirs))
            self.NDirectories += len(dirs)
            for d in dirs:
                d = canonic_path(d)
                if self.dir_ignored(d):
                    if scan:
                        print(d, " - ignored")
                        self.IgnoredDirs += 1
                else:
                    self.addDirectory(d, scan, allow_recursive)
            self.show_progress()
            self.report()

    @synchronized
    def report(self):
        if time.time() > self.LastReport + self.REPORT_INTERVAL:
            waiting, active = self.ScannerQueue.tasks()
            #sys.stderr.write("--- Locations to scan: %d\n" % (len(active)+len(waiting),))
            self.LastReport = time.time()

    @synchronized
    def scanner_failed(self, scanner, error):
        path = scanner.Location
        with self:
            # update error counts
            if scanner.WasRecursive:
                parent = self.parent(path)
                self.RecursiveFailed[parent] = self.RecursiveFailed.get(parent, 0) + 1
            else:
                self.Errors[path] = self.Errors.get(path, 0) + 1
                
        retry = (scanner.RecAttempts > 0) or (scanner.FlatAttempts > 0)
        if retry:
            print("resubmitted:", scanner.Location, scanner.RecAttempts, scanner.FlatAttempts)
            self.ScannerQueue.addTask(scanner)
        else:
            print("Gave up:", scanner.Location)
            self.GaveUp[scanner.Location] = error
            self.NScanned += 1  
            #sys.stderr.write("Gave up on: %s\n" % (path,))
            self.show_progress()            #"Error scanning %s: %s -- retrying" % (scanner.Location, error))
        
    @synchronized
    def scanner_succeeded(self, location, was_recursive, files, dirs):
        with self:
            if len(files) == 0 and (was_recursive or len(dirs) == 0):
                self.EmptyDirs.add(location)
            else:
                if location in self.EmptyDirs:
                    self.EmptyDirs.remove(location)
            if was_recursive:
                parent = self.parent(location)
                nfailed = self.RecursiveFailed.get(parent, 0)
                self.RecursiveFailed[parent] = nfailed - 1      
        self.NScanned += 1
        if files:
            paths, sizes = zip(*files)
            self.addFiles(paths)
            #for path, size in files:
            #    print(f"path: {path}, size:{size}")
            #print("total size:", sum(sizes), location)
            if self.IncludeSizes:
                self.TotalSize += sum(sizes)
        if dirs:
            paths, sizes = zip(*dirs)
            scan = not was_recursive
            allow_recursive = scan and len(dirs) > 1
            self.addDirectories(paths, scan, allow_recursive)
            #if self.IncludeSizes:
            #    self.TotalSize += sum(sizes)
        self.show_progress()

    def files(self):
        yield from self.paths('f')
                        
    def paths(self, type=None):
        for t, lst in self.Results:
            if lst and (type is None or type == t):
                for path in lst:
                    path = canonic_path(path)
                    if self.file_ignored(path):
                        self.IgnoredFiles += 1
                    else:
                        if type is None:
                            yield t, path
                        else:
                            yield path
                        
    @synchronized
    def show_progress(self, message=None):
        if self.DisplayProgress:
            self.TQ.total = self.NToScan
            delta = max(0, self.NScanned - self.LastV)
            self.TQ.update(delta)
            self.LastV = self.NScanned
            enf = 0
            if self.NScanned > 0:
                enf = int(self.NFiles * self.NToScan/self.NScanned)
            self.TQ.set_postfix(f=self.NFiles, ed=len(self.EmptyDirs), d=self.NDirectories, enf=enf)
            if message:
                self.TQ.write(message)   
                
    @synchronized
    def message(self, message):
        if not self.Quiet:
                if self.DisplayProgress:
                    self.TQ.write(message)
                else:
                    print(message)
                    sys.stdout.flush()

    def close_progress(self):
        if self.DisplayProgress:
            self.TQ.close()
                
    def purgeEmptyDirs(self):
        if self.EmptyDirs:
            queue = TaskQueue(self.MaxScanners)
            for path in self.EmptyDirs:
                queue.addTask(RMDir(self.Server, path))
            queue.waitUntilEmpty()
Esempio n. 7
0
            print(f"No flights for {airport} (lo:[{lomin}:{lomax}], la:[{lamin}:{lamax})]")
            return []
    
        timestamp = data["time"]
    
        data = [
            {"icao":d[ICAO24].strip(), "callsign":d[CALL].strip(), "country":d[COUNTRY]}
            for d in states       
        ]
    
        self.DB.add(timestamp, airport, data)
            
    
if __name__ == "__main__":
    tstart = time.time()
    window = 20       # km
    db = Database("flights.sqlite")
    db.start()
    scanner_queue = TaskQueue(10, stagger=0.5)
    for airport in Airports.keys():
        scanner_queue.addTask(ScanTask(db, airport))
    scanner_queue.waitUntilEmpty()
    db.stop()
    db.join()
    tend = time.time()
    print("runtime:", tend-tstart)
    
        
        

Esempio n. 8
0
class TCPServerThread(PyThread):
    def __init__(self,
                 port,
                 ip='',
                 max_clients=None,
                 queue_capacity=None,
                 stagger=None,
                 enabled=True):
        PyThread.__init__(self)
        self.Sock = None
        self.Clients = TaskQueue(max_clients,
                                 capacity=queue_capacity,
                                 stagger=stagger)
        self.Port = port
        self.IP = ip
        self.Enabled = enabled
        self.Shutdown = False
        self.LastIdle = 0.0

    def run(self):
        self.Sock = socket(AF_INET, SOCK_STREAM)
        self.Sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.Sock.bind((self.IP, self.Port))
        if self.Enabled:
            self.enable()
        while not self.Shutdown:
            fd = self.Sock.fileno()
            #print("TCPServerThread: select...")
            r, w, e = select.select([fd], [fd], [fd], 1.0)
            #print("TCPServerThread: r,w,e:", r, w, e)
            if fd in r or fd in e or fd in w:
                csock, caddr = self.Sock.accept()
                task = self.createClientInterface(csock, caddr)
                #print ("TCPServerThread: client task created:", task)
                if task is not None:
                    self.Clients.addTask(task)
            else:
                t = time.time()
                self.idle(t, self.LastIdle)
                self.LastIdle = t
        self.Sock.close()

    @synchronized
    def enable(self, backlog=5):
        if self.Sock is not None:
            self.Sock.listen(backlog)
        self.Clients.release()
        self.Enabled = True

    @synchronized
    def disable(self):
        self.Sock.listen(0)
        self.Clients.hold()
        self.Enabled = False

    def shutdown(self):
        self.Shutdown = True

    def waitForClients(self):
        self.Clients.waitUntilEmpty()

    # overridables
    def idle(self, now, last_idle):
        pass

    def createClientInterface(self, sock, addr):
        return None
        pass  # virtual
Esempio n. 9
0
               -N <n> - run all <n> tasks at once
            """

MaxPipes = 30
NRUN = 1000
stagger = 0.1

output = None  #open("/dev/null", "w")

opts, args = getopt.getopt(sys.argv[1:], "m:n:s:N:")
for opt, val in opts:
    if opt == '-m': MaxPipes = int(val)
    if opt == '-n': NRUN = int(val)
    if opt == '-s': stagger = float(val)
    if opt == '-N':
        NRUN = int(val)
        MaxPipes = NRUN

if not args:
    print Usage
    sys.exit(1)

command = args

tq = TaskQueue(MaxPipes)
for i in xrange(NRUN):
    tq.addTask(SubprocessTask(i, NRUN, command))
    time.sleep(stagger)

tq.waitUntilEmpty()
Esempio n. 10
0
from pythreader import TaskQueue, Task
from threading import Timer


class MyTask(Task):
    def __init__(self, tid):
        Task.__init__(self)
        self.Id = tid

    def run(self):
        print(time.time(), self.Id, "started as instance")
        time.sleep(random.random() * 3)
        print(self.Id, "ended")

    def failed(self, e):
        print(e)


q = TaskQueue(5, stagger=1.0, tasks=[MyTask(x) for x in range(10)])
q << MyTask(30) << MyTask(31)
MyTask(32) >> q
q += MyTask(33)

Timer(3.5, lambda q: q.addTask(MyTask(40)), (q, )).start()
Timer(3.51, lambda q: q.addTask(MyTask(41)), (q, )).start()
Timer(3.52, lambda q: q.addTask(MyTask(42)), (q, )).start()
Timer(3.53, lambda q: q.addTask(MyTask(43)), (q, )).start()
Timer(3.9, lambda q: q.addTask(MyTask(44)), (q, )).start()

q.waitUntilEmpty()