def _handle_write(self): """ This method is called from the IOManager thread when there the socket is writable and marked writable in the IO poller. It uses the stringio object of the current send buffer to get the next data to send and makes sure that the stringio object is set at the correct position, based on the amount of bytes actually sent. """ with self.__send_lock: if not self.__send_buffer: # No data to write, make sure that this # socket is marked not writable in the # IOManager if self.connected(): mgr = IOManager() mgr.set_writable(self, False) raise IOWrapperEnd() cur_id, cur_buffer = self.__send_buffer[0] cur_buffer.seek(self.__buffer_start_pos) data = cur_buffer.read(self.__buffer_size) if not data: # If the buffer ran out of data, # remove it from the queue and return. # The next attempt to write will set # the socket non-writable if there is # no next send buffer. cur_buffer.close() self.__send_buffer.pop(0) self.__send_buffer_ids.remove(cur_id) self.__buffer_start_pos = 0 return sent_bytes = 0 try: sent_bytes = self.__socket.send(data) self.__buffer_start_pos += sent_bytes except socket.error as err: if err.errno == errno.EAGAIN: # Resource temporarily unavailable raise IOWrapperEnd() raise if self.__log_output: self.__logger.debug("Sent data: %s" % repr(data[:sent_bytes])) self.__total_bytes += sent_bytes return sent_bytes
def _handle_write(self): """ This method is called from the IOManager thread when there the socket is writable and marked writable in the IO poller. It uses the stringio object of the current send buffer to get the next data to send and makes sure that the stringio object is set at the correct position, based on the amount of bytes actually sent. """ if not self.__send_buffer: # No data to write, make sure that this # socket is marked not writable in the # IOManager if self.connected(): mgr = IOManager() mgr.set_writable(self, False) raise IOWrapperEnd() with self.__send_lock: cur_id, cur_buffer = self.__send_buffer[0] cur_buffer.seek(self.__buffer_start_pos) data = cur_buffer.read(self.__buffer_size) if not data: # If the buffer ran out of data, # remove it from the queue and return. # The next attempt to write will set # the socket non-writable if there is # no next send buffer. cur_buffer.close() self.__send_buffer.pop(0) self.__send_buffer_ids.remove(cur_id) self.__buffer_start_pos = 0 return sent_bytes = 0 try: sent_bytes = self.__socket.send(data) self.__buffer_start_pos += sent_bytes except socket.error as err: if err.errno == errno.EAGAIN: # Resource temporarily unavailable raise IOWrapperEnd() raise if self.__log_output: self.__logger.debug("Sent data: %s" % repr(data[:sent_bytes])) self.__total_bytes += sent_bytes return sent_bytes
def __connect(self): """ This method is called by the _do_attempt method when the socket is a connecting socket that should try to connect """ if self.__socket: return False if self.__unix_socket: sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) address = (self.__port) to_what = "Unix Domain Socket %s" % self.__port else: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) address = (self.__host, self.__port) to_what = "TCP port %d" % self.__port try: sock.connect(address) self.__set_socket_options(sock) except socket.error as e: self.__logger.error("Could not connect to %s: %s" \ % (to_what, str(e))) return False except Exception as e: # Other exceptions mean bad settings. Try one more time but do not # keep on trying forever.. self.__logger.error("Could not connect to %s: %s" \ % (to_what, str(e))) self.__giveup = 2 return False self.__socket = sock self.__connected = True self.__fileno = self.__socket.fileno() mgr = IOManager() mgr.register(self) if not self.send_buffer_empty(): mgr.set_writable(self, True) return True
def send(self, data, optional=False): """ This method enqueues new data to be send. It wraps the data by pickling it if configured to do so and creates a new StringIO buffer to store the new data. """ if self.__listener: if not self.__client_sockets: self.__logger.warning("No clients connected to send data") return False with self.__receive_lock: for wrapper in self.__client_sockets: wrapper.send(data) return True if self.__use_pickle: try: data = pickle.dumps(data) except pickle.PicklingError: self.__logger.error("Cannot pickle data %s" % repr(data)) return False with self.__send_lock: set_writable = False if not self.__send_buffer: set_writable = True id = self.__send_id self.__send_id += 1 buffer = stringio.StringIO(data) self.__send_buffer.append((id, buffer)) self.__send_buffer_ids.add(id) if set_writable and self.connected(): mgr = IOManager() mgr.set_writable(self, True) return id