Beispiel #1
0
    def work_repack(self, work, shared_state, ctx=None, **repack_kwargs):
        runner = ctx['runner']
        current_walk = encode.decode(work)

        walk_id, branch_id, current_walk = encode.decode(work)
        call = runner.prep_work_call((walk_id, branch_id, current_walk,
                                      repack_kwargs.get('serial_action',
                                                        None)))
        return call
Beispiel #2
0
def load_from_master(log_file, walk_id):
    """
    Load a ``Walk`` from a master log file. A master log file provides paths to
    trace files which were produced by ``Walk`` running services. This presumes
    the trace files are available locally, so if they were produced on a remote
    node, you'll need to make them available by whatever method you prefer.

    :param str log_file: a path to the master log file
    :param int walk_id: a ``walk_id`` which appears in the trace file
    """
    with open(log_file, 'r') as f:
        # Burn the first line, which identifies the file as a master log
        f.readline()
        for line in f:
            decoded = encode.decode(line)

            logs = decoded['logs']
            trace_file = logs[1]
            if trace_file:
                try:
                    return load_from_trace(trace_file, walk_id)
                except (ValueError, OSError):
                    pass

        raise ValueError("Cannot find walk with id %d", walk_id)
Beispiel #3
0
def load_from_trace(trace_file, walk_id):
    """
    Load a ``Walk`` from a trace file.

    :param str trace_file: a path to the trace file
    :param int walk_id: a ``walk_id`` which appears in the trace file
    """
    found = False
    walk_out = walk.Walk()
    with open(trace_file, 'r') as f:
        for line in f:
            decoded = encode.decode(line)
            walk_id = decoded['walk_id']
            if walk_id != walk_id:
                continue

            found = True
            serial_action = decoded.get('serial_action', None)
            walk_segment = decoded['walk']

            if serial_action is not None:
                walk_out.append(serial_action)

            walk_out += walk_segment

    if found:
        return walk_out
    raise ValueError("Cannot find walk with id %d" % walk_id)
Beispiel #4
0
    def prep_work_call(self, work):
        walk_id, branch_id, walk_to_run, serial_action = work

        if serial_action is not None:
            serial_action = encode.decode(serial_action)

        def run(state):
            try:
                self.run_walk(walk_id,
                              branch_id,
                              walk_to_run,
                              state,
                              serial_action=serial_action)
            except CancelWalk:
                self.count_cancel()
            except Exception as e:
                self.count_error()
                self.stats['failed_walk_ids'].add(walk_id)
                try:
                    self._state_supplement[walk_id]['cancel'] = True
                except KeyError:
                    self._state_supplement[walk_id] = {'cancel': True}
                central_logger.log_remote_error(e)
                raise

        return run
Beispiel #5
0
def _load_walk(log_file, walk_id):
    with open(log_file, 'r') as f:
        first_line = f.readline()
        try:
            first_line = encode.decode(first_line)
        except ValueError:
            raise ValueError("I couldn't interpret this as a log file: %s" %
                             log_file)

    if 'id' in first_line:
        return load_from_master(log_file, walk_id)
    return load_from_trace(log_file, walk_id)
Beispiel #6
0
    def gather_state(self, connection, worker_id, full=False):
        """
        Gather ``state`` from a remote service for a given worker. A running
        :class:`Walk` is free to mutate its ``state``, and sometimes that is
        what really constitutes the "response" or "output" of a quantum of
        work.

        :param tuple connection: str hostname/ip of the remote service, int
                                 port number
        :param int worker_id: id of remote worker, as returned when starting
                              the work (see :func:`scatter_work`).
        """
        if full:
            state = rpyc.utils.classic.obtain(
                self.clients[connection].gather_full_state(worker_id))
        else:
            state = rpyc.utils.classic.obtain(
                self.clients[connection].gather_state(worker_id))
        return encode.decode(state)
Beispiel #7
0
    def work_repack(self, work, shared_state, ctx=None, **repack_kwargs):
        """
        This is called back to repackage each work item sent to the service.
        The call is an opportunity to e.g. do some deserialization, wrap the
        ``Walk`` in a ``WalkRunner``, or anything else the user needs to prep
        the work for execution.

        :param object work: the work to execute; typically this will be e.g. a
                            JSONified ``Walk``.
        :param object shared_state: a ``state`` copied in for executing the
                                    ``Walk``
        :param object ctx: the object returned by repack_ctx before
        """
        runner = ctx['runner']
        current_walk = encode.decode(work)

        # walk_state is a single copy of shared_state. The Runner will store a
        # copy for retrieval later.
        walk_state = copy.copy(shared_state)

        walk_id = self.get_walk_id()
        call = runner.prep_work_call(current_walk, walk_state)
        return call
Beispiel #8
0
                        type=str,
                        help="Qualname for function used for replay; see %s" %
                        DEFAULT_REPLAY_FUNC_NAME,
                        default=DEFAULT_REPLAY_FUNC_NAME)
    parser.add_argument('--state',
                        type=str,
                        help="state provided as a "
                        "JSON string, decodable by %s" %
                        utils.get_class_qualname(encode.decode))
    parser.add_argument('walk_id', type=int)
    parser.add_argument('--print_state', action='store_true')
    args = parser.parse_args()

    command = args.command

    step = command == 'step'

    if args.state:
        state = encode.decode(args.state)
    else:
        state = None

    state = replay_walk_by_id(args.log_file,
                              args.walk_id,
                              step=step,
                              replay_func_qualname=args.replay_func,
                              state=state)

    if args.print_state:
        print(encode.encode(state))
Beispiel #9
0
    def test_walk_replay(self):
        log_dir = tempfile.mkdtemp()

        walk_order = [actions.ActionSingleton1,
                      actions.ActionSingleton2,
                      actions.SerialActionSingleton1,
                      actions.ActionSingleton3]
        # See classes.py
        expected = [1, 2, 0, 3]

        state = {}
        walk_count, error_count, _, _, states, logs, _ = \
                runner.run_tests(walk_order,
                                 verbose=2,
                                 log_dir=log_dir,
                                 state=state,
                                 gather_states=True)
        self.assertEqual(walk_count, 1)
        self.assertEqual(error_count, 0)

        # Single worker
        self.assertEqual(len(states), 1)
        # Single walk on that worker
        worker_states = states[0]
        self.assertEqual(len(worker_states), 1)
        state = worker_states[0]
        state = state['inner']
        self.assertEqual(state, expected)

        trace_logs = [log_locs[1] for log_locs in
                      logs['remote'].values()]
        # Maps walk_id->list of stuff
        walks = {}
        for trace_log in trace_logs:
            with open(trace_log, 'r') as f:
                for line in f:
                    record = encode.decode(line)
                    walk_id = record['walk_id']
                    current_walk = record['walk']
                    serial_action = record['serial_action']

                    if walk_id not in walks:
                        walks[walk_id] = []
                    walks[walk_id].append((current_walk, serial_action))
        # Checking my assumptions
        self.assertEqual(len(walks), 1)

        walk_to_replay = walk.Walk()
        for segment in list(walks.values())[0]:
            walk_segment = segment[0]
            serial_action = segment[1]
            if serial_action:
                walk_to_replay.append(serial_action)
            walk_to_replay += walk_segment

        # Replay walk directly
        state = {}
        runner.replay_walk(walk_to_replay, state=state)
        self.assertTrue('inner' in state)
        self.assertEqual(state['inner'], expected)

        # Now let's test the replay lib
        state = {}
        state = replay.replay_walk_by_id(logs, walk_id, step=False,
                                         state=state)
        self.assertTrue('inner' in state)
        self.assertEqual(state['inner'], expected)

        shutil.rmtree(log_dir)