redis-server 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +38 -0
- data/README.md +33 -0
- data/bin/redis +114 -0
- data/redis/Makefile +5 -0
- data/redis/extconf.rb +3 -0
- data/redis/redis-2.2.11/00-RELEASENOTES +199 -0
- data/redis/redis-2.2.11/BUGS +1 -0
- data/redis/redis-2.2.11/CONTRIBUTING +13 -0
- data/redis/redis-2.2.11/COPYING +10 -0
- data/redis/redis-2.2.11/Changelog +1032 -0
- data/redis/redis-2.2.11/INSTALL +30 -0
- data/redis/redis-2.2.11/Makefile +22 -0
- data/redis/redis-2.2.11/README +83 -0
- data/redis/redis-2.2.11/TODO +4 -0
- data/redis/redis-2.2.11/client-libraries/README +11 -0
- data/redis/redis-2.2.11/deps/hiredis/COPYING +10 -0
- data/redis/redis-2.2.11/deps/hiredis/Makefile +115 -0
- data/redis/redis-2.2.11/deps/hiredis/README.md +311 -0
- data/redis/redis-2.2.11/deps/hiredis/TODO +2 -0
- data/redis/redis-2.2.11/deps/hiredis/adapters/ae.h +95 -0
- data/redis/redis-2.2.11/deps/hiredis/adapters/libev.h +113 -0
- data/redis/redis-2.2.11/deps/hiredis/adapters/libevent.h +76 -0
- data/redis/redis-2.2.11/deps/hiredis/async.c +321 -0
- data/redis/redis-2.2.11/deps/hiredis/async.h +112 -0
- data/redis/redis-2.2.11/deps/hiredis/example-ae.c +53 -0
- data/redis/redis-2.2.11/deps/hiredis/example-libev.c +47 -0
- data/redis/redis-2.2.11/deps/hiredis/example-libevent.c +48 -0
- data/redis/redis-2.2.11/deps/hiredis/example.c +67 -0
- data/redis/redis-2.2.11/deps/hiredis/fmacros.h +15 -0
- data/redis/redis-2.2.11/deps/hiredis/hiredis.c +1058 -0
- data/redis/redis-2.2.11/deps/hiredis/hiredis.h +170 -0
- data/redis/redis-2.2.11/deps/hiredis/net.c +170 -0
- data/redis/redis-2.2.11/deps/hiredis/net.h +43 -0
- data/redis/redis-2.2.11/deps/hiredis/sds.c +479 -0
- data/redis/redis-2.2.11/deps/hiredis/sds.h +77 -0
- data/redis/redis-2.2.11/deps/hiredis/test.c +479 -0
- data/redis/redis-2.2.11/deps/hiredis/util.h +40 -0
- data/redis/redis-2.2.11/deps/linenoise/Makefile +10 -0
- data/redis/redis-2.2.11/deps/linenoise/README.markdown +45 -0
- data/redis/redis-2.2.11/deps/linenoise/example.c +27 -0
- data/redis/redis-2.2.11/deps/linenoise/linenoise.c +609 -0
- data/redis/redis-2.2.11/deps/linenoise/linenoise.h +55 -0
- data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER +214 -0
- data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER-2 +343 -0
- data/redis/redis-2.2.11/doc/AppendCommand.html +48 -0
- data/redis/redis-2.2.11/doc/AppendOnlyFileHowto.html +41 -0
- data/redis/redis-2.2.11/doc/AuthCommand.html +39 -0
- data/redis/redis-2.2.11/doc/Benchmarks.html +129 -0
- data/redis/redis-2.2.11/doc/BgrewriteaofCommand.html +41 -0
- data/redis/redis-2.2.11/doc/BgsaveCommand.html +39 -0
- data/redis/redis-2.2.11/doc/BlpopCommand.html +51 -0
- data/redis/redis-2.2.11/doc/BrpoplpushCommand.html +39 -0
- data/redis/redis-2.2.11/doc/CommandReference.html +47 -0
- data/redis/redis-2.2.11/doc/Comparisons.html +42 -0
- data/redis/redis-2.2.11/doc/ConfigCommand.html +76 -0
- data/redis/redis-2.2.11/doc/Configuration.html +38 -0
- data/redis/redis-2.2.11/doc/ConnectionHandlingSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/ControlCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/Credits.html +38 -0
- data/redis/redis-2.2.11/doc/DbsizeCommand.html +38 -0
- data/redis/redis-2.2.11/doc/DelCommand.html +41 -0
- data/redis/redis-2.2.11/doc/DesignPatterns.html +37 -0
- data/redis/redis-2.2.11/doc/EventLibray.html +44 -0
- data/redis/redis-2.2.11/doc/ExistsCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ExpireCommand.html +96 -0
- data/redis/redis-2.2.11/doc/FAQ.html +70 -0
- data/redis/redis-2.2.11/doc/Features.html +38 -0
- data/redis/redis-2.2.11/doc/FlushallCommand.html +39 -0
- data/redis/redis-2.2.11/doc/FlushdbCommand.html +39 -0
- data/redis/redis-2.2.11/doc/FromSqlToDataStructures.html +37 -0
- data/redis/redis-2.2.11/doc/GenericCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/GetCommand.html +39 -0
- data/redis/redis-2.2.11/doc/GetbitCommand.html +39 -0
- data/redis/redis-2.2.11/doc/GetsetCommand.html +38 -0
- data/redis/redis-2.2.11/doc/HackingStrings.html +83 -0
- data/redis/redis-2.2.11/doc/HashCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/Hashes.html +37 -0
- data/redis/redis-2.2.11/doc/HdelCommand.html +39 -0
- data/redis/redis-2.2.11/doc/HexistsCommand.html +39 -0
- data/redis/redis-2.2.11/doc/HgetCommand.html +39 -0
- data/redis/redis-2.2.11/doc/HgetallCommand.html +40 -0
- data/redis/redis-2.2.11/doc/HincrbyCommand.html +45 -0
- data/redis/redis-2.2.11/doc/HlenCommand.html +38 -0
- data/redis/redis-2.2.11/doc/HmgetCommand.html +40 -0
- data/redis/redis-2.2.11/doc/HmsetCommand.html +40 -0
- data/redis/redis-2.2.11/doc/HsetCommand.html +40 -0
- data/redis/redis-2.2.11/doc/HsetnxCommand.html +41 -0
- data/redis/redis-2.2.11/doc/IncrCommand.html +43 -0
- data/redis/redis-2.2.11/doc/InfoCommand.html +48 -0
- data/redis/redis-2.2.11/doc/IntroductionToRedisDataTypes.html +152 -0
- data/redis/redis-2.2.11/doc/KeysCommand.html +43 -0
- data/redis/redis-2.2.11/doc/LastsaveCommand.html +39 -0
- data/redis/redis-2.2.11/doc/LindexCommand.html +40 -0
- data/redis/redis-2.2.11/doc/ListCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/Lists.html +42 -0
- data/redis/redis-2.2.11/doc/LlenCommand.html +41 -0
- data/redis/redis-2.2.11/doc/LpopCommand.html +41 -0
- data/redis/redis-2.2.11/doc/LrangeCommand.html +47 -0
- data/redis/redis-2.2.11/doc/LremCommand.html +41 -0
- data/redis/redis-2.2.11/doc/LsetCommand.html +38 -0
- data/redis/redis-2.2.11/doc/LtrimCommand.html +47 -0
- data/redis/redis-2.2.11/doc/MgetCommand.html +52 -0
- data/redis/redis-2.2.11/doc/MonitorCommand.html +63 -0
- data/redis/redis-2.2.11/doc/MoveCommand.html +42 -0
- data/redis/redis-2.2.11/doc/MsetCommand.html +44 -0
- data/redis/redis-2.2.11/doc/MultiExecCommand.html +166 -0
- data/redis/redis-2.2.11/doc/NonexistentCommands.html +51 -0
- data/redis/redis-2.2.11/doc/ObjectHashMappers.html +39 -0
- data/redis/redis-2.2.11/doc/Pipelining.html +36 -0
- data/redis/redis-2.2.11/doc/ProgrammingExamples.html +38 -0
- data/redis/redis-2.2.11/doc/ProtocolSpecification.html +137 -0
- data/redis/redis-2.2.11/doc/PublishSubscribe.html +115 -0
- data/redis/redis-2.2.11/doc/QuickStart.html +68 -0
- data/redis/redis-2.2.11/doc/QuitCommand.html +38 -0
- data/redis/redis-2.2.11/doc/README.html +119 -0
- data/redis/redis-2.2.11/doc/RandomkeyCommand.html +39 -0
- data/redis/redis-2.2.11/doc/Redis0100ChangeLog.html +67 -0
- data/redis/redis-2.2.11/doc/Redis0900ChangeLog.html +56 -0
- data/redis/redis-2.2.11/doc/RedisBigData.html +61 -0
- data/redis/redis-2.2.11/doc/RedisCLI.html +37 -0
- data/redis/redis-2.2.11/doc/RedisEventLibrary.html +70 -0
- data/redis/redis-2.2.11/doc/RedisGuides.html +37 -0
- data/redis/redis-2.2.11/doc/RedisInternals.html +38 -0
- data/redis/redis-2.2.11/doc/RedisPipelining.html +93 -0
- data/redis/redis-2.2.11/doc/RedisStatus.html +56 -0
- data/redis/redis-2.2.11/doc/Redis_1_2_0_Changelog.html +40 -0
- data/redis/redis-2.2.11/doc/Redis_2_0_0_Changelog.html +62 -0
- data/redis/redis-2.2.11/doc/Redis_2_0_Whats_new.html +59 -0
- data/redis/redis-2.2.11/doc/RenameCommand.html +39 -0
- data/redis/redis-2.2.11/doc/RenamenxCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ReplicationHowto.html +43 -0
- data/redis/redis-2.2.11/doc/ReplyTypes.html +42 -0
- data/redis/redis-2.2.11/doc/RoadMap.html +38 -0
- data/redis/redis-2.2.11/doc/RpoplpushCommand.html +44 -0
- data/redis/redis-2.2.11/doc/RpushCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SaddCommand.html +41 -0
- data/redis/redis-2.2.11/doc/SaveCommand.html +39 -0
- data/redis/redis-2.2.11/doc/ScardCommand.html +41 -0
- data/redis/redis-2.2.11/doc/SdiffCommand.html +45 -0
- data/redis/redis-2.2.11/doc/SdiffstoreCommand.html +38 -0
- data/redis/redis-2.2.11/doc/SelectCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SetCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SetCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/SetbitCommand.html +45 -0
- data/redis/redis-2.2.11/doc/SetexCommand.html +42 -0
- data/redis/redis-2.2.11/doc/SetnxCommand.html +51 -0
- data/redis/redis-2.2.11/doc/SetrangeCommand.html +58 -0
- data/redis/redis-2.2.11/doc/Sets.html +36 -0
- data/redis/redis-2.2.11/doc/ShutdownCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SideBar.html +36 -0
- data/redis/redis-2.2.11/doc/SinterCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SinterstoreCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SismemberCommand.html +42 -0
- data/redis/redis-2.2.11/doc/SlaveofCommand.html +41 -0
- data/redis/redis-2.2.11/doc/SmembersCommand.html +38 -0
- data/redis/redis-2.2.11/doc/SmoveCommand.html +44 -0
- data/redis/redis-2.2.11/doc/SortCommand.html +75 -0
- data/redis/redis-2.2.11/doc/SortedSetCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/SortedSets.html +36 -0
- data/redis/redis-2.2.11/doc/Speed.html +38 -0
- data/redis/redis-2.2.11/doc/SponsorshipHistory.html +38 -0
- data/redis/redis-2.2.11/doc/SpopCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SrandmemberCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SremCommand.html +42 -0
- data/redis/redis-2.2.11/doc/StringCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/Strings.html +37 -0
- data/redis/redis-2.2.11/doc/StrlenCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SubstrCommand.html +52 -0
- data/redis/redis-2.2.11/doc/SunionCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SunionstoreCommand.html +38 -0
- data/redis/redis-2.2.11/doc/SupportedLanguages.html +60 -0
- data/redis/redis-2.2.11/doc/SupportedPlatforms.html +37 -0
- data/redis/redis-2.2.11/doc/TemplateCommand.html +38 -0
- data/redis/redis-2.2.11/doc/TtlCommand.html +38 -0
- data/redis/redis-2.2.11/doc/TwitterAlikeExample.html +250 -0
- data/redis/redis-2.2.11/doc/TypeCommand.html +46 -0
- data/redis/redis-2.2.11/doc/UnstableSource.html +39 -0
- data/redis/redis-2.2.11/doc/VirtualMemorySpecification.html +156 -0
- data/redis/redis-2.2.11/doc/VirtualMemoryUserGuide.html +66 -0
- data/redis/redis-2.2.11/doc/ZaddCommand.html +43 -0
- data/redis/redis-2.2.11/doc/ZcardCommand.html +41 -0
- data/redis/redis-2.2.11/doc/ZincrbyCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ZrangeCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ZrangebyscoreCommand.html +77 -0
- data/redis/redis-2.2.11/doc/ZrankCommand.html +43 -0
- data/redis/redis-2.2.11/doc/ZremCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ZremrangebyrankCommand.html +39 -0
- data/redis/redis-2.2.11/doc/ZremrangebyscoreCommand.html +39 -0
- data/redis/redis-2.2.11/doc/ZscoreCommand.html +41 -0
- data/redis/redis-2.2.11/doc/ZunionCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ZunionstoreCommand.html +43 -0
- data/redis/redis-2.2.11/doc/index.html +43 -0
- data/redis/redis-2.2.11/doc/redis.png +0 -0
- data/redis/redis-2.2.11/doc/style.css +25 -0
- data/redis/redis-2.2.11/redis.conf +417 -0
- data/redis/redis-2.2.11/src/Makefile +177 -0
- data/redis/redis-2.2.11/src/adlist.c +325 -0
- data/redis/redis-2.2.11/src/adlist.h +92 -0
- data/redis/redis-2.2.11/src/ae.c +390 -0
- data/redis/redis-2.2.11/src/ae.h +117 -0
- data/redis/redis-2.2.11/src/ae_epoll.c +91 -0
- data/redis/redis-2.2.11/src/ae_kqueue.c +93 -0
- data/redis/redis-2.2.11/src/ae_select.c +72 -0
- data/redis/redis-2.2.11/src/anet.c +347 -0
- data/redis/redis-2.2.11/src/anet.h +57 -0
- data/redis/redis-2.2.11/src/aof.c +675 -0
- data/redis/redis-2.2.11/src/config.c +627 -0
- data/redis/redis-2.2.11/src/config.h +64 -0
- data/redis/redis-2.2.11/src/db.c +543 -0
- data/redis/redis-2.2.11/src/debug.c +314 -0
- data/redis/redis-2.2.11/src/dict.c +721 -0
- data/redis/redis-2.2.11/src/dict.h +156 -0
- data/redis/redis-2.2.11/src/fmacros.h +15 -0
- data/redis/redis-2.2.11/src/help.h +638 -0
- data/redis/redis-2.2.11/src/intset.c +422 -0
- data/redis/redis-2.2.11/src/intset.h +19 -0
- data/redis/redis-2.2.11/src/lzf.h +100 -0
- data/redis/redis-2.2.11/src/lzfP.h +159 -0
- data/redis/redis-2.2.11/src/lzf_c.c +295 -0
- data/redis/redis-2.2.11/src/lzf_d.c +150 -0
- data/redis/redis-2.2.11/src/mkreleasehdr.sh +9 -0
- data/redis/redis-2.2.11/src/multi.c +268 -0
- data/redis/redis-2.2.11/src/networking.c +899 -0
- data/redis/redis-2.2.11/src/object.c +484 -0
- data/redis/redis-2.2.11/src/pqsort.c +197 -0
- data/redis/redis-2.2.11/src/pqsort.h +15 -0
- data/redis/redis-2.2.11/src/pubsub.c +267 -0
- data/redis/redis-2.2.11/src/rdb.c +1020 -0
- data/redis/redis-2.2.11/src/redis-benchmark.c +530 -0
- data/redis/redis-2.2.11/src/redis-check-aof.c +185 -0
- data/redis/redis-2.2.11/src/redis-check-dump.c +681 -0
- data/redis/redis-2.2.11/src/redis-cli.c +773 -0
- data/redis/redis-2.2.11/src/redis.c +1677 -0
- data/redis/redis-2.2.11/src/redis.h +1022 -0
- data/redis/redis-2.2.11/src/release.c +13 -0
- data/redis/redis-2.2.11/src/replication.c +557 -0
- data/redis/redis-2.2.11/src/sds.c +639 -0
- data/redis/redis-2.2.11/src/sds.h +78 -0
- data/redis/redis-2.2.11/src/sha1.c +276 -0
- data/redis/redis-2.2.11/src/sha1.h +17 -0
- data/redis/redis-2.2.11/src/solarisfixes.h +22 -0
- data/redis/redis-2.2.11/src/sort.c +389 -0
- data/redis/redis-2.2.11/src/syncio.c +154 -0
- data/redis/redis-2.2.11/src/t_hash.c +476 -0
- data/redis/redis-2.2.11/src/t_list.c +986 -0
- data/redis/redis-2.2.11/src/t_set.c +610 -0
- data/redis/redis-2.2.11/src/t_string.c +438 -0
- data/redis/redis-2.2.11/src/t_zset.c +1084 -0
- data/redis/redis-2.2.11/src/testhelp.h +54 -0
- data/redis/redis-2.2.11/src/util.c +243 -0
- data/redis/redis-2.2.11/src/valgrind.sup +5 -0
- data/redis/redis-2.2.11/src/version.h +1 -0
- data/redis/redis-2.2.11/src/vm.c +1149 -0
- data/redis/redis-2.2.11/src/ziplist.c +1323 -0
- data/redis/redis-2.2.11/src/ziplist.h +15 -0
- data/redis/redis-2.2.11/src/zipmap.c +455 -0
- data/redis/redis-2.2.11/src/zipmap.h +48 -0
- data/redis/redis-2.2.11/src/zmalloc.c +278 -0
- data/redis/redis-2.2.11/src/zmalloc.h +47 -0
- data/redis/redis-2.2.11/tests/assets/default.conf +308 -0
- data/redis/redis-2.2.11/tests/integration/aof.tcl +104 -0
- data/redis/redis-2.2.11/tests/integration/redis-cli.tcl +208 -0
- data/redis/redis-2.2.11/tests/integration/replication.tcl +98 -0
- data/redis/redis-2.2.11/tests/support/redis.tcl +241 -0
- data/redis/redis-2.2.11/tests/support/server.tcl +294 -0
- data/redis/redis-2.2.11/tests/support/test.tcl +190 -0
- data/redis/redis-2.2.11/tests/support/tmpfile.tcl +15 -0
- data/redis/redis-2.2.11/tests/support/util.tcl +296 -0
- data/redis/redis-2.2.11/tests/test_helper.tcl +221 -0
- data/redis/redis-2.2.11/tests/unit/auth.tcl +15 -0
- data/redis/redis-2.2.11/tests/unit/basic.tcl +616 -0
- data/redis/redis-2.2.11/tests/unit/cas.tcl +135 -0
- data/redis/redis-2.2.11/tests/unit/expire.tcl +74 -0
- data/redis/redis-2.2.11/tests/unit/other.tcl +240 -0
- data/redis/redis-2.2.11/tests/unit/printver.tcl +6 -0
- data/redis/redis-2.2.11/tests/unit/protocol.tcl +62 -0
- data/redis/redis-2.2.11/tests/unit/pubsub.tcl +195 -0
- data/redis/redis-2.2.11/tests/unit/quit.tcl +40 -0
- data/redis/redis-2.2.11/tests/unit/sort.tcl +189 -0
- data/redis/redis-2.2.11/tests/unit/type/hash.tcl +300 -0
- data/redis/redis-2.2.11/tests/unit/type/list.tcl +819 -0
- data/redis/redis-2.2.11/tests/unit/type/set.tcl +334 -0
- data/redis/redis-2.2.11/tests/unit/type/zset.tcl +587 -0
- data/redis/redis-2.2.11/utils/build-static-symbols.tcl +22 -0
- data/redis/redis-2.2.11/utils/generate-command-help.rb +112 -0
- data/redis/redis-2.2.11/utils/mktarball.sh +13 -0
- data/redis/redis-2.2.11/utils/redis-copy.rb +78 -0
- data/redis/redis-2.2.11/utils/redis-sha1.rb +52 -0
- data/redis/redis-2.2.11/utils/redis_init_script +42 -0
- metadata +362 -0
@@ -0,0 +1,104 @@
|
|
1
|
+
set defaults { appendonly {yes} appendfilename {appendonly.aof} }
|
2
|
+
set server_path [tmpdir server.aof]
|
3
|
+
set aof_path "$server_path/appendonly.aof"
|
4
|
+
|
5
|
+
proc append_to_aof {str} {
|
6
|
+
upvar fp fp
|
7
|
+
puts -nonewline $fp $str
|
8
|
+
}
|
9
|
+
|
10
|
+
proc create_aof {code} {
|
11
|
+
upvar fp fp aof_path aof_path
|
12
|
+
set fp [open $aof_path w+]
|
13
|
+
uplevel 1 $code
|
14
|
+
close $fp
|
15
|
+
}
|
16
|
+
|
17
|
+
proc start_server_aof {overrides code} {
|
18
|
+
upvar defaults defaults srv srv server_path server_path
|
19
|
+
set config [concat $defaults $overrides]
|
20
|
+
set srv [start_server [list overrides $config]]
|
21
|
+
uplevel 1 $code
|
22
|
+
kill_server $srv
|
23
|
+
}
|
24
|
+
|
25
|
+
tags {"aof"} {
|
26
|
+
## Test the server doesn't start when the AOF contains an unfinished MULTI
|
27
|
+
create_aof {
|
28
|
+
append_to_aof [formatCommand set foo hello]
|
29
|
+
append_to_aof [formatCommand multi]
|
30
|
+
append_to_aof [formatCommand set bar world]
|
31
|
+
}
|
32
|
+
|
33
|
+
start_server_aof [list dir $server_path] {
|
34
|
+
test "Unfinished MULTI: Server should not have been started" {
|
35
|
+
assert_equal 0 [is_alive $srv]
|
36
|
+
}
|
37
|
+
|
38
|
+
test "Unfinished MULTI: Server should have logged an error" {
|
39
|
+
set result [exec cat [dict get $srv stdout] | tail -n1]
|
40
|
+
assert_match "*Unexpected end of file reading the append only file*" $result
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
## Test that the server exits when the AOF contains a short read
|
45
|
+
create_aof {
|
46
|
+
append_to_aof [formatCommand set foo hello]
|
47
|
+
append_to_aof [string range [formatCommand set bar world] 0 end-1]
|
48
|
+
}
|
49
|
+
|
50
|
+
start_server_aof [list dir $server_path] {
|
51
|
+
test "Short read: Server should not have been started" {
|
52
|
+
assert_equal 0 [is_alive $srv]
|
53
|
+
}
|
54
|
+
|
55
|
+
test "Short read: Server should have logged an error" {
|
56
|
+
set result [exec cat [dict get $srv stdout] | tail -n1]
|
57
|
+
assert_match "*Bad file format reading the append only file*" $result
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
## Test that redis-check-aof indeed sees this AOF is not valid
|
62
|
+
test "Short read: Utility should confirm the AOF is not valid" {
|
63
|
+
catch {
|
64
|
+
exec src/redis-check-aof $aof_path
|
65
|
+
} result
|
66
|
+
assert_match "*not valid*" $result
|
67
|
+
}
|
68
|
+
|
69
|
+
test "Short read: Utility should be able to fix the AOF" {
|
70
|
+
set result [exec echo y | src/redis-check-aof --fix $aof_path]
|
71
|
+
assert_match "*Successfully truncated AOF*" $result
|
72
|
+
}
|
73
|
+
|
74
|
+
## Test that the server can be started using the truncated AOF
|
75
|
+
start_server_aof [list dir $server_path] {
|
76
|
+
test "Fixed AOF: Server should have been started" {
|
77
|
+
assert_equal 1 [is_alive $srv]
|
78
|
+
}
|
79
|
+
|
80
|
+
test "Fixed AOF: Keyspace should contain values that were parsable" {
|
81
|
+
set client [redis [dict get $srv host] [dict get $srv port]]
|
82
|
+
assert_equal "hello" [$client get foo]
|
83
|
+
assert_equal "" [$client get bar]
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
## Test that SPOP (that modifies the client its argc/argv) is correctly free'd
|
88
|
+
create_aof {
|
89
|
+
append_to_aof [formatCommand sadd set foo]
|
90
|
+
append_to_aof [formatCommand sadd set bar]
|
91
|
+
append_to_aof [formatCommand spop set]
|
92
|
+
}
|
93
|
+
|
94
|
+
start_server_aof [list dir $server_path] {
|
95
|
+
test "AOF+SPOP: Server should have been started" {
|
96
|
+
assert_equal 1 [is_alive $srv]
|
97
|
+
}
|
98
|
+
|
99
|
+
test "AOF+SPOP: Set should have 1 member" {
|
100
|
+
set client [redis [dict get $srv host] [dict get $srv port]]
|
101
|
+
assert_equal 1 [$client scard set]
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
@@ -0,0 +1,208 @@
|
|
1
|
+
start_server {tags {"cli"}} {
|
2
|
+
proc open_cli {} {
|
3
|
+
set ::env(TERM) dumb
|
4
|
+
set fd [open [format "|src/redis-cli -p %d -n 9" [srv port]] "r+"]
|
5
|
+
fconfigure $fd -buffering none
|
6
|
+
fconfigure $fd -blocking false
|
7
|
+
fconfigure $fd -translation binary
|
8
|
+
assert_equal "redis> " [read_cli $fd]
|
9
|
+
set _ $fd
|
10
|
+
}
|
11
|
+
|
12
|
+
proc close_cli {fd} {
|
13
|
+
close $fd
|
14
|
+
}
|
15
|
+
|
16
|
+
proc read_cli {fd} {
|
17
|
+
set buf [read $fd]
|
18
|
+
while {[string length $buf] == 0} {
|
19
|
+
# wait some time and try again
|
20
|
+
after 10
|
21
|
+
set buf [read $fd]
|
22
|
+
}
|
23
|
+
set _ $buf
|
24
|
+
}
|
25
|
+
|
26
|
+
proc write_cli {fd buf} {
|
27
|
+
puts $fd $buf
|
28
|
+
flush $fd
|
29
|
+
}
|
30
|
+
|
31
|
+
# Helpers to run tests in interactive mode
|
32
|
+
proc run_command {fd cmd} {
|
33
|
+
write_cli $fd $cmd
|
34
|
+
set lines [split [read_cli $fd] "\n"]
|
35
|
+
assert_equal "redis> " [lindex $lines end]
|
36
|
+
join [lrange $lines 0 end-1] "\n"
|
37
|
+
}
|
38
|
+
|
39
|
+
proc test_interactive_cli {name code} {
|
40
|
+
set ::env(FAKETTY) 1
|
41
|
+
set fd [open_cli]
|
42
|
+
test "Interactive CLI: $name" $code
|
43
|
+
close_cli $fd
|
44
|
+
unset ::env(FAKETTY)
|
45
|
+
}
|
46
|
+
|
47
|
+
# Helpers to run tests where stdout is not a tty
|
48
|
+
proc write_tmpfile {contents} {
|
49
|
+
set tmp [tmpfile "cli"]
|
50
|
+
set tmpfd [open $tmp "w"]
|
51
|
+
puts -nonewline $tmpfd $contents
|
52
|
+
close $tmpfd
|
53
|
+
set _ $tmp
|
54
|
+
}
|
55
|
+
|
56
|
+
proc _run_cli {opts args} {
|
57
|
+
set cmd [format "src/redis-cli -p %d -n 9 $args" [srv port]]
|
58
|
+
foreach {key value} $opts {
|
59
|
+
if {$key eq "pipe"} {
|
60
|
+
set cmd "sh -c \"$value | $cmd\""
|
61
|
+
}
|
62
|
+
if {$key eq "path"} {
|
63
|
+
set cmd "$cmd < $value"
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
set fd [open "|$cmd" "r"]
|
68
|
+
fconfigure $fd -buffering none
|
69
|
+
fconfigure $fd -translation binary
|
70
|
+
set resp [read $fd 1048576]
|
71
|
+
close $fd
|
72
|
+
set _ $resp
|
73
|
+
}
|
74
|
+
|
75
|
+
proc run_cli {args} {
|
76
|
+
_run_cli {} {*}$args
|
77
|
+
}
|
78
|
+
|
79
|
+
proc run_cli_with_input_pipe {cmd args} {
|
80
|
+
_run_cli [list pipe $cmd] {*}$args
|
81
|
+
}
|
82
|
+
|
83
|
+
proc run_cli_with_input_file {path args} {
|
84
|
+
_run_cli [list path $path] {*}$args
|
85
|
+
}
|
86
|
+
|
87
|
+
proc test_nontty_cli {name code} {
|
88
|
+
test "Non-interactive non-TTY CLI: $name" $code
|
89
|
+
}
|
90
|
+
|
91
|
+
# Helpers to run tests where stdout is a tty (fake it)
|
92
|
+
proc test_tty_cli {name code} {
|
93
|
+
set ::env(FAKETTY) 1
|
94
|
+
test "Non-interactive TTY CLI: $name" $code
|
95
|
+
unset ::env(FAKETTY)
|
96
|
+
}
|
97
|
+
|
98
|
+
test_interactive_cli "INFO response should be printed raw" {
|
99
|
+
set lines [split [run_command $fd info] "\n"]
|
100
|
+
foreach line $lines {
|
101
|
+
assert [regexp {^[a-z0-9_]+:[a-z0-9_]+} $line]
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
test_interactive_cli "Status reply" {
|
106
|
+
assert_equal "OK" [run_command $fd "set key foo"]
|
107
|
+
}
|
108
|
+
|
109
|
+
test_interactive_cli "Integer reply" {
|
110
|
+
assert_equal "(integer) 1" [run_command $fd "incr counter"]
|
111
|
+
}
|
112
|
+
|
113
|
+
test_interactive_cli "Bulk reply" {
|
114
|
+
r set key foo
|
115
|
+
assert_equal "\"foo\"" [run_command $fd "get key"]
|
116
|
+
}
|
117
|
+
|
118
|
+
test_interactive_cli "Multi-bulk reply" {
|
119
|
+
r rpush list foo
|
120
|
+
r rpush list bar
|
121
|
+
assert_equal "1. \"foo\"\n2. \"bar\"" [run_command $fd "lrange list 0 -1"]
|
122
|
+
}
|
123
|
+
|
124
|
+
test_interactive_cli "Parsing quotes" {
|
125
|
+
assert_equal "OK" [run_command $fd "set key \"bar\""]
|
126
|
+
assert_equal "bar" [r get key]
|
127
|
+
assert_equal "OK" [run_command $fd "set key \" bar \""]
|
128
|
+
assert_equal " bar " [r get key]
|
129
|
+
assert_equal "OK" [run_command $fd "set key \"\\\"bar\\\"\""]
|
130
|
+
assert_equal "\"bar\"" [r get key]
|
131
|
+
assert_equal "OK" [run_command $fd "set key \"\tbar\t\""]
|
132
|
+
assert_equal "\tbar\t" [r get key]
|
133
|
+
|
134
|
+
# invalid quotation
|
135
|
+
assert_equal "Invalid argument(s)" [run_command $fd "get \"\"key"]
|
136
|
+
assert_equal "Invalid argument(s)" [run_command $fd "get \"key\"x"]
|
137
|
+
|
138
|
+
# quotes after the argument are weird, but should be allowed
|
139
|
+
assert_equal "OK" [run_command $fd "set key\"\" bar"]
|
140
|
+
assert_equal "bar" [r get key]
|
141
|
+
}
|
142
|
+
|
143
|
+
test_tty_cli "Status reply" {
|
144
|
+
assert_equal "OK\n" [run_cli set key bar]
|
145
|
+
assert_equal "bar" [r get key]
|
146
|
+
}
|
147
|
+
|
148
|
+
test_tty_cli "Integer reply" {
|
149
|
+
r del counter
|
150
|
+
assert_equal "(integer) 1\n" [run_cli incr counter]
|
151
|
+
}
|
152
|
+
|
153
|
+
test_tty_cli "Bulk reply" {
|
154
|
+
r set key "tab\tnewline\n"
|
155
|
+
assert_equal "\"tab\\tnewline\\n\"\n" [run_cli get key]
|
156
|
+
}
|
157
|
+
|
158
|
+
test_tty_cli "Multi-bulk reply" {
|
159
|
+
r del list
|
160
|
+
r rpush list foo
|
161
|
+
r rpush list bar
|
162
|
+
assert_equal "1. \"foo\"\n2. \"bar\"\n" [run_cli lrange list 0 -1]
|
163
|
+
}
|
164
|
+
|
165
|
+
test_tty_cli "Read last argument from pipe" {
|
166
|
+
assert_equal "OK\n" [run_cli_with_input_pipe "echo foo" set key]
|
167
|
+
assert_equal "foo\n" [r get key]
|
168
|
+
}
|
169
|
+
|
170
|
+
test_tty_cli "Read last argument from file" {
|
171
|
+
set tmpfile [write_tmpfile "from file"]
|
172
|
+
assert_equal "OK\n" [run_cli_with_input_file $tmpfile set key]
|
173
|
+
assert_equal "from file" [r get key]
|
174
|
+
}
|
175
|
+
|
176
|
+
test_nontty_cli "Status reply" {
|
177
|
+
assert_equal "OK" [run_cli set key bar]
|
178
|
+
assert_equal "bar" [r get key]
|
179
|
+
}
|
180
|
+
|
181
|
+
test_nontty_cli "Integer reply" {
|
182
|
+
r del counter
|
183
|
+
assert_equal "1" [run_cli incr counter]
|
184
|
+
}
|
185
|
+
|
186
|
+
test_nontty_cli "Bulk reply" {
|
187
|
+
r set key "tab\tnewline\n"
|
188
|
+
assert_equal "tab\tnewline\n" [run_cli get key]
|
189
|
+
}
|
190
|
+
|
191
|
+
test_nontty_cli "Multi-bulk reply" {
|
192
|
+
r del list
|
193
|
+
r rpush list foo
|
194
|
+
r rpush list bar
|
195
|
+
assert_equal "foo\nbar" [run_cli lrange list 0 -1]
|
196
|
+
}
|
197
|
+
|
198
|
+
test_nontty_cli "Read last argument from pipe" {
|
199
|
+
assert_equal "OK" [run_cli_with_input_pipe "echo foo" set key]
|
200
|
+
assert_equal "foo\n" [r get key]
|
201
|
+
}
|
202
|
+
|
203
|
+
test_nontty_cli "Read last argument from file" {
|
204
|
+
set tmpfile [write_tmpfile "from file"]
|
205
|
+
assert_equal "OK" [run_cli_with_input_file $tmpfile set key]
|
206
|
+
assert_equal "from file" [r get key]
|
207
|
+
}
|
208
|
+
}
|
@@ -0,0 +1,98 @@
|
|
1
|
+
start_server {tags {"repl"}} {
|
2
|
+
start_server {} {
|
3
|
+
test {First server should have role slave after SLAVEOF} {
|
4
|
+
r -1 slaveof [srv 0 host] [srv 0 port]
|
5
|
+
after 1000
|
6
|
+
s -1 role
|
7
|
+
} {slave}
|
8
|
+
|
9
|
+
test {BRPOPLPUSH replication, when blocking against empty list} {
|
10
|
+
set rd [redis_deferring_client]
|
11
|
+
$rd brpoplpush a b 5
|
12
|
+
r lpush a foo
|
13
|
+
after 1000
|
14
|
+
assert_equal [r debug digest] [r -1 debug digest]
|
15
|
+
}
|
16
|
+
|
17
|
+
test {BRPOPLPUSH replication, list exists} {
|
18
|
+
set rd [redis_deferring_client]
|
19
|
+
r lpush c 1
|
20
|
+
r lpush c 2
|
21
|
+
r lpush c 3
|
22
|
+
$rd brpoplpush c d 5
|
23
|
+
after 1000
|
24
|
+
assert_equal [r debug digest] [r -1 debug digest]
|
25
|
+
}
|
26
|
+
|
27
|
+
test {MASTER and SLAVE dataset should be identical after complex ops} {
|
28
|
+
createComplexDataset r 10000
|
29
|
+
after 500
|
30
|
+
if {[r debug digest] ne [r -1 debug digest]} {
|
31
|
+
set csv1 [csvdump r]
|
32
|
+
set csv2 [csvdump {r -1}]
|
33
|
+
set fd [open /tmp/repldump1.txt w]
|
34
|
+
puts -nonewline $fd $csv1
|
35
|
+
close $fd
|
36
|
+
set fd [open /tmp/repldump2.txt w]
|
37
|
+
puts -nonewline $fd $csv2
|
38
|
+
close $fd
|
39
|
+
puts "Master - Slave inconsistency"
|
40
|
+
puts "Run diff -u against /tmp/repldump*.txt for more info"
|
41
|
+
}
|
42
|
+
assert_equal [r debug digest] [r -1 debug digest]
|
43
|
+
}
|
44
|
+
|
45
|
+
test {MASTER and SLAVE consistency with expire} {
|
46
|
+
createComplexDataset r 50000 useexpire
|
47
|
+
after 4000 ;# Make sure everything expired before taking the digest
|
48
|
+
r keys * ;# Force DEL syntesizing to slave
|
49
|
+
after 1000 ;# Wait another second. Now everything should be fine.
|
50
|
+
if {[r debug digest] ne [r -1 debug digest]} {
|
51
|
+
set csv1 [csvdump r]
|
52
|
+
set csv2 [csvdump {r -1}]
|
53
|
+
set fd [open /tmp/repldump1.txt w]
|
54
|
+
puts -nonewline $fd $csv1
|
55
|
+
close $fd
|
56
|
+
set fd [open /tmp/repldump2.txt w]
|
57
|
+
puts -nonewline $fd $csv2
|
58
|
+
close $fd
|
59
|
+
puts "Master - Slave inconsistency"
|
60
|
+
puts "Run diff -u against /tmp/repldump*.txt for more info"
|
61
|
+
}
|
62
|
+
assert_equal [r debug digest] [r -1 debug digest]
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
start_server {tags {"repl"}} {
|
68
|
+
r set mykey foo
|
69
|
+
|
70
|
+
start_server {} {
|
71
|
+
test {Second server should have role master at first} {
|
72
|
+
s role
|
73
|
+
} {master}
|
74
|
+
|
75
|
+
test {SLAVEOF should start with link status "down"} {
|
76
|
+
r slaveof [srv -1 host] [srv -1 port]
|
77
|
+
s master_link_status
|
78
|
+
} {down}
|
79
|
+
|
80
|
+
test {The role should immediately be changed to "slave"} {
|
81
|
+
s role
|
82
|
+
} {slave}
|
83
|
+
|
84
|
+
wait_for_sync r
|
85
|
+
test {Sync should have transferred keys from master} {
|
86
|
+
r get mykey
|
87
|
+
} {foo}
|
88
|
+
|
89
|
+
test {The link status should be up} {
|
90
|
+
s master_link_status
|
91
|
+
} {up}
|
92
|
+
|
93
|
+
test {SET on the master should immediately propagate} {
|
94
|
+
r -1 set mykey bar
|
95
|
+
r 0 get mykey
|
96
|
+
} {bar}
|
97
|
+
}
|
98
|
+
}
|
@@ -0,0 +1,241 @@
|
|
1
|
+
# Tcl clinet library - used by test-redis.tcl script for now
|
2
|
+
# Copyright (C) 2009 Salvatore Sanfilippo
|
3
|
+
# Released under the BSD license like Redis itself
|
4
|
+
#
|
5
|
+
# Example usage:
|
6
|
+
#
|
7
|
+
# set r [redis 127.0.0.1 6379]
|
8
|
+
# $r lpush mylist foo
|
9
|
+
# $r lpush mylist bar
|
10
|
+
# $r lrange mylist 0 -1
|
11
|
+
# $r close
|
12
|
+
#
|
13
|
+
# Non blocking usage example:
|
14
|
+
#
|
15
|
+
# proc handlePong {r type reply} {
|
16
|
+
# puts "PONG $type '$reply'"
|
17
|
+
# if {$reply ne "PONG"} {
|
18
|
+
# $r ping [list handlePong]
|
19
|
+
# }
|
20
|
+
# }
|
21
|
+
#
|
22
|
+
# set r [redis]
|
23
|
+
# $r blocking 0
|
24
|
+
# $r get fo [list handlePong]
|
25
|
+
#
|
26
|
+
# vwait forever
|
27
|
+
|
28
|
+
package require Tcl 8.5
|
29
|
+
package provide redis 0.1
|
30
|
+
|
31
|
+
namespace eval redis {}
|
32
|
+
set ::redis::id 0
|
33
|
+
array set ::redis::fd {}
|
34
|
+
array set ::redis::blocking {}
|
35
|
+
array set ::redis::deferred {}
|
36
|
+
array set ::redis::callback {}
|
37
|
+
array set ::redis::state {} ;# State in non-blocking reply reading
|
38
|
+
array set ::redis::statestack {} ;# Stack of states, for nested mbulks
|
39
|
+
|
40
|
+
proc redis {{server 127.0.0.1} {port 6379} {defer 0}} {
|
41
|
+
set fd [socket $server $port]
|
42
|
+
fconfigure $fd -translation binary
|
43
|
+
set id [incr ::redis::id]
|
44
|
+
set ::redis::fd($id) $fd
|
45
|
+
set ::redis::blocking($id) 1
|
46
|
+
set ::redis::deferred($id) $defer
|
47
|
+
::redis::redis_reset_state $id
|
48
|
+
interp alias {} ::redis::redisHandle$id {} ::redis::__dispatch__ $id
|
49
|
+
}
|
50
|
+
|
51
|
+
proc ::redis::__dispatch__ {id method args} {
|
52
|
+
set fd $::redis::fd($id)
|
53
|
+
set blocking $::redis::blocking($id)
|
54
|
+
set deferred $::redis::deferred($id)
|
55
|
+
if {$blocking == 0} {
|
56
|
+
if {[llength $args] == 0} {
|
57
|
+
error "Please provide a callback in non-blocking mode"
|
58
|
+
}
|
59
|
+
set callback [lindex $args end]
|
60
|
+
set args [lrange $args 0 end-1]
|
61
|
+
}
|
62
|
+
if {[info command ::redis::__method__$method] eq {}} {
|
63
|
+
set cmd "*[expr {[llength $args]+1}]\r\n"
|
64
|
+
append cmd "$[string length $method]\r\n$method\r\n"
|
65
|
+
foreach a $args {
|
66
|
+
append cmd "$[string length $a]\r\n$a\r\n"
|
67
|
+
}
|
68
|
+
::redis::redis_write $fd $cmd
|
69
|
+
flush $fd
|
70
|
+
|
71
|
+
if {!$deferred} {
|
72
|
+
if {$blocking} {
|
73
|
+
::redis::redis_read_reply $fd
|
74
|
+
} else {
|
75
|
+
# Every well formed reply read will pop an element from this
|
76
|
+
# list and use it as a callback. So pipelining is supported
|
77
|
+
# in non blocking mode.
|
78
|
+
lappend ::redis::callback($id) $callback
|
79
|
+
fileevent $fd readable [list ::redis::redis_readable $fd $id]
|
80
|
+
}
|
81
|
+
}
|
82
|
+
} else {
|
83
|
+
uplevel 1 [list ::redis::__method__$method $id $fd] $args
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
proc ::redis::__method__blocking {id fd val} {
|
88
|
+
set ::redis::blocking($id) $val
|
89
|
+
fconfigure $fd -blocking $val
|
90
|
+
}
|
91
|
+
|
92
|
+
proc ::redis::__method__read {id fd} {
|
93
|
+
::redis::redis_read_reply $fd
|
94
|
+
}
|
95
|
+
|
96
|
+
proc ::redis::__method__write {id fd buf} {
|
97
|
+
::redis::redis_write $fd $buf
|
98
|
+
}
|
99
|
+
|
100
|
+
proc ::redis::__method__flush {id fd} {
|
101
|
+
flush $fd
|
102
|
+
}
|
103
|
+
|
104
|
+
proc ::redis::__method__close {id fd} {
|
105
|
+
catch {close $fd}
|
106
|
+
catch {unset ::redis::fd($id)}
|
107
|
+
catch {unset ::redis::blocking($id)}
|
108
|
+
catch {unset ::redis::state($id)}
|
109
|
+
catch {unset ::redis::statestack($id)}
|
110
|
+
catch {unset ::redis::callback($id)}
|
111
|
+
catch {interp alias {} ::redis::redisHandle$id {}}
|
112
|
+
}
|
113
|
+
|
114
|
+
proc ::redis::__method__channel {id fd} {
|
115
|
+
return $fd
|
116
|
+
}
|
117
|
+
|
118
|
+
proc ::redis::redis_write {fd buf} {
|
119
|
+
puts -nonewline $fd $buf
|
120
|
+
}
|
121
|
+
|
122
|
+
proc ::redis::redis_writenl {fd buf} {
|
123
|
+
redis_write $fd $buf
|
124
|
+
redis_write $fd "\r\n"
|
125
|
+
flush $fd
|
126
|
+
}
|
127
|
+
|
128
|
+
proc ::redis::redis_readnl {fd len} {
|
129
|
+
set buf [read $fd $len]
|
130
|
+
read $fd 2 ; # discard CR LF
|
131
|
+
return $buf
|
132
|
+
}
|
133
|
+
|
134
|
+
proc ::redis::redis_bulk_read {fd} {
|
135
|
+
set count [redis_read_line $fd]
|
136
|
+
if {$count == -1} return {}
|
137
|
+
set buf [redis_readnl $fd $count]
|
138
|
+
return $buf
|
139
|
+
}
|
140
|
+
|
141
|
+
proc ::redis::redis_multi_bulk_read fd {
|
142
|
+
set count [redis_read_line $fd]
|
143
|
+
if {$count == -1} return {}
|
144
|
+
set l {}
|
145
|
+
for {set i 0} {$i < $count} {incr i} {
|
146
|
+
lappend l [redis_read_reply $fd]
|
147
|
+
}
|
148
|
+
return $l
|
149
|
+
}
|
150
|
+
|
151
|
+
proc ::redis::redis_read_line fd {
|
152
|
+
string trim [gets $fd]
|
153
|
+
}
|
154
|
+
|
155
|
+
proc ::redis::redis_read_reply fd {
|
156
|
+
set type [read $fd 1]
|
157
|
+
switch -exact -- $type {
|
158
|
+
: -
|
159
|
+
+ {redis_read_line $fd}
|
160
|
+
- {return -code error [redis_read_line $fd]}
|
161
|
+
$ {redis_bulk_read $fd}
|
162
|
+
* {redis_multi_bulk_read $fd}
|
163
|
+
default {return -code error "Bad protocol, $type as reply type byte"}
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
proc ::redis::redis_reset_state id {
|
168
|
+
set ::redis::state($id) [dict create buf {} mbulk -1 bulk -1 reply {}]
|
169
|
+
set ::redis::statestack($id) {}
|
170
|
+
}
|
171
|
+
|
172
|
+
proc ::redis::redis_call_callback {id type reply} {
|
173
|
+
set cb [lindex $::redis::callback($id) 0]
|
174
|
+
set ::redis::callback($id) [lrange $::redis::callback($id) 1 end]
|
175
|
+
uplevel #0 $cb [list ::redis::redisHandle$id $type $reply]
|
176
|
+
::redis::redis_reset_state $id
|
177
|
+
}
|
178
|
+
|
179
|
+
# Read a reply in non-blocking mode.
|
180
|
+
proc ::redis::redis_readable {fd id} {
|
181
|
+
if {[eof $fd]} {
|
182
|
+
redis_call_callback $id eof {}
|
183
|
+
::redis::__method__close $id $fd
|
184
|
+
return
|
185
|
+
}
|
186
|
+
if {[dict get $::redis::state($id) bulk] == -1} {
|
187
|
+
set line [gets $fd]
|
188
|
+
if {$line eq {}} return ;# No complete line available, return
|
189
|
+
switch -exact -- [string index $line 0] {
|
190
|
+
: -
|
191
|
+
+ {redis_call_callback $id reply [string range $line 1 end-1]}
|
192
|
+
- {redis_call_callback $id err [string range $line 1 end-1]}
|
193
|
+
$ {
|
194
|
+
dict set ::redis::state($id) bulk \
|
195
|
+
[expr [string range $line 1 end-1]+2]
|
196
|
+
if {[dict get $::redis::state($id) bulk] == 1} {
|
197
|
+
# We got a $-1, hack the state to play well with this.
|
198
|
+
dict set ::redis::state($id) bulk 2
|
199
|
+
dict set ::redis::state($id) buf "\r\n"
|
200
|
+
::redis::redis_readable $fd $id
|
201
|
+
}
|
202
|
+
}
|
203
|
+
* {
|
204
|
+
dict set ::redis::state($id) mbulk [string range $line 1 end-1]
|
205
|
+
# Handle *-1
|
206
|
+
if {[dict get $::redis::state($id) mbulk] == -1} {
|
207
|
+
redis_call_callback $id reply {}
|
208
|
+
}
|
209
|
+
}
|
210
|
+
default {
|
211
|
+
redis_call_callback $id err \
|
212
|
+
"Bad protocol, $type as reply type byte"
|
213
|
+
}
|
214
|
+
}
|
215
|
+
} else {
|
216
|
+
set totlen [dict get $::redis::state($id) bulk]
|
217
|
+
set buflen [string length [dict get $::redis::state($id) buf]]
|
218
|
+
set toread [expr {$totlen-$buflen}]
|
219
|
+
set data [read $fd $toread]
|
220
|
+
set nread [string length $data]
|
221
|
+
dict append ::redis::state($id) buf $data
|
222
|
+
# Check if we read a complete bulk reply
|
223
|
+
if {[string length [dict get $::redis::state($id) buf]] ==
|
224
|
+
[dict get $::redis::state($id) bulk]} {
|
225
|
+
if {[dict get $::redis::state($id) mbulk] == -1} {
|
226
|
+
redis_call_callback $id reply \
|
227
|
+
[string range [dict get $::redis::state($id) buf] 0 end-2]
|
228
|
+
} else {
|
229
|
+
dict with ::redis::state($id) {
|
230
|
+
lappend reply [string range $buf 0 end-2]
|
231
|
+
incr mbulk -1
|
232
|
+
set bulk -1
|
233
|
+
}
|
234
|
+
if {[dict get $::redis::state($id) mbulk] == 0} {
|
235
|
+
redis_call_callback $id reply \
|
236
|
+
[dict get $::redis::state($id) reply]
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
}
|
241
|
+
}
|