Ejemplo n.º 1
0
class OutgoingTupleHelper(object):
  """Helper class for preparing and pushing tuples to Out-Stream

  This is a Python implementation of OutgoingTupleCollection.java

  Handles basic methods for sending out tuples
  1. ``init_new_control_tuple()`` or ``init_new_data_tuple()``
  2. ``add_data_tuple()``, ``add_ack_tuple()`` and ``add_fail_tuple()``
  3. ``flush_remaining()`` tuples and send out the tuples

  :ivar out_stream: (HeronCommunicator) Out-Stream. Pushed message is an instance of HeronTupleSet
  :ivar pplan_helper: (PhysicalPlanHelper) Physical Plan Helper for this component
  :ivar current_data_tuple_set: (HeronDataTupleSet) currently buffered data tuple
  :ivar current_control_tuple_set: (HeronControlTupleSet) currently buffered control tuple
  """
  make_data_tuple_set = lambda _: tuple_pb2.HeronDataTupleSet()
  make_control_tuple_set = lambda _: tuple_pb2.HeronControlTupleSet()
  make_tuple_set = lambda _: tuple_pb2.HeronTupleSet()
  make_stream_id = lambda _: topology_pb2.StreamId()

  def __init__(self, pplan_helper, out_stream):
    self.out_stream = out_stream
    self.pplan_helper = pplan_helper

    self.current_data_tuple_set = None
    self.current_control_tuple_set = None

    self.current_data_tuple_size_in_bytes = 0
    self.total_data_emitted_in_bytes = 0

    self.sys_config = system_config.get_sys_config()

    # read the config values
    self.data_tuple_set_capacity = self.sys_config[constants.INSTANCE_SET_DATA_TUPLE_CAPACITY]
    self.max_data_tuple_size_in_bytes =\
      self.sys_config.get(constants.INSTANCE_SET_DATA_TUPLE_SIZE_BYTES, sys.maxint)
    self.control_tuple_set_capacity = self.sys_config[constants.INSTANCE_SET_CONTROL_TUPLE_CAPACITY]

  def send_out_tuples(self):
    """Sends out currently buffered tuples into the Out-Stream"""
    self._flush_remaining()

  def add_data_tuple(self, stream_id, new_data_tuple, tuple_size_in_bytes):
    """Add a new data tuple to the currently buffered set of tuples"""
    if (self.current_data_tuple_set is None) or \
        (self.current_data_tuple_set.stream.id != stream_id) or \
        (len(self.current_data_tuple_set.tuples) >= self.data_tuple_set_capacity) or \
        (self.current_data_tuple_size_in_bytes >= self.max_data_tuple_size_in_bytes):
      self._init_new_data_tuple(stream_id)

    added_tuple = self.current_data_tuple_set.tuples.add()
    added_tuple.CopyFrom(new_data_tuple)

    self.current_data_tuple_size_in_bytes += tuple_size_in_bytes
    self.total_data_emitted_in_bytes += tuple_size_in_bytes

  def add_control_tuple(self, new_control_tuple, tuple_size_in_bytes, is_ack):
    """Add a new control (Ack/Fail) tuple to the currently buffered set of tuples

    :param is_ack: ``True`` if Ack, ``False`` if Fail
    """
    if self.current_control_tuple_set is None:
      self._init_new_control_tuple()
    elif is_ack and (len(self.current_control_tuple_set.fails) > 0 or
                     len(self.current_control_tuple_set.acks) >= self.control_tuple_set_capacity):
      self._init_new_control_tuple()
    elif not is_ack and \
        (len(self.current_control_tuple_set.acks) > 0 or
         len(self.current_control_tuple_set.fails) >= self.control_tuple_set_capacity):
      self._init_new_control_tuple()

    if is_ack:
      added_tuple = self.current_control_tuple_set.acks.add()
    else:
      added_tuple = self.current_control_tuple_set.fails.add()

    added_tuple.CopyFrom(new_control_tuple)

    self.total_data_emitted_in_bytes += tuple_size_in_bytes

  def add_ckpt_state(self, ckpt_id, ckpt_state):
    """Add the checkpoint state message to be sent back the stmgr

    :param ckpt_id: The id of the checkpoint
    :ckpt_state: The checkpoint state
    """
    # first flush any buffered tuples
    self._flush_remaining()
    msg = ckptmgr_pb2.StoreInstanceStateCheckpoint()
    istate = ckptmgr_pb2.InstanceStateCheckpoint()
    istate.checkpoint_id = ckpt_id
    istate.state = ckpt_state
    msg.state.CopyFrom(istate)
    self._push_tuple_to_stream(msg)

  def clear(self):
    """Clears current data and the streams"""
    self._flush_remaining()
    self.out_stream.clear()

  def _init_new_data_tuple(self, stream_id):
    self._flush_remaining()
    self.current_data_tuple_size_in_bytes = 0

    new_stream_id = self.make_stream_id()
    new_stream_id.id = stream_id
    new_stream_id.component_name = self.pplan_helper.my_component_name

    new_data_tuple_set = self.make_data_tuple_set()
    new_data_tuple_set.stream.CopyFrom(new_stream_id)
    self.current_data_tuple_set = new_data_tuple_set

  def _init_new_control_tuple(self):
    self._flush_remaining()
    self.current_control_tuple_set = self.make_control_tuple_set()

  def _flush_remaining(self):
    if self.current_data_tuple_set is not None:
      Log.debug("In flush_remaining() - flush data tuple set")
      tuple_set = self.make_tuple_set()
      tuple_set.data.CopyFrom(self.current_data_tuple_set)
      self._push_tuple_to_stream(tuple_set)
      self.current_data_tuple_set = None
      self.current_data_tuple_size_in_bytes = 0


    if self.current_control_tuple_set is not None:
      Log.debug("In flush_remaining() - flush control tuple set")
      tuple_set = self.make_tuple_set()
      tuple_set.control.CopyFrom(self.current_control_tuple_set)
      self._push_tuple_to_stream(tuple_set)
      self.current_control_tuple_set = None

  def _push_tuple_to_stream(self, tuple_set):
    self.out_stream.offer(tuple_set)

  def is_out_queue_available(self):
    return self.out_stream.get_available_capacity() > 0
Ejemplo n.º 2
0
class OutgoingTupleHelper(object):
    """Helper class for preparing and pushing tuples to Out-Stream

  This is a Python implementation of OutgoingTupleCollection.java

  Handles basic methods for sending out tuples
  1. ``init_new_control_tuple()`` or ``init_new_data_tuple()``
  2. ``add_data_tuple()``, ``add_ack_tuple()`` and ``add_fail_tuple()``
  3. ``flush_remaining()`` tuples and send out the tuples

  :ivar out_stream: (HeronCommunicator) Out-Stream. Pushed message is an instance of HeronTupleSet
  :ivar pplan_helper: (PhysicalPlanHelper) Physical Plan Helper for this component
  :ivar current_data_tuple_set: (HeronDataTupleSet) currently buffered data tuple
  :ivar current_control_tuple_set: (HeronControlTupleSet) currently buffered control tuple
  """
    # pylint: disable=no-value-for-parameter
    make_data_tuple_set = lambda _: tuple_pb2.HeronDataTupleSet()
    make_control_tuple_set = lambda _: tuple_pb2.HeronControlTupleSet()
    make_tuple_set = lambda _: tuple_pb2.HeronTupleSet()
    make_stream_id = lambda _: topology_pb2.StreamId()

    def __init__(self, pplan_helper, out_stream):
        self.out_stream = out_stream
        self.pplan_helper = pplan_helper

        self.current_data_tuple_set = None
        self.current_control_tuple_set = None

        self.current_data_tuple_size_in_bytes = 0
        self.total_data_emitted_in_bytes = 0

    def send_out_tuples(self):
        """Sends out currently buffered tuples into the Out-Stream"""
        self._flush_remaining()

    def add_data_tuple(self, stream_id, new_data_tuple, tuple_size_in_bytes):
        """Add a new data tuple to the currently buffered set of tuples"""
        if (self.current_data_tuple_set is None) or \
            (self.current_data_tuple_set.stream.id != stream_id):
            self._init_new_data_tuple(stream_id)

        added_tuple = self.current_data_tuple_set.tuples.add()
        added_tuple.CopyFrom(new_data_tuple)

        self.current_data_tuple_size_in_bytes += tuple_size_in_bytes
        self.total_data_emitted_in_bytes += tuple_size_in_bytes

    def add_control_tuple(self, new_control_tuple, tuple_size_in_bytes,
                          is_ack):
        """Add a new control (Ack/Fail) tuple to the currently buffered set of tuples

    :param is_ack: ``True`` if Ack, ``False`` if Fail
    """
        if (self.current_control_tuple_set is None) or \
            (is_ack and len(self.current_control_tuple_set.fails) > 0) or \
            (not is_ack and len(self.current_control_tuple_set.acks) > 0):
            self._init_new_control_tuple()

        if is_ack:
            added_tuple = self.current_control_tuple_set.acks.add()
        else:
            added_tuple = self.current_control_tuple_set.fails.add()

        added_tuple.CopyFrom(new_control_tuple)

        self.total_data_emitted_in_bytes += tuple_size_in_bytes

    def _init_new_data_tuple(self, stream_id):
        self._flush_remaining()
        self.current_data_tuple_size_in_bytes = 0

        new_stream_id = self.make_stream_id()
        new_stream_id.id = stream_id
        new_stream_id.component_name = self.pplan_helper.my_component_name

        new_data_tuple_set = self.make_data_tuple_set()
        new_data_tuple_set.stream.CopyFrom(new_stream_id)
        self.current_data_tuple_set = new_data_tuple_set

    def _init_new_control_tuple(self):
        self._flush_remaining()
        self.current_control_tuple_set = self.make_control_tuple_set()

    def _flush_remaining(self):
        if self.current_data_tuple_set is not None:
            Log.debug("In flush_remaining() - flush data tuple set")
            tuple_set = self.make_tuple_set()
            tuple_set.data.CopyFrom(self.current_data_tuple_set)
            self._push_tuple_to_stream(tuple_set)
            self.current_data_tuple_set = None
            self.current_data_tuple_size_in_bytes = 0

        if self.current_control_tuple_set is not None:
            Log.debug("In flush_remaining() - flush control tuple set")
            tuple_set = self.make_tuple_set()
            tuple_set.control.CopyFrom(self.current_control_tuple_set)
            self._push_tuple_to_stream(tuple_set)
            self.current_control_tuple_set = None

    def _push_tuple_to_stream(self, tuple_set):
        self.out_stream.offer(tuple_set)