Пример #1
0
 def wrapper(send_obj, message):
     """
     :param send_obj:
     :param message:
     :return:
     """
     # 避免循环import和局部import
     if message.__class__.__name__ != "OperationMessage":
         raise exception.ETypeMismatch("only OperationMessage can be send()")
     if not message.operation_id:
         raise exception.EMissingParam("OperationMessage need operation_id")
     if message.name == "SENSED_MESSAGE" or \
        message.name == "DECIDED_MESSAGE" or \
        message.name == "COMPLETE_MESSAGE":
         guardian_context = GuardianContext.get_context()
         try:
             operation = guardian_context.get_operation(
                 message.operation_id)
         except KeyError:
             # 此处使用深拷贝,防止后续处理中造成环形引用
             operation = Operation(
                 message.operation_id, copy.deepcopy(message.params))
             guardian_context.create_operation(
                 message.operation_id, operation)
         operation.append_period(message.name)
     ret = func(send_obj, message)
     return ret
Пример #2
0
        def wrapper(send_obj, message):
            """

            :param send_obj:
            :param message:
            :return:
            """
            # 避免循环import和局部import
            if message.__class__.__name__ != "OperationMessage":
                raise exception.ETypeMismatch("only OperationMessage can be send()")
            if not message.operation_id:
                raise exception.EMissingParam("OperationMessage need operation_id")
            if message.name == "STATE_COMPLETE_MESSAGE" or \
                    message.name == "PERSIST_SESSION_MESSAGE":
                guardian_context = GuardianContext.get_context()
                operation = guardian_context.get_operation(
                    message.operation_id)
                finished_node = message.params["finished_node"]
                current_node = message.params["current_node"]
                timestamp = message.params["timestamp"]
                session = message.params["session"]
                if current_node:
                    operation.add_action(current_node)
                if finished_node:
                    operation.update_action(
                        finished_node, "FINISHED", timestamp)
                if session:
                    operation.update_session(session)

                # 状态机节点持久化
                guardian_context.update_operation(operation.operation_id, operation)
            else:
                pass
            ret = func(send_obj, message)
            return ret
Пример #3
0
def patch_logging():
    """
    打logging补丁

    :return:
    """
    _monkeypatch_os_fork_functions()
    logging = sys.modules.get('logging')
    if logging and getattr(logging, 'fixed_for_atfork', None):
        return
    if logging:
        warnings.warn('logging module already imported before patch')
    import logging
    if logging.getLogger().handlers:
        raise exception.ETypeMismatch('logging handlers registered before')

    logging._acquireLock()
    try:

        def fork_safe_createLock(self):
            """
            线程安全的锁
            :param self:
            :return:
            """
            self._orig_createLock()
            _atfork(self.lock.acquire, self.lock.release, self.lock.release)

        logging.Handler._orig_createLock = logging.Handler.createLock
        logging.Handler.createLock = fork_safe_createLock
        _atfork(logging._acquireLock, logging._releaseLock,
                logging._releaseLock)
        logging.fixed_for_atfork = True
    finally:
        logging._releaseLock()
Пример #4
0
    def __init__(self, job_adapter, stage_builder=None, process_count=1):
        """
        初始化方法

        :param JobAdapter job_adapter: 任务处理器,分级操作解析器与任务处理器绑定,完成分级任务的具体执行操作
        :param StageBuilder stage_builder: 分级操作构建器
        :param int process_count: 最大进程数
        """
        if not issubclass(job_adapter, stage.JobAdapter):
            raise exception.ETypeMismatch(
                "job_adapter is not subclass of "
                "JobAdapter, type:{}", format(type(job_adapter)))
        if stage_builder is not None and not isinstance(
                stage_builder, stage.StageBuilder):
            raise exception.ETypeMismatch("stage_builder is not instance of "
                                          "StageBuilder,type:{}".format(
                                              type(stage_builder)))
        super(StageStateMachineExecutor, self).__init__(None, process_count)
        self._stage_builder = stage_builder or stage.StageBuilder()
        self._bind_job_type(job_adapter)
Пример #5
0
    def validate_listeners(self):
        """
        验证消息处理器是否符合要求。通常,我们认为一个Guardian包含的消息处理器数量应该为:
        至少一个感知器、一个决策器、一个执行器。

        :return: 无返回
        :rtype: None
        :raises ETypeMismatch: 消息处理器验证失败
        """
        sensor_count, decision_count, executor_count = 0, 0, 0
        for listener in self._listener_list:
            if isinstance(listener, BaseSensor):
                sensor_count += 1
            elif isinstance(listener, BaseDecisionMaker):
                decision_count += 1
            elif isinstance(listener, BaseExecutor):
                executor_count += 1
            else:
                raise exception.ETypeMismatch("listener type is not match")
        if sensor_count < 1 or decision_count != 1 or executor_count != 1:
            raise exception.ETypeMismatch("listener must be: one decision, "
                                          "one executor, at least one sensor")
Пример #6
0
 def _list_and_watch():
     node_list = []
     for node_name in os.listdir(path):
         if node_name == ".data" or node_name == ".sequence":
             continue
         if not include_data:
             node_list.append(node_name)
         else:
             data = self.get_data("/".join((path[len(self._base):], node_name)))
             node_list.append((node_name, data))
     if watcher:
         if not callable(watcher):
             raise exception.ETypeMismatch("watcher must callable")
         with self._lock:
             self._ob_paths[path] = watcher
     return node_list
Пример #7
0
    def add_node(self, node):
        """
        增加节点

        :param Node  node: 节点
        :return: None
        :raises ETypeMismatch: 节点类型错误
        :raises EInvalidOperation: 操作不合法
        """
        if not isinstance(node, Node):
            raise exception.ETypeMismatch("param node type must be Node")
        elif node in self._nodes:
            raise exception.EInvalidOperation(
                "node {} already added".format(node.name))
        else:
            self._nodes.append(node)
            self._nodes_process[node.name] = False
Пример #8
0
    def __init__(self, process_count=1):
        """
        初始化方法

        :param int process_count: 进程数
        :return: 无返回
        :rtype: None
        :raises ETypeMismatch: 参数类型不匹配
        """
        if not isinstance(process_count, int) or process_count < 1 \
                or process_count > 1000:
            raise exception.ETypeMismatch(
                "param process_count must be 1-1000 integer")
        manager = multiprocessing.Manager()
        self._result_queue = manager.Queue()
        self._concerned_message_list = ["IDLE_MESSAGE", "DECIDED_MESSAGE"]
        self._process_count = process_count
        self._process_pool = None
Пример #9
0
    def on_message(self, message):
        """
        触发执行并返回结果,``on_execute_message`` 可能为同步或异步操作,
        若为异步操作,则应返回None

        :param Message message: 消息对象
        :return: 无返回
        :rtype: None
        :raises ETypeMismatch: 返回值类型不匹配
        :raises EMissingParam: 返回值缺字段
        """
        message = self.on_execute_message(message)
        if not message:
            return
        elif not isinstance(message, Message):
            raise exception.ETypeMismatch()
        else:
            log.i("execute message return:{}".format(message))
            self.send(message)
Пример #10
0
def make_driver(driver_cls):
    """

    :param driver_cls:
    :return:
    :rtype: persistence.BasePersistence
    """
    if driver_cls == persistence.FilePersistence:
        driver_conf = {"STATE_SERVICE_HOSTS": "/tmp/persist"}
    elif driver_cls == persistence.RedisPersistence:
        driver_conf = {"STATE_SERVICE_HOSTS": "redis://127.0.0.1:6379/0"}
    elif driver_cls == persistence.ZkPersistence:
        driver_conf = {"STATE_SERVICE_HOSTS": "redis://127.0.0.1:6379/0"}
    else:
        raise exception.ETypeMismatch("Unknown persistence class")

    cfg = {"LOG_CONF_DIR": "./", "LOG_ROOT": "./log"}
    cfg.update(driver_conf)
    config.GuardianConfig.set(cfg)
    dv = driver_cls()
    return dv
Пример #11
0
 def get_children(self, path, watcher=None, include_data=False):
     """
     获取所有子节点
     :param str path: 待获取子节点的路径
     :param watcher: 状态监听函数。函数形参为(event),event是一个对象,包括三个成员属性:path(发生状态变化的路径)、state(server链接状态)、type(事件类型,包括CREATED|DELETED|CHANGED|CHILD|NONE)
     :param bool include_data: 是否同时返回数据
     :return: 子节点名字列表
     :rtype: str
     :raises: exception.EPNoNodeError 节点不存在
     :raises: exception.EPIOError IO异常
     """
     chd = self._valid_chd(path, include_data)
     if not include_data:
         node_list = chd.keys()
     else:
         node_list = chd.items()
     if watcher:
         if not callable(watcher):
             raise exception.ETypeMismatch("watcher must callable")
         self._new_ob(path, watcher)
     return node_list
Пример #12
0
    def decision_logic(self, message):
        """
        具体决策逻辑

        :param Message message: 消息对象
        :return: 决策完成的消息
        :rtype: Message
        :raises ETypeMismatch: 事件参数不匹配异常
        """
        log.i("begin decision logic, message:{}".format(message.name))
        operation_id = message.operation_id
        params = message.params
        if self._from_key in params \
                and params[self._from_key] in self._mapping:
            params_cp = copy.deepcopy(params)
            params_cp[self._to_key] = self._mapping[params_cp[self._from_key]]
            decided_message = framework.OperationMessage(
                "DECIDED_MESSAGE", operation_id, params_cp)
            return decided_message
        else:
            raise exception.ETypeMismatch(
                "{} not in params or params[{}] not in "
                "mapping".format(self._from_key, self._from_key))
Пример #13
0
        def wrapper(send_obj, message):
            """

            :param send_obj:
            :param message:
            :return:
            """
            # 避免循环import和局部import
            if message.__class__.__name__ != "OperationMessage":
                raise exception.ETypeMismatch(
                    "only OperationMessage can be send()")
            if not message.operation_id:
                raise exception.EMissingParam(
                    "OperationMessage need operation_id")
            if message.name == "COMPLETE_MESSAGE":
                guardian_context = GuardianContext.get_context()
                operation = guardian_context.get_operation(
                    message.operation_id)
                operation.end_operation()
                guardian_context.delete_operation(message.operation_id)
            else:
                pass
            ret = func(send_obj, message)
            return ret