Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
3cba0c3e
Commit
3cba0c3e
authored
Jun 18, 2014
by
antirez
Browse files
Test: Tcl client initial support for automatic reconnection.
parent
256046fd
Changes
1
Hide whitespace changes
Inline
Side-by-side
tests/support/redis.tcl
View file @
3cba0c3e
...
@@ -31,8 +31,10 @@ package provide redis 0.1
...
@@ -31,8 +31,10 @@ package provide redis 0.1
namespace eval redis
{}
namespace eval redis
{}
set ::redis::id 0
set ::redis::id 0
array set ::redis::fd
{}
array set ::redis::fd
{}
array set ::redis::addr
{}
array set ::redis::blocking
{}
array set ::redis::blocking
{}
array set ::redis::deferred
{}
array set ::redis::deferred
{}
array set ::redis::reconnect
{}
array set ::redis::callback
{}
array set ::redis::callback
{}
array set ::redis::state
{}
;
# State in non-blocking reply reading
array set ::redis::state
{}
;
# State in non-blocking reply reading
array set ::redis::statestack
{}
;
# Stack of states, for nested mbulks
array set ::redis::statestack
{}
;
# Stack of states, for nested mbulks
...
@@ -42,35 +44,63 @@ proc redis {{server 127.0.0.1} {port 6379} {defer 0}} {
...
@@ -42,35 +44,63 @@ proc redis {{server 127.0.0.1} {port 6379} {defer 0}} {
fconfigure $fd -translation binary
fconfigure $fd -translation binary
set id
[
incr ::redis::id
]
set id
[
incr ::redis::id
]
set ::redis::fd
(
$id
)
$fd
set ::redis::fd
(
$id
)
$fd
set ::redis::addr
(
$id
)
[
list $server $port
]
set ::redis::blocking
(
$id
)
1
set ::redis::blocking
(
$id
)
1
set ::redis::deferred
(
$id
)
$defer
set ::redis::deferred
(
$id
)
$defer
set ::redis::reconnect
(
$id
)
0
::redis::redis_reset_state $id
::redis::redis_reset_state $id
interp alias
{}
::redis::redisHandle$id
{}
::redis::__dispatch__ $id
interp alias
{}
::redis::redisHandle$id
{}
::redis::__dispatch__ $id
}
}
# This is a wrapper to the actual dispatching procedure that handles
# reconnection if needed.
proc ::redis::__dispatch__
{
id method args
}
{
proc ::redis::__dispatch__
{
id method args
}
{
set errorcode
[
catch
{
::redis::__dispatch__raw__ $id $method $args
}
retval
]
if
{
$errorcode
&& $::redis::reconnect
(
$id
)
&& $::redis::fd
(
$id
)
eq
{}}
{
# Try again if the connection was lost.
# FIXME: we don't re-select the previously selected DB, nor we check
# if we are inside a transaction that needs to be re-issued from
# scratch.
set errorcode
[
catch
{
::redis::__dispatch__raw__ $id $method $args
}
retval
]
}
return -code $errorcode $retval
}
proc ::redis::__dispatch__raw__
{
id method argv
}
{
set fd $::redis::fd
(
$id
)
set fd $::redis::fd
(
$id
)
# Reconnect the link if needed.
if
{
$fd
eq
{}}
{
lassign $::redis::addr
(
$id
)
host port
set ::redis::fd
(
$id
)
[
socket $host $port
]
fconfigure $::redis::fd
(
$id
)
-translation binary
set fd $::redis::fd
(
$id
)
}
set blocking $::redis::blocking
(
$id
)
set blocking $::redis::blocking
(
$id
)
set deferred $::redis::deferred
(
$id
)
set deferred $::redis::deferred
(
$id
)
if
{
$blocking
== 0
}
{
if
{
$blocking
== 0
}
{
if
{[
llength $arg
s
]
== 0
}
{
if
{[
llength $arg
v
]
== 0
}
{
error
"Please provide a callback in non-blocking mode"
error
"Please provide a callback in non-blocking mode"
}
}
set callback
[
lindex $arg
s
end
]
set callback
[
lindex $arg
v
end
]
set arg
s
[
lrange $arg
s
0 end-1
]
set arg
v
[
lrange $arg
v
0 end-1
]
}
}
if
{[
info command ::redis::__method__$method
]
eq
{}}
{
if
{[
info command ::redis::__method__$method
]
eq
{}}
{
set cmd
"*
[
expr
{[
llength $arg
s
]
+1
}]
\r\n
"
set cmd
"*
[
expr
{[
llength $arg
v
]
+1
}]
\r\n
"
append cmd
"
$
[
string length $method
]
\r\n
$method
\r\n
"
append cmd
"
$
[
string length $method
]
\r\n
$method
\r\n
"
foreach a $arg
s
{
foreach a $arg
v
{
append cmd
"
$
[
string length $a
]
\r\n
$a
\r\n
"
append cmd
"
$
[
string length $a
]
\r\n
$a
\r\n
"
}
}
::redis::redis_write $fd $cmd
::redis::redis_write $fd $cmd
flush $fd
if
{[
catch
{
flush $fd
}]}
{
set ::redis::fd
(
$id
)
{}
return -code error
"I/O error reading reply"
}
if
{
!$deferred
}
{
if
{
!$deferred
}
{
if
{
$blocking
}
{
if
{
$blocking
}
{
::redis::redis_read_reply $fd
::redis::redis_read_reply
$id
$fd
}
else
{
}
else
{
# Every well formed reply read will pop an element from this
# Every well formed reply read will pop an element from this
# list and use it as a callback. So pipelining is supported
# list and use it as a callback. So pipelining is supported
...
@@ -80,7 +110,7 @@ proc ::redis::__dispatch__ {id method args} {
...
@@ -80,7 +110,7 @@ proc ::redis::__dispatch__ {id method args} {
}
}
}
}
}
else
{
}
else
{
uplevel 1
[
list ::redis::__method__$method $id $fd
]
$arg
s
uplevel 1
[
list ::redis::__method__$method $id $fd
]
$arg
v
}
}
}
}
...
@@ -89,8 +119,12 @@ proc ::redis::__method__blocking {id fd val} {
...
@@ -89,8 +119,12 @@ proc ::redis::__method__blocking {id fd val} {
fconfigure $fd -blocking $val
fconfigure $fd -blocking $val
}
}
proc ::redis::__method__reconnect
{
id fd val
}
{
set ::redis::reconnect
(
$id
)
$val
}
proc ::redis::__method__read
{
id fd
}
{
proc ::redis::__method__read
{
id fd
}
{
::redis::redis_read_reply $fd
::redis::redis_read_reply
$id
$fd
}
}
proc ::redis::__method__write
{
id fd buf
}
{
proc ::redis::__method__write
{
id fd buf
}
{
...
@@ -104,8 +138,10 @@ proc ::redis::__method__flush {id fd} {
...
@@ -104,8 +138,10 @@ proc ::redis::__method__flush {id fd} {
proc ::redis::__method__close
{
id fd
}
{
proc ::redis::__method__close
{
id fd
}
{
catch
{
close $fd
}
catch
{
close $fd
}
catch
{
unset ::redis::fd
(
$id
)}
catch
{
unset ::redis::fd
(
$id
)}
catch
{
unset ::redis::addr
(
$id
)}
catch
{
unset ::redis::blocking
(
$id
)}
catch
{
unset ::redis::blocking
(
$id
)}
catch
{
unset ::redis::deferred
(
$id
)}
catch
{
unset ::redis::deferred
(
$id
)}
catch
{
unset ::redis::reconnect
(
$id
)}
catch
{
unset ::redis::state
(
$id
)}
catch
{
unset ::redis::state
(
$id
)}
catch
{
unset ::redis::statestack
(
$id
)}
catch
{
unset ::redis::statestack
(
$id
)}
catch
{
unset ::redis::callback
(
$id
)}
catch
{
unset ::redis::callback
(
$id
)}
...
@@ -143,14 +179,14 @@ proc ::redis::redis_bulk_read {fd} {
...
@@ -143,14 +179,14 @@ proc ::redis::redis_bulk_read {fd} {
return $buf
return $buf
}
}
proc ::redis::redis_multi_bulk_read fd
{
proc ::redis::redis_multi_bulk_read
{
id
fd
}
{
set count
[
redis_read_line $fd
]
set count
[
redis_read_line $fd
]
if
{
$count
== -1
}
return
{}
if
{
$count
== -1
}
return
{}
set l
{}
set l
{}
set err
{}
set err
{}
for
{
set i 0
}
{
$i
< $count
}
{
incr i
}
{
for
{
set i 0
}
{
$i
< $count
}
{
incr i
}
{
if
{[
catch
{
if
{[
catch
{
lappend l
[
redis_read_reply $fd
]
lappend l
[
redis_read_reply
$id
$fd
]
}
e
]
&& $err eq
{}}
{
}
e
]
&& $err eq
{}}
{
set err $e
set err $e
}
}
...
@@ -163,16 +199,19 @@ proc ::redis::redis_read_line fd {
...
@@ -163,16 +199,19 @@ proc ::redis::redis_read_line fd {
string trim
[
gets $fd
]
string trim
[
gets $fd
]
}
}
proc ::redis::redis_read_reply fd
{
proc ::redis::redis_read_reply
{
id
fd
}
{
set type
[
read $fd 1
]
set type
[
read $fd 1
]
switch -exact -- $type
{
switch -exact -- $type
{
: -
: -
+
{
redis_read_line $fd
}
+
{
redis_read_line $fd
}
-
{
return -code error
[
redis_read_line $fd
]}
-
{
return -code error
[
redis_read_line $fd
]}
$
{
redis_bulk_read $fd
}
$
{
redis_bulk_read $fd
}
*
{
redis_multi_bulk_read $fd
}
*
{
redis_multi_bulk_read
$id
$fd
}
default
{
default
{
if
{
$type
eq
{}}
{
return -code error
"I/O error reading reply"
}
if
{
$type
eq
{}}
{
set ::redis::fd
(
$id
)
{}
return -code error
"I/O error reading reply"
}
return -code error
"Bad protocol, '
$type
' as reply type byte"
return -code error
"Bad protocol, '
$type
' as reply type byte"
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment