mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-28 13:17:43 +08:00
144 lines
3.9 KiB
Python
144 lines
3.9 KiB
Python
import os
|
|
import sys
|
|
import logbook
|
|
|
|
from zipline.transforms import BaseTransform
|
|
from zipline.components import Feed, Merge, PassthroughTransform, \
|
|
DataSource
|
|
from zipline.protocol import CONTROL_PROTOCOL, COMPONENT_STATE
|
|
|
|
log = logbook.Logger('Topology')
|
|
|
|
class ComponentHost(object):
|
|
"""
|
|
Components that can launch multiple sub-components, synchronize
|
|
their start, and then wait for all components to be finished.
|
|
"""
|
|
|
|
def __init__(self, addresses):
|
|
self.addresses = addresses
|
|
self.running = False
|
|
|
|
# Component Registry, keyed by unique string
|
|
# ----------------------
|
|
self.components = {}
|
|
# ----------------------
|
|
# Internal Registry, keyed by guid
|
|
self._components = {}
|
|
# ----------------------
|
|
|
|
self.exception = None
|
|
|
|
self.feed = Feed()
|
|
self.merge = Merge()
|
|
self.passthrough = PassthroughTransform()
|
|
self.controller = None
|
|
|
|
self.register_components([self.feed, self.merge, self.passthrough])
|
|
|
|
def _run(self):
|
|
self.open()
|
|
|
|
def run(self, catch_exceptions=True):
|
|
"""
|
|
Run the host.
|
|
"""
|
|
log.info('===== PARENT PID: %s' % os.getppid())
|
|
log.info('===== PID: %s' % os.getpid())
|
|
|
|
self.open()
|
|
#self.shutdown()
|
|
|
|
def shutdown(self, ensure_clean=True):
|
|
raise NotImplementedError
|
|
|
|
def register_controller(self, controller):
|
|
"""
|
|
Add the given components to the registry. Establish
|
|
communication with them.
|
|
"""
|
|
if self.controller != None:
|
|
raise Exception("There can be only one!")
|
|
|
|
self.controller = controller
|
|
self.controller.zmq_flavor = self.zmq_flavor
|
|
|
|
# Propogate the controller to all the subcomponents
|
|
for component in self.components.itervalues():
|
|
component.controller = controller
|
|
|
|
def register_components(self, components):
|
|
"""
|
|
Add the given components to the registry. Establish
|
|
communication with them.
|
|
"""
|
|
assert isinstance(components, list)
|
|
for component in components:
|
|
|
|
component.addresses = self.addresses
|
|
component.controller = self.controller
|
|
|
|
# Hosts share their zmq flavor with hosted components
|
|
component.zmq_flavor = self.zmq_flavor
|
|
|
|
self._components[component.guid] = component
|
|
self.components[component.get_id] = component
|
|
|
|
if isinstance(component, DataSource):
|
|
self.feed.add_source(component.get_id)
|
|
if isinstance(component, BaseTransform):
|
|
self.merge.add_source(component.get_id)
|
|
|
|
def unregister_component(self, component_id):
|
|
del self.components[component_id]
|
|
|
|
@property
|
|
def pids(self):
|
|
return [proc.pid for proc in self.subprocesses]
|
|
|
|
def open(self):
|
|
assert hasattr(self, 'zmq_flavor'), \
|
|
""" You must specify a flavor of ZeroMQ for all Topology
|
|
subclasses. """
|
|
|
|
|
|
log.info('== Roll Call ==')
|
|
log.info('Monitor')
|
|
|
|
self.launch_controller()
|
|
|
|
for component in self.components.itervalues():
|
|
log.info(component)
|
|
|
|
log.info('== End Roll Call ==')
|
|
|
|
for component in self.components.itervalues():
|
|
self.launch_component(component)
|
|
|
|
|
|
def is_running(self):
|
|
"""
|
|
DEPRECATED, left in for compatability for now.
|
|
"""
|
|
|
|
if len(self.components) == 0:
|
|
log.info("Component register is empty.")
|
|
return False
|
|
|
|
return True
|
|
|
|
def ready(self):
|
|
return True
|
|
|
|
# ------------------
|
|
# Simulation Control
|
|
# ------------------
|
|
|
|
# Overloaded by simulator
|
|
|
|
def launch_controller(self, controller):
|
|
raise NotImplementedError
|
|
|
|
def launch_component(self, component):
|
|
raise NotImplementedError
|