summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-04-30 15:47:17 +0200
committerantirez <antirez@gmail.com>2014-04-30 15:47:19 +0200
commite8357d0f858f2cd90fb1671fcfa02620d246e7c1 (patch)
tree99b104738a75824d03203a7f1394663c76031fb4
parent1db45ba58cf612f9b7857771ffc8c41e8a355f50 (diff)
downloadredis-e8357d0f858f2cd90fb1671fcfa02620d246e7c1.tar.gz
Cluster test: Tcl cluster library initial skeleton.
-rw-r--r--tests/support/cluster.tcl93
-rw-r--r--tests/support/redis.tcl4
2 files changed, 95 insertions, 2 deletions
diff --git a/tests/support/cluster.tcl b/tests/support/cluster.tcl
new file mode 100644
index 000000000..7097fbb48
--- /dev/null
+++ b/tests/support/cluster.tcl
@@ -0,0 +1,93 @@
+# Tcl redis cluster client as a wrapper of redis.rb.
+# Copyright (C) 2014 Salvatore Sanfilippo
+# Released under the BSD license like Redis itself
+#
+# Example usage:
+#
+# set c [redis_cluster 127.0.0.1 6379 127.0.0.1 6380]
+# $c set foo
+# $c get foo
+# $c close
+
+package require Tcl 8.5
+package provide redis_cluster 0.1
+
+namespace eval redis_cluster {}
+set ::redis_cluster::id 0
+array set ::redis_cluster::start_nodes {}
+array set ::redis_cluster::nodes {}
+array set ::redis_cluster::slots {}
+
+# List of "plain" commands, which are commands where the sole key is always
+# the first argument.
+set ::redis_cluster::plain_commands {
+ get set setnx setex psetex append strlen exists setbit getbit
+ setrange getrange substr incr decr rpush lpush rpushx lpushx
+ linsert rpop lpop brpop llen lindex lset lrange ltrim lrem
+ sadd srem sismember scard spop srandmember smembers sscan zadd
+ zincrby zrem zremrangebyscore zremrangebyrank zremrangebylex zrange
+ zrangebyscore zrevrangebyscore zrangebylex zrevrangebylex zcount
+ zlexcount zrevrange zcard zscore zrank zrevrank zscan hset hsetnx
+ hget hmset hmget hincrby hincrbyfloat hdel hlen hkeys hvals
+ hgetall hexists hscan incrby decrby incrbyfloat getset move
+ expire expireat pexpire pexpireat type ttl pttl persist restore
+ dump bitcount bitpos pfadd pfcount
+}
+
+proc redis_cluster {nodes} {
+ set id [incr ::redis_cluster::id]
+ set ::redis_cluster::start_nodes($id) $nodes
+ set ::redis_cluster::nodes($id) {}
+ set ::redis_cluster::slots($id) {}
+ set handle [interp alias {} ::redis_cluster::instance$id {} ::redis_cluster::__dispatch__ $id]
+ $handle refresh_nodes_map
+ return $handle
+}
+
+proc ::redis_cluster::__dispatch__ {id method args} {
+ if {[info command ::redis_cluster::__method__$method] eq {}} {
+ # Get the keys from the command.
+ set keys [::redis_cluster::get_keys_from_command $method $args]
+ if {$keys eq {}} {
+ error "Redis command '$method' is not supported by redis_cluster."
+ }
+
+ # Resolve the keys in the corresponding hash slot they hash to.
+ set slot [::redis_cluster::get_slot_from_keys $keys]
+ if {$slot eq {}} {
+ error "Invalid command: multiple keys not hashing to the same slot."
+ }
+
+ # Get the node mapped to this slot.
+ set node_id [dict get $::redis_cluster::slots($id) $slot]
+ if {$node_id eq {}} {
+ error "No mapped node for slot $slot."
+ }
+
+ # Execute the command in the node we think is the slot owner.
+ set node [dict get $::redis_cluster::nodes($id) $node_id]
+ set link [dict get $node link]
+ if {[catch {$link $method {*}$args} e]} {
+ # TODO: trap redirection error
+ }
+ return $e
+ } else {
+ uplevel 1 [list ::redis_cluster::__method__$method $id $fd] $args
+ }
+}
+
+proc ::redis_cluster::get_keys_from_command {cmd argv} {
+ set cmd [string tolower $cmd]
+ # Most Redis commands get just one key as first argument.
+ if {[lsearch -exact $::redis_cluster::plain_commands $cmd] != -1} {
+ return [list [lindex $argv 0]]
+ }
+
+ # Special handling for other commands
+ switch -exact $cmd {
+ mget {return $argv}
+ }
+
+ # All the other commands are not handled.
+ return {}
+}
diff --git a/tests/support/redis.tcl b/tests/support/redis.tcl
index 36b005a17..256fbc899 100644
--- a/tests/support/redis.tcl
+++ b/tests/support/redis.tcl
@@ -1,5 +1,5 @@
-# Tcl clinet library - used by test-redis.tcl script for now
-# Copyright (C) 2009 Salvatore Sanfilippo
+# Tcl client library - used by the Redis test
+# Copyright (C) 2009-2014 Salvatore Sanfilippo
# Released under the BSD license like Redis itself
#
# Example usage: