Example #1
0
class Publisher(object):
    def __init__(self, name="(publisher-only)"):
        self.name = name
        address = self._get_address()

        try:
          self.connection = Connection(address, whoiam=name)
          self._log(syslog.LOG_DEBUG, "Stablished a connection with the notifier server (%s)." % esc(str(address)))
        except:
          self._log(syslog.LOG_ERR, "Error when creating a connection with the notifier server (%s): %s." % esc(str(address), traceback.format_exc()))
          raise 

        self.connection.send_object(pack_message(message_type='introduce_myself', name=name))
        self._safe_topics = set()
        
    def publish(self, topic, data):
        if topic not in self._safe_topics:
            fail_if_topic_isnt_valid(topic, allow_empty=False)
            self._safe_topics.add(topic)

        #self._log(syslog.LOG_DEBUG, "Sending publication of an event with topic '%s'." % esc(topic))
        self.connection.send_object(pack_message(message_type='publish', topic=topic, obj=data, dont_pack_object=False))
        #self._log(syslog.LOG_DEBUG, "Publication of an event sent.")


    def close(self, *args, **kargs):
       self.connection.close()
    
    def _get_address(self):
        import os, ConfigParser
        script_home = os.path.abspath(os.path.dirname(__file__))
        parent = os.path.pardir

        # TODO This shouldn't be hardcoded!
        config_file = os.path.join(script_home, parent, parent, parent, "config", "publish_subscribe.cfg")

        config = ConfigParser.SafeConfigParser(defaults={
                    'wait_on_address': "localhost",
                    'wait_on_port': "5555",
                     })

        config.read([config_file])
        if not config.has_section("notifier"):
           config.add_section("notifier")


        address = (config.get("notifier", 'wait_on_address'), config.getint("notifier", 'wait_on_port'))

        return address

    def __repr__(self):
        return "Endpoint (%s)" % self.name

    def _log(self, level, message): #TODO remove the "%" stuff over an unknow string (not local string)
        header = "%s: " % esc(repr(self))
        message = header + message

        syslog.syslog(level, message)
        return message
Example #2
0
class _Endpoint(threading.Thread):
   def __init__(self, socket, notifier, codename):
      threading.Thread.__init__(self)
      self.connection = Connection(socket)
      self.is_finished = False
      self.notifier = notifier
      self.codename = codename

      self.name = ""

      self.start()

   def _is_valid_message(self, message_type, message_body):
      if not message_type in ("subscribe", "publish", "unsubscribe", "introduce_myself"):
         return False


      return True


   def _process_message(self, message_type, message_body):
         if message_type == "publish":
            topic, raw_obj = unpack_message_body(message_type, message_body, dont_unpack_object=True)
            self.notifier.distribute_event(topic, raw_obj)

         elif message_type == "unsubscribe":
            topic = unpack_message_body(message_type, message_body)
            self.notifier.unsubscribe_me(topic, self)

         elif message_type == "introduce_myself":
            self.name = unpack_message_body(message_type, message_body)
            self._log(syslog.LOG_NOTICE, "Introduced himself as '%s'." % esc(self.name))
         
         elif message_type == "subscribe":
            topic = unpack_message_body(message_type, message_body)
            self.notifier.register_subscriber(topic, self)

         else:
            self._log(syslog.LOG_ERR, "Invalid message. Unknown type: '%s'." % esc(message_type))
            raise Exception("Invalid message.")

   def run(self):
      try:
         while not self.connection.end_of_the_communication:
            message_type, message_body = self.connection.receive_object()
            self._process_message(message_type, message_body)

         self._log(syslog.LOG_NOTICE, "The connection was closed by the other point of the connection.")
      except:
         self._log(syslog.LOG_ERR, "An exception has occurred when receiving/processing the messages: %s." % esc(traceback.format_exc()))
      finally:
         self.is_finished = True


   def send_event(self, topic, obj_raw):
      try:
         self.connection.send_object(pack_message(message_type="publish", topic=topic, obj=obj_raw, dont_pack_object=True))
      except:
         self._log(syslog.LOG_ERR, "An exception when sending a message to it: %s." % esc(traceback.format_exc()))
         self.is_finished = True

   def close(self):
      self._log(syslog.LOG_NOTICE, "Closing the connection with the endpoint.")
      self.is_finished = True
      self.connection.close()
      self._log(syslog.LOG_NOTICE, "Connection closed")

   def __repr__(self):
      return "%s%s%s" % (self.codename, ((" (%s)" % self.name) if self.name else ""), (" [dead]" if self.is_finished else ""))

   def _log(self, level, message):
      message = ("%s: " % esc(repr(self))) + message
      syslog.syslog(level, message)