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.
Files changed (290) hide show
  1. data/LICENSE +38 -0
  2. data/README.md +33 -0
  3. data/bin/redis +114 -0
  4. data/redis/Makefile +5 -0
  5. data/redis/extconf.rb +3 -0
  6. data/redis/redis-2.2.11/00-RELEASENOTES +199 -0
  7. data/redis/redis-2.2.11/BUGS +1 -0
  8. data/redis/redis-2.2.11/CONTRIBUTING +13 -0
  9. data/redis/redis-2.2.11/COPYING +10 -0
  10. data/redis/redis-2.2.11/Changelog +1032 -0
  11. data/redis/redis-2.2.11/INSTALL +30 -0
  12. data/redis/redis-2.2.11/Makefile +22 -0
  13. data/redis/redis-2.2.11/README +83 -0
  14. data/redis/redis-2.2.11/TODO +4 -0
  15. data/redis/redis-2.2.11/client-libraries/README +11 -0
  16. data/redis/redis-2.2.11/deps/hiredis/COPYING +10 -0
  17. data/redis/redis-2.2.11/deps/hiredis/Makefile +115 -0
  18. data/redis/redis-2.2.11/deps/hiredis/README.md +311 -0
  19. data/redis/redis-2.2.11/deps/hiredis/TODO +2 -0
  20. data/redis/redis-2.2.11/deps/hiredis/adapters/ae.h +95 -0
  21. data/redis/redis-2.2.11/deps/hiredis/adapters/libev.h +113 -0
  22. data/redis/redis-2.2.11/deps/hiredis/adapters/libevent.h +76 -0
  23. data/redis/redis-2.2.11/deps/hiredis/async.c +321 -0
  24. data/redis/redis-2.2.11/deps/hiredis/async.h +112 -0
  25. data/redis/redis-2.2.11/deps/hiredis/example-ae.c +53 -0
  26. data/redis/redis-2.2.11/deps/hiredis/example-libev.c +47 -0
  27. data/redis/redis-2.2.11/deps/hiredis/example-libevent.c +48 -0
  28. data/redis/redis-2.2.11/deps/hiredis/example.c +67 -0
  29. data/redis/redis-2.2.11/deps/hiredis/fmacros.h +15 -0
  30. data/redis/redis-2.2.11/deps/hiredis/hiredis.c +1058 -0
  31. data/redis/redis-2.2.11/deps/hiredis/hiredis.h +170 -0
  32. data/redis/redis-2.2.11/deps/hiredis/net.c +170 -0
  33. data/redis/redis-2.2.11/deps/hiredis/net.h +43 -0
  34. data/redis/redis-2.2.11/deps/hiredis/sds.c +479 -0
  35. data/redis/redis-2.2.11/deps/hiredis/sds.h +77 -0
  36. data/redis/redis-2.2.11/deps/hiredis/test.c +479 -0
  37. data/redis/redis-2.2.11/deps/hiredis/util.h +40 -0
  38. data/redis/redis-2.2.11/deps/linenoise/Makefile +10 -0
  39. data/redis/redis-2.2.11/deps/linenoise/README.markdown +45 -0
  40. data/redis/redis-2.2.11/deps/linenoise/example.c +27 -0
  41. data/redis/redis-2.2.11/deps/linenoise/linenoise.c +609 -0
  42. data/redis/redis-2.2.11/deps/linenoise/linenoise.h +55 -0
  43. data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER +214 -0
  44. data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER-2 +343 -0
  45. data/redis/redis-2.2.11/doc/AppendCommand.html +48 -0
  46. data/redis/redis-2.2.11/doc/AppendOnlyFileHowto.html +41 -0
  47. data/redis/redis-2.2.11/doc/AuthCommand.html +39 -0
  48. data/redis/redis-2.2.11/doc/Benchmarks.html +129 -0
  49. data/redis/redis-2.2.11/doc/BgrewriteaofCommand.html +41 -0
  50. data/redis/redis-2.2.11/doc/BgsaveCommand.html +39 -0
  51. data/redis/redis-2.2.11/doc/BlpopCommand.html +51 -0
  52. data/redis/redis-2.2.11/doc/BrpoplpushCommand.html +39 -0
  53. data/redis/redis-2.2.11/doc/CommandReference.html +47 -0
  54. data/redis/redis-2.2.11/doc/Comparisons.html +42 -0
  55. data/redis/redis-2.2.11/doc/ConfigCommand.html +76 -0
  56. data/redis/redis-2.2.11/doc/Configuration.html +38 -0
  57. data/redis/redis-2.2.11/doc/ConnectionHandlingSidebar.html +36 -0
  58. data/redis/redis-2.2.11/doc/ControlCommandsSidebar.html +36 -0
  59. data/redis/redis-2.2.11/doc/Credits.html +38 -0
  60. data/redis/redis-2.2.11/doc/DbsizeCommand.html +38 -0
  61. data/redis/redis-2.2.11/doc/DelCommand.html +41 -0
  62. data/redis/redis-2.2.11/doc/DesignPatterns.html +37 -0
  63. data/redis/redis-2.2.11/doc/EventLibray.html +44 -0
  64. data/redis/redis-2.2.11/doc/ExistsCommand.html +42 -0
  65. data/redis/redis-2.2.11/doc/ExpireCommand.html +96 -0
  66. data/redis/redis-2.2.11/doc/FAQ.html +70 -0
  67. data/redis/redis-2.2.11/doc/Features.html +38 -0
  68. data/redis/redis-2.2.11/doc/FlushallCommand.html +39 -0
  69. data/redis/redis-2.2.11/doc/FlushdbCommand.html +39 -0
  70. data/redis/redis-2.2.11/doc/FromSqlToDataStructures.html +37 -0
  71. data/redis/redis-2.2.11/doc/GenericCommandsSidebar.html +36 -0
  72. data/redis/redis-2.2.11/doc/GetCommand.html +39 -0
  73. data/redis/redis-2.2.11/doc/GetbitCommand.html +39 -0
  74. data/redis/redis-2.2.11/doc/GetsetCommand.html +38 -0
  75. data/redis/redis-2.2.11/doc/HackingStrings.html +83 -0
  76. data/redis/redis-2.2.11/doc/HashCommandsSidebar.html +36 -0
  77. data/redis/redis-2.2.11/doc/Hashes.html +37 -0
  78. data/redis/redis-2.2.11/doc/HdelCommand.html +39 -0
  79. data/redis/redis-2.2.11/doc/HexistsCommand.html +39 -0
  80. data/redis/redis-2.2.11/doc/HgetCommand.html +39 -0
  81. data/redis/redis-2.2.11/doc/HgetallCommand.html +40 -0
  82. data/redis/redis-2.2.11/doc/HincrbyCommand.html +45 -0
  83. data/redis/redis-2.2.11/doc/HlenCommand.html +38 -0
  84. data/redis/redis-2.2.11/doc/HmgetCommand.html +40 -0
  85. data/redis/redis-2.2.11/doc/HmsetCommand.html +40 -0
  86. data/redis/redis-2.2.11/doc/HsetCommand.html +40 -0
  87. data/redis/redis-2.2.11/doc/HsetnxCommand.html +41 -0
  88. data/redis/redis-2.2.11/doc/IncrCommand.html +43 -0
  89. data/redis/redis-2.2.11/doc/InfoCommand.html +48 -0
  90. data/redis/redis-2.2.11/doc/IntroductionToRedisDataTypes.html +152 -0
  91. data/redis/redis-2.2.11/doc/KeysCommand.html +43 -0
  92. data/redis/redis-2.2.11/doc/LastsaveCommand.html +39 -0
  93. data/redis/redis-2.2.11/doc/LindexCommand.html +40 -0
  94. data/redis/redis-2.2.11/doc/ListCommandsSidebar.html +36 -0
  95. data/redis/redis-2.2.11/doc/Lists.html +42 -0
  96. data/redis/redis-2.2.11/doc/LlenCommand.html +41 -0
  97. data/redis/redis-2.2.11/doc/LpopCommand.html +41 -0
  98. data/redis/redis-2.2.11/doc/LrangeCommand.html +47 -0
  99. data/redis/redis-2.2.11/doc/LremCommand.html +41 -0
  100. data/redis/redis-2.2.11/doc/LsetCommand.html +38 -0
  101. data/redis/redis-2.2.11/doc/LtrimCommand.html +47 -0
  102. data/redis/redis-2.2.11/doc/MgetCommand.html +52 -0
  103. data/redis/redis-2.2.11/doc/MonitorCommand.html +63 -0
  104. data/redis/redis-2.2.11/doc/MoveCommand.html +42 -0
  105. data/redis/redis-2.2.11/doc/MsetCommand.html +44 -0
  106. data/redis/redis-2.2.11/doc/MultiExecCommand.html +166 -0
  107. data/redis/redis-2.2.11/doc/NonexistentCommands.html +51 -0
  108. data/redis/redis-2.2.11/doc/ObjectHashMappers.html +39 -0
  109. data/redis/redis-2.2.11/doc/Pipelining.html +36 -0
  110. data/redis/redis-2.2.11/doc/ProgrammingExamples.html +38 -0
  111. data/redis/redis-2.2.11/doc/ProtocolSpecification.html +137 -0
  112. data/redis/redis-2.2.11/doc/PublishSubscribe.html +115 -0
  113. data/redis/redis-2.2.11/doc/QuickStart.html +68 -0
  114. data/redis/redis-2.2.11/doc/QuitCommand.html +38 -0
  115. data/redis/redis-2.2.11/doc/README.html +119 -0
  116. data/redis/redis-2.2.11/doc/RandomkeyCommand.html +39 -0
  117. data/redis/redis-2.2.11/doc/Redis0100ChangeLog.html +67 -0
  118. data/redis/redis-2.2.11/doc/Redis0900ChangeLog.html +56 -0
  119. data/redis/redis-2.2.11/doc/RedisBigData.html +61 -0
  120. data/redis/redis-2.2.11/doc/RedisCLI.html +37 -0
  121. data/redis/redis-2.2.11/doc/RedisEventLibrary.html +70 -0
  122. data/redis/redis-2.2.11/doc/RedisGuides.html +37 -0
  123. data/redis/redis-2.2.11/doc/RedisInternals.html +38 -0
  124. data/redis/redis-2.2.11/doc/RedisPipelining.html +93 -0
  125. data/redis/redis-2.2.11/doc/RedisStatus.html +56 -0
  126. data/redis/redis-2.2.11/doc/Redis_1_2_0_Changelog.html +40 -0
  127. data/redis/redis-2.2.11/doc/Redis_2_0_0_Changelog.html +62 -0
  128. data/redis/redis-2.2.11/doc/Redis_2_0_Whats_new.html +59 -0
  129. data/redis/redis-2.2.11/doc/RenameCommand.html +39 -0
  130. data/redis/redis-2.2.11/doc/RenamenxCommand.html +42 -0
  131. data/redis/redis-2.2.11/doc/ReplicationHowto.html +43 -0
  132. data/redis/redis-2.2.11/doc/ReplyTypes.html +42 -0
  133. data/redis/redis-2.2.11/doc/RoadMap.html +38 -0
  134. data/redis/redis-2.2.11/doc/RpoplpushCommand.html +44 -0
  135. data/redis/redis-2.2.11/doc/RpushCommand.html +40 -0
  136. data/redis/redis-2.2.11/doc/SaddCommand.html +41 -0
  137. data/redis/redis-2.2.11/doc/SaveCommand.html +39 -0
  138. data/redis/redis-2.2.11/doc/ScardCommand.html +41 -0
  139. data/redis/redis-2.2.11/doc/SdiffCommand.html +45 -0
  140. data/redis/redis-2.2.11/doc/SdiffstoreCommand.html +38 -0
  141. data/redis/redis-2.2.11/doc/SelectCommand.html +39 -0
  142. data/redis/redis-2.2.11/doc/SetCommand.html +39 -0
  143. data/redis/redis-2.2.11/doc/SetCommandsSidebar.html +36 -0
  144. data/redis/redis-2.2.11/doc/SetbitCommand.html +45 -0
  145. data/redis/redis-2.2.11/doc/SetexCommand.html +42 -0
  146. data/redis/redis-2.2.11/doc/SetnxCommand.html +51 -0
  147. data/redis/redis-2.2.11/doc/SetrangeCommand.html +58 -0
  148. data/redis/redis-2.2.11/doc/Sets.html +36 -0
  149. data/redis/redis-2.2.11/doc/ShutdownCommand.html +39 -0
  150. data/redis/redis-2.2.11/doc/SideBar.html +36 -0
  151. data/redis/redis-2.2.11/doc/SinterCommand.html +40 -0
  152. data/redis/redis-2.2.11/doc/SinterstoreCommand.html +39 -0
  153. data/redis/redis-2.2.11/doc/SismemberCommand.html +42 -0
  154. data/redis/redis-2.2.11/doc/SlaveofCommand.html +41 -0
  155. data/redis/redis-2.2.11/doc/SmembersCommand.html +38 -0
  156. data/redis/redis-2.2.11/doc/SmoveCommand.html +44 -0
  157. data/redis/redis-2.2.11/doc/SortCommand.html +75 -0
  158. data/redis/redis-2.2.11/doc/SortedSetCommandsSidebar.html +36 -0
  159. data/redis/redis-2.2.11/doc/SortedSets.html +36 -0
  160. data/redis/redis-2.2.11/doc/Speed.html +38 -0
  161. data/redis/redis-2.2.11/doc/SponsorshipHistory.html +38 -0
  162. data/redis/redis-2.2.11/doc/SpopCommand.html +40 -0
  163. data/redis/redis-2.2.11/doc/SrandmemberCommand.html +40 -0
  164. data/redis/redis-2.2.11/doc/SremCommand.html +42 -0
  165. data/redis/redis-2.2.11/doc/StringCommandsSidebar.html +36 -0
  166. data/redis/redis-2.2.11/doc/Strings.html +37 -0
  167. data/redis/redis-2.2.11/doc/StrlenCommand.html +39 -0
  168. data/redis/redis-2.2.11/doc/SubstrCommand.html +52 -0
  169. data/redis/redis-2.2.11/doc/SunionCommand.html +40 -0
  170. data/redis/redis-2.2.11/doc/SunionstoreCommand.html +38 -0
  171. data/redis/redis-2.2.11/doc/SupportedLanguages.html +60 -0
  172. data/redis/redis-2.2.11/doc/SupportedPlatforms.html +37 -0
  173. data/redis/redis-2.2.11/doc/TemplateCommand.html +38 -0
  174. data/redis/redis-2.2.11/doc/TtlCommand.html +38 -0
  175. data/redis/redis-2.2.11/doc/TwitterAlikeExample.html +250 -0
  176. data/redis/redis-2.2.11/doc/TypeCommand.html +46 -0
  177. data/redis/redis-2.2.11/doc/UnstableSource.html +39 -0
  178. data/redis/redis-2.2.11/doc/VirtualMemorySpecification.html +156 -0
  179. data/redis/redis-2.2.11/doc/VirtualMemoryUserGuide.html +66 -0
  180. data/redis/redis-2.2.11/doc/ZaddCommand.html +43 -0
  181. data/redis/redis-2.2.11/doc/ZcardCommand.html +41 -0
  182. data/redis/redis-2.2.11/doc/ZincrbyCommand.html +42 -0
  183. data/redis/redis-2.2.11/doc/ZrangeCommand.html +42 -0
  184. data/redis/redis-2.2.11/doc/ZrangebyscoreCommand.html +77 -0
  185. data/redis/redis-2.2.11/doc/ZrankCommand.html +43 -0
  186. data/redis/redis-2.2.11/doc/ZremCommand.html +42 -0
  187. data/redis/redis-2.2.11/doc/ZremrangebyrankCommand.html +39 -0
  188. data/redis/redis-2.2.11/doc/ZremrangebyscoreCommand.html +39 -0
  189. data/redis/redis-2.2.11/doc/ZscoreCommand.html +41 -0
  190. data/redis/redis-2.2.11/doc/ZunionCommand.html +42 -0
  191. data/redis/redis-2.2.11/doc/ZunionstoreCommand.html +43 -0
  192. data/redis/redis-2.2.11/doc/index.html +43 -0
  193. data/redis/redis-2.2.11/doc/redis.png +0 -0
  194. data/redis/redis-2.2.11/doc/style.css +25 -0
  195. data/redis/redis-2.2.11/redis.conf +417 -0
  196. data/redis/redis-2.2.11/src/Makefile +177 -0
  197. data/redis/redis-2.2.11/src/adlist.c +325 -0
  198. data/redis/redis-2.2.11/src/adlist.h +92 -0
  199. data/redis/redis-2.2.11/src/ae.c +390 -0
  200. data/redis/redis-2.2.11/src/ae.h +117 -0
  201. data/redis/redis-2.2.11/src/ae_epoll.c +91 -0
  202. data/redis/redis-2.2.11/src/ae_kqueue.c +93 -0
  203. data/redis/redis-2.2.11/src/ae_select.c +72 -0
  204. data/redis/redis-2.2.11/src/anet.c +347 -0
  205. data/redis/redis-2.2.11/src/anet.h +57 -0
  206. data/redis/redis-2.2.11/src/aof.c +675 -0
  207. data/redis/redis-2.2.11/src/config.c +627 -0
  208. data/redis/redis-2.2.11/src/config.h +64 -0
  209. data/redis/redis-2.2.11/src/db.c +543 -0
  210. data/redis/redis-2.2.11/src/debug.c +314 -0
  211. data/redis/redis-2.2.11/src/dict.c +721 -0
  212. data/redis/redis-2.2.11/src/dict.h +156 -0
  213. data/redis/redis-2.2.11/src/fmacros.h +15 -0
  214. data/redis/redis-2.2.11/src/help.h +638 -0
  215. data/redis/redis-2.2.11/src/intset.c +422 -0
  216. data/redis/redis-2.2.11/src/intset.h +19 -0
  217. data/redis/redis-2.2.11/src/lzf.h +100 -0
  218. data/redis/redis-2.2.11/src/lzfP.h +159 -0
  219. data/redis/redis-2.2.11/src/lzf_c.c +295 -0
  220. data/redis/redis-2.2.11/src/lzf_d.c +150 -0
  221. data/redis/redis-2.2.11/src/mkreleasehdr.sh +9 -0
  222. data/redis/redis-2.2.11/src/multi.c +268 -0
  223. data/redis/redis-2.2.11/src/networking.c +899 -0
  224. data/redis/redis-2.2.11/src/object.c +484 -0
  225. data/redis/redis-2.2.11/src/pqsort.c +197 -0
  226. data/redis/redis-2.2.11/src/pqsort.h +15 -0
  227. data/redis/redis-2.2.11/src/pubsub.c +267 -0
  228. data/redis/redis-2.2.11/src/rdb.c +1020 -0
  229. data/redis/redis-2.2.11/src/redis-benchmark.c +530 -0
  230. data/redis/redis-2.2.11/src/redis-check-aof.c +185 -0
  231. data/redis/redis-2.2.11/src/redis-check-dump.c +681 -0
  232. data/redis/redis-2.2.11/src/redis-cli.c +773 -0
  233. data/redis/redis-2.2.11/src/redis.c +1677 -0
  234. data/redis/redis-2.2.11/src/redis.h +1022 -0
  235. data/redis/redis-2.2.11/src/release.c +13 -0
  236. data/redis/redis-2.2.11/src/replication.c +557 -0
  237. data/redis/redis-2.2.11/src/sds.c +639 -0
  238. data/redis/redis-2.2.11/src/sds.h +78 -0
  239. data/redis/redis-2.2.11/src/sha1.c +276 -0
  240. data/redis/redis-2.2.11/src/sha1.h +17 -0
  241. data/redis/redis-2.2.11/src/solarisfixes.h +22 -0
  242. data/redis/redis-2.2.11/src/sort.c +389 -0
  243. data/redis/redis-2.2.11/src/syncio.c +154 -0
  244. data/redis/redis-2.2.11/src/t_hash.c +476 -0
  245. data/redis/redis-2.2.11/src/t_list.c +986 -0
  246. data/redis/redis-2.2.11/src/t_set.c +610 -0
  247. data/redis/redis-2.2.11/src/t_string.c +438 -0
  248. data/redis/redis-2.2.11/src/t_zset.c +1084 -0
  249. data/redis/redis-2.2.11/src/testhelp.h +54 -0
  250. data/redis/redis-2.2.11/src/util.c +243 -0
  251. data/redis/redis-2.2.11/src/valgrind.sup +5 -0
  252. data/redis/redis-2.2.11/src/version.h +1 -0
  253. data/redis/redis-2.2.11/src/vm.c +1149 -0
  254. data/redis/redis-2.2.11/src/ziplist.c +1323 -0
  255. data/redis/redis-2.2.11/src/ziplist.h +15 -0
  256. data/redis/redis-2.2.11/src/zipmap.c +455 -0
  257. data/redis/redis-2.2.11/src/zipmap.h +48 -0
  258. data/redis/redis-2.2.11/src/zmalloc.c +278 -0
  259. data/redis/redis-2.2.11/src/zmalloc.h +47 -0
  260. data/redis/redis-2.2.11/tests/assets/default.conf +308 -0
  261. data/redis/redis-2.2.11/tests/integration/aof.tcl +104 -0
  262. data/redis/redis-2.2.11/tests/integration/redis-cli.tcl +208 -0
  263. data/redis/redis-2.2.11/tests/integration/replication.tcl +98 -0
  264. data/redis/redis-2.2.11/tests/support/redis.tcl +241 -0
  265. data/redis/redis-2.2.11/tests/support/server.tcl +294 -0
  266. data/redis/redis-2.2.11/tests/support/test.tcl +190 -0
  267. data/redis/redis-2.2.11/tests/support/tmpfile.tcl +15 -0
  268. data/redis/redis-2.2.11/tests/support/util.tcl +296 -0
  269. data/redis/redis-2.2.11/tests/test_helper.tcl +221 -0
  270. data/redis/redis-2.2.11/tests/unit/auth.tcl +15 -0
  271. data/redis/redis-2.2.11/tests/unit/basic.tcl +616 -0
  272. data/redis/redis-2.2.11/tests/unit/cas.tcl +135 -0
  273. data/redis/redis-2.2.11/tests/unit/expire.tcl +74 -0
  274. data/redis/redis-2.2.11/tests/unit/other.tcl +240 -0
  275. data/redis/redis-2.2.11/tests/unit/printver.tcl +6 -0
  276. data/redis/redis-2.2.11/tests/unit/protocol.tcl +62 -0
  277. data/redis/redis-2.2.11/tests/unit/pubsub.tcl +195 -0
  278. data/redis/redis-2.2.11/tests/unit/quit.tcl +40 -0
  279. data/redis/redis-2.2.11/tests/unit/sort.tcl +189 -0
  280. data/redis/redis-2.2.11/tests/unit/type/hash.tcl +300 -0
  281. data/redis/redis-2.2.11/tests/unit/type/list.tcl +819 -0
  282. data/redis/redis-2.2.11/tests/unit/type/set.tcl +334 -0
  283. data/redis/redis-2.2.11/tests/unit/type/zset.tcl +587 -0
  284. data/redis/redis-2.2.11/utils/build-static-symbols.tcl +22 -0
  285. data/redis/redis-2.2.11/utils/generate-command-help.rb +112 -0
  286. data/redis/redis-2.2.11/utils/mktarball.sh +13 -0
  287. data/redis/redis-2.2.11/utils/redis-copy.rb +78 -0
  288. data/redis/redis-2.2.11/utils/redis-sha1.rb +52 -0
  289. data/redis/redis-2.2.11/utils/redis_init_script +42 -0
  290. 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
+