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,78 @@
|
|
1
|
+
/* SDSLib, A C dynamic strings library
|
2
|
+
*
|
3
|
+
* Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
4
|
+
* All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions are met:
|
8
|
+
*
|
9
|
+
* * Redistributions of source code must retain the above copyright notice,
|
10
|
+
* this list of conditions and the following disclaimer.
|
11
|
+
* * Redistributions in binary form must reproduce the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer in the
|
13
|
+
* documentation and/or other materials provided with the distribution.
|
14
|
+
* * Neither the name of Redis nor the names of its contributors may be used
|
15
|
+
* to endorse or promote products derived from this software without
|
16
|
+
* specific prior written permission.
|
17
|
+
*
|
18
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
21
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
22
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
23
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
24
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
25
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
26
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
27
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
28
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#ifndef __SDS_H
|
32
|
+
#define __SDS_H
|
33
|
+
|
34
|
+
#include <sys/types.h>
|
35
|
+
#include <stdarg.h>
|
36
|
+
|
37
|
+
typedef char *sds;
|
38
|
+
|
39
|
+
struct sdshdr {
|
40
|
+
int len;
|
41
|
+
int free;
|
42
|
+
char buf[];
|
43
|
+
};
|
44
|
+
|
45
|
+
sds sdsnewlen(const void *init, size_t initlen);
|
46
|
+
sds sdsnew(const char *init);
|
47
|
+
sds sdsempty();
|
48
|
+
size_t sdslen(const sds s);
|
49
|
+
sds sdsdup(const sds s);
|
50
|
+
void sdsfree(sds s);
|
51
|
+
size_t sdsavail(sds s);
|
52
|
+
sds sdsgrowzero(sds s, size_t len);
|
53
|
+
sds sdscatlen(sds s, void *t, size_t len);
|
54
|
+
sds sdscat(sds s, char *t);
|
55
|
+
sds sdscpylen(sds s, char *t, size_t len);
|
56
|
+
sds sdscpy(sds s, char *t);
|
57
|
+
|
58
|
+
sds sdscatvprintf(sds s, const char *fmt, va_list ap);
|
59
|
+
#ifdef __GNUC__
|
60
|
+
sds sdscatprintf(sds s, const char *fmt, ...)
|
61
|
+
__attribute__((format(printf, 2, 3)));
|
62
|
+
#else
|
63
|
+
sds sdscatprintf(sds s, const char *fmt, ...);
|
64
|
+
#endif
|
65
|
+
|
66
|
+
sds sdstrim(sds s, const char *cset);
|
67
|
+
sds sdsrange(sds s, int start, int end);
|
68
|
+
void sdsupdatelen(sds s);
|
69
|
+
int sdscmp(sds s1, sds s2);
|
70
|
+
sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count);
|
71
|
+
void sdsfreesplitres(sds *tokens, int count);
|
72
|
+
void sdstolower(sds s);
|
73
|
+
void sdstoupper(sds s);
|
74
|
+
sds sdsfromlonglong(long long value);
|
75
|
+
sds sdscatrepr(sds s, char *p, size_t len);
|
76
|
+
sds *sdssplitargs(char *line, int *argc);
|
77
|
+
|
78
|
+
#endif
|
@@ -0,0 +1,276 @@
|
|
1
|
+
|
2
|
+
/* from valgrind tests */
|
3
|
+
|
4
|
+
/* ================ sha1.c ================ */
|
5
|
+
/*
|
6
|
+
SHA-1 in C
|
7
|
+
By Steve Reid <steve@edmweb.com>
|
8
|
+
100% Public Domain
|
9
|
+
|
10
|
+
Test Vectors (from FIPS PUB 180-1)
|
11
|
+
"abc"
|
12
|
+
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
13
|
+
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
14
|
+
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
15
|
+
A million repetitions of "a"
|
16
|
+
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
17
|
+
*/
|
18
|
+
|
19
|
+
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
|
20
|
+
/* #define SHA1HANDSOFF * Copies data before messing with it. */
|
21
|
+
|
22
|
+
#define SHA1HANDSOFF
|
23
|
+
|
24
|
+
#include <stdio.h>
|
25
|
+
#include <string.h>
|
26
|
+
#include <sys/types.h> /* for u_int*_t */
|
27
|
+
#if defined(__sun)
|
28
|
+
#include "solarisfixes.h"
|
29
|
+
#endif
|
30
|
+
#include "sha1.h"
|
31
|
+
|
32
|
+
#ifndef BYTE_ORDER
|
33
|
+
#if (BSD >= 199103)
|
34
|
+
# include <machine/endian.h>
|
35
|
+
#else
|
36
|
+
#if defined(linux) || defined(__linux__)
|
37
|
+
# include <endian.h>
|
38
|
+
#else
|
39
|
+
#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */
|
40
|
+
#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */
|
41
|
+
#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/
|
42
|
+
|
43
|
+
#if defined(vax) || defined(ns32000) || defined(sun386) || defined(__i386__) || \
|
44
|
+
defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
|
45
|
+
defined(__alpha__) || defined(__alpha)
|
46
|
+
#define BYTE_ORDER LITTLE_ENDIAN
|
47
|
+
#endif
|
48
|
+
|
49
|
+
#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
|
50
|
+
defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
|
51
|
+
defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
|
52
|
+
defined(apollo) || defined(__convex__) || defined(_CRAY) || \
|
53
|
+
defined(__hppa) || defined(__hp9000) || \
|
54
|
+
defined(__hp9000s300) || defined(__hp9000s700) || \
|
55
|
+
defined (BIT_ZERO_ON_LEFT) || defined(m68k) || defined(__sparc)
|
56
|
+
#define BYTE_ORDER BIG_ENDIAN
|
57
|
+
#endif
|
58
|
+
#endif /* linux */
|
59
|
+
#endif /* BSD */
|
60
|
+
#endif /* BYTE_ORDER */
|
61
|
+
|
62
|
+
#if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
|
63
|
+
#if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
64
|
+
#define BYTE_ORDER LITTLE_ENDIAN
|
65
|
+
#else
|
66
|
+
#define BYTE_ORDER BIG_ENDIAN
|
67
|
+
#endif
|
68
|
+
#endif
|
69
|
+
|
70
|
+
#if !defined(BYTE_ORDER) || \
|
71
|
+
(BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \
|
72
|
+
BYTE_ORDER != PDP_ENDIAN)
|
73
|
+
/* you must determine what the correct bit order is for
|
74
|
+
* your compiler - the next line is an intentional error
|
75
|
+
* which will force your compiles to bomb until you fix
|
76
|
+
* the above macros.
|
77
|
+
*/
|
78
|
+
#error "Undefined or invalid BYTE_ORDER"
|
79
|
+
#endif
|
80
|
+
|
81
|
+
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
82
|
+
|
83
|
+
/* blk0() and blk() perform the initial expand. */
|
84
|
+
/* I got the idea of expanding during the round function from SSLeay */
|
85
|
+
#if BYTE_ORDER == LITTLE_ENDIAN
|
86
|
+
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
87
|
+
|(rol(block->l[i],8)&0x00FF00FF))
|
88
|
+
#elif BYTE_ORDER == BIG_ENDIAN
|
89
|
+
#define blk0(i) block->l[i]
|
90
|
+
#else
|
91
|
+
#error "Endianness not defined!"
|
92
|
+
#endif
|
93
|
+
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
94
|
+
^block->l[(i+2)&15]^block->l[i&15],1))
|
95
|
+
|
96
|
+
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
97
|
+
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
98
|
+
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
99
|
+
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
100
|
+
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
101
|
+
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
102
|
+
|
103
|
+
|
104
|
+
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
105
|
+
|
106
|
+
void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64])
|
107
|
+
{
|
108
|
+
u_int32_t a, b, c, d, e;
|
109
|
+
typedef union {
|
110
|
+
unsigned char c[64];
|
111
|
+
u_int32_t l[16];
|
112
|
+
} CHAR64LONG16;
|
113
|
+
#ifdef SHA1HANDSOFF
|
114
|
+
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
|
115
|
+
memcpy(block, buffer, 64);
|
116
|
+
#else
|
117
|
+
/* The following had better never be used because it causes the
|
118
|
+
* pointer-to-const buffer to be cast into a pointer to non-const.
|
119
|
+
* And the result is written through. I threw a "const" in, hoping
|
120
|
+
* this will cause a diagnostic.
|
121
|
+
*/
|
122
|
+
CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
|
123
|
+
#endif
|
124
|
+
/* Copy context->state[] to working vars */
|
125
|
+
a = state[0];
|
126
|
+
b = state[1];
|
127
|
+
c = state[2];
|
128
|
+
d = state[3];
|
129
|
+
e = state[4];
|
130
|
+
/* 4 rounds of 20 operations each. Loop unrolled. */
|
131
|
+
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
132
|
+
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
133
|
+
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
134
|
+
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
135
|
+
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
136
|
+
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
137
|
+
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
138
|
+
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
139
|
+
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
140
|
+
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
141
|
+
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
142
|
+
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
143
|
+
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
144
|
+
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
145
|
+
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
146
|
+
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
147
|
+
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
148
|
+
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
149
|
+
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
150
|
+
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
151
|
+
/* Add the working vars back into context.state[] */
|
152
|
+
state[0] += a;
|
153
|
+
state[1] += b;
|
154
|
+
state[2] += c;
|
155
|
+
state[3] += d;
|
156
|
+
state[4] += e;
|
157
|
+
/* Wipe variables */
|
158
|
+
a = b = c = d = e = 0;
|
159
|
+
#ifdef SHA1HANDSOFF
|
160
|
+
memset(block, '\0', sizeof(block));
|
161
|
+
#endif
|
162
|
+
}
|
163
|
+
|
164
|
+
|
165
|
+
/* SHA1Init - Initialize new context */
|
166
|
+
|
167
|
+
void SHA1Init(SHA1_CTX* context)
|
168
|
+
{
|
169
|
+
/* SHA1 initialization constants */
|
170
|
+
context->state[0] = 0x67452301;
|
171
|
+
context->state[1] = 0xEFCDAB89;
|
172
|
+
context->state[2] = 0x98BADCFE;
|
173
|
+
context->state[3] = 0x10325476;
|
174
|
+
context->state[4] = 0xC3D2E1F0;
|
175
|
+
context->count[0] = context->count[1] = 0;
|
176
|
+
}
|
177
|
+
|
178
|
+
|
179
|
+
/* Run your data through this. */
|
180
|
+
|
181
|
+
void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len)
|
182
|
+
{
|
183
|
+
u_int32_t i;
|
184
|
+
u_int32_t j;
|
185
|
+
|
186
|
+
j = context->count[0];
|
187
|
+
if ((context->count[0] += len << 3) < j)
|
188
|
+
context->count[1]++;
|
189
|
+
context->count[1] += (len>>29);
|
190
|
+
j = (j >> 3) & 63;
|
191
|
+
if ((j + len) > 63) {
|
192
|
+
memcpy(&context->buffer[j], data, (i = 64-j));
|
193
|
+
SHA1Transform(context->state, context->buffer);
|
194
|
+
for ( ; i + 63 < len; i += 64) {
|
195
|
+
SHA1Transform(context->state, &data[i]);
|
196
|
+
}
|
197
|
+
j = 0;
|
198
|
+
}
|
199
|
+
else i = 0;
|
200
|
+
memcpy(&context->buffer[j], &data[i], len - i);
|
201
|
+
}
|
202
|
+
|
203
|
+
|
204
|
+
/* Add padding and return the message digest. */
|
205
|
+
|
206
|
+
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
|
207
|
+
{
|
208
|
+
unsigned i;
|
209
|
+
unsigned char finalcount[8];
|
210
|
+
unsigned char c;
|
211
|
+
|
212
|
+
#if 0 /* untested "improvement" by DHR */
|
213
|
+
/* Convert context->count to a sequence of bytes
|
214
|
+
* in finalcount. Second element first, but
|
215
|
+
* big-endian order within element.
|
216
|
+
* But we do it all backwards.
|
217
|
+
*/
|
218
|
+
unsigned char *fcp = &finalcount[8];
|
219
|
+
|
220
|
+
for (i = 0; i < 2; i++)
|
221
|
+
{
|
222
|
+
u_int32_t t = context->count[i];
|
223
|
+
int j;
|
224
|
+
|
225
|
+
for (j = 0; j < 4; t >>= 8, j++)
|
226
|
+
*--fcp = (unsigned char) t
|
227
|
+
}
|
228
|
+
#else
|
229
|
+
for (i = 0; i < 8; i++) {
|
230
|
+
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
231
|
+
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
232
|
+
}
|
233
|
+
#endif
|
234
|
+
c = 0200;
|
235
|
+
SHA1Update(context, &c, 1);
|
236
|
+
while ((context->count[0] & 504) != 448) {
|
237
|
+
c = 0000;
|
238
|
+
SHA1Update(context, &c, 1);
|
239
|
+
}
|
240
|
+
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
241
|
+
for (i = 0; i < 20; i++) {
|
242
|
+
digest[i] = (unsigned char)
|
243
|
+
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
244
|
+
}
|
245
|
+
/* Wipe variables */
|
246
|
+
memset(context, '\0', sizeof(*context));
|
247
|
+
memset(&finalcount, '\0', sizeof(finalcount));
|
248
|
+
}
|
249
|
+
/* ================ end of sha1.c ================ */
|
250
|
+
|
251
|
+
#if 0
|
252
|
+
#define BUFSIZE 4096
|
253
|
+
|
254
|
+
int
|
255
|
+
main(int argc, char **argv)
|
256
|
+
{
|
257
|
+
SHA1_CTX ctx;
|
258
|
+
unsigned char hash[20], buf[BUFSIZE];
|
259
|
+
int i;
|
260
|
+
|
261
|
+
for(i=0;i<BUFSIZE;i++)
|
262
|
+
buf[i] = i;
|
263
|
+
|
264
|
+
SHA1Init(&ctx);
|
265
|
+
for(i=0;i<1000;i++)
|
266
|
+
SHA1Update(&ctx, buf, BUFSIZE);
|
267
|
+
SHA1Final(hash, &ctx);
|
268
|
+
|
269
|
+
printf("SHA1=");
|
270
|
+
for(i=0;i<20;i++)
|
271
|
+
printf("%02x", hash[i]);
|
272
|
+
printf("\n");
|
273
|
+
return 0;
|
274
|
+
}
|
275
|
+
|
276
|
+
#endif
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/* ================ sha1.h ================ */
|
2
|
+
/*
|
3
|
+
SHA-1 in C
|
4
|
+
By Steve Reid <steve@edmweb.com>
|
5
|
+
100% Public Domain
|
6
|
+
*/
|
7
|
+
|
8
|
+
typedef struct {
|
9
|
+
u_int32_t state[5];
|
10
|
+
u_int32_t count[2];
|
11
|
+
unsigned char buffer[64];
|
12
|
+
} SHA1_CTX;
|
13
|
+
|
14
|
+
void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]);
|
15
|
+
void SHA1Init(SHA1_CTX* context);
|
16
|
+
void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len);
|
17
|
+
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/* Solaris specific fixes */
|
2
|
+
|
3
|
+
#if defined(__GNUC__)
|
4
|
+
#include <math.h>
|
5
|
+
#undef isnan
|
6
|
+
#define isnan(x) \
|
7
|
+
__extension__({ __typeof (x) __x_a = (x); \
|
8
|
+
__builtin_expect(__x_a != __x_a, 0); })
|
9
|
+
|
10
|
+
#undef isfinite
|
11
|
+
#define isfinite(x) \
|
12
|
+
__extension__ ({ __typeof (x) __x_f = (x); \
|
13
|
+
__builtin_expect(!isnan(__x_f - __x_f), 1); })
|
14
|
+
|
15
|
+
#undef isinf
|
16
|
+
#define isinf(x) \
|
17
|
+
__extension__ ({ __typeof (x) __x_i = (x); \
|
18
|
+
__builtin_expect(!isnan(__x_i) && !isfinite(__x_i), 0); })
|
19
|
+
|
20
|
+
#define u_int uint
|
21
|
+
#define u_int32_t uint32_t
|
22
|
+
#endif /* __GNUC__ */
|
@@ -0,0 +1,389 @@
|
|
1
|
+
#include "redis.h"
|
2
|
+
#include "pqsort.h" /* Partial qsort for SORT+LIMIT */
|
3
|
+
|
4
|
+
redisSortOperation *createSortOperation(int type, robj *pattern) {
|
5
|
+
redisSortOperation *so = zmalloc(sizeof(*so));
|
6
|
+
so->type = type;
|
7
|
+
so->pattern = pattern;
|
8
|
+
return so;
|
9
|
+
}
|
10
|
+
|
11
|
+
/* Return the value associated to the key with a name obtained
|
12
|
+
* substituting the first occurence of '*' in 'pattern' with 'subst'.
|
13
|
+
* The returned object will always have its refcount increased by 1
|
14
|
+
* when it is non-NULL. */
|
15
|
+
robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) {
|
16
|
+
char *p, *f;
|
17
|
+
sds spat, ssub;
|
18
|
+
robj keyobj, fieldobj, *o;
|
19
|
+
int prefixlen, sublen, postfixlen, fieldlen;
|
20
|
+
/* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */
|
21
|
+
struct {
|
22
|
+
int len;
|
23
|
+
int free;
|
24
|
+
char buf[REDIS_SORTKEY_MAX+1];
|
25
|
+
} keyname, fieldname;
|
26
|
+
|
27
|
+
/* If the pattern is "#" return the substitution object itself in order
|
28
|
+
* to implement the "SORT ... GET #" feature. */
|
29
|
+
spat = pattern->ptr;
|
30
|
+
if (spat[0] == '#' && spat[1] == '\0') {
|
31
|
+
incrRefCount(subst);
|
32
|
+
return subst;
|
33
|
+
}
|
34
|
+
|
35
|
+
/* The substitution object may be specially encoded. If so we create
|
36
|
+
* a decoded object on the fly. Otherwise getDecodedObject will just
|
37
|
+
* increment the ref count, that we'll decrement later. */
|
38
|
+
subst = getDecodedObject(subst);
|
39
|
+
|
40
|
+
ssub = subst->ptr;
|
41
|
+
if (sdslen(spat)+sdslen(ssub)-1 > REDIS_SORTKEY_MAX) return NULL;
|
42
|
+
p = strchr(spat,'*');
|
43
|
+
if (!p) {
|
44
|
+
decrRefCount(subst);
|
45
|
+
return NULL;
|
46
|
+
}
|
47
|
+
|
48
|
+
/* Find out if we're dealing with a hash dereference. */
|
49
|
+
if ((f = strstr(p+1, "->")) != NULL) {
|
50
|
+
fieldlen = sdslen(spat)-(f-spat);
|
51
|
+
/* this also copies \0 character */
|
52
|
+
memcpy(fieldname.buf,f+2,fieldlen-1);
|
53
|
+
fieldname.len = fieldlen-2;
|
54
|
+
} else {
|
55
|
+
fieldlen = 0;
|
56
|
+
}
|
57
|
+
|
58
|
+
prefixlen = p-spat;
|
59
|
+
sublen = sdslen(ssub);
|
60
|
+
postfixlen = sdslen(spat)-(prefixlen+1)-fieldlen;
|
61
|
+
memcpy(keyname.buf,spat,prefixlen);
|
62
|
+
memcpy(keyname.buf+prefixlen,ssub,sublen);
|
63
|
+
memcpy(keyname.buf+prefixlen+sublen,p+1,postfixlen);
|
64
|
+
keyname.buf[prefixlen+sublen+postfixlen] = '\0';
|
65
|
+
keyname.len = prefixlen+sublen+postfixlen;
|
66
|
+
decrRefCount(subst);
|
67
|
+
|
68
|
+
/* Lookup substituted key */
|
69
|
+
initStaticStringObject(keyobj,((char*)&keyname)+(sizeof(struct sdshdr)));
|
70
|
+
o = lookupKeyRead(db,&keyobj);
|
71
|
+
if (o == NULL) return NULL;
|
72
|
+
|
73
|
+
if (fieldlen > 0) {
|
74
|
+
if (o->type != REDIS_HASH || fieldname.len < 1) return NULL;
|
75
|
+
|
76
|
+
/* Retrieve value from hash by the field name. This operation
|
77
|
+
* already increases the refcount of the returned object. */
|
78
|
+
initStaticStringObject(fieldobj,((char*)&fieldname)+(sizeof(struct sdshdr)));
|
79
|
+
o = hashTypeGetObject(o, &fieldobj);
|
80
|
+
} else {
|
81
|
+
if (o->type != REDIS_STRING) return NULL;
|
82
|
+
|
83
|
+
/* Every object that this function returns needs to have its refcount
|
84
|
+
* increased. sortCommand decreases it again. */
|
85
|
+
incrRefCount(o);
|
86
|
+
}
|
87
|
+
|
88
|
+
return o;
|
89
|
+
}
|
90
|
+
|
91
|
+
/* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with
|
92
|
+
* the additional parameter is not standard but a BSD-specific we have to
|
93
|
+
* pass sorting parameters via the global 'server' structure */
|
94
|
+
int sortCompare(const void *s1, const void *s2) {
|
95
|
+
const redisSortObject *so1 = s1, *so2 = s2;
|
96
|
+
int cmp;
|
97
|
+
|
98
|
+
if (!server.sort_alpha) {
|
99
|
+
/* Numeric sorting. Here it's trivial as we precomputed scores */
|
100
|
+
if (so1->u.score > so2->u.score) {
|
101
|
+
cmp = 1;
|
102
|
+
} else if (so1->u.score < so2->u.score) {
|
103
|
+
cmp = -1;
|
104
|
+
} else {
|
105
|
+
cmp = 0;
|
106
|
+
}
|
107
|
+
} else {
|
108
|
+
/* Alphanumeric sorting */
|
109
|
+
if (server.sort_bypattern) {
|
110
|
+
if (!so1->u.cmpobj || !so2->u.cmpobj) {
|
111
|
+
/* At least one compare object is NULL */
|
112
|
+
if (so1->u.cmpobj == so2->u.cmpobj)
|
113
|
+
cmp = 0;
|
114
|
+
else if (so1->u.cmpobj == NULL)
|
115
|
+
cmp = -1;
|
116
|
+
else
|
117
|
+
cmp = 1;
|
118
|
+
} else {
|
119
|
+
/* We have both the objects, use strcoll */
|
120
|
+
cmp = strcoll(so1->u.cmpobj->ptr,so2->u.cmpobj->ptr);
|
121
|
+
}
|
122
|
+
} else {
|
123
|
+
/* Compare elements directly. */
|
124
|
+
cmp = compareStringObjects(so1->obj,so2->obj);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
return server.sort_desc ? -cmp : cmp;
|
128
|
+
}
|
129
|
+
|
130
|
+
/* The SORT command is the most complex command in Redis. Warning: this code
|
131
|
+
* is optimized for speed and a bit less for readability */
|
132
|
+
void sortCommand(redisClient *c) {
|
133
|
+
list *operations;
|
134
|
+
unsigned int outputlen = 0;
|
135
|
+
int desc = 0, alpha = 0;
|
136
|
+
int limit_start = 0, limit_count = -1, start, end;
|
137
|
+
int j, dontsort = 0, vectorlen;
|
138
|
+
int getop = 0; /* GET operation counter */
|
139
|
+
robj *sortval, *sortby = NULL, *storekey = NULL;
|
140
|
+
redisSortObject *vector; /* Resulting vector to sort */
|
141
|
+
|
142
|
+
/* Lookup the key to sort. It must be of the right types */
|
143
|
+
sortval = lookupKeyRead(c->db,c->argv[1]);
|
144
|
+
if (sortval == NULL) {
|
145
|
+
addReply(c,shared.emptymultibulk);
|
146
|
+
return;
|
147
|
+
}
|
148
|
+
if (sortval->type != REDIS_SET && sortval->type != REDIS_LIST &&
|
149
|
+
sortval->type != REDIS_ZSET)
|
150
|
+
{
|
151
|
+
addReply(c,shared.wrongtypeerr);
|
152
|
+
return;
|
153
|
+
}
|
154
|
+
|
155
|
+
/* Create a list of operations to perform for every sorted element.
|
156
|
+
* Operations can be GET/DEL/INCR/DECR */
|
157
|
+
operations = listCreate();
|
158
|
+
listSetFreeMethod(operations,zfree);
|
159
|
+
j = 2;
|
160
|
+
|
161
|
+
/* Now we need to protect sortval incrementing its count, in the future
|
162
|
+
* SORT may have options able to overwrite/delete keys during the sorting
|
163
|
+
* and the sorted key itself may get destroied */
|
164
|
+
incrRefCount(sortval);
|
165
|
+
|
166
|
+
/* The SORT command has an SQL-alike syntax, parse it */
|
167
|
+
while(j < c->argc) {
|
168
|
+
int leftargs = c->argc-j-1;
|
169
|
+
if (!strcasecmp(c->argv[j]->ptr,"asc")) {
|
170
|
+
desc = 0;
|
171
|
+
} else if (!strcasecmp(c->argv[j]->ptr,"desc")) {
|
172
|
+
desc = 1;
|
173
|
+
} else if (!strcasecmp(c->argv[j]->ptr,"alpha")) {
|
174
|
+
alpha = 1;
|
175
|
+
} else if (!strcasecmp(c->argv[j]->ptr,"limit") && leftargs >= 2) {
|
176
|
+
limit_start = atoi(c->argv[j+1]->ptr);
|
177
|
+
limit_count = atoi(c->argv[j+2]->ptr);
|
178
|
+
j+=2;
|
179
|
+
} else if (!strcasecmp(c->argv[j]->ptr,"store") && leftargs >= 1) {
|
180
|
+
storekey = c->argv[j+1];
|
181
|
+
j++;
|
182
|
+
} else if (!strcasecmp(c->argv[j]->ptr,"by") && leftargs >= 1) {
|
183
|
+
sortby = c->argv[j+1];
|
184
|
+
/* If the BY pattern does not contain '*', i.e. it is constant,
|
185
|
+
* we don't need to sort nor to lookup the weight keys. */
|
186
|
+
if (strchr(c->argv[j+1]->ptr,'*') == NULL) dontsort = 1;
|
187
|
+
j++;
|
188
|
+
} else if (!strcasecmp(c->argv[j]->ptr,"get") && leftargs >= 1) {
|
189
|
+
listAddNodeTail(operations,createSortOperation(
|
190
|
+
REDIS_SORT_GET,c->argv[j+1]));
|
191
|
+
getop++;
|
192
|
+
j++;
|
193
|
+
} else {
|
194
|
+
decrRefCount(sortval);
|
195
|
+
listRelease(operations);
|
196
|
+
addReply(c,shared.syntaxerr);
|
197
|
+
return;
|
198
|
+
}
|
199
|
+
j++;
|
200
|
+
}
|
201
|
+
|
202
|
+
/* Load the sorting vector with all the objects to sort */
|
203
|
+
switch(sortval->type) {
|
204
|
+
case REDIS_LIST: vectorlen = listTypeLength(sortval); break;
|
205
|
+
case REDIS_SET: vectorlen = setTypeSize(sortval); break;
|
206
|
+
case REDIS_ZSET: vectorlen = dictSize(((zset*)sortval->ptr)->dict); break;
|
207
|
+
default: vectorlen = 0; redisPanic("Bad SORT type"); /* Avoid GCC warning */
|
208
|
+
}
|
209
|
+
vector = zmalloc(sizeof(redisSortObject)*vectorlen);
|
210
|
+
j = 0;
|
211
|
+
|
212
|
+
if (sortval->type == REDIS_LIST) {
|
213
|
+
listTypeIterator *li = listTypeInitIterator(sortval,0,REDIS_TAIL);
|
214
|
+
listTypeEntry entry;
|
215
|
+
while(listTypeNext(li,&entry)) {
|
216
|
+
vector[j].obj = listTypeGet(&entry);
|
217
|
+
vector[j].u.score = 0;
|
218
|
+
vector[j].u.cmpobj = NULL;
|
219
|
+
j++;
|
220
|
+
}
|
221
|
+
listTypeReleaseIterator(li);
|
222
|
+
} else if (sortval->type == REDIS_SET) {
|
223
|
+
setTypeIterator *si = setTypeInitIterator(sortval);
|
224
|
+
robj *ele;
|
225
|
+
while((ele = setTypeNextObject(si)) != NULL) {
|
226
|
+
vector[j].obj = ele;
|
227
|
+
vector[j].u.score = 0;
|
228
|
+
vector[j].u.cmpobj = NULL;
|
229
|
+
j++;
|
230
|
+
}
|
231
|
+
setTypeReleaseIterator(si);
|
232
|
+
} else if (sortval->type == REDIS_ZSET) {
|
233
|
+
dict *set = ((zset*)sortval->ptr)->dict;
|
234
|
+
dictIterator *di;
|
235
|
+
dictEntry *setele;
|
236
|
+
di = dictGetIterator(set);
|
237
|
+
while((setele = dictNext(di)) != NULL) {
|
238
|
+
vector[j].obj = dictGetEntryKey(setele);
|
239
|
+
vector[j].u.score = 0;
|
240
|
+
vector[j].u.cmpobj = NULL;
|
241
|
+
j++;
|
242
|
+
}
|
243
|
+
dictReleaseIterator(di);
|
244
|
+
} else {
|
245
|
+
redisPanic("Unknown type");
|
246
|
+
}
|
247
|
+
redisAssert(j == vectorlen);
|
248
|
+
|
249
|
+
/* Now it's time to load the right scores in the sorting vector */
|
250
|
+
if (dontsort == 0) {
|
251
|
+
for (j = 0; j < vectorlen; j++) {
|
252
|
+
robj *byval;
|
253
|
+
if (sortby) {
|
254
|
+
/* lookup value to sort by */
|
255
|
+
byval = lookupKeyByPattern(c->db,sortby,vector[j].obj);
|
256
|
+
if (!byval) continue;
|
257
|
+
} else {
|
258
|
+
/* use object itself to sort by */
|
259
|
+
byval = vector[j].obj;
|
260
|
+
}
|
261
|
+
|
262
|
+
if (alpha) {
|
263
|
+
if (sortby) vector[j].u.cmpobj = getDecodedObject(byval);
|
264
|
+
} else {
|
265
|
+
if (byval->encoding == REDIS_ENCODING_RAW) {
|
266
|
+
vector[j].u.score = strtod(byval->ptr,NULL);
|
267
|
+
} else if (byval->encoding == REDIS_ENCODING_INT) {
|
268
|
+
/* Don't need to decode the object if it's
|
269
|
+
* integer-encoded (the only encoding supported) so
|
270
|
+
* far. We can just cast it */
|
271
|
+
vector[j].u.score = (long)byval->ptr;
|
272
|
+
} else {
|
273
|
+
redisAssert(1 != 1);
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
277
|
+
/* when the object was retrieved using lookupKeyByPattern,
|
278
|
+
* its refcount needs to be decreased. */
|
279
|
+
if (sortby) {
|
280
|
+
decrRefCount(byval);
|
281
|
+
}
|
282
|
+
}
|
283
|
+
}
|
284
|
+
|
285
|
+
/* We are ready to sort the vector... perform a bit of sanity check
|
286
|
+
* on the LIMIT option too. We'll use a partial version of quicksort. */
|
287
|
+
start = (limit_start < 0) ? 0 : limit_start;
|
288
|
+
end = (limit_count < 0) ? vectorlen-1 : start+limit_count-1;
|
289
|
+
if (start >= vectorlen) {
|
290
|
+
start = vectorlen-1;
|
291
|
+
end = vectorlen-2;
|
292
|
+
}
|
293
|
+
if (end >= vectorlen) end = vectorlen-1;
|
294
|
+
|
295
|
+
if (dontsort == 0) {
|
296
|
+
server.sort_desc = desc;
|
297
|
+
server.sort_alpha = alpha;
|
298
|
+
server.sort_bypattern = sortby ? 1 : 0;
|
299
|
+
if (sortby && (start != 0 || end != vectorlen-1))
|
300
|
+
pqsort(vector,vectorlen,sizeof(redisSortObject),sortCompare, start,end);
|
301
|
+
else
|
302
|
+
qsort(vector,vectorlen,sizeof(redisSortObject),sortCompare);
|
303
|
+
}
|
304
|
+
|
305
|
+
/* Send command output to the output buffer, performing the specified
|
306
|
+
* GET/DEL/INCR/DECR operations if any. */
|
307
|
+
outputlen = getop ? getop*(end-start+1) : end-start+1;
|
308
|
+
if (storekey == NULL) {
|
309
|
+
/* STORE option not specified, sent the sorting result to client */
|
310
|
+
addReplyMultiBulkLen(c,outputlen);
|
311
|
+
for (j = start; j <= end; j++) {
|
312
|
+
listNode *ln;
|
313
|
+
listIter li;
|
314
|
+
|
315
|
+
if (!getop) addReplyBulk(c,vector[j].obj);
|
316
|
+
listRewind(operations,&li);
|
317
|
+
while((ln = listNext(&li))) {
|
318
|
+
redisSortOperation *sop = ln->value;
|
319
|
+
robj *val = lookupKeyByPattern(c->db,sop->pattern,
|
320
|
+
vector[j].obj);
|
321
|
+
|
322
|
+
if (sop->type == REDIS_SORT_GET) {
|
323
|
+
if (!val) {
|
324
|
+
addReply(c,shared.nullbulk);
|
325
|
+
} else {
|
326
|
+
addReplyBulk(c,val);
|
327
|
+
decrRefCount(val);
|
328
|
+
}
|
329
|
+
} else {
|
330
|
+
redisAssert(sop->type == REDIS_SORT_GET); /* always fails */
|
331
|
+
}
|
332
|
+
}
|
333
|
+
}
|
334
|
+
} else {
|
335
|
+
robj *sobj = createZiplistObject();
|
336
|
+
|
337
|
+
/* STORE option specified, set the sorting result as a List object */
|
338
|
+
for (j = start; j <= end; j++) {
|
339
|
+
listNode *ln;
|
340
|
+
listIter li;
|
341
|
+
|
342
|
+
if (!getop) {
|
343
|
+
listTypePush(sobj,vector[j].obj,REDIS_TAIL);
|
344
|
+
} else {
|
345
|
+
listRewind(operations,&li);
|
346
|
+
while((ln = listNext(&li))) {
|
347
|
+
redisSortOperation *sop = ln->value;
|
348
|
+
robj *val = lookupKeyByPattern(c->db,sop->pattern,
|
349
|
+
vector[j].obj);
|
350
|
+
|
351
|
+
if (sop->type == REDIS_SORT_GET) {
|
352
|
+
if (!val) val = createStringObject("",0);
|
353
|
+
|
354
|
+
/* listTypePush does an incrRefCount, so we should take care
|
355
|
+
* care of the incremented refcount caused by either
|
356
|
+
* lookupKeyByPattern or createStringObject("",0) */
|
357
|
+
listTypePush(sobj,val,REDIS_TAIL);
|
358
|
+
decrRefCount(val);
|
359
|
+
} else {
|
360
|
+
/* always fails */
|
361
|
+
redisAssert(sop->type == REDIS_SORT_GET);
|
362
|
+
}
|
363
|
+
}
|
364
|
+
}
|
365
|
+
}
|
366
|
+
lookupKeyWrite(c->db,storekey); /* Force expire of old key if needed. */
|
367
|
+
dbReplace(c->db,storekey,sobj);
|
368
|
+
/* Note: we add 1 because the DB is dirty anyway since even if the
|
369
|
+
* SORT result is empty a new key is set and maybe the old content
|
370
|
+
* replaced. */
|
371
|
+
server.dirty += 1+outputlen;
|
372
|
+
touchWatchedKey(c->db,storekey);
|
373
|
+
addReplyLongLong(c,outputlen);
|
374
|
+
}
|
375
|
+
|
376
|
+
/* Cleanup */
|
377
|
+
if (sortval->type == REDIS_LIST || sortval->type == REDIS_SET)
|
378
|
+
for (j = 0; j < vectorlen; j++)
|
379
|
+
decrRefCount(vector[j].obj);
|
380
|
+
decrRefCount(sortval);
|
381
|
+
listRelease(operations);
|
382
|
+
for (j = 0; j < vectorlen; j++) {
|
383
|
+
if (alpha && vector[j].u.cmpobj)
|
384
|
+
decrRefCount(vector[j].u.cmpobj);
|
385
|
+
}
|
386
|
+
zfree(vector);
|
387
|
+
}
|
388
|
+
|
389
|
+
|