diff options
Diffstat (limited to 'intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket')
3 files changed, 293 insertions, 0 deletions
diff --git a/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/NativeSocket.php b/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/NativeSocket.php new file mode 100644 index 0000000..192dd73 --- /dev/null +++ b/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/NativeSocket.php @@ -0,0 +1,130 @@ +<?php + +namespace Pheanstalk\Socket; + +use Pheanstalk\Exception; +use Pheanstalk\Socket; + +/** + * A Socket implementation around a fsockopen() stream. + * + * @author Paul Annesley + * @package Pheanstalk + * @license http://www.opensource.org/licenses/mit-license.php + */ +class NativeSocket implements Socket +{ + /** + * The default timeout for a blocking read on the socket + */ + const SOCKET_TIMEOUT = 1; + + /** + * Number of retries for attempted writes which return zero length. + */ + const WRITE_RETRIES = 8; + + private $_socket; + + /** + * @param string $host + * @param int $port + * @param int $connectTimeout + */ + public function __construct($host, $port, $connectTimeout, $connectPersistent) + { + if ($connectPersistent) { + $this->_socket = $this->_wrapper() + ->pfsockopen($host, $port, $errno, $errstr, $connectTimeout, $connectPersistent); + } else { + $this->_socket = $this->_wrapper() + ->fsockopen($host, $port, $errno, $errstr, $connectTimeout, $connectPersistent); + } + + if (!$this->_socket) { + throw new Exception\ConnectionException($errno, $errstr . " (connecting to $host:$port)"); + } + + $this->_wrapper() + ->stream_set_timeout($this->_socket, self::SOCKET_TIMEOUT); + } + + /* (non-phpdoc) + * @see Socket::write() + */ + public function write($data) + { + $history = new WriteHistory(self::WRITE_RETRIES); + + for ($written = 0, $fwrite = 0; $written < strlen($data); $written += $fwrite) { + $fwrite = $this->_wrapper() + ->fwrite($this->_socket, substr($data, $written)); + + $history->log($fwrite); + + if ($history->isFullWithNoWrites()) { + throw new Exception\SocketException(sprintf( + 'fwrite() failed to write data after %u tries', + self::WRITE_RETRIES + )); + } + } + } + + /* (non-phpdoc) + * @see Socket::write() + */ + public function read($length) + { + $read = 0; + $parts = ''; + + while ($read < $length && !$this->_wrapper()->feof($this->_socket)) { + $data = $this->_wrapper() + ->fread($this->_socket, $length - $read); + + if ($data === false) { + throw new Exception\SocketException('fread() returned false'); + } + + $read += strlen($data); + $parts .= $data; + } + + return $parts; + } + + /* (non-phpdoc) + * @see Socket::write() + */ + public function getLine($length = null) + { + do { + $data = isset($length) ? + $this->_wrapper()->fgets($this->_socket, $length) : + $this->_wrapper()->fgets($this->_socket); + + if ($this->_wrapper()->feof($this->_socket)) { + throw new Exception\SocketException("Socket closed by server!"); + } + } while ($data === false); + + return rtrim($data); + } + + public function disconnect() + { + $this->_wrapper()->fclose($this->_socket); + } + + // ---------------------------------------- + + /** + * Wrapper class for all stream functions. + * Facilitates mocking/stubbing stream operations in unit tests. + */ + private function _wrapper() + { + return StreamFunctions::instance(); + } +} diff --git a/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/StreamFunctions.php b/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/StreamFunctions.php new file mode 100644 index 0000000..6f793f8 --- /dev/null +++ b/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/StreamFunctions.php @@ -0,0 +1,99 @@ +<?php + +namespace Pheanstalk\Socket; + +/** + * Wrapper around PHP stream functions. + * Facilitates mocking/stubbing stream operations in unit tests. + * + * @author Paul Annesley + * @package Pheanstalk + * @license http://www.opensource.org/licenses/mit-license.php + */ +class StreamFunctions +{ + private static $_instance; + + /** + * Singleton accessor. + */ + public static function instance() + { + if (empty(self::$_instance)) { + self::$_instance = new self; + } + + return self::$_instance; + } + + /** + * Sets an alternative or mocked instance. + */ + public function setInstance($instance) + { + self::$_instance = $instance; + } + + /** + * Unsets the instance, so a new one will be created. + */ + public function unsetInstance() + { + self::$_instance = null; + } + + // ---------------------------------------- + + public function feof($handle) + { + return feof($handle); + } + + public function fgets($handle, $length = null) + { + if (isset($length)) { + return fgets($handle, $length); + } else { + return fgets($handle); + } + } + + public function fopen($filename, $mode) + { + return fopen($filename, $mode); + } + + public function fread($handle, $length) + { + return fread($handle, $length); + } + + public function fsockopen($hostname, $port = -1, &$errno = null, &$errstr = null, $timeout = null) + { + return @fsockopen($hostname, $port, $errno, $errstr, $timeout); + } + + public function pfsockopen($hostname, $port = -1, &$errno = null, &$errstr = null, $timeout = null) + { + return @pfsockopen($hostname, $port, $errno, $errstr, $timeout); + } + + public function fwrite($handle, $string, $length = null) + { + if (isset($length)) { + return fwrite($handle, $string, $length); + } else { + return fwrite($handle, $string); + } + } + + public function fclose($handle) + { + fclose($handle); + } + + public function stream_set_timeout($stream, $seconds, $microseconds = 0) + { + return stream_set_timeout($stream, $seconds, $microseconds); + } +} diff --git a/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/WriteHistory.php b/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/WriteHistory.php new file mode 100644 index 0000000..a01fe4c --- /dev/null +++ b/intern.gospeladlershof.de/vendor/pda/pheanstalk/src/Socket/WriteHistory.php @@ -0,0 +1,64 @@ +<?php + +namespace Pheanstalk\Socket; + +/** + * A limited history of recent socket write length/success. + * Facilitates retrying zero-length writes a limited number of times, + * avoiding infinite loops. + * + * Based on a patch from https://github.com/leprechaun + * https://github.com/pda/pheanstalk/pull/24 + * + * A bitfield could be used instead of an array for efficiency. + * + * @author Paul Annesley + * @package Pheanstalk + * @license http://www.opensource.org/licenses/mit-license.php + */ +class WriteHistory +{ + private $_limit; + private $_data = array(); + + /** + * @param int $limit + */ + public function __construct($limit) + { + $this->_limit = $limit; + } + + /** + * Whether the history has reached its limit of entries. + */ + public function isFull() + { + return count($this->_data) >= $this->_limit; + } + + public function hasWrites() + { + return (bool) array_sum($this->_data); + } + + public function isFullWithNoWrites() + { + return $this->isFull() && !$this->hasWrites(); + } + + /** + * Logs the return value from a write call. + * Returns the input value. + */ + public function log($write) + { + if ($this->isFull()) { + array_shift($this->_data); + } + + $this->_data[] = (int) $write; + + return $write; + } +} |
