瀏覽代碼

Merge branch 'command_hashing'

Daniele Alessandri 14 年之前
父節點
當前提交
2201dd1df2
共有 47 個文件被更改,包括 111 次插入57 次删除
  1. 1 1
      lib/Predis/Commands/Auth.php
  2. 1 1
      lib/Predis/Commands/BackgroundRewriteAppendOnlyFile.php
  3. 1 1
      lib/Predis/Commands/BackgroundSave.php
  4. 29 14
      lib/Predis/Commands/Command.php
  5. 1 1
      lib/Predis/Commands/Config.php
  6. 1 1
      lib/Predis/Commands/DatabaseSize.php
  7. 7 0
      lib/Predis/Commands/Delete.php
  8. 1 1
      lib/Predis/Commands/Discard.php
  9. 1 1
      lib/Predis/Commands/DoEcho.php
  10. 1 1
      lib/Predis/Commands/Exec.php
  11. 1 1
      lib/Predis/Commands/FlushAll.php
  12. 1 1
      lib/Predis/Commands/FlushDatabase.php
  13. 3 1
      lib/Predis/Commands/GetMultiple.php
  14. 0 1
      lib/Predis/Commands/ICommand.php
  15. 1 1
      lib/Predis/Commands/Info.php
  16. 0 1
      lib/Predis/Commands/InfoV24x.php
  17. 1 1
      lib/Predis/Commands/Keys.php
  18. 1 1
      lib/Predis/Commands/LastSave.php
  19. 5 0
      lib/Predis/Commands/ListPopFirstBlocking.php
  20. 1 1
      lib/Predis/Commands/ListPopLastBlocking.php
  21. 3 0
      lib/Predis/Commands/ListPopLastPushHead.php
  22. 5 0
      lib/Predis/Commands/ListPopLastPushHeadBlocking.php
  23. 1 1
      lib/Predis/Commands/MoveKey.php
  24. 1 1
      lib/Predis/Commands/Multi.php
  25. 1 1
      lib/Predis/Commands/Ping.php
  26. 1 1
      lib/Predis/Commands/Publish.php
  27. 1 1
      lib/Predis/Commands/Quit.php
  28. 1 1
      lib/Predis/Commands/RandomKey.php
  29. 1 1
      lib/Predis/Commands/Rename.php
  30. 1 1
      lib/Predis/Commands/RenamePreserve.php
  31. 1 1
      lib/Predis/Commands/Save.php
  32. 1 1
      lib/Predis/Commands/SelectDatabase.php
  33. 3 0
      lib/Predis/Commands/SetIntersection.php
  34. 3 0
      lib/Predis/Commands/SetIntersectionStore.php
  35. 1 1
      lib/Predis/Commands/SetMove.php
  36. 8 1
      lib/Predis/Commands/SetMultiple.php
  37. 0 1
      lib/Predis/Commands/SetMultiplePreserve.php
  38. 1 1
      lib/Predis/Commands/Shutdown.php
  39. 1 1
      lib/Predis/Commands/SlaveOf.php
  40. 1 1
      lib/Predis/Commands/Subscribe.php
  41. 1 1
      lib/Predis/Commands/SubscribeByPattern.php
  42. 1 1
      lib/Predis/Commands/Unsubscribe.php
  43. 1 1
      lib/Predis/Commands/UnsubscribeByPattern.php
  44. 1 1
      lib/Predis/Commands/Unwatch.php
  45. 1 1
      lib/Predis/Commands/Watch.php
  46. 6 0
      lib/Predis/Commands/ZSetUnionStore.php
  47. 6 5
      lib/Predis/Network/ConnectionCluster.php

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Auth extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'AUTH'; }
 }

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class BackgroundRewriteAppendOnlyFile extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'BGREWRITEAOF'; }
     public function parseResponse($data) {
         return $data == 'Background append only file rewriting started';

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class BackgroundSave extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'BGSAVE'; }
     public function parseResponse($data) {
         if ($data == 'Background saving started') {

+ 29 - 14
lib/Predis/Commands/Command.php

@@ -8,7 +8,33 @@ abstract class Command implements ICommand {
     private $_hash;
     private $_arguments = array();
 
-    public function canBeHashed() {
+    protected function canBeHashed() {
+        return isset($this->_arguments[0]);
+    }
+
+    protected function getHashablePart($key) {
+        $start = strpos($key, '{');
+        if ($start !== false) {
+            $end = strpos($key, '}', $start);
+            if ($end !== false) {
+                $key = substr($key, ++$start, $end - $start);
+            }
+        }
+        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;
     }
 
@@ -16,19 +42,8 @@ abstract class Command implements ICommand {
         if (isset($this->_hash)) {
             return $this->_hash;
         }
-        if (isset($this->_arguments[0])) {
-            // TODO: should we throw an exception if the command does not
-            // support sharding?
-            $key = $this->_arguments[0];
-
-            $start = strpos($key, '{');
-            if ($start !== false) {
-                $end = strpos($key, '}', $start);
-                if ($end !== false) {
-                    $key = substr($key, ++$start, $end - $start);
-                }
-            }
-
+        if ($this->canBeHashed()) {
+            $key = $this->getHashablePart($this->_arguments[0]);
             $this->_hash = $distributor->generateKey($key);
             return $this->_hash;
         }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Config extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'CONFIG'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class DatabaseSize extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'DBSIZE'; }
 }

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

@@ -5,6 +5,13 @@ namespace Predis\Commands;
 use Predis\Utils;
 
 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 filterArguments(Array $arguments) {
         return Utils::filterArrayArguments($arguments);

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Discard extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'DISCARD'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class DoEcho extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'ECHO'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Exec extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'EXEC'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class FlushAll extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'FLUSHALL'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class FlushDatabase extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'FLUSHDB'; }
 }

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

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

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

@@ -6,7 +6,6 @@ use Predis\Distribution\IDistributionStrategy;
 
 interface ICommand {
     public function getId();
-    public function canBeHashed();
     public function getHash(IDistributionStrategy $distributor);
     public function setArgumentsArray(Array $arguments);
     public function getArguments();

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class Info extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'INFO'; }
     public function parseResponse($data) {
         $info      = array();

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

@@ -3,7 +3,6 @@
 namespace Predis\Commands;
 
 class InfoV24x extends Info {
-    public function canBeHashed()  { return false; }
     public function parseResponse($data) {
         $info      = array();
         $current   = null;

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Keys extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'KEYS'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class LastSave extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'LASTSAVE'; }
 }

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

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

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

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

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

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

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

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

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class MoveKey extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'MOVE'; }
     public function parseResponse($data) { return (bool) $data; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Multi extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'MULTI'; }
 }

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class Ping extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'PING'; }
     public function parseResponse($data) {
         return $data === 'PONG' ? true : false;

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Publish extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'PUBLISH'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Quit extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'QUIT'; }
 }

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class RandomKey extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'RANDOMKEY'; }
     public function parseResponse($data) { return $data !== '' ? $data : null; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Rename extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'RENAME'; }
 }

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class RenamePreserve extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'RENAMENX'; }
     public function parseResponse($data) { return (bool) $data; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Save extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'SAVE'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class SelectDatabase extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'SELECT'; }
 }

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

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

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

@@ -5,6 +5,9 @@ namespace Predis\Commands;
 use Predis\Utils;
 
 class SetIntersectionStore extends Command {
+    protected function canBeHashed() {
+        return $this->checkSameHashForKeys($this->getArguments());
+    }
     public function getId() { return 'SINTERSTORE'; }
     public function filterArguments(Array $arguments) {
         if (count($arguments) === 2 && is_array($arguments[1])) {

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class SetMove extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'SMOVE'; }
     public function parseResponse($data) { return (bool) $data; }
 }

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

@@ -3,7 +3,14 @@
 namespace Predis\Commands;
 
 class SetMultiple extends Command {
-    public 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 filterArguments(Array $arguments) {
         if (count($arguments) === 1 && is_array($arguments[0])) {

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

@@ -3,7 +3,6 @@
 namespace Predis\Commands;
 
 class SetMultiplePreserve extends SetMultiple {
-    public function canBeHashed()  { return false; }
     public function getId() { return 'MSETNX'; }
     public function parseResponse($data) { return (bool) $data; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Shutdown extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'SHUTDOWN'; }
 }

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class SlaveOf extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'SLAVEOF'; }
     public function filterArguments(Array $arguments) {
         if (count($arguments) === 0 || $arguments[0] === 'NO ONE') {

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

@@ -5,7 +5,7 @@ namespace Predis\Commands;
 use Predis\Utils;
 
 class Subscribe extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'SUBSCRIBE'; }
     public function filterArguments(Array $arguments) {
         return Utils::filterArrayArguments($arguments);

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class SubscribeByPattern extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'PSUBSCRIBE'; }
     public function filterArguments(Array $arguments) {
         return Utils::filterArrayArguments($arguments);

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class Unsubscribe extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'UNSUBSCRIBE'; }
 }

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

@@ -3,6 +3,6 @@
 namespace Predis\Commands;
 
 class UnsubscribeByPattern extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'PUNSUBSCRIBE'; }
 }

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class Unwatch extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'UNWATCH'; }
     public function parseResponse($data) { return (bool) $data; }
 }

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

@@ -3,7 +3,7 @@
 namespace Predis\Commands;
 
 class Watch extends Command {
-    public function canBeHashed()  { return false; }
+    protected function canBeHashed() { return false; }
     public function getId() { return 'WATCH'; }
     public function filterArguments(Array $arguments) {
         if (isset($arguments[0]) && is_array($arguments[0])) {

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

@@ -3,6 +3,12 @@
 namespace Predis\Commands;
 
 class ZSetUnionStore extends Command {
+    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 filterArguments(Array $arguments) {
         $options = array();

+ 6 - 5
lib/Predis/Network/ConnectionCluster.php

@@ -47,12 +47,13 @@ class ConnectionCluster implements IConnectionCluster, \IteratorAggregate {
     }
 
     public function getConnection(ICommand $command) {
-        if ($command->canBeHashed() === false) {
-            throw new ClientException(
-                sprintf("Cannot send '%s' commands to a cluster of connections", $command->getId())
-            );
+        $cmdHash = $command->getHash($this->_distributor);
+        if (isset($cmdHash)) {
+            return $this->_distributor->get($cmdHash);
         }
-        return $this->_distributor->get($command->getHash($this->_distributor));
+        throw new ClientException(
+            sprintf("Cannot send '%s' commands to a cluster of connections", $command->getId())
+        );
     }
 
     public function getConnectionById($id = null) {