Users can now choose at runtime how to handle multibulk responses. The new (and optional) iterator-based approach is slightly slower than the usual fetch-all behaviour, but in certain scenarios (e.g. when dealing with massive multibulk responses) it can save a lot of memory on the client.

This commit is contained in:
Daniele Alessandri
2010-02-25 12:46:10 +01:00
parent 8df4eaf7b3
commit 0cd7b446c6
+27 -2
View File
@@ -85,6 +85,10 @@ class Client {
return $this->_serverProfile;
}
public function useMultiBulkIterator($value = true) {
Response::useMultiBulkIterator($value);
}
public function connect() {
$this->_connection->connect();
}
@@ -336,6 +340,15 @@ class ResponseMultiBulkHandler implements IResponseHandler {
}
}
class ResponseMultiBulkStreamHandler implements IResponseHandler {
public function handle($socket, $prefix, $rawLength) {
if (!is_numeric($rawLength)) {
throw new ClientException("Cannot parse '$rawLength' as data length");
}
return new Utilities\MultiBulkResponseIterator($socket, (int)$rawLength);
}
}
class ResponseIntegerHandler implements IResponseHandler {
public function handle($socket, $prefix, $number) {
if (is_numeric($number)) {
@@ -357,7 +370,7 @@ class Response {
const QUEUED = 'QUEUED';
const NULL = 'nil';
private static $_prefixHandlers;
private static $_prefixHandlers, $_useMultiBulkIterator;
private static function initializePrefixHandlers() {
return array(
@@ -365,10 +378,22 @@ class Response {
'-' => new ResponseErrorHandler(),
':' => new ResponseIntegerHandler(),
'$' => new ResponseBulkHandler(),
'*' => new ResponseMultiBulkHandler()
'*' => self::$_useMultiBulkIterator
? new ResponseMultiBulkStreamHandler()
: new ResponseMultiBulkHandler()
);
}
public static function useMultiBulkIterator($value = null) {
if (is_bool($value)) {
self::$_useMultiBulkIterator = $value;
self::$_prefixHandlers = self::initializePrefixHandlers();
}
else {
return self::$_useMultiBulkIterator;
}
}
public static function read($socket) {
$header = fgets($socket);
if ($header === false) {