Ver Fonte

Some commands accepting multiple keys can be hashed if all the keys return the same hash (key tags).

List of the commands affected by this change (based on Redis 2.2):
    MSET, MGET, DEL, BLPOP, BRPOP, RPOPLPUSH, BRPOPLPUSH, SINTER, SINTERSTORE,
    SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, ZINTERSTORE, ZUNIONSTORE.
Daniele Alessandri há 14 anos atrás
pai
commit
c4064e5801

+ 15 - 0
lib/Predis/Commands/Command.php

@@ -23,6 +23,21 @@ abstract class Command implements ICommand {
         return $key;
         return $key;
     }
     }
 
 
+    protected function checkSameHashForKeys(Array $keys) {
+        if (($count = count($keys)) === 0) {
+            return false;
+        }
+        $currentKey = $this->getHashablePart($keys[0]);
+        for ($i = 1; $i < $count; $i++) {
+            $nextKey = $this->getHashablePart($keys[$i]);
+            if ($currentKey !== $nextKey) {
+                return false;
+            }
+            $currentKey = $nextKey;
+        }
+        return true;
+    }
+
     public function getHash(IDistributionStrategy $distributor) {
     public function getHash(IDistributionStrategy $distributor) {
         if (isset($this->_hash)) {
         if (isset($this->_hash)) {
             return $this->_hash;
             return $this->_hash;

+ 7 - 0
lib/Predis/Commands/Delete.php

@@ -5,6 +5,13 @@ namespace Predis\Commands;
 use Predis\Utils;
 use Predis\Utils;
 
 
 class Delete extends Command {
 class Delete extends Command {
+    protected function canBeHashed() {
+        $args = $this->getArguments();
+        if (count($args) === 1) {
+            return true;
+        }
+        return $this->checkSameHashForKeys($args);
+    }
     public function getId() { return 'DEL'; }
     public function getId() { return 'DEL'; }
     public function filterArguments(Array $arguments) {
     public function filterArguments(Array $arguments) {
         return Utils::filterArrayArguments($arguments);
         return Utils::filterArrayArguments($arguments);

+ 3 - 1
lib/Predis/Commands/GetMultiple.php

@@ -5,7 +5,9 @@ namespace Predis\Commands;
 use Predis\Utils;
 use Predis\Utils;
 
 
 class GetMultiple extends Command {
 class GetMultiple extends Command {
-    protected function canBeHashed() { return false; }
+    protected function canBeHashed() {
+        return $this->checkSameHashForKeys($this->getArguments());
+    }
     public function getId() { return 'MGET'; }
     public function getId() { return 'MGET'; }
     public function filterArguments(Array $arguments) {
     public function filterArguments(Array $arguments) {
         return Utils::filterArrayArguments($arguments);
         return Utils::filterArrayArguments($arguments);

+ 5 - 0
lib/Predis/Commands/ListPopFirstBlocking.php

@@ -3,5 +3,10 @@
 namespace Predis\Commands;
 namespace Predis\Commands;
 
 
 class ListPopFirstBlocking extends Command {
 class ListPopFirstBlocking extends Command {
+    protected function canBeHashed() {
+        return $this->checkSameHashForKeys(
+            array_slice(($args = $this->getArguments()), 0, count($args) - 1)
+        );
+    }
     public function getId() { return 'BLPOP'; }
     public function getId() { return 'BLPOP'; }
 }
 }

+ 1 - 1
lib/Predis/Commands/ListPopLastBlocking.php

@@ -2,6 +2,6 @@
 
 
 namespace Predis\Commands;
 namespace Predis\Commands;
 
 
-class ListPopLastBlocking extends Command {
+class ListPopLastBlocking extends ListPopFirstBlocking {
     public function getId() { return 'BRPOP'; }
     public function getId() { return 'BRPOP'; }
 }
 }

+ 3 - 0
lib/Predis/Commands/ListPopLastPushHead.php

@@ -3,5 +3,8 @@
 namespace Predis\Commands;
 namespace Predis\Commands;
 
 
 class ListPopLastPushHead extends Command {
 class ListPopLastPushHead extends Command {
+    protected function canBeHashed() {
+        return $this->checkSameHashForKeys($this->getArguments());
+    }
     public function getId() { return 'RPOPLPUSH'; }
     public function getId() { return 'RPOPLPUSH'; }
 }
 }

+ 5 - 0
lib/Predis/Commands/ListPopLastPushHeadBlocking.php

@@ -3,5 +3,10 @@
 namespace Predis\Commands;
 namespace Predis\Commands;
 
 
 class ListPopLastPushHeadBlocking extends Command {
 class ListPopLastPushHeadBlocking extends Command {
+    protected function canBeHashed() {
+        return $this->checkSameHashForKeys(
+            array_slice($args = $this->getArguments(), 0, count($args) - 1)
+        );
+    }
     public function getId() { return 'BRPOPLPUSH'; }
     public function getId() { return 'BRPOPLPUSH'; }
 }
 }

+ 3 - 1
lib/Predis/Commands/SetIntersection.php

@@ -5,7 +5,9 @@ namespace Predis\Commands;
 use Predis\Utils;
 use Predis\Utils;
 
 
 class SetIntersection extends Command {
 class SetIntersection extends Command {
-    protected function canBeHashed() { return false; }
+    protected function canBeHashed() {
+        return $this->checkSameHashForKeys($this->getArguments());
+    }
     public function getId() { return 'SINTER'; }
     public function getId() { return 'SINTER'; }
     public function filterArguments(Array $arguments) {
     public function filterArguments(Array $arguments) {
         return Utils::filterArrayArguments($arguments);
         return Utils::filterArrayArguments($arguments);

+ 3 - 1
lib/Predis/Commands/SetIntersectionStore.php

@@ -5,7 +5,9 @@ namespace Predis\Commands;
 use Predis\Utils;
 use Predis\Utils;
 
 
 class SetIntersectionStore extends Command {
 class SetIntersectionStore extends Command {
-    protected function canBeHashed() { return false; }
+    protected function canBeHashed() {
+        return $this->checkSameHashForKeys($this->getArguments());
+    }
     public function getId() { return 'SINTERSTORE'; }
     public function getId() { return 'SINTERSTORE'; }
     public function filterArguments(Array $arguments) {
     public function filterArguments(Array $arguments) {
         return Utils::filterArrayArguments($arguments);
         return Utils::filterArrayArguments($arguments);

+ 8 - 1
lib/Predis/Commands/SetMultiple.php

@@ -3,7 +3,14 @@
 namespace Predis\Commands;
 namespace Predis\Commands;
 
 
 class SetMultiple extends Command {
 class SetMultiple extends Command {
-    protected function canBeHashed() { return false; }
+    protected function canBeHashed() {
+        $args = $this->getArguments();
+        $keys = array();
+        for ($i = 0; $i < count($args); $i += 2) {
+            $keys[] = $args[$i];
+        }
+        return $this->checkSameHashForKeys($keys);
+    }
     public function getId() { return 'MSET'; }
     public function getId() { return 'MSET'; }
     public function filterArguments(Array $arguments) {
     public function filterArguments(Array $arguments) {
         if (count($arguments) === 1 && is_array($arguments[0])) {
         if (count($arguments) === 1 && is_array($arguments[0])) {

+ 0 - 1
lib/Predis/Commands/ZSetIntersectionStore.php

@@ -3,6 +3,5 @@
 namespace Predis\Commands;
 namespace Predis\Commands;
 
 
 class ZSetIntersectionStore extends ZSetUnionStore {
 class ZSetIntersectionStore extends ZSetUnionStore {
-    protected function canBeHashed() { return false; }
     public function getId() { return 'ZINTERSTORE'; }
     public function getId() { return 'ZINTERSTORE'; }
 }
 }

+ 6 - 1
lib/Predis/Commands/ZSetUnionStore.php

@@ -3,7 +3,12 @@
 namespace Predis\Commands;
 namespace Predis\Commands;
 
 
 class ZSetUnionStore extends Command {
 class ZSetUnionStore extends Command {
-    protected function canBeHashed() { return false; }
+    protected function canBeHashed() {
+        $args = $this->getArguments();
+        return $this->checkSameHashForKeys(
+            array_merge(array($args[0]), array_slice($args, 2, $args[1]))
+        );
+    }
     public function getId() { return 'ZUNIONSTORE'; }
     public function getId() { return 'ZUNIONSTORE'; }
     public function filterArguments(Array $arguments) {
     public function filterArguments(Array $arguments) {
         $options = array();
         $options = array();