Compare commits
1732
Commits
v5.3.0
...
async_rehash
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbe8b859f5 | ||
|
|
584709ce1d | ||
|
|
3249e4683c | ||
|
|
86c6977937 | ||
|
|
eb8d294a95 | ||
|
|
285afd226b | ||
|
|
7273086bfa | ||
|
|
08303b767b | ||
|
|
774aa1e03e | ||
|
|
165333b0fc | ||
|
|
cc827e157a | ||
|
|
7b4e25008a | ||
|
|
f66e5a9c3d | ||
|
|
9954f5b4a4 | ||
|
|
53936661c8 | ||
|
|
e2552ff8a9 | ||
|
|
6ab08cc3e1 | ||
|
|
3205373bb3 | ||
|
|
3b8d1f7076 | ||
|
|
5832c25ad1 | ||
|
|
569a3d9ff8 | ||
|
|
69bc7108bd | ||
|
|
8a557e9d71 | ||
|
|
fe0f071993 | ||
|
|
effa53339c | ||
|
|
f6fb0e4620 | ||
|
|
cf46a014c1 | ||
|
|
d72b5fa16d | ||
|
|
0151507cef | ||
|
|
0fea781f8f | ||
|
|
3c4cadc020 | ||
|
|
e2615ccf88 | ||
|
|
595deb0e13 | ||
|
|
5372d1aab2 | ||
|
|
52eca14ca6 | ||
|
|
1155f5ac63 | ||
|
|
7319953ae3 | ||
|
|
b8e106a72e | ||
|
|
f30f8eba2f | ||
|
|
7ed2296fc5 | ||
|
|
0691a46669 | ||
|
|
d7f01c1f7d | ||
|
|
4d71929c60 | ||
|
|
dadce055f8 | ||
|
|
d2867580ab | ||
|
|
8dc238efae | ||
|
|
7cd4b5e11c | ||
|
|
00043f9509 | ||
|
|
9b81f3f263 | ||
|
|
2747d1a1a9 | ||
|
|
9f7ed0b232 | ||
|
|
c176ea7366 | ||
|
|
8d70d498d5 | ||
|
|
5745b469d3 | ||
|
|
a11c842ecd | ||
|
|
615eb0db86 | ||
|
|
203feb6ea2 | ||
|
|
08c3f0bca6 | ||
|
|
3bf02ea7e8 | ||
|
|
acb4cd2135 | ||
|
|
fb86ecb802 | ||
|
|
2c5865cd90 | ||
|
|
ebbcd05e03 | ||
|
|
de4f04a272 | ||
|
|
f2f57eb44f | ||
|
|
8119259bb6 | ||
|
|
e664f38170 | ||
|
|
f464cf2380 | ||
|
|
02c395a179 | ||
|
|
acdccab019 | ||
|
|
e9f674e5fb | ||
|
|
0f8d47c9ed | ||
|
|
f1d56c981d | ||
|
|
ea595784f9 | ||
|
|
549fe1f3af | ||
|
|
cf6b0f9cef | ||
|
|
02e930624a | ||
|
|
ec56906bd6 | ||
|
|
23d299234c | ||
|
|
f84c181eac | ||
|
|
8ff0226361 | ||
|
|
d756b11fa2 | ||
|
|
ec74ae7ec1 | ||
|
|
785851a736 | ||
|
|
2a2d5a7a1f | ||
|
|
a60ed4a599 | ||
|
|
5ed6662145 | ||
|
|
f885e364ba | ||
|
|
3ac666b3e6 | ||
|
|
4b37eb13dc | ||
|
|
3a13c654e6 | ||
|
|
d50e4bb819 | ||
|
|
4485ca74f6 | ||
|
|
7f72b214e5 | ||
|
|
bc8cc1adb3 | ||
|
|
d03c2de901 | ||
|
|
7d3c5f1e64 | ||
|
|
81573de393 | ||
|
|
a80dd5d001 | ||
|
|
7e0077f293 | ||
|
|
1eb035e6ad | ||
|
|
bdd14ac517 | ||
|
|
63e5d00bdf | ||
|
|
c25fb3d74f | ||
|
|
572d41325b | ||
|
|
e02120cdf7 | ||
|
|
7b1221a74d | ||
|
|
d6b4f994ad | ||
|
|
66a41dafc4 | ||
|
|
f19b9c155e | ||
|
|
5d016fdb6b | ||
|
|
cae9924fd9 | ||
|
|
089f28e8ba | ||
|
|
dcb44d3a09 | ||
|
|
f99cba0b92 | ||
|
|
e10dc0dace | ||
|
|
49a89d636b | ||
|
|
b94f91b9b2 | ||
|
|
06a17c8511 | ||
|
|
eebd70aaa6 | ||
|
|
779c775df9 | ||
|
|
1d4d2925c2 | ||
|
|
b67db7c2d5 | ||
|
|
18953b2998 | ||
|
|
527b7eb074 | ||
|
|
34a97c447f | ||
|
|
1c525e20b1 | ||
|
|
0bcce50285 | ||
|
|
96e0b2a2b1 | ||
|
|
f3794d2c42 | ||
|
|
97fd736923 | ||
|
|
ba950a3d1f | ||
|
|
dad5a902d3 | ||
|
|
25214bd7dc | ||
|
|
3cc673bdd8 | ||
|
|
de0919cd62 | ||
|
|
5aa0fef2ce | ||
|
|
3988e32f41 | ||
|
|
6f16e52a6d | ||
|
|
c6c2de9567 | ||
|
|
cebc1f2696 | ||
|
|
56d8ad932d | ||
|
|
0103dc09d2 | ||
|
|
71c1427a1b | ||
|
|
30bb0dd595 | ||
|
|
99f39d32ab | ||
|
|
851ec530b4 | ||
|
|
79e6ab31d8 | ||
|
|
b20af834ff | ||
|
|
1453277294 | ||
|
|
e4e24460f9 | ||
|
|
db9cffe7c2 | ||
|
|
9c475272da | ||
|
|
6f2c894d69 | ||
|
|
4147a2202e | ||
|
|
28d1fe6718 | ||
|
|
116a2042a7 | ||
|
|
945983ac52 | ||
|
|
e7c8002b56 | ||
|
|
86b5e1a72f | ||
|
|
bab834574c | ||
|
|
76f3a63de1 | ||
|
|
93b4c6b31e | ||
|
|
12055ed8c2 | ||
|
|
c80f6219d5 | ||
|
|
801c7307fb | ||
|
|
a7b95b7c72 | ||
|
|
919580a228 | ||
|
|
e83d6b0cfa | ||
|
|
cb070accb4 | ||
|
|
9ce6fc7322 | ||
|
|
a7b9cfbe98 | ||
|
|
219bab2d85 | ||
|
|
d51bebd4d7 | ||
|
|
120c6b43e1 | ||
|
|
63075b81e6 | ||
|
|
9418083770 | ||
|
|
5d1ac2df64 | ||
|
|
90555566ed | ||
|
|
bb7e00b699 | ||
|
|
faa431c98d | ||
|
|
757ad7cdf2 | ||
|
|
31491202aa | ||
|
|
26c1c60187 | ||
|
|
2ccbba650c | ||
|
|
c73406c2bd | ||
|
|
c1423c016c | ||
|
|
ecf51b0b3d | ||
|
|
9d0388a043 | ||
|
|
6a4da4958e | ||
|
|
e8f772efff | ||
|
|
59866fcd30 | ||
|
|
4832cf4fd6 | ||
|
|
fd610ae025 | ||
|
|
88441019a5 | ||
|
|
aa1feec746 | ||
|
|
e5e353c81d | ||
|
|
0bdddd3c89 | ||
|
|
7bc0726016 | ||
|
|
ea4bf91abc | ||
|
|
5d9332266d | ||
|
|
7601ed344c | ||
|
|
405f041e90 | ||
|
|
aa6b869c15 | ||
|
|
00a767db38 | ||
|
|
5106a144f0 | ||
|
|
3efdbbc79c | ||
|
|
2ae7f49115 | ||
|
|
3e33fbcd35 | ||
|
|
444555d3e4 | ||
|
|
6a74f524e5 | ||
|
|
9c5b59ac01 | ||
|
|
1840601f8e | ||
|
|
88962af8b2 | ||
|
|
df22cdf6e9 | ||
|
|
041446005b | ||
|
|
7c39a9b0e1 | ||
|
|
05cd92f766 | ||
|
|
d724e7226c | ||
|
|
738c782f02 | ||
|
|
33b05c859a | ||
|
|
ed369d7223 | ||
|
|
fb32bb12b1 | ||
|
|
3e996035ea | ||
|
|
ae8a94d615 | ||
|
|
69a74a567b | ||
|
|
1b46d4f09a | ||
|
|
c6f13892e0 | ||
|
|
05e0f32345 | ||
|
|
8171e6de13 | ||
|
|
b042495f37 | ||
|
|
420ccdfbae | ||
|
|
41466a4147 | ||
|
|
9798f2d711 | ||
|
|
5f3543921b | ||
|
|
a41366cc3a | ||
|
|
4c7e4b91a6 | ||
|
|
28183f4b66 | ||
|
|
a0abc1eddd | ||
|
|
676644f2db | ||
|
|
22ac56d62d | ||
|
|
143f7f634d | ||
|
|
955faef23a | ||
|
|
2e159e6ea3 | ||
|
|
02b533fec3 | ||
|
|
de3099e6d8 | ||
|
|
368f67f422 | ||
|
|
13c9a094d1 | ||
|
|
0f8b7a19ef | ||
|
|
8f7d977f90 | ||
|
|
064440ee84 | ||
|
|
50641d0569 | ||
|
|
f5ecc77e29 | ||
|
|
655bb6e21c | ||
|
|
ab4cdd2ed4 | ||
|
|
d3834c5069 | ||
|
|
7a1b2c58c3 | ||
|
|
7fc6d6c6b1 | ||
|
|
dec5db4e71 | ||
|
|
03b59cd5f0 | ||
|
|
5380716a70 | ||
|
|
18b30467f7 | ||
|
|
0052d5196d | ||
|
|
b55b0ea0f2 | ||
|
|
25e211bcf0 | ||
|
|
635704d424 | ||
|
|
47364bce69 | ||
|
|
3cd6c26056 | ||
|
|
8b0d797ecd | ||
|
|
3c8b394511 | ||
|
|
84ba2ec82b | ||
|
|
cf3375bf7c | ||
|
|
643d3e0b79 | ||
|
|
874c3a9978 | ||
|
|
781e50d41f | ||
|
|
57dbd6e90d | ||
|
|
e9fef49e12 | ||
|
|
a227bc8053 | ||
|
|
d410dc3162 | ||
|
|
41c7c7919c | ||
|
|
db6c763d8b | ||
|
|
72d6f966ac | ||
|
|
28e074608c | ||
|
|
5b8de5b7f2 | ||
|
|
bce350c666 | ||
|
|
332aa2f919 | ||
|
|
e4db67ea57 | ||
|
|
b983015dd4 | ||
|
|
9b718d41f0 | ||
|
|
da33a18588 | ||
|
|
d47aeb1fc8 | ||
|
|
e47584b286 | ||
|
|
dbea5f7a8d | ||
|
|
4bb40a9688 | ||
|
|
d2532d1335 | ||
|
|
00d0d870d2 | ||
|
|
f38e2802b6 | ||
|
|
1b100a167a | ||
|
|
d4e1c88052 | ||
|
|
2c0c5a809c | ||
|
|
f6d04d01b9 | ||
|
|
2fc915f509 | ||
|
|
e3cfc92180 | ||
|
|
7fcf29e615 | ||
|
|
e81bac32fd | ||
|
|
2257f38b68 | ||
|
|
2165a78d10 | ||
|
|
e6f6731c66 | ||
|
|
5a9a653f3e | ||
|
|
ff0846cbb7 | ||
|
|
3e2ed279fd | ||
|
|
19ef1f371d | ||
|
|
8d79702d8a | ||
|
|
6cfcf76e0b | ||
|
|
c9478a3b4e | ||
|
|
113d5ae872 | ||
|
|
1bd75aafdb | ||
|
|
ba48e7e9cd | ||
|
|
4e19358d65 | ||
|
|
43bc1ea065 | ||
|
|
3842bfd899 | ||
|
|
6dcd641681 | ||
|
|
1180537589 | ||
|
|
2e7ad58918 | ||
|
|
39ffc3702f | ||
|
|
31415cb27a | ||
|
|
840a9951b5 | ||
|
|
3c87d572b9 | ||
|
|
d3831559cf | ||
|
|
44ef19743e | ||
|
|
171f83306e | ||
|
|
0314429c8f | ||
|
|
086707315f | ||
|
|
9fd0c027e7 | ||
|
|
0e581e0044 | ||
|
|
e8801f7eaa | ||
|
|
3a677b45ac | ||
|
|
dc46f6f041 | ||
|
|
916b215fc5 | ||
|
|
9f0e8f7849 | ||
|
|
a5294c4e52 | ||
|
|
e511ab2cc6 | ||
|
|
7200b3aa0f | ||
|
|
e8efcdee0a | ||
|
|
2bcc056a41 | ||
|
|
b2bd3c0653 | ||
|
|
4238df5436 | ||
|
|
c68b3908a6 | ||
|
|
1c05b87e30 | ||
|
|
67750ce3b3 | ||
|
|
096285ab64 | ||
|
|
0b2f7c6407 | ||
|
|
8a4240b1fa | ||
|
|
395d339234 | ||
|
|
6daa8b9adb | ||
|
|
e00b6248c9 | ||
|
|
e8aa5583d0 | ||
|
|
f1d5d5d28e | ||
|
|
cc7f4ba67e | ||
|
|
af907e4b6d | ||
|
|
d2f09a054c | ||
|
|
cef46edebc | ||
|
|
9e997cd0d1 | ||
|
|
171aa22b0b | ||
|
|
f17d178d03 | ||
|
|
d88fd1588d | ||
|
|
7bf665f125 | ||
|
|
a5696bdf4f | ||
|
|
e15528bf1d | ||
|
|
e28aa99af1 | ||
|
|
3051430040 | ||
|
|
29b20fd528 | ||
|
|
5b36681213 | ||
|
|
0f75036c07 | ||
|
|
b1a01fda91 | ||
|
|
83f55f61a6 | ||
|
|
f89f50dbd0 | ||
|
|
05f8975d21 | ||
|
|
4780cc5efa | ||
|
|
9bc6af2449 | ||
|
|
c4b428a388 | ||
|
|
aea4db2f5a | ||
|
|
b5c5f870a4 | ||
|
|
23bf3d1cb9 | ||
|
|
1be6dbbdf6 | ||
|
|
1acdc84d10 | ||
|
|
52929b61f8 | ||
|
|
b0faf6113e | ||
|
|
f838df92d2 | ||
|
|
7a536c2912 | ||
|
|
6f1e828454 | ||
|
|
2d3687655b | ||
|
|
b057ff81ee | ||
|
|
a9d1014fb2 | ||
|
|
183bdc11c0 | ||
|
|
95ba01b538 | ||
|
|
7b21b8c3fb | ||
|
|
33ca884cc5 | ||
|
|
2b5f23197c | ||
|
|
1104113c07 | ||
|
|
62f8583445 | ||
|
|
3155adb299 | ||
|
|
14a59d4ce7 | ||
|
|
17aaf5ec97 | ||
|
|
3f5cf24da9 | ||
|
|
05e483cbb3 | ||
|
|
c8f250f8dd | ||
|
|
9412094f25 | ||
|
|
8312aa27d4 | ||
|
|
d3aa3791fe | ||
|
|
2b189f098e | ||
|
|
3328b7a514 | ||
|
|
88e1f80eee | ||
|
|
0ebbc36059 | ||
|
|
43ed3c3589 | ||
|
|
8095daea4a | ||
|
|
51e178454d | ||
|
|
82b2bfd20b | ||
|
|
ec1faeec72 | ||
|
|
c1326d7b10 | ||
|
|
845fb2d1c1 | ||
|
|
930fac8058 | ||
|
|
119797014c | ||
|
|
e8f568644b | ||
|
|
b736a95b0d | ||
|
|
d909d12cb3 | ||
|
|
201ffa9d62 | ||
|
|
5619f51528 | ||
|
|
d99d06b125 | ||
|
|
1b9ade7f65 | ||
|
|
e01312642b | ||
|
|
cd9514f4c8 | ||
|
|
f111c23415 | ||
|
|
6857c4c208 | ||
|
|
52897f8f9a | ||
|
|
8bc70e9840 | ||
|
|
5b81303f04 | ||
|
|
ede524c064 | ||
|
|
aeed09c346 | ||
|
|
0cae0900cf | ||
|
|
e0022d8cfe | ||
|
|
495327c020 | ||
|
|
afb8b3c030 | ||
|
|
31c9cd8604 | ||
|
|
70b80aa5fa | ||
|
|
51efb7fe25 | ||
|
|
a7d3670da5 | ||
|
|
ee8dd01bbc | ||
|
|
a4a856d532 | ||
|
|
e2046b3003 | ||
|
|
b35fdf1de1 | ||
|
|
1d7bf208ce | ||
|
|
676445ad95 | ||
|
|
4846c0c8af | ||
|
|
e8d4d095cc | ||
|
|
c50a3568a5 | ||
|
|
17e96b91b5 | ||
|
|
c5e7a8517b | ||
|
|
c36773777d | ||
|
|
d69e0b8561 | ||
|
|
19ccc22a43 | ||
|
|
6968a0cfcb | ||
|
|
df618fbd9f | ||
|
|
94acd43340 | ||
|
|
14bdd745d1 | ||
|
|
aa3f5de16f | ||
|
|
9f7890cb1a | ||
|
|
1dc34c16b5 | ||
|
|
b0e7be7ce2 | ||
|
|
026ab4c922 | ||
|
|
07ba64c200 | ||
|
|
b4b35cf904 | ||
|
|
ba974c9810 | ||
|
|
9817db7edd | ||
|
|
515bb0e6bd | ||
|
|
bc7ea8fb20 | ||
|
|
2caf8e4c80 | ||
|
|
e1f3cd6ec3 | ||
|
|
02e821530a | ||
|
|
b6c3d80edb | ||
|
|
f33de403ed | ||
|
|
49af4d07e4 | ||
|
|
329fddbda1 | ||
|
|
925a2cd5aa | ||
|
|
84a7a90586 | ||
|
|
cd63359a17 | ||
|
|
0042586190 | ||
|
|
c6dce838b7 | ||
|
|
5b885bb164 | ||
|
|
95f46e6077 | ||
|
|
31f58311e3 | ||
|
|
130613e166 | ||
|
|
50fd4fa7e6 | ||
|
|
e6a9a6b428 | ||
|
|
d6be93537e | ||
|
|
1ef35cf466 | ||
|
|
1eb0e3c1c6 | ||
|
|
e50313b207 | ||
|
|
ac3f8d1ac7 | ||
|
|
202b97eff7 | ||
|
|
f25aebf269 | ||
|
|
9b1e636a66 | ||
|
|
5147f0153a | ||
|
|
88f7739ae0 | ||
|
|
c0c033a0c1 | ||
|
|
73300c5700 | ||
|
|
37033179fe | ||
|
|
3e6a5ac9cf | ||
|
|
dcd297eb5b | ||
|
|
4a9742e696 | ||
|
|
8edbae2e04 | ||
|
|
63c6735ffc | ||
|
|
8a0441c144 | ||
|
|
460c5ed2b3 | ||
|
|
8f44f0937b | ||
|
|
1803b1587b | ||
|
|
a5325061f2 | ||
|
|
a10a0df09f | ||
|
|
031044c7ea | ||
|
|
ca755e4905 | ||
|
|
3063a028b3 | ||
|
|
2c659acc7d | ||
|
|
341a8caef9 | ||
|
|
366f8c2dc6 | ||
|
|
5803540422 | ||
|
|
f17c492a63 | ||
|
|
aad6a7ce15 | ||
|
|
1cb48c7bf6 | ||
|
|
f25c405ad2 | ||
|
|
c9920849dd | ||
|
|
81b240f81d | ||
|
|
6a902b29e1 | ||
|
|
9c31ac7925 | ||
|
|
f0d8d1680f | ||
|
|
6dcbcacb10 | ||
|
|
3196717cee | ||
|
|
f95578ac02 | ||
|
|
57ca6facc3 | ||
|
|
886d287c40 | ||
|
|
59cd4c9f65 | ||
|
|
6c1bb7b194 | ||
|
|
1aee695e52 | ||
|
|
a2ae463520 | ||
|
|
86e562d691 | ||
|
|
ab2984b1e2 | ||
|
|
1ff5a222de | ||
|
|
cc549b46a4 | ||
|
|
377dd0515c | ||
|
|
3f8d113f1b | ||
|
|
d4541349dc | ||
|
|
2112a57028 | ||
|
|
d2eb6e0b47 | ||
|
|
9c1df3b769 | ||
|
|
115ed1911e | ||
|
|
11c748aaca | ||
|
|
8f10137227 | ||
|
|
561a1f8d8a | ||
|
|
1449c8b9fe | ||
|
|
1938af27f5 | ||
|
|
2e591fc4a4 | ||
|
|
cbb51fb8f9 | ||
|
|
e0fc88b4d9 | ||
|
|
e3f864b5fd | ||
|
|
8af1e513f6 | ||
|
|
3c21418cd8 | ||
|
|
123bc125cf | ||
|
|
ecbe168b54 | ||
|
|
00cef78858 | ||
|
|
d05da0fabd | ||
|
|
4db3f2a443 | ||
|
|
fd710d590a | ||
|
|
9b98c9edd3 | ||
|
|
4893eedacb | ||
|
|
fb50163b47 | ||
|
|
3b8463f9d2 | ||
|
|
42c7677690 | ||
|
|
8665f25031 | ||
|
|
1c6b573147 | ||
|
|
90162da1a6 | ||
|
|
1ca6c1dd56 | ||
|
|
2d27c8ecdb | ||
|
|
59cda9cfb9 | ||
|
|
091af64003 | ||
|
|
a12210c875 | ||
|
|
43649fc5b4 | ||
|
|
01cc25653a | ||
|
|
a010e4a4b2 | ||
|
|
817a11ff11 | ||
|
|
c52e1fc78c | ||
|
|
d74871da40 | ||
|
|
a25cf15ecd | ||
|
|
e201f83cee | ||
|
|
58fc456cbd | ||
|
|
3febc5c29e | ||
|
|
8d67385593 | ||
|
|
7a35eec540 | ||
|
|
f93e1417b9 | ||
|
|
d0c9e44545 | ||
|
|
1cde6a0603 | ||
|
|
436be34986 | ||
|
|
f9d2ffdc5d | ||
|
|
d7968ee920 | ||
|
|
a902e6b251 | ||
|
|
9564ed7c39 | ||
|
|
2e41827435 | ||
|
|
eb2c8b2c61 | ||
|
|
928e6976bb | ||
|
|
cdcf5af5aa | ||
|
|
e8b09d2203 | ||
|
|
57b4fb0d84 | ||
|
|
29f25e4111 | ||
|
|
00d8b92b89 | ||
|
|
5e17e6276c | ||
|
|
96e7c011e2 | ||
|
|
c505df8830 | ||
|
|
f214ada545 | ||
|
|
c10aa3b8b0 | ||
|
|
6311d709c3 | ||
|
|
8ab77465db | ||
|
|
201bf73ef7 | ||
|
|
49784c8122 | ||
|
|
3e03f308b5 | ||
|
|
95cecb0229 | ||
|
|
7676f5b15f | ||
|
|
d5b057534a | ||
|
|
7a15f6dfc7 | ||
|
|
712d825c23 | ||
|
|
7803b1148d | ||
|
|
1eab62f7e5 | ||
|
|
ae306a3df6 | ||
|
|
16ba33c05b | ||
|
|
77ae66930c | ||
|
|
389697988a | ||
|
|
2435341d74 | ||
|
|
80c906bd30 | ||
|
|
4073758874 | ||
|
|
74249be4a2 | ||
|
|
8bf660af90 | ||
|
|
9da134cd88 | ||
|
|
f7f219a137 | ||
|
|
693629585b | ||
|
|
e3b5648df0 | ||
|
|
5c41802d55 | ||
|
|
3543a3c763 | ||
|
|
3122912920 | ||
|
|
f11fdf6717 | ||
|
|
572bcca9c2 | ||
|
|
10fa064109 | ||
|
|
7cd779d304 | ||
|
|
628d168049 | ||
|
|
37423757b5 | ||
|
|
58752bb8fe | ||
|
|
7e7f70ff3e | ||
|
|
f77c227b2d | ||
|
|
21d842b0b0 | ||
|
|
a23cdbb94b | ||
|
|
1276058ea8 | ||
|
|
002fcde3da | ||
|
|
960186a71f | ||
|
|
cb683a84f7 | ||
|
|
3672875b4c | ||
|
|
84d9766d6a | ||
|
|
24e12641d5 | ||
|
|
ec1e106ec5 | ||
|
|
c7edffbd56 | ||
|
|
e48c37316e | ||
|
|
8a9c84f4a5 | ||
|
|
1e561cfaaf | ||
|
|
d1af82a883 | ||
|
|
897a360d06 | ||
|
|
3a441c7d95 | ||
|
|
c57d9146f4 | ||
|
|
ac316d8cc5 | ||
|
|
75addb4fe2 | ||
|
|
3d3861dd88 | ||
|
|
fc7bc32045 | ||
|
|
a6e55c096d | ||
|
|
b062fd5235 | ||
|
|
4efb25d9c0 | ||
|
|
d6436eb7cf | ||
|
|
86f9ed6248 | ||
|
|
47ff13637e | ||
|
|
db73d0998f | ||
|
|
7c0fe72714 | ||
|
|
8fe25edc75 | ||
|
|
dcd7b684bb | ||
|
|
17dfd7cabb | ||
|
|
1f9b82bd56 | ||
|
|
3fcffe7d04 | ||
|
|
455d8a05c1 | ||
|
|
70287bbc94 | ||
|
|
7be21139aa | ||
|
|
e1ee1a49d6 | ||
|
|
d56f058c08 | ||
|
|
96dd5fc932 | ||
|
|
5b59d9c5d7 | ||
|
|
c163d4addc | ||
|
|
aab74b7151 | ||
|
|
606134f9de | ||
|
|
ee627bb667 | ||
|
|
47b8a7f9b8 | ||
|
|
6c0bc608a1 | ||
|
|
5bfc18950a | ||
|
|
56d628f851 | ||
|
|
cac9d7cf7e | ||
|
|
f715d0b860 | ||
|
|
98d690b849 | ||
|
|
45535e8a63 | ||
|
|
c78895aaea | ||
|
|
b712fba17c | ||
|
|
ea63aea72d | ||
|
|
64e588bfab | ||
|
|
0d1e8c93bf | ||
|
|
a1bed447b3 | ||
|
|
a75fa3aad1 | ||
|
|
52c75e9db1 | ||
|
|
8110ba8880 | ||
|
|
e4d2bb62b2 | ||
|
|
fea9788cc4 | ||
|
|
2144047e14 | ||
|
|
43329c9b64 | ||
|
|
1e17d3de79 | ||
|
|
d5ede50b04 | ||
|
|
fab6132cb3 | ||
|
|
3722f89f49 | ||
|
|
373ae6061a | ||
|
|
f03f1fad67 | ||
|
|
374ffdf1c1 | ||
|
|
4db38d2efd | ||
|
|
f0a261448c | ||
|
|
fbdef6a9bd | ||
|
|
05a41da75b | ||
|
|
345c3768de | ||
|
|
639c8a1d91 | ||
|
|
321acea038 | ||
|
|
b0920e6e86 | ||
|
|
149b658b56 | ||
|
|
06917e581c | ||
|
|
e434b2ce4f | ||
|
|
f3a1728873 | ||
|
|
e63bb7ec8c | ||
|
|
6791ff0525 | ||
|
|
725b8cc680 | ||
|
|
3575b8706d | ||
|
|
a76c67578c | ||
|
|
3a27064c41 | ||
|
|
e0a8709c09 | ||
|
|
17795fd5ce | ||
|
|
d6738ffa5d | ||
|
|
5c4c73e2c2 | ||
|
|
6148f94939 | ||
|
|
51d3012d48 | ||
|
|
c39f16c422 | ||
|
|
e72642667f | ||
|
|
3785b1efd4 | ||
|
|
7aeae62f84 | ||
|
|
e5e33f8cb7 | ||
|
|
a836d5947d | ||
|
|
7cf0a77d59 | ||
|
|
9f594e2432 | ||
|
|
48781dd95c | ||
|
|
7cdd5d9e41 | ||
|
|
3f5d3fec36 | ||
|
|
90094a2dca | ||
|
|
cc9924ffa6 | ||
|
|
5e6b4ab99e | ||
|
|
2d6d374162 | ||
|
|
3137d4f35c | ||
|
|
6ff9d23fd4 | ||
|
|
d4939c838b | ||
|
|
cd306f1d23 | ||
|
|
5fd07e0889 | ||
|
|
b0796ff5fd | ||
|
|
9dfa074cd6 | ||
|
|
033761c5f9 | ||
|
|
2926ac494e | ||
|
|
06143c2e8c | ||
|
|
f00d28fdab | ||
|
|
4705f29e2f | ||
|
|
371ab0cff8 | ||
|
|
b86140ac5f | ||
|
|
bec68bff29 | ||
|
|
414debfd04 | ||
|
|
a7ee3c3e77 | ||
|
|
0f239e51b0 | ||
|
|
e5b9eb8171 | ||
|
|
f855db61b0 | ||
|
|
0f31bb5c1a | ||
|
|
23094ba015 | ||
|
|
b92d9a895f | ||
|
|
8161a7a3ef | ||
|
|
8f896e57ae | ||
|
|
61b153073f | ||
|
|
8f5157058b | ||
|
|
ddeda9ceb7 | ||
|
|
bde1f0a8e2 | ||
|
|
b2cb10de5f | ||
|
|
1005a725d4 | ||
|
|
50768cd242 | ||
|
|
cc3ebbe519 | ||
|
|
8056e349e0 | ||
|
|
0001f59c8d | ||
|
|
2941792a85 | ||
|
|
320bc3c032 | ||
|
|
2825e51550 | ||
|
|
cbdd47d056 | ||
|
|
516c8c6e23 | ||
|
|
ef1236b600 | ||
|
|
28cbed1d13 | ||
|
|
cde199a797 | ||
|
|
5589a0a69c | ||
|
|
09e8fb17cd | ||
|
|
d71c4c2215 | ||
|
|
6f621e6480 | ||
|
|
8e33c2d301 | ||
|
|
52aca124c3 | ||
|
|
c7159d58f1 | ||
|
|
5d6e8fe3e3 | ||
|
|
99762dac23 | ||
|
|
57956b3fd2 | ||
|
|
b323645227 | ||
|
|
dd9502f373 | ||
|
|
aa8a3077a2 | ||
|
|
8e81e5f29e | ||
|
|
63dd1fb599 | ||
|
|
32561a9912 | ||
|
|
cbcd07777d | ||
|
|
2437455f27 | ||
|
|
35c64b898c | ||
|
|
c3ac717487 | ||
|
|
c8dbcff9db | ||
|
|
abd5156f25 | ||
|
|
5719b3054a | ||
|
|
c89e1f2937 | ||
|
|
0b16f8d444 | ||
|
|
9254a805d7 | ||
|
|
a4c4907035 | ||
|
|
cb92c23de0 | ||
|
|
56a52e804c | ||
|
|
ebb09a5c3b | ||
|
|
a9f8a8cba0 | ||
|
|
4aa24e62a4 | ||
|
|
2b67b6b87e | ||
|
|
420aac7274 | ||
|
|
a518a9a766 | ||
|
|
026cc11b05 | ||
|
|
02b594f6ad | ||
|
|
f695d18306 | ||
|
|
0e42cfc365 | ||
|
|
024c380b9d | ||
|
|
eba28e2cea | ||
|
|
c35a53169f | ||
|
|
91ed9b3c47 | ||
|
|
a38ff404bd | ||
|
|
15c9e79a7d | ||
|
|
6fe66e0969 | ||
|
|
3e0d209625 | ||
|
|
814874d68b | ||
|
|
cd2b5df971 | ||
|
|
240094c9b0 | ||
|
|
061616c1b1 | ||
|
|
8cdc153f58 | ||
|
|
209f3a1eba | ||
|
|
7764996bec | ||
|
|
b35407fa7c | ||
|
|
4395889c9e | ||
|
|
1907e0f18f | ||
|
|
193fc241ca | ||
|
|
3fdc8608f3 | ||
|
|
9e2e2067c6 | ||
|
|
f112c77fcc | ||
|
|
888d69a87a | ||
|
|
bd183cdee1 | ||
|
|
957e917a84 | ||
|
|
ef1b1f01a8 | ||
|
|
9f347fabba | ||
|
|
a509400d58 | ||
|
|
c3b268a0bc | ||
|
|
0f7dfc378c | ||
|
|
805c8c94a9 | ||
|
|
97b80b57e9 | ||
|
|
4f6b6b8008 | ||
|
|
616b1cb7ac | ||
|
|
08fdef4bf6 | ||
|
|
26b79ca18c | ||
|
|
fa41863752 | ||
|
|
bbbc80acae | ||
|
|
67643ead69 | ||
|
|
ad94066ec8 | ||
|
|
a443ec2e9a | ||
|
|
6862fd70da | ||
|
|
30f1df8c48 | ||
|
|
7add0f2490 | ||
|
|
9d6d177994 | ||
|
|
316a8f1545 | ||
|
|
11db53f875 | ||
|
|
95b4f899c5 | ||
|
|
2946155313 | ||
|
|
f2ca2aa1f7 | ||
|
|
b20bf10fda | ||
|
|
208c15bc16 | ||
|
|
c3d3c82f3a | ||
|
|
b22d9cc27d | ||
|
|
908cf5042e | ||
|
|
6ec1641294 | ||
|
|
7b79ec360b | ||
|
|
718aee242d | ||
|
|
56fc6b7deb | ||
|
|
e257f121e1 | ||
|
|
5f72f69688 | ||
|
|
8caa271476 | ||
|
|
e43cd8316f | ||
|
|
34b8983220 | ||
|
|
70a98a43ea | ||
|
|
8783304a2d | ||
|
|
ec9cf002d5 | ||
|
|
b3e4abf06e | ||
|
|
50f8f9504b | ||
|
|
f2f3dc5e73 | ||
|
|
eb80887936 | ||
|
|
cdcab0e820 | ||
|
|
50dcd9f96d | ||
|
|
87dbd8f54c | ||
|
|
81e8686cc7 | ||
|
|
c7524a7e44 | ||
|
|
2dd1ca6af0 | ||
|
|
95324b8190 | ||
|
|
7c07841632 | ||
|
|
b3e0305448 | ||
|
|
e628f94436 | ||
|
|
76d57161d9 | ||
|
|
04c53fa145 | ||
|
|
9cc7038e54 | ||
|
|
5d4c4df3ef | ||
|
|
0e5820d893 | ||
|
|
0578157d56 | ||
|
|
da8c7c49bf | ||
|
|
da14982d1e | ||
|
|
299f1d0258 | ||
|
|
bdb338cf77 | ||
|
|
dc8885a1ca | ||
|
|
61b98f32a2 | ||
|
|
bfb18e5519 | ||
|
|
34ea2f4e1a | ||
|
|
cbbf9b3931 | ||
|
|
9c2e42ddfc | ||
|
|
d387f67dcb | ||
|
|
528a43bd6c | ||
|
|
b357803362 | ||
|
|
448808529a | ||
|
|
a0bc208412 | ||
|
|
6b0172b9bf | ||
|
|
bc1eccb66d | ||
|
|
a9249d4a82 | ||
|
|
3c373494d6 | ||
|
|
40761e4031 | ||
|
|
5aef606d3b | ||
|
|
4671cd6002 | ||
|
|
2ec0b2cd20 | ||
|
|
07effa3925 | ||
|
|
cd76a71de3 | ||
|
|
916dd79f19 | ||
|
|
c0c67c9be3 | ||
|
|
e1c29434b2 | ||
|
|
e5a063bcb4 | ||
|
|
d28cbaf770 | ||
|
|
23d5e8b8e4 | ||
|
|
6173815408 | ||
|
|
70e0e49952 | ||
|
|
b3e4aa6797 | ||
|
|
e74e68c84f | ||
|
|
4af0d7fd94 | ||
|
|
6ef018785b | ||
|
|
fe81d5c8a9 | ||
|
|
c2f01d7f9e | ||
|
|
127e09bca1 | ||
|
|
a20303c623 | ||
|
|
baaf869fc3 | ||
|
|
be4bc1a5be | ||
|
|
7a23b94559 | ||
|
|
07dc1b42fb | ||
|
|
10e71b3d01 | ||
|
|
edc0ed1415 | ||
|
|
c5319612b4 | ||
|
|
fff6b26ae3 | ||
|
|
650484604c | ||
|
|
3144a278dd | ||
|
|
afe0b16c02 | ||
|
|
df152b0ce7 | ||
|
|
e3c1f43952 | ||
|
|
5e63c0955d | ||
|
|
e523afa741 | ||
|
|
c2a98a60f9 | ||
|
|
6bc92d6d31 | ||
|
|
13cf8bbeb7 | ||
|
|
60c0d4104d | ||
|
|
52fd4445a4 | ||
|
|
693ba4ed4a | ||
|
|
5397f0b033 | ||
|
|
6c78ec7c41 | ||
|
|
fed4bd5269 | ||
|
|
c0882864f2 | ||
|
|
1a7e2e663e | ||
|
|
faa87ed839 | ||
|
|
83f585e30a | ||
|
|
7a244bb847 | ||
|
|
1b925119b5 | ||
|
|
3eb847e28f | ||
|
|
9dc8f30e47 | ||
|
|
3ce6441a0c | ||
|
|
6d00a1a5cf | ||
|
|
aaca32a5cd | ||
|
|
54c96d1995 | ||
|
|
e5a2d59446 | ||
|
|
141c0679a0 | ||
|
|
973297336f | ||
|
|
fe902461f4 | ||
|
|
15ea13245a | ||
|
|
9d4219ebac | ||
|
|
4d12c37c54 | ||
|
|
8424306433 | ||
|
|
12626ce9bb | ||
|
|
dafb94db79 | ||
|
|
2ecab0b63a | ||
|
|
ea697b6345 | ||
|
|
635321d47e | ||
|
|
dd4798802c | ||
|
|
0b988fa9ec | ||
|
|
ecf3b2ef32 | ||
|
|
60096bc1a1 | ||
|
|
2966132c52 | ||
|
|
b439542604 | ||
|
|
7277e5d8a8 | ||
|
|
ef3551d149 | ||
|
|
1bb5ee9c68 | ||
|
|
72c053519c | ||
|
|
349aa24511 | ||
|
|
294c9af469 | ||
|
|
b4ddc7b7ba | ||
|
|
ba0270799e | ||
|
|
73806f74ca | ||
|
|
5d0890c0a8 | ||
|
|
b6129f86c1 | ||
|
|
d1f22eaca4 | ||
|
|
762fbcb687 | ||
|
|
f15fb727a0 | ||
|
|
e374573f30 | ||
|
|
73d47d5749 | ||
|
|
b7cb28d501 | ||
|
|
df83892760 | ||
|
|
1db7257107 | ||
|
|
0517da3618 | ||
|
|
fe96e29d5f | ||
|
|
3c16d6b32d | ||
|
|
f21be1ec55 | ||
|
|
3b4f147775 | ||
|
|
6fb1aa2381 | ||
|
|
d4fe79a174 | ||
|
|
abb81c6351 | ||
|
|
77da960815 | ||
|
|
3e8c69a9de | ||
|
|
a788c373e6 | ||
|
|
d95bead383 | ||
|
|
51ea3cf30c | ||
|
|
6ad6c1d780 | ||
|
|
32f34f63fd | ||
|
|
98aefac09b | ||
|
|
5dc84850ad | ||
|
|
45b711f9d1 | ||
|
|
1ef187533c | ||
|
|
6a71de7835 | ||
|
|
18496b6285 | ||
|
|
b9db899f6c | ||
|
|
4e9d2f08b1 | ||
|
|
06ad1c15d7 | ||
|
|
30a603ce05 | ||
|
|
63ae679fe1 | ||
|
|
b92bbf4de8 | ||
|
|
4781eda722 | ||
|
|
2fd93c5789 | ||
|
|
5e762d847c | ||
|
|
54f5499aee | ||
|
|
0c952b13d0 | ||
|
|
dd34f70368 | ||
|
|
5e042dbc05 | ||
|
|
dcbe8bfad1 | ||
|
|
36caf2e42b | ||
|
|
3067352a8d | ||
|
|
9baaf858f9 | ||
|
|
4440133e9a | ||
|
|
c957794144 | ||
|
|
1333a46b7e | ||
|
|
8e7282eb3e | ||
|
|
a678390e52 | ||
|
|
f42ce57d0f | ||
|
|
919fbf421d | ||
|
|
df096bc96b | ||
|
|
22e45d46fe | ||
|
|
a55e584706 | ||
|
|
ba28924418 | ||
|
|
5a6cfbf4ca | ||
|
|
fae306b374 | ||
|
|
736309660f | ||
|
|
488e194787 | ||
|
|
c82ccf0670 | ||
|
|
51c1a9f8fb | ||
|
|
ea1e1b12c9 | ||
|
|
7379c78a9b | ||
|
|
9f6e84f6be | ||
|
|
82790e510f | ||
|
|
943008ebac | ||
|
|
e271a61103 | ||
|
|
f1974d5d67 | ||
|
|
d9b153c9f6 | ||
|
|
577fc4388b | ||
|
|
329519d4aa | ||
|
|
52434a583a | ||
|
|
18a5f46b61 | ||
|
|
16a019dba0 | ||
|
|
1a4c3224c9 | ||
|
|
c3317686f8 | ||
|
|
4622472123 | ||
|
|
f1748f8c76 | ||
|
|
0c101dccc8 | ||
|
|
dc78bf1ccb | ||
|
|
a7cc3aac28 | ||
|
|
339631530a | ||
|
|
fb2bdf7d05 | ||
|
|
c45f1328ac | ||
|
|
050d58007f | ||
|
|
49d86746ed | ||
|
|
6fe55c2f29 | ||
|
|
f7a94526dd | ||
|
|
bbce3ba974 | ||
|
|
eecfa9793e | ||
|
|
40295fb3fe | ||
|
|
d2509811b7 | ||
|
|
29d4a1502a | ||
|
|
ec0c61da05 | ||
|
|
ef4e11ecb8 | ||
|
|
fd702e43f1 | ||
|
|
249e0fdd36 | ||
|
|
6208118b13 | ||
|
|
73020b6a93 | ||
|
|
a9667e84ad | ||
|
|
ab1524ff1a | ||
|
|
1069d0b4bf | ||
|
|
4a980f4ddb | ||
|
|
9fbb9a551e | ||
|
|
c24a7c03c2 | ||
|
|
5a8280d577 | ||
|
|
da83e84125 | ||
|
|
ef9a3cadcf | ||
|
|
c983d57f73 | ||
|
|
3204a39ada | ||
|
|
f4319c1280 | ||
|
|
721a39ddff | ||
|
|
cbabf779c2 | ||
|
|
ecd17e819c | ||
|
|
8e9d19bc65 | ||
|
|
5be3a15a82 | ||
|
|
658749cc54 | ||
|
|
1927932b43 | ||
|
|
ba146d4c09 | ||
|
|
47988c9666 | ||
|
|
f2df5773b1 | ||
|
|
cc90f79baf | ||
|
|
b3ff8a4b6d | ||
|
|
b1f2c51037 | ||
|
|
762396d997 | ||
|
|
c575e7df94 | ||
|
|
aa6409f2e8 | ||
|
|
e603e57588 | ||
|
|
049b48ef79 | ||
|
|
0ba0a6ab0a | ||
|
|
7475ea1b0b | ||
|
|
7bbafc5639 | ||
|
|
c7f752667e | ||
|
|
ed7ea13a2a | ||
|
|
3be7762388 | ||
|
|
15f6b74814 | ||
|
|
1b5bf40c20 | ||
|
|
954c20edd9 | ||
|
|
11c3afd711 | ||
|
|
b752e83db5 | ||
|
|
e16eb87465 | ||
|
|
35ea9d231b | ||
|
|
3872912679 | ||
|
|
b9a1530345 | ||
|
|
d0654af74f | ||
|
|
d5f8df5997 | ||
|
|
5e7e5e6b61 | ||
|
|
e61dde8806 | ||
|
|
cddf1da2e9 | ||
|
|
52ea44e53b | ||
|
|
0f28ea16a7 | ||
|
|
00e5fefe6d | ||
|
|
baafd30ba6 | ||
|
|
d3a9dff6b9 | ||
|
|
9a7b6a9f51 | ||
|
|
f4b8197060 | ||
|
|
c5bc1c14c0 | ||
|
|
ef0b45ece8 | ||
|
|
5a72c5058c | ||
|
|
e6e58e455c | ||
|
|
5b9d3ac6c6 | ||
|
|
9d1baa0705 | ||
|
|
58554396d6 | ||
|
|
24044f3356 | ||
|
|
b7c78b7651 | ||
|
|
4348d25fc4 | ||
|
|
f3d67b3842 | ||
|
|
7f04a15311 | ||
|
|
a511a37bb7 | ||
|
|
7b3e3d6a13 | ||
|
|
12caffee61 | ||
|
|
576a08908b | ||
|
|
44aa22c635 | ||
|
|
c95a582a74 | ||
|
|
f891b64a83 | ||
|
|
67aa527b22 | ||
|
|
034dcf185c | ||
|
|
e9b99c78df | ||
|
|
901b7469b9 | ||
|
|
aa3f13761f | ||
|
|
276a093753 | ||
|
|
096592506e | ||
|
|
ba28738083 | ||
|
|
0283db5883 | ||
|
|
ef6e263fde | ||
|
|
118db9eeae | ||
|
|
d7a87d0ea4 | ||
|
|
81dc180323 | ||
|
|
476333d192 | ||
|
|
c227f5e7bd | ||
|
|
2968d8e3cb | ||
|
|
b5f3247ca5 | ||
|
|
c6fb9d0963 | ||
|
|
a37cca3644 | ||
|
|
25b36f8d65 | ||
|
|
441cd9713c | ||
|
|
29fddf3291 | ||
|
|
389faae58e | ||
|
|
e4b6070c0f | ||
|
|
14045adf92 | ||
|
|
5941730c37 | ||
|
|
52d83d57f9 | ||
|
|
7e24e219fd | ||
|
|
08c3fe8063 | ||
|
|
2271cf03f5 | ||
|
|
ecb742acc5 | ||
|
|
7b5f4b175b | ||
|
|
89849c8b01 | ||
|
|
5661b19005 | ||
|
|
4092a75d85 | ||
|
|
e5b5f9a2f6 | ||
|
|
ce7ec725e3 | ||
|
|
ff14945e22 | ||
|
|
731f10225b | ||
|
|
ddde700b64 | ||
|
|
1ed5f84a79 | ||
|
|
07b365b7d7 | ||
|
|
6b4366b85b | ||
|
|
f5d48537f1 | ||
|
|
18e72c5cc7 | ||
|
|
28beb05aa3 | ||
|
|
e0cc3c99d2 | ||
|
|
a1b654819c | ||
|
|
a40669893e | ||
|
|
6203ed0474 | ||
|
|
d39afb687d | ||
|
|
ef5186d920 | ||
|
|
a5e4c95cfd | ||
|
|
6b056d29f3 | ||
|
|
2c970532dc | ||
|
|
c73d70fb46 | ||
|
|
37a10cef02 | ||
|
|
e8f4010e27 | ||
|
|
d50ae36e17 | ||
|
|
818a4e0f70 | ||
|
|
519822bcf9 | ||
|
|
73841e8c49 | ||
|
|
097c4a6536 | ||
|
|
b93945585a | ||
|
|
64c2508ee3 | ||
|
|
f1f259de5b | ||
|
|
da47d52c79 | ||
|
|
fef1e63c70 | ||
|
|
70469b76d6 | ||
|
|
bfd8c1fdd2 | ||
|
|
c7b68d10ea | ||
|
|
803d765d49 | ||
|
|
c697edf4f4 | ||
|
|
808394b77d | ||
|
|
99b5696390 | ||
|
|
129d14e143 | ||
|
|
ec5681f0f1 | ||
|
|
5bbc112fb1 | ||
|
|
641c64ada1 | ||
|
|
ed2269762b | ||
|
|
45025713a8 | ||
|
|
e7144fbed8 | ||
|
|
e916058f0b | ||
|
|
fe5aea38c3 | ||
|
|
065872e001 | ||
|
|
446f24e66d | ||
|
|
b311a368e0 | ||
|
|
936e01e5bb | ||
|
|
2151b82be9 | ||
|
|
06a24b9cfa | ||
|
|
8e95064408 | ||
|
|
397a8b57cc | ||
|
|
ce03d68332 | ||
|
|
b42466b925 | ||
|
|
6a9851c7f8 | ||
|
|
2d1e893b3e | ||
|
|
77ad9aaafe | ||
|
|
2f41c8d518 | ||
|
|
656e40eed2 | ||
|
|
5b80a41cad | ||
|
|
1530a3cfc6 | ||
|
|
32a8301073 | ||
|
|
3d89210477 | ||
|
|
a7122f4518 | ||
|
|
70016f7861 | ||
|
|
64a78f5ba3 | ||
|
|
7c95e89ec3 | ||
|
|
4ece8bd7a7 | ||
|
|
3243252cb0 | ||
|
|
e8ceba4e64 | ||
|
|
2ab51a644d | ||
|
|
1ccc270a2c | ||
|
|
84b01f63db | ||
|
|
2766805680 | ||
|
|
ffc7e509aa | ||
|
|
2f6fe5ce3a | ||
|
|
8d50a8327e | ||
|
|
c426bbf3a5 | ||
|
|
2d30afc45f | ||
|
|
9c76875f41 | ||
|
|
4a12047c61 | ||
|
|
253d9d6d12 | ||
|
|
0bc3dab095 | ||
|
|
0f8692b464 | ||
|
|
11c6ce812a | ||
|
|
960c25ac0a | ||
|
|
28c20b4ef9 | ||
|
|
02f21113ab | ||
|
|
7059eceeb0 | ||
|
|
9593ffde2e | ||
|
|
0f026af185 | ||
|
|
e45239e350 | ||
|
|
1833d008b3 | ||
|
|
c032dc45d1 | ||
|
|
aded138a59 | ||
|
|
089ee5979d | ||
|
|
8b2c0f9044 | ||
|
|
824f5f0b7a | ||
|
|
e542132b07 | ||
|
|
5350e7669e | ||
|
|
a15a5d7097 | ||
|
|
a68c19df6c | ||
|
|
060af1858d | ||
|
|
60ec2b78b3 | ||
|
|
3adf10b809 | ||
|
|
576a7b8caf | ||
|
|
bbdbfabf9e | ||
|
|
b12d2f65d6 | ||
|
|
3f14bfd809 | ||
|
|
720d1fd3bb | ||
|
|
18b62a51e2 | ||
|
|
327cb45ed5 | ||
|
|
23c681b51d | ||
|
|
dcc4347c53 | ||
|
|
da44c54897 | ||
|
|
b81f486c2f | ||
|
|
0423309768 | ||
|
|
deebed23e1 | ||
|
|
87332ce524 | ||
|
|
779aebc91c | ||
|
|
4d580438b0 | ||
|
|
fdaea2a7a7 | ||
|
|
1ee195d255 | ||
|
|
dd5feec5e8 | ||
|
|
825adcf3f5 | ||
|
|
9f32d0eed2 | ||
|
|
37bf3e18cb | ||
|
|
66f55bc5c1 | ||
|
|
629081f839 | ||
|
|
91f4bdc9f9 | ||
|
|
4534960b29 | ||
|
|
228bc89ecb | ||
|
|
215b72c0ba | ||
|
|
fb6110ac20 | ||
|
|
3649568ff2 | ||
|
|
5eb2290f68 | ||
|
|
51c3ff8d75 | ||
|
|
a0cfd519e3 | ||
|
|
e978bdf9ef | ||
|
|
764b420f5f | ||
|
|
568dfd4b49 | ||
|
|
94973fd0eb | ||
|
|
90169cdf16 | ||
|
|
43e2a398f9 | ||
|
|
469a6e5f1a | ||
|
|
0399b5a27e | ||
|
|
cee6dead3c | ||
|
|
cfcb475435 | ||
|
|
a12f07792f | ||
|
|
8337e083b6 | ||
|
|
c328c807e7 | ||
|
|
d2658f8387 | ||
|
|
5aab012676 | ||
|
|
e097c99681 | ||
|
|
6f2fc34228 | ||
|
|
c6c65d9ab3 | ||
|
|
d070221707 | ||
|
|
24fdc87fe0 | ||
|
|
56a7c45521 | ||
|
|
c74398e130 | ||
|
|
cb2ca37f88 | ||
|
|
cd02c5944f | ||
|
|
fb1f4f4e7e | ||
|
|
e3b1d6d3ad | ||
|
|
183d264e9e | ||
|
|
5dd1130272 | ||
|
|
6e98214f74 | ||
|
|
39f2ab595c | ||
|
|
be352633a0 | ||
|
|
7cefbeaad5 | ||
|
|
d3266d516b | ||
|
|
dddfde85ef | ||
|
|
61ac2aef2b | ||
|
|
8cccc6b468 | ||
|
|
83de18805c | ||
|
|
89af7e4c85 | ||
|
|
bc1ef48e56 | ||
|
|
ed833c9f99 | ||
|
|
8ec2fc3969 | ||
|
|
db8c9a8520 | ||
|
|
18d1607f5e | ||
|
|
c379fdbae2 | ||
|
|
cf52e0ad44 | ||
|
|
94c50314f1 | ||
|
|
019ac37e9c | ||
|
|
d54652682d | ||
|
|
1e78681df8 | ||
|
|
b9af7e24e4 | ||
|
|
6e56f513b4 | ||
|
|
21d8544128 | ||
|
|
e9b5484ddd | ||
|
|
6ea8641ae0 | ||
|
|
d2d74ca0f3 | ||
|
|
bebb2e1994 | ||
|
|
3170f63330 | ||
|
|
ed2ba31e4c | ||
|
|
0381f14acc | ||
|
|
1ac30300f0 | ||
|
|
673c9d7029 | ||
|
|
97f6e314c1 | ||
|
|
8651e6a10d | ||
|
|
efb6495a44 | ||
|
|
8e29b0b22b | ||
|
|
0db3b0a0ff | ||
|
|
b8e02f2b40 | ||
|
|
c469f6ad9e | ||
|
|
71f10de4de | ||
|
|
0132189007 | ||
|
|
dd29d44136 | ||
|
|
8e3d910d4e | ||
|
|
363604a27d | ||
|
|
1677f4223c | ||
|
|
14a9da0613 | ||
|
|
1d9d27c91a | ||
|
|
509fe9cba1 | ||
|
|
747be463d2 | ||
|
|
2fae0192e8 | ||
|
|
98600c9a11 | ||
|
|
1a292e0634 | ||
|
|
a92921da13 | ||
|
|
17bf0b25c1 | ||
|
|
009862ab7e | ||
|
|
d7f2681a0c | ||
|
|
61733ded14 | ||
|
|
6b6294807c | ||
|
|
5a47794606 | ||
|
|
b087dd1db6 | ||
|
|
3ef6b79c80 | ||
|
|
c65347ab17 | ||
|
|
c448f6fe55 | ||
|
|
58cdc054e3 | ||
|
|
c10889150e | ||
|
|
bea0384f5d | ||
|
|
f019f28e7b | ||
|
|
d1a005ab39 | ||
|
|
bd60447066 | ||
|
|
9073d56eec | ||
|
|
0f1969f16f | ||
|
|
bf759cc9c3 | ||
|
|
ee1cef189f | ||
|
|
264778af0a | ||
|
|
c326f28833 | ||
|
|
3eaff2941e | ||
|
|
2a81e49dde | ||
|
|
1b8b8c029f | ||
|
|
55a3da87f8 | ||
|
|
45cd8e03ca | ||
|
|
1bca62c4b7 | ||
|
|
e938bbc543 | ||
|
|
c549513acd | ||
|
|
2e19b94113 | ||
|
|
758b39be99 | ||
|
|
f49f0a6f72 | ||
|
|
98426e9886 | ||
|
|
40acb4412d | ||
|
|
2e2fe98f9c | ||
|
|
3281ebb495 | ||
|
|
beebb3c013 | ||
|
|
1b4f888109 | ||
|
|
d5c14c70b7 | ||
|
|
a9628142fd | ||
|
|
09041b9359 | ||
|
|
ea7c3fe7fd | ||
|
|
eb2114b9cd | ||
|
|
2478b47b89 | ||
|
|
6a2831c24a | ||
|
|
23f5cb4233 | ||
|
|
ad45d7e407 | ||
|
|
916c4e5d86 | ||
|
|
8b5848a4f5 | ||
|
|
b394817754 | ||
|
|
0a07f8ffee | ||
|
|
721d3c9e0c | ||
|
|
de1f82aa33 | ||
|
|
82845f8d04 | ||
|
|
beb1356b5b | ||
|
|
ae3ef964c1 | ||
|
|
b7c33af4a5 | ||
|
|
6129758558 | ||
|
|
6578119a23 | ||
|
|
fddc4757c8 | ||
|
|
83e87bac76 | ||
|
|
b7b23bdfb8 | ||
|
|
c1ea6175c5 | ||
|
|
959fb5cf68 | ||
|
|
b0a90d8fa8 | ||
|
|
af15b285fa | ||
|
|
388bc55344 | ||
|
|
b3d6cb268a | ||
|
|
f3aaf2b4d8 | ||
|
|
f6cf08e582 | ||
|
|
8a531cedb0 | ||
|
|
0a4d2bbd9c | ||
|
|
733280d9cb | ||
|
|
eda703ab28 | ||
|
|
b21dd082c3 | ||
|
|
cc108057ff | ||
|
|
8ea185ea30 | ||
|
|
bb7546c913 | ||
|
|
5e399d5d33 | ||
|
|
264708427b | ||
|
|
7a73b7f168 | ||
|
|
c3899720f6 | ||
|
|
5a8a005026 | ||
|
|
2e4fa7bb48 | ||
|
|
1dd36347ed | ||
|
|
630638dcde | ||
|
|
f135d6295b | ||
|
|
3976f4c88e | ||
|
|
d0050db236 | ||
|
|
975eb73145 | ||
|
|
0a146a8be4 | ||
|
|
bd90c99f83 | ||
|
|
f42ac40d7c | ||
|
|
a1a65d238c | ||
|
|
30a3644e64 | ||
|
|
74e3a622a2 | ||
|
|
474a923160 | ||
|
|
cb384127d1 | ||
|
|
dd2f695d7e | ||
|
|
1b3cb3b0de | ||
|
|
ff9a5d231b | ||
|
|
aca5482fbf | ||
|
|
68519b7034 | ||
|
|
8ea4bdd91d | ||
|
|
89f929b12a | ||
|
|
19aba4ac78 | ||
|
|
e8e30bc402 | ||
|
|
c1cc5ca767 | ||
|
|
f01f0c02d1 | ||
|
|
6931004969 | ||
|
|
2cc4d0286c | ||
|
|
ca81d49006 | ||
|
|
c792504fab | ||
|
|
dad38c19c8 | ||
|
|
4a30a26f8f | ||
|
|
819a661be5 | ||
|
|
888efc1b36 | ||
|
|
26b6c697d3 | ||
|
|
93c52ff5ff | ||
|
|
b170a01fa7 | ||
|
|
ae5054b476 | ||
|
|
9d2ecf6be3 | ||
|
|
f4d37173fe | ||
|
|
ae8cab3296 | ||
|
|
a092f20d87 | ||
|
|
781f3fd8be | ||
|
|
cc8f06ece9 | ||
|
|
86aade9a02 | ||
|
|
3bfcae247a | ||
|
|
89ad0ca566 | ||
|
|
12c56a8e75 | ||
|
|
f7090f43ad | ||
|
|
66a5c1cd7e | ||
|
|
b2e10131c0 | ||
|
|
06d490342f | ||
|
|
b12ccc840e | ||
|
|
e57067b677 | ||
|
|
2303ba1441 | ||
|
|
ca5ccc58c5 | ||
|
|
16435e02bf | ||
|
|
d7c25806c0 | ||
|
|
5cbc73c657 | ||
|
|
78bbb9b58d | ||
|
|
d5536e0480 | ||
|
|
61853ad8de | ||
|
|
1d6e5dc4dc | ||
|
|
1026d2caf8 | ||
|
|
0a97149dec | ||
|
|
b27f388344 | ||
|
|
0e9b5adbd3 | ||
|
|
5e0faf4959 | ||
|
|
a368209b1d | ||
|
|
d3f7eb0c87 | ||
|
|
583933e2d6 | ||
|
|
2a8a63af44 | ||
|
|
f899c31fbc | ||
|
|
fc5c2052b5 | ||
|
|
e1b13b4d39 | ||
|
|
b2079cb508 | ||
|
|
f0c10d4360 | ||
|
|
40c4183196 | ||
|
|
07b1abab95 | ||
|
|
e5187ad2ae | ||
|
|
4339706e07 | ||
|
|
f42846e8c7 | ||
|
|
ce72cac0f8 | ||
|
|
e4b3c8bbc3 | ||
|
|
cc8125a779 | ||
|
|
d659654f53 | ||
|
|
f1c6c658ac | ||
|
|
505a855000 | ||
|
|
0714581e0c | ||
|
|
5591a14c0a | ||
|
|
e91d9a6fff | ||
|
|
fde5e737dc | ||
|
|
e53a26b5d8 | ||
|
|
0b780a5477 | ||
|
|
32efd9adf8 | ||
|
|
a67d0411e7 | ||
|
|
48f4cfb601 | ||
|
|
dbee7ca007 | ||
|
|
c98e7717bb | ||
|
|
9268493e8d | ||
|
|
47ce1cebeb | ||
|
|
9012e587ca | ||
|
|
7d21754710 | ||
|
|
8fe173452a | ||
|
|
3b6aeea44c | ||
|
|
c41f94d2a3 | ||
|
|
09c06698e9 | ||
|
|
436d02dd7b | ||
|
|
7d3992a80a | ||
|
|
842b44dc46 | ||
|
|
f850201c64 | ||
|
|
e00442eb13 | ||
|
|
004c26ec28 | ||
|
|
d7d028a7a7 | ||
|
|
ff682d7902 | ||
|
|
bc5cb168f5 | ||
|
|
70534846d1 | ||
|
|
5f450e4928 | ||
|
|
bd0f06c18c | ||
|
|
41ed85bd26 | ||
|
|
947319cadd | ||
|
|
f59119aad6 | ||
|
|
42b6305964 | ||
|
|
6b72b04a37 | ||
|
|
5189db3d81 | ||
|
|
48d91cf4cc | ||
|
|
c56b4ddc6f | ||
|
|
56258c6b7d | ||
|
|
6191ea90a1 | ||
|
|
6e07fac405 | ||
|
|
241d18d954 | ||
|
|
5827b69861 | ||
|
|
4b2579a064 | ||
|
|
3f1c84751a | ||
|
|
6100a82a3a | ||
|
|
54c4e7f86c | ||
|
|
2a99f199bc | ||
|
|
dad0e916ff | ||
|
|
7567323071 | ||
|
|
c7aaf8db4d | ||
|
|
923e4fb312 | ||
|
|
7c9f6ebc8f | ||
|
|
3bbb9a1413 | ||
|
|
3300e98ff0 | ||
|
|
dfcbeaf115 | ||
|
|
81b18fa3a0 | ||
|
|
d984732b35 | ||
|
|
2de544cfcc | ||
|
|
41c5ebcab6 | ||
|
|
593f6656c1 | ||
|
|
2d236d7aec | ||
|
|
09f99c2a92 | ||
|
|
2fec7d9c6c | ||
|
|
412eb67d21 | ||
|
|
52686f4866 | ||
|
|
c1455dc060 | ||
|
|
656cd1a00a | ||
|
|
c2b7f14c56 | ||
|
|
3c05bc561d | ||
|
|
a2ac5c3840 | ||
|
|
68fd59056b | ||
|
|
283d6cfd58 | ||
|
|
b00e1891c0 | ||
|
|
6b818efeb6 | ||
|
|
a344c4cfad | ||
|
|
42366959ec | ||
|
|
dda8cc1821 | ||
|
|
dcffca0a31 |
No files matched your search
@@ -0,0 +1,58 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
|
||||
test-ubuntu-latest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make BUILD_TLS=yes -j2
|
||||
- name: gen-cert
|
||||
run: ./utils/gen-test-certs.sh
|
||||
- name: test-tls
|
||||
run: |
|
||||
sudo apt-get -y install tcl tcl-tls
|
||||
./runtest --clients 2 --verbose --tls
|
||||
- name: cluster-test
|
||||
run: |
|
||||
./runtest-cluster --tls
|
||||
- name: sentinel test
|
||||
run: |
|
||||
./runtest-sentinel
|
||||
- name: module tests
|
||||
run: |
|
||||
./runtest-moduleapi
|
||||
|
||||
build-ubuntu-old:
|
||||
runs-on: ubuntu-16.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: make -j2
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make -j2
|
||||
|
||||
build-macos-latest:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: make -j2
|
||||
|
||||
build-libc-malloc:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make MALLOC=libc -j2
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
name: Daily
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
# any PR to a release branch.
|
||||
- '[0-9].[0-9]'
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
|
||||
test-ubuntu-jemalloc:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'redis/redis'
|
||||
timeout-minutes: 14400
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make
|
||||
- name: test
|
||||
run: |
|
||||
sudo apt-get install tcl8.5
|
||||
./runtest --accurate --verbose
|
||||
- name: module api test
|
||||
run: ./runtest-moduleapi --verbose
|
||||
- name: sentinel tests
|
||||
run: ./runtest-sentinel
|
||||
- name: cluster tests
|
||||
run: ./runtest-cluster
|
||||
|
||||
test-ubuntu-libc-malloc:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'redis/redis'
|
||||
timeout-minutes: 14400
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make MALLOC=libc
|
||||
- name: test
|
||||
run: |
|
||||
sudo apt-get install tcl8.5
|
||||
./runtest --accurate --verbose
|
||||
- name: module api test
|
||||
run: ./runtest-moduleapi --verbose
|
||||
- name: sentinel tests
|
||||
run: ./runtest-sentinel
|
||||
- name: cluster tests
|
||||
run: ./runtest-cluster
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'redis/redis'
|
||||
timeout-minutes: 14400
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make BUILD_TLS=yes -j2
|
||||
- name: "test (tls)"
|
||||
run: |
|
||||
sudo apt-get install tcl8.5 tcl-tls
|
||||
./utils/gen-test-certs.sh
|
||||
./runtest --accurate --verbose --tls
|
||||
- name: test
|
||||
run: ./runtest --accurate --verbose
|
||||
- name: module api test (tls)
|
||||
run: ./runtest-moduleapi --verbose --tls
|
||||
|
||||
test-ubuntu-arm:
|
||||
runs-on: [self-hosted, linux, arm]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make -j4
|
||||
- name: test
|
||||
run: |
|
||||
sudo apt-get -y install tcl8.5
|
||||
./runtest --clients 2 --verbose
|
||||
- name: module tests
|
||||
run: |
|
||||
./runtest-moduleapi
|
||||
|
||||
test-valgrind:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'redis/redis'
|
||||
timeout-minutes: 14400
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make valgrind
|
||||
- name: test
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install tcl8.5 valgrind -y
|
||||
./runtest --valgrind --verbose --clients 1
|
||||
- name: module api test
|
||||
run: ./runtest-moduleapi --valgrind --verbose --clients 1
|
||||
|
||||
test-centos7-jemalloc:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'redis/redis'
|
||||
container: centos:7
|
||||
timeout-minutes: 14400
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
yum -y install centos-release-scl
|
||||
yum -y install devtoolset-7
|
||||
scl enable devtoolset-7 "make"
|
||||
- name: test
|
||||
run: |
|
||||
yum -y install tcl
|
||||
./runtest --accurate --verbose
|
||||
- name: module api test
|
||||
run: ./runtest-moduleapi --verbose
|
||||
- name: sentinel tests
|
||||
run: ./runtest-sentinel
|
||||
- name: cluster tests
|
||||
run: ./runtest-cluster
|
||||
|
||||
test-centos7-tls:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'redis/redis'
|
||||
container: centos:7
|
||||
timeout-minutes: 14400
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: |
|
||||
yum -y install centos-release-scl epel-release
|
||||
yum -y install devtoolset-7 openssl-devel openssl
|
||||
scl enable devtoolset-7 "make BUILD_TLS=yes"
|
||||
- name: test
|
||||
run: |
|
||||
yum -y install tcl tcltls
|
||||
./utils/gen-test-certs.sh
|
||||
./runtest --accurate --verbose --tls
|
||||
./runtest --accurate --verbose
|
||||
- name: module api test
|
||||
run: |
|
||||
./runtest-moduleapi --verbose --tls
|
||||
./runtest-moduleapi --verbose
|
||||
- name: sentinel tests
|
||||
run: |
|
||||
./runtest-sentinel --tls
|
||||
./runtest-sentinel
|
||||
- name: cluster tests
|
||||
run: |
|
||||
./runtest-cluster --tls
|
||||
./runtest-cluster
|
||||
|
||||
test-macos-latest:
|
||||
runs-on: macos-latest
|
||||
if: github.repository == 'redis/redis'
|
||||
timeout-minutes: 14400
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
run: make
|
||||
- name: test
|
||||
run: |
|
||||
./runtest --accurate --verbose --no-latency
|
||||
- name: module api test
|
||||
run: ./runtest-moduleapi --verbose
|
||||
- name: sentinel tests
|
||||
run: ./runtest-sentinel
|
||||
- name: cluster tests
|
||||
run: ./runtest-cluster
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Endurance
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 * * * *'
|
||||
|
||||
jobs:
|
||||
|
||||
test-endurance:
|
||||
runs-on: octocore
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
|
||||
make -j8
|
||||
- name: test-multithread (5X)
|
||||
run: |
|
||||
sudo apt-get install -y tcl tcl-tls
|
||||
./runtest --loopn 5 --config server-threads 3 --clients 5 --endurance
|
||||
|
||||
+24
-3
@@ -1,9 +1,27 @@
|
||||
.*.swp
|
||||
core
|
||||
*.o
|
||||
*.xo
|
||||
*.so
|
||||
*.d
|
||||
!**/bash_completion.d
|
||||
!**/logrotate.d
|
||||
!**/keydb.service.d
|
||||
!**/keydb-sentinel.service.d
|
||||
*.log
|
||||
dump.rdb
|
||||
src/keydb-server
|
||||
**/bin/keydb-server
|
||||
**/app/keydb-server
|
||||
*.deb
|
||||
*.rpm
|
||||
keydb-pro-server
|
||||
src/keydb-cli
|
||||
**/bin/keydb-cli
|
||||
**/app/keydb-cli
|
||||
src/keydb-sentinel
|
||||
**/bin/keydb-sentinel
|
||||
**/app/keydb-sentinel
|
||||
redis-benchmark
|
||||
keydb-benchmark
|
||||
redis-check-aof
|
||||
@@ -13,11 +31,8 @@ keydb-check-rdb
|
||||
redis-check-dump
|
||||
keydb-check-dump
|
||||
redis-cli
|
||||
keydb-cli
|
||||
redis-sentinel
|
||||
keydb-sentinel
|
||||
redis-server
|
||||
keydb-server
|
||||
doc-tools
|
||||
release
|
||||
misc/*
|
||||
@@ -33,7 +48,13 @@ src/nodes.conf
|
||||
deps/lua/src/lua
|
||||
deps/lua/src/luac
|
||||
deps/lua/src/liblua.a
|
||||
tests/tls/*
|
||||
.make-*
|
||||
.prerequisites
|
||||
*.dSYM
|
||||
Makefile.dep
|
||||
.vscode/*
|
||||
.idea/*
|
||||
.ccls
|
||||
.ccls-cache/*
|
||||
compile_commands.json
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "deps/depot_tools"]
|
||||
path = deps/depot_tools
|
||||
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
language: generic
|
||||
os: osx
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
script: make
|
||||
env: COMPILER_NAME=g++-6 CXX=g++-6 CC=gcc-6
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-6
|
||||
- nasm
|
||||
- uuid-dev
|
||||
sources: &sources
|
||||
- llvm-toolchain-precise-3.8
|
||||
- ubuntu-toolchain-r-test
|
||||
- os: linux
|
||||
script: make MALLOC=libc
|
||||
env: COMPILER_NAME=clang CXX=clang++-3.8 CC=clang-3.8 CXXFLAGS="-I/usr/include/libcxxabi/" LDFLAGS="-lc++"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libc++abi-dev
|
||||
- clang-3.8
|
||||
- libc++-dev
|
||||
- libc++abi-dev
|
||||
- nasm
|
||||
- uuid-dev
|
||||
sources: *sources
|
||||
+3275
-11
File diff suppressed because it is too large.
Load diff
@@ -1 +1 @@
|
||||
Please check https://github.com/antirez/redis/issues
|
||||
Please check https://github.com/redis/redis/issues
|
||||
@@ -1,50 +0,0 @@
|
||||
Note: by contributing code to the Redis project in any form, including sending
|
||||
a pull request via Github, a code fragment or patch via private email or
|
||||
public discussion groups, you agree to release your code under the terms
|
||||
of the BSD license that you can find in the COPYING file included in the Redis
|
||||
source distribution. You will include BSD license in the COPYING file within
|
||||
each source file that you contribute.
|
||||
|
||||
# IMPORTANT: HOW TO USE REDIS GITHUB ISSUES
|
||||
|
||||
* Github issues SHOULD ONLY BE USED to report bugs, and for DETAILED feature
|
||||
requests. Everything else belongs to the Redis Google Group:
|
||||
|
||||
https://groups.google.com/forum/m/#!forum/Redis-db
|
||||
|
||||
PLEASE DO NOT POST GENERAL QUESTIONS that are not about bugs or suspected
|
||||
bugs in the Github issues system. We'll be very happy to help you and provide
|
||||
all the support in the mailing list.
|
||||
|
||||
There is also an active community of Redis users at Stack Overflow:
|
||||
|
||||
http://stackoverflow.com/questions/tagged/redis
|
||||
|
||||
# How to provide a patch for a new feature
|
||||
|
||||
1. If it is a major feature or a semantical change, please don't start coding
|
||||
straight away: if your feature is not a conceptual fit you'll lose a lot of
|
||||
time writing the code without any reason. Start by posting in the mailing list
|
||||
and creating an issue at Github with the description of, exactly, what you want
|
||||
to accomplish and why. Use cases are important for features to be accepted.
|
||||
Here you'll see if there is consensus about your idea.
|
||||
|
||||
2. If in step 1 you get an acknowledgment from the project leaders, use the
|
||||
following procedure to submit a patch:
|
||||
|
||||
a. Fork Redis on github ( http://help.github.com/fork-a-repo/ )
|
||||
b. Create a topic branch (git checkout -b my_branch)
|
||||
c. Push to your branch (git push origin my_branch)
|
||||
d. Initiate a pull request on github ( https://help.github.com/articles/creating-a-pull-request/ )
|
||||
e. Done :)
|
||||
|
||||
3. Keep in mind that we are very overloaded, so issues and PRs sometimes wait
|
||||
for a *very* long time. However this is not lack of interest, as the project
|
||||
gets more and more users, we find ourselves in a constant need to prioritize
|
||||
certain issues/PRs over others. If you think your issue/PR is very important
|
||||
try to popularize it, have other users commenting and sharing their point of
|
||||
view and so forth. This helps.
|
||||
|
||||
4. For minor fixes just open a pull request on Github.
|
||||
|
||||
Thanks!
|
||||
@@ -1,5 +1,5 @@
|
||||
Copyright (c) 2006-2015, Salvatore Sanfilippo
|
||||
Copyright (C) 2019, John Sully
|
||||
Copyright (c) 2006-2020, Salvatore Sanfilippo
|
||||
Copyright (C) 2019-2020, John Sully
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
|
||||
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -qqy \
|
||||
build-essential nasm autotools-dev autoconf libcurl4-openssl-dev libjemalloc-dev tcl tcl-dev uuid-dev libcurl4-openssl-dev \
|
||||
&& apt-get clean
|
||||
|
||||
CMD make
|
||||
@@ -1,9 +1,15 @@
|
||||

|
||||
[](https://travis-ci.org/JohnSully/KeyDB) [](https://gitter.im/KeyDB/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||

|
||||
[](https://stackshare.io/eq-alpha-technology-inc/eq-alpha-technology-inc)
|
||||
|
||||
##### New! Want to extend KeyDB with Javascript? Try [ModJS](https://github.com/JohnSully/ModJS)
|
||||
|
||||
##### Need Help? Check out our extensive [documentation](https://docs.keydb.dev).
|
||||
|
||||
##### Have feedback? Take our quick survey: https://www.surveymonkey.com/r/Y9XNS93
|
||||
|
||||
##### KeyDB is Hiring! We are currently building out our dev team. If you are interested please see the posting here: https://keydb.dev/careers.html
|
||||
|
||||
What is KeyDB?
|
||||
--------------
|
||||
|
||||
@@ -11,9 +17,13 @@ KeyDB is a high performance fork of Redis with a focus on multithreading, memory
|
||||
|
||||
KeyDB maintains full compatibility with the Redis protocol, modules, and scripts. This includes the atomicity guarantees for scripts and transactions. Because KeyDB keeps in sync with Redis development KeyDB is a superset of Redis functionality, making KeyDB a drop in replacement for existing Redis deployments.
|
||||
|
||||
On the same hardware KeyDB can perform twice as many queries per second as Redis, with 60% lower latency. Active-Replication simplifies hot-spare failover allowing you to easily distribute writes over replicas and use simple TCP based load balancing/failover. KeyDB's higher performance allows you to do more on less hardware which reduces operation costs and complexity.
|
||||
On the same hardware KeyDB can achieve significantly higher throughput than Redis. Active-Replication simplifies hot-spare failover allowing you to easily distribute writes over replicas and use simple TCP based load balancing/failover. KeyDB's higher performance allows you to do more on less hardware which reduces operation costs and complexity.
|
||||
|
||||
<img src=https://cdn-images-1.medium.com/max/1400/1*s7mTb7Qb0kxc951mz8bdgA.png width=420 height=300/><img src=https://cdn-images-1.medium.com/max/1400/1*R00A5U4AFGohGOYHMfT6fA.png height=300/>
|
||||
The chart below compares several KeyDB and Redis setups, including the latest Redis6 io-threads option, and TLS benchmarks.
|
||||
|
||||
<img src="https://docs.keydb.dev/img/blog/2020-09-15/ops_comparison.png"/>
|
||||
|
||||
See the full benchmark results and setup information here: https://docs.keydb.dev/blog/2020/09/29/blog-post/
|
||||
|
||||
Why fork Redis?
|
||||
---------------
|
||||
@@ -76,6 +86,8 @@ Building KeyDB
|
||||
|
||||
KeyDB can be compiled and is tested for use on Linux. KeyDB currently relies on SO_REUSEPORT's load balancing behavior which is available only in Linux. When we support marshalling connections across threads we plan to support other operating systems such as FreeBSD.
|
||||
|
||||
More on CentOS/Archlinux/Alpine/Debian/Ubuntu dependencies and builds can be found here: https://docs.keydb.dev/docs/build/
|
||||
|
||||
Install dependencies:
|
||||
|
||||
% sudo apt install build-essential nasm autotools-dev autoconf libjemalloc-dev tcl tcl-dev uuid-dev libcurl4-openssl-dev
|
||||
@@ -84,17 +96,34 @@ Compiling is as simple as:
|
||||
|
||||
% make
|
||||
|
||||
You can enable flash support with:
|
||||
To build with TLS support, you'll need OpenSSL development libraries (e.g.
|
||||
libssl-dev on Debian/Ubuntu) and run:
|
||||
|
||||
% make MALLOC=memkind
|
||||
% make BUILD_TLS=yes
|
||||
|
||||
To build with systemd support, you'll need systemd development libraries (such
|
||||
as libsystemd-dev on Debian/Ubuntu or systemd-devel on CentOS) and run:
|
||||
|
||||
% make USE_SYSTEMD=yes
|
||||
|
||||
To append a suffix to KeyDB program names, use:
|
||||
|
||||
% make PROG_SUFFIX="-alt"
|
||||
|
||||
***Note that the following dependencies may be needed:
|
||||
% sudo apt-get install autoconf autotools-dev libnuma-dev libtool
|
||||
|
||||
If TLS is built, running the tests with TLS enabled (you will need `tcl-tls`
|
||||
installed):
|
||||
|
||||
% ./utils/gen-test-certs.sh
|
||||
% ./runtest --tls
|
||||
|
||||
|
||||
Fixing build problems with dependencies or cached build options
|
||||
---------
|
||||
|
||||
KeyDB has some dependencies which are included into the `deps` directory.
|
||||
KeyDB has some dependencies which are included in the `deps` directory.
|
||||
`make` does not automatically rebuild dependencies even if something in
|
||||
the source code of dependencies changes.
|
||||
|
||||
@@ -121,7 +150,7 @@ with a 64 bit target, or the other way around, you need to perform a
|
||||
In case of build errors when trying to build a 32 bit binary of KeyDB, try
|
||||
the following steps:
|
||||
|
||||
* Install the packages libc6-dev-i386 (also try g++-multilib).
|
||||
* Install the package libc6-dev-i386 (also try g++-multilib).
|
||||
* Try using the following command line instead of `make 32bit`:
|
||||
`make CFLAGS="-m32 -march=native" LDFLAGS="-m32"`
|
||||
|
||||
@@ -146,14 +175,14 @@ Verbose build
|
||||
-------------
|
||||
|
||||
KeyDB will build with a user friendly colorized output by default.
|
||||
If you want to see a more verbose output use the following:
|
||||
If you want to see a more verbose output, use the following:
|
||||
|
||||
% make V=1
|
||||
|
||||
Running KeyDB
|
||||
-------------
|
||||
|
||||
To run KeyDB with the default configuration just type:
|
||||
To run KeyDB with the default configuration, just type:
|
||||
|
||||
% cd src
|
||||
% ./keydb-server
|
||||
@@ -173,6 +202,14 @@ as options using the command line. Examples:
|
||||
All the options in keydb.conf are also supported as options using the command
|
||||
line, with exactly the same name.
|
||||
|
||||
|
||||
Running Redis with TLS:
|
||||
------------------
|
||||
|
||||
Please consult the [TLS.md](TLS.md) file for more information on
|
||||
how to use Redis with TLS.
|
||||
|
||||
|
||||
Playing with KeyDB
|
||||
------------------
|
||||
|
||||
@@ -198,7 +235,7 @@ You can find the list of all the available commands at https://docs.keydb.dev/do
|
||||
Installing KeyDB
|
||||
-----------------
|
||||
|
||||
In order to install KeyDB binaries into /usr/local/bin just use:
|
||||
In order to install KeyDB binaries into /usr/local/bin, just use:
|
||||
|
||||
% make install
|
||||
|
||||
@@ -207,8 +244,8 @@ different destination.
|
||||
|
||||
Make install will just install binaries in your system, but will not configure
|
||||
init scripts and configuration files in the appropriate place. This is not
|
||||
needed if you want just to play a bit with KeyDB, but if you are installing
|
||||
it the proper way for a production system, we have a script doing this
|
||||
needed if you just want to play a bit with KeyDB, but if you are installing
|
||||
it the proper way for a production system, we have a script that does this
|
||||
for Ubuntu and Debian systems:
|
||||
|
||||
% cd utils
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
TLS Support
|
||||
===========
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
### Building
|
||||
|
||||
To build with TLS support you'll need OpenSSL development libraries (e.g.
|
||||
libssl-dev on Debian/Ubuntu).
|
||||
|
||||
Run `make BUILD_TLS=yes`.
|
||||
|
||||
### Tests
|
||||
|
||||
To run Redis test suite with TLS, you'll need TLS support for TCL (i.e.
|
||||
`tcl-tls` package on Debian/Ubuntu).
|
||||
|
||||
1. Run `./utils/gen-test-certs.sh` to generate a root CA and a server
|
||||
certificate.
|
||||
|
||||
2. Run `./runtest --tls` or `./runtest-cluster --tls` to run Redis and Redis
|
||||
Cluster tests in TLS mode.
|
||||
|
||||
### Running manually
|
||||
|
||||
To manually run a Redis server with TLS mode (assuming `gen-test-certs.sh` was
|
||||
invoked so sample certificates/keys are available):
|
||||
|
||||
./src/redis-server --tls-port 6379 --port 0 \
|
||||
--tls-cert-file ./tests/tls/redis.crt \
|
||||
--tls-key-file ./tests/tls/redis.key \
|
||||
--tls-ca-cert-file ./tests/tls/ca.crt
|
||||
|
||||
To connect to this Redis server with `redis-cli`:
|
||||
|
||||
./src/redis-cli --tls \
|
||||
--cert ./tests/tls/redis.crt \
|
||||
--key ./tests/tls/redis.key \
|
||||
--cacert ./tests/tls/ca.crt
|
||||
|
||||
This will disable TCP and enable TLS on port 6379. It's also possible to have
|
||||
both TCP and TLS available, but you'll need to assign different ports.
|
||||
|
||||
To make a Replica connect to the master using TLS, use `--tls-replication yes`,
|
||||
and to make Redis Cluster use TLS across nodes use `--tls-cluster yes`.
|
||||
|
||||
Connections
|
||||
-----------
|
||||
|
||||
All socket operations now go through a connection abstraction layer that hides
|
||||
I/O and read/write event handling from the caller.
|
||||
|
||||
Note that unlike Redis, KeyDB fully supports multithreading of TLS connections.
|
||||
|
||||
To-Do List
|
||||
----------
|
||||
|
||||
- [ ] redis-benchmark support. The current implementation is a mix of using
|
||||
hiredis for parsing and basic networking (establishing connections), but
|
||||
directly manipulating sockets for most actions. This will need to be cleaned
|
||||
up for proper TLS support. The best approach is probably to migrate to hiredis
|
||||
async mode.
|
||||
- [ ] redis-cli `--slave` and `--rdb` support.
|
||||
|
||||
Multi-port
|
||||
----------
|
||||
|
||||
Consider the implications of allowing TLS to be configured on a separate port,
|
||||
making Redis listening on multiple ports:
|
||||
|
||||
1. Startup banner port notification
|
||||
2. Proctitle
|
||||
3. How slaves announce themselves
|
||||
4. Cluster bus port calculation
|
||||
Vendored
+5
-1
@@ -41,9 +41,13 @@ distclean:
|
||||
|
||||
.PHONY: distclean
|
||||
|
||||
ifeq ($(BUILD_TLS),yes)
|
||||
HIREDIS_MAKE_FLAGS = USE_SSL=1
|
||||
endif
|
||||
|
||||
hiredis: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd hiredis && $(MAKE) static
|
||||
cd hiredis && $(MAKE) static $(HIREDIS_MAKE_FLAGS)
|
||||
|
||||
.PHONY: hiredis
|
||||
|
||||
|
||||
Vendored
+5
-5
@@ -21,7 +21,7 @@ just following tose steps:
|
||||
|
||||
1. Remove the jemalloc directory.
|
||||
2. Substitute it with the new jemalloc source tree.
|
||||
3. Edit the Makefile localted in the same directory as the README you are
|
||||
3. Edit the Makefile located in the same directory as the README you are
|
||||
reading, and change the --with-version in the Jemalloc configure script
|
||||
options with the version you are using. This is required because otherwise
|
||||
Jemalloc configuration script is broken and will not work nested in another
|
||||
@@ -33,7 +33,7 @@ If you want to upgrade Jemalloc while also providing support for
|
||||
active defragmentation, in addition to the above steps you need to perform
|
||||
the following additional steps:
|
||||
|
||||
5. In Jemalloc three, file `include/jemalloc/jemalloc_macros.h.in`, make sure
|
||||
5. In Jemalloc tree, file `include/jemalloc/jemalloc_macros.h.in`, make sure
|
||||
to add `#define JEMALLOC_FRAG_HINT`.
|
||||
6. Implement the function `je_get_defrag_hint()` inside `src/jemalloc.c`. You
|
||||
can see how it is implemented in the current Jemalloc source tree shipped
|
||||
@@ -47,9 +47,9 @@ Hiredis
|
||||
Hiredis uses the SDS string library, that must be the same version used inside Redis itself. Hiredis is also very critical for Sentinel. Historically Redis often used forked versions of hiredis in a way or the other. In order to upgrade it is advised to take a lot of care:
|
||||
|
||||
1. Check with diff if hiredis API changed and what impact it could have in Redis.
|
||||
2. Make sure thet the SDS library inside Hiredis and inside Redis are compatible.
|
||||
2. Make sure that the SDS library inside Hiredis and inside Redis are compatible.
|
||||
3. After the upgrade, run the Redis Sentinel test.
|
||||
4. Check manually that redis-cli and redis-benchmark behave as expecteed, since we have no tests for CLI utilities currently.
|
||||
4. Check manually that redis-cli and redis-benchmark behave as expected, since we have no tests for CLI utilities currently.
|
||||
|
||||
Linenoise
|
||||
---
|
||||
@@ -77,6 +77,6 @@ and our version:
|
||||
|
||||
1. Makefile is modified to allow a different compiler than GCC.
|
||||
2. We have the implementation source code, and directly link to the following external libraries: `lua_cjson.o`, `lua_struct.o`, `lua_cmsgpack.o` and `lua_bit.o`.
|
||||
3. There is a security fix in `ldo.c`, line 498: The check for `LUA_SIGNATURE[0]` is removed in order toa void direct bytecode execution.
|
||||
3. There is a security fix in `ldo.c`, line 498: The check for `LUA_SIGNATURE[0]` is removed in order to avoid direct bytecode execution.
|
||||
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
/*.dylib
|
||||
/*.a
|
||||
/*.pc
|
||||
*.dSYM
|
||||
Vendored
+63
-11
@@ -26,20 +26,72 @@ addons:
|
||||
- libc6-dev-i386
|
||||
- libc6-dbg:i386
|
||||
- gcc-multilib
|
||||
- g++-multilib
|
||||
- valgrind
|
||||
|
||||
env:
|
||||
- CFLAGS="-Werror"
|
||||
- PRE="valgrind --track-origins=yes --leak-check=full"
|
||||
- TARGET="32bit" TARGET_VARS="32bit-vars" CFLAGS="-Werror"
|
||||
- TARGET="32bit" TARGET_VARS="32bit-vars" PRE="valgrind --track-origins=yes --leak-check=full"
|
||||
- BITS="32"
|
||||
- BITS="64"
|
||||
|
||||
script:
|
||||
- EXTRA_CMAKE_OPTS="-DENABLE_EXAMPLES:BOOL=ON -DHIREDIS_SSL:BOOL=ON";
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
if [ "$BITS" == "32" ]; then
|
||||
CFLAGS="-m32 -Werror";
|
||||
CXXFLAGS="-m32 -Werror";
|
||||
LDFLAGS="-m32";
|
||||
EXTRA_CMAKE_OPTS=;
|
||||
else
|
||||
CFLAGS="-Werror";
|
||||
CXXFLAGS="-Werror";
|
||||
fi;
|
||||
else
|
||||
TEST_PREFIX="valgrind --track-origins=yes --leak-check=full";
|
||||
if [ "$BITS" == "32" ]; then
|
||||
CFLAGS="-m32 -Werror";
|
||||
CXXFLAGS="-m32 -Werror";
|
||||
LDFLAGS="-m32";
|
||||
EXTRA_CMAKE_OPTS=;
|
||||
else
|
||||
CFLAGS="-Werror";
|
||||
CXXFLAGS="-Werror";
|
||||
fi;
|
||||
fi;
|
||||
export CFLAGS CXXFLAGS LDFLAGS TEST_PREFIX EXTRA_CMAKE_OPTS
|
||||
- mkdir build/ && cd build/
|
||||
- cmake .. ${EXTRA_CMAKE_OPTS}
|
||||
- make VERBOSE=1
|
||||
- ctest -V
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- os: osx
|
||||
env: PRE="valgrind --track-origins=yes --leak-check=full"
|
||||
include:
|
||||
# Windows MinGW cross compile on Linux
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: mingw
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ninja-build
|
||||
- gcc-mingw-w64-x86-64
|
||||
- g++-mingw-w64-x86-64
|
||||
script:
|
||||
- mkdir build && cd build
|
||||
- CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_WITH_INSTALL_RPATH=on
|
||||
- ninja -v
|
||||
|
||||
- os: osx
|
||||
env: TARGET="32bit" TARGET_VARS="32bit-vars" PRE="valgrind --track-origins=yes --leak-check=full"
|
||||
|
||||
script: make $TARGET CFLAGS="$CFLAGS" && make check PRE="$PRE" && make $TARGET_VARS hiredis-example
|
||||
# Windows MSVC 2017
|
||||
- os: windows
|
||||
compiler: msvc
|
||||
env:
|
||||
- MATRIX_EVAL="CC=cl.exe && CXX=cl.exe"
|
||||
before_install:
|
||||
- eval "${MATRIX_EVAL}"
|
||||
install:
|
||||
- choco install ninja
|
||||
script:
|
||||
- mkdir build && cd build
|
||||
- cmd.exe /C '"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64 &&
|
||||
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release &&
|
||||
ninja -v'
|
||||
- ctest -V
|
||||
Vendored
+13
-2
@@ -12,6 +12,16 @@
|
||||
compare to other values, casting might be necessary or can be removed, if
|
||||
casting was applied before.
|
||||
|
||||
### 0.x.x (unreleased)
|
||||
**BREAKING CHANGES**:
|
||||
|
||||
* Change `redisReply.len` to `size_t`, as it denotes the the size of a string
|
||||
|
||||
User code should compare this to `size_t` values as well.
|
||||
If it was used to compare to other values, casting might be necessary or can be removed, if casting was applied before.
|
||||
|
||||
* `redisReplyObjectFunctions.createArray` now takes `size_t` for its length parameter.
|
||||
|
||||
### 0.14.0 (2018-09-25)
|
||||
|
||||
* Make string2ll static to fix conflict with Redis (Tom Lee [c3188b])
|
||||
@@ -50,8 +60,9 @@
|
||||
* Import latest upstream sds. This breaks applications that are linked against the old hiredis v0.13
|
||||
* Fix warnings, when compiled with -Wshadow
|
||||
* Make hiredis compile in Cygwin on Windows, now CI-tested
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
* Bulk and multi-bulk lengths less than -1 or greater than `LLONG_MAX` are now
|
||||
protocol errors. This is consistent with the RESP specification. On 32-bit
|
||||
platforms, the upper bound is lowered to `SIZE_MAX`.
|
||||
|
||||
* Remove backwards compatibility macro's
|
||||
|
||||
|
||||
Vendored
+90
@@ -0,0 +1,90 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.4.0)
|
||||
INCLUDE(GNUInstallDirs)
|
||||
PROJECT(hiredis)
|
||||
|
||||
OPTION(ENABLE_SSL "Build hiredis_ssl for SSL support" OFF)
|
||||
|
||||
MACRO(getVersionBit name)
|
||||
SET(VERSION_REGEX "^#define ${name} (.+)$")
|
||||
FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/hiredis.h"
|
||||
VERSION_BIT REGEX ${VERSION_REGEX})
|
||||
STRING(REGEX REPLACE ${VERSION_REGEX} "\\1" ${name} "${VERSION_BIT}")
|
||||
ENDMACRO(getVersionBit)
|
||||
|
||||
getVersionBit(HIREDIS_MAJOR)
|
||||
getVersionBit(HIREDIS_MINOR)
|
||||
getVersionBit(HIREDIS_PATCH)
|
||||
getVersionBit(HIREDIS_SONAME)
|
||||
SET(VERSION "${HIREDIS_MAJOR}.${HIREDIS_MINOR}.${HIREDIS_PATCH}")
|
||||
MESSAGE("Detected version: ${VERSION}")
|
||||
|
||||
PROJECT(hiredis VERSION "${VERSION}")
|
||||
|
||||
SET(ENABLE_EXAMPLES OFF CACHE BOOL "Enable building hiredis examples")
|
||||
|
||||
ADD_LIBRARY(hiredis SHARED
|
||||
async.c
|
||||
dict.c
|
||||
hiredis.c
|
||||
net.c
|
||||
read.c
|
||||
sds.c
|
||||
sockcompat.c)
|
||||
|
||||
SET_TARGET_PROPERTIES(hiredis
|
||||
PROPERTIES
|
||||
VERSION "${HIREDIS_SONAME}")
|
||||
IF(WIN32 OR MINGW)
|
||||
TARGET_LINK_LIBRARIES(hiredis PRIVATE ws2_32)
|
||||
ENDIF()
|
||||
TARGET_INCLUDE_DIRECTORIES(hiredis PUBLIC .)
|
||||
|
||||
CONFIGURE_FILE(hiredis.pc.in hiredis.pc @ONLY)
|
||||
|
||||
INSTALL(TARGETS hiredis
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
INSTALL(FILES hiredis.h read.h sds.h async.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis)
|
||||
|
||||
INSTALL(DIRECTORY adapters
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis)
|
||||
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredis.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
|
||||
IF(ENABLE_SSL)
|
||||
IF (NOT OPENSSL_ROOT_DIR)
|
||||
IF (APPLE)
|
||||
SET(OPENSSL_ROOT_DIR "/usr/local/opt/openssl")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
FIND_PACKAGE(OpenSSL REQUIRED)
|
||||
ADD_LIBRARY(hiredis_ssl SHARED
|
||||
ssl.c)
|
||||
TARGET_INCLUDE_DIRECTORIES(hiredis_ssl PRIVATE "${OPENSSL_INCLUDE_DIR}")
|
||||
TARGET_LINK_LIBRARIES(hiredis_ssl PRIVATE ${OPENSSL_LIBRARIES})
|
||||
CONFIGURE_FILE(hiredis_ssl.pc.in hiredis_ssl.pc @ONLY)
|
||||
|
||||
INSTALL(TARGETS hiredis_ssl
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
INSTALL(FILES hiredis_ssl.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis)
|
||||
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredis_ssl.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
ENDIF()
|
||||
|
||||
IF(NOT (WIN32 OR MINGW))
|
||||
ENABLE_TESTING()
|
||||
ADD_EXECUTABLE(hiredis-test test.c)
|
||||
TARGET_LINK_LIBRARIES(hiredis-test hiredis)
|
||||
ADD_TEST(NAME hiredis-test
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test.sh)
|
||||
ENDIF()
|
||||
|
||||
# Add examples
|
||||
IF(ENABLE_EXAMPLES)
|
||||
ADD_SUBDIRECTORY(examples)
|
||||
ENDIF(ENABLE_EXAMPLES)
|
||||
Vendored
+83
-23
@@ -3,11 +3,17 @@
|
||||
# Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
# This file is released under the BSD license, see the COPYING file
|
||||
|
||||
OBJ=net.o hiredis.o sds.o async.o read.o
|
||||
OBJ=net.o hiredis.o sds.o async.o read.o sockcompat.o
|
||||
SSL_OBJ=ssl.o
|
||||
EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib
|
||||
ifeq ($(USE_SSL),1)
|
||||
EXAMPLES+=hiredis-example-ssl hiredis-example-libevent-ssl
|
||||
endif
|
||||
TESTS=hiredis-test
|
||||
LIBNAME=libhiredis
|
||||
SSL_LIBNAME=libhiredis_ssl
|
||||
PKGCONFNAME=hiredis.pc
|
||||
SSL_PKGCONFNAME=hiredis_ssl.pc
|
||||
|
||||
HIREDIS_MAJOR=$(shell grep HIREDIS_MAJOR hiredis.h | awk '{print $$3}')
|
||||
HIREDIS_MINOR=$(shell grep HIREDIS_MINOR hiredis.h | awk '{print $$3}')
|
||||
@@ -39,7 +45,7 @@ export REDIS_TEST_CONFIG
|
||||
CC:=$(shell sh -c 'type $${CC%% *} >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
||||
CXX:=$(shell sh -c 'type $${CXX%% *} >/dev/null 2>/dev/null && echo $(CXX) || echo g++')
|
||||
OPTIMIZATION?=-O3
|
||||
WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings
|
||||
WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers
|
||||
DEBUG_FLAGS?= -g -ggdb
|
||||
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS)
|
||||
REAL_LDFLAGS=$(LDFLAGS)
|
||||
@@ -49,12 +55,30 @@ STLIBSUFFIX=a
|
||||
DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_SONAME)
|
||||
DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)
|
||||
DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)
|
||||
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
|
||||
SSL_DYLIBNAME=$(SSL_LIBNAME).$(DYLIBSUFFIX)
|
||||
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME)
|
||||
STLIBNAME=$(LIBNAME).$(STLIBSUFFIX)
|
||||
STLIB_MAKE_CMD=ar rcs $(STLIBNAME)
|
||||
SSL_STLIBNAME=$(SSL_LIBNAME).$(STLIBSUFFIX)
|
||||
STLIB_MAKE_CMD=$(AR) rcs
|
||||
|
||||
# Platform-specific overrides
|
||||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||
|
||||
USE_SSL?=0
|
||||
|
||||
# This is required for test.c only
|
||||
ifeq ($(USE_SSL),1)
|
||||
CFLAGS+=-DHIREDIS_TEST_SSL
|
||||
endif
|
||||
|
||||
ifeq ($(uname_S),Linux)
|
||||
SSL_LDFLAGS=-lssl -lcrypto
|
||||
else
|
||||
OPENSSL_PREFIX?=/usr/local/opt/openssl
|
||||
CFLAGS+=-I$(OPENSSL_PREFIX)/include
|
||||
SSL_LDFLAGS+=-L$(OPENSSL_PREFIX)/lib -lssl -lcrypto
|
||||
endif
|
||||
|
||||
ifeq ($(uname_S),SunOS)
|
||||
REAL_LDFLAGS+= -ldl -lnsl -lsocket
|
||||
DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)
|
||||
@@ -66,40 +90,61 @@ ifeq ($(uname_S),Darwin)
|
||||
endif
|
||||
|
||||
all: $(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME)
|
||||
ifeq ($(USE_SSL),1)
|
||||
all: $(SSL_DYLIBNAME) $(SSL_STLIBNAME) $(SSL_PKGCONFNAME)
|
||||
endif
|
||||
|
||||
# Deps (use make dep to generate this)
|
||||
async.o: async.c fmacros.h async.h hiredis.h read.h sds.h net.h dict.c dict.h
|
||||
dict.o: dict.c fmacros.h dict.h
|
||||
hiredis.o: hiredis.c fmacros.h hiredis.h read.h sds.h net.h
|
||||
net.o: net.c fmacros.h net.h hiredis.h read.h sds.h
|
||||
hiredis.o: hiredis.c fmacros.h hiredis.h read.h sds.h net.h win32.h
|
||||
net.o: net.c fmacros.h net.h hiredis.h read.h sds.h sockcompat.h win32.h
|
||||
read.o: read.c fmacros.h read.h sds.h
|
||||
sds.o: sds.c sds.h
|
||||
sockcompat.o: sockcompat.c sockcompat.h
|
||||
ssl.o: ssl.c hiredis.h
|
||||
test.o: test.c fmacros.h hiredis.h read.h sds.h
|
||||
|
||||
$(DYLIBNAME): $(OBJ)
|
||||
$(DYLIB_MAKE_CMD) $(OBJ)
|
||||
$(DYLIB_MAKE_CMD) -o $(DYLIBNAME) $(OBJ) $(REAL_LDFLAGS)
|
||||
|
||||
$(STLIBNAME): $(OBJ)
|
||||
$(STLIB_MAKE_CMD) $(OBJ)
|
||||
$(STLIB_MAKE_CMD) $(STLIBNAME) $(OBJ)
|
||||
|
||||
$(SSL_DYLIBNAME): $(SSL_OBJ)
|
||||
$(DYLIB_MAKE_CMD) -o $(SSL_DYLIBNAME) $(SSL_OBJ) $(REAL_LDFLAGS) $(SSL_LDFLAGS)
|
||||
|
||||
$(SSL_STLIBNAME): $(SSL_OBJ)
|
||||
$(STLIB_MAKE_CMD) $(SSL_STLIBNAME) $(SSL_OBJ)
|
||||
|
||||
dynamic: $(DYLIBNAME)
|
||||
static: $(STLIBNAME)
|
||||
ifeq ($(USE_SSL),1)
|
||||
dynamic: $(SSL_DYLIBNAME)
|
||||
static: $(SSL_STLIBNAME)
|
||||
endif
|
||||
|
||||
# Binaries:
|
||||
hiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -levent $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -levent $(STLIBNAME) $(REAL_LDFLAGS)
|
||||
|
||||
hiredis-example-libevent-ssl: examples/example-libevent-ssl.c adapters/libevent.h $(STLIBNAME) $(SSL_STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -levent $(STLIBNAME) $(SSL_STLIBNAME) $(REAL_LDFLAGS) $(SSL_LDFLAGS)
|
||||
|
||||
hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -lev $(STLIBNAME) $(REAL_LDFLAGS)
|
||||
|
||||
hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(shell pkg-config --cflags --libs glib-2.0) $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(shell pkg-config --cflags --libs glib-2.0) $(STLIBNAME) $(REAL_LDFLAGS)
|
||||
|
||||
hiredis-example-ivykis: examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -livykis $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -livykis $(STLIBNAME) $(REAL_LDFLAGS)
|
||||
|
||||
hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -framework CoreFoundation $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -framework CoreFoundation $(STLIBNAME) $(REAL_LDFLAGS)
|
||||
|
||||
hiredis-example-ssl: examples/example-ssl.c $(STLIBNAME) $(SSL_STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(STLIBNAME) $(SSL_STLIBNAME) $(REAL_LDFLAGS) $(SSL_LDFLAGS)
|
||||
|
||||
ifndef AE_DIR
|
||||
hiredis-example-ae:
|
||||
@@ -116,7 +161,7 @@ hiredis-example-libuv:
|
||||
@false
|
||||
else
|
||||
hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME) $(REAL_LDFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(and $(QT_MOC),$(QT_INCLUDE_DIR),$(QT_LIBRARY_DIR)),)
|
||||
@@ -133,32 +178,33 @@ hiredis-example-qt: examples/example-qt.cpp adapters/qt.h $(STLIBNAME)
|
||||
endif
|
||||
|
||||
hiredis-example: examples/example.c $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(STLIBNAME) $(REAL_LDFLAGS)
|
||||
|
||||
examples: $(EXAMPLES)
|
||||
|
||||
hiredis-test: test.o $(STLIBNAME)
|
||||
TEST_LIBS = $(STLIBNAME)
|
||||
ifeq ($(USE_SSL),1)
|
||||
TEST_LIBS += $(SSL_STLIBNAME) -lssl -lcrypto -lpthread
|
||||
endif
|
||||
hiredis-test: test.o $(TEST_LIBS)
|
||||
|
||||
hiredis-%: %.o $(STLIBNAME)
|
||||
$(CC) $(REAL_CFLAGS) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)
|
||||
$(CC) $(REAL_CFLAGS) -o $@ $< $(TEST_LIBS) $(REAL_LDFLAGS)
|
||||
|
||||
test: hiredis-test
|
||||
./hiredis-test
|
||||
|
||||
check: hiredis-test
|
||||
@echo "$$REDIS_TEST_CONFIG" | $(REDIS_SERVER) -
|
||||
$(PRE) ./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \
|
||||
( kill `cat /tmp/hiredis-test-redis.pid` && false )
|
||||
kill `cat /tmp/hiredis-test-redis.pid`
|
||||
TEST_SSL=$(USE_SSL) ./test.sh
|
||||
|
||||
.c.o:
|
||||
$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<
|
||||
|
||||
clean:
|
||||
rm -rf $(DYLIBNAME) $(STLIBNAME) $(TESTS) $(PKGCONFNAME) examples/hiredis-example* *.o *.gcda *.gcno *.gcov
|
||||
rm -rf $(DYLIBNAME) $(STLIBNAME) $(SSL_DYLIBNAME) $(SSL_STLIBNAME) $(TESTS) $(PKGCONFNAME) examples/hiredis-example* *.o *.gcda *.gcno *.gcov
|
||||
|
||||
dep:
|
||||
$(CC) -MM *.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -MM *.c
|
||||
|
||||
INSTALL?= cp -pPR
|
||||
|
||||
@@ -175,6 +221,20 @@ $(PKGCONFNAME): hiredis.h
|
||||
@echo Libs: -L\$${libdir} -lhiredis >> $@
|
||||
@echo Cflags: -I\$${includedir} -D_FILE_OFFSET_BITS=64 >> $@
|
||||
|
||||
$(SSL_PKGCONFNAME): hiredis.h
|
||||
@echo "Generating $@ for pkgconfig..."
|
||||
@echo prefix=$(PREFIX) > $@
|
||||
@echo exec_prefix=\$${prefix} >> $@
|
||||
@echo libdir=$(PREFIX)/$(LIBRARY_PATH) >> $@
|
||||
@echo includedir=$(PREFIX)/$(INCLUDE_PATH) >> $@
|
||||
@echo >> $@
|
||||
@echo Name: hiredis_ssl >> $@
|
||||
@echo Description: SSL Support for hiredis. >> $@
|
||||
@echo Version: $(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(HIREDIS_PATCH) >> $@
|
||||
@echo Requires: hiredis >> $@
|
||||
@echo Libs: -L\$${libdir} -lhiredis_ssl >> $@
|
||||
@echo Libs.private: -lssl -lcrypto >> $@
|
||||
|
||||
install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
|
||||
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL_LIBRARY_PATH)
|
||||
$(INSTALL) hiredis.h async.h read.h sds.h $(INSTALL_INCLUDE_PATH)
|
||||
|
||||
Vendored
+2
-1
@@ -286,6 +286,7 @@ return `REDIS_ERR`. The function to set the disconnect callback has the followin
|
||||
```c
|
||||
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
|
||||
```
|
||||
`ac->data` may be used to pass user data to this callback, the same can be done for redisConnectCallback.
|
||||
### Sending commands and their callbacks
|
||||
|
||||
In an asynchronous context, commands are automatically pipelined due to the nature of an event loop.
|
||||
@@ -406,6 +407,6 @@ as soon as possible in order to prevent allocation of useless memory.
|
||||
## AUTHORS
|
||||
|
||||
Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and
|
||||
Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license.
|
||||
Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license.
|
||||
Hiredis is currently maintained by Matt Stancliff (matt at genges dot com) and
|
||||
Jan-Erik Rediger (janerik at fnordig dot com)
|
||||
Vendored
+88
-24
@@ -34,48 +34,113 @@
|
||||
#include "../hiredis.h"
|
||||
#include "../async.h"
|
||||
|
||||
#define REDIS_LIBEVENT_DELETED 0x01
|
||||
#define REDIS_LIBEVENT_ENTERED 0x02
|
||||
|
||||
typedef struct redisLibeventEvents {
|
||||
redisAsyncContext *context;
|
||||
struct event *rev, *wev;
|
||||
struct event *ev;
|
||||
struct event_base *base;
|
||||
struct timeval tv;
|
||||
short flags;
|
||||
short state;
|
||||
} redisLibeventEvents;
|
||||
|
||||
static void redisLibeventReadEvent(int fd, short event, void *arg) {
|
||||
((void)fd); ((void)event);
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)arg;
|
||||
redisAsyncHandleRead(e->context);
|
||||
static void redisLibeventDestroy(redisLibeventEvents *e) {
|
||||
free(e);
|
||||
}
|
||||
|
||||
static void redisLibeventWriteEvent(int fd, short event, void *arg) {
|
||||
((void)fd); ((void)event);
|
||||
static void redisLibeventHandler(int fd, short event, void *arg) {
|
||||
((void)fd);
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)arg;
|
||||
redisAsyncHandleWrite(e->context);
|
||||
e->state |= REDIS_LIBEVENT_ENTERED;
|
||||
|
||||
#define CHECK_DELETED() if (e->state & REDIS_LIBEVENT_DELETED) {\
|
||||
redisLibeventDestroy(e);\
|
||||
return; \
|
||||
}
|
||||
|
||||
if ((event & EV_TIMEOUT) && (e->state & REDIS_LIBEVENT_DELETED) == 0) {
|
||||
redisAsyncHandleTimeout(e->context);
|
||||
CHECK_DELETED();
|
||||
}
|
||||
|
||||
if ((event & EV_READ) && e->context && (e->state & REDIS_LIBEVENT_DELETED) == 0) {
|
||||
redisAsyncHandleRead(e->context);
|
||||
CHECK_DELETED();
|
||||
}
|
||||
|
||||
if ((event & EV_WRITE) && e->context && (e->state & REDIS_LIBEVENT_DELETED) == 0) {
|
||||
redisAsyncHandleWrite(e->context);
|
||||
CHECK_DELETED();
|
||||
}
|
||||
|
||||
e->state &= ~REDIS_LIBEVENT_ENTERED;
|
||||
#undef CHECK_DELETED
|
||||
}
|
||||
|
||||
static void redisLibeventUpdate(void *privdata, short flag, int isRemove) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents *)privdata;
|
||||
const struct timeval *tv = e->tv.tv_sec || e->tv.tv_usec ? &e->tv : NULL;
|
||||
|
||||
if (isRemove) {
|
||||
if ((e->flags & flag) == 0) {
|
||||
return;
|
||||
} else {
|
||||
e->flags &= ~flag;
|
||||
}
|
||||
} else {
|
||||
if (e->flags & flag) {
|
||||
return;
|
||||
} else {
|
||||
e->flags |= flag;
|
||||
}
|
||||
}
|
||||
|
||||
event_del(e->ev);
|
||||
event_assign(e->ev, e->base, e->context->c.fd, e->flags | EV_PERSIST,
|
||||
redisLibeventHandler, privdata);
|
||||
event_add(e->ev, tv);
|
||||
}
|
||||
|
||||
static void redisLibeventAddRead(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_add(e->rev,NULL);
|
||||
redisLibeventUpdate(privdata, EV_READ, 0);
|
||||
}
|
||||
|
||||
static void redisLibeventDelRead(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_del(e->rev);
|
||||
redisLibeventUpdate(privdata, EV_READ, 1);
|
||||
}
|
||||
|
||||
static void redisLibeventAddWrite(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_add(e->wev,NULL);
|
||||
redisLibeventUpdate(privdata, EV_WRITE, 0);
|
||||
}
|
||||
|
||||
static void redisLibeventDelWrite(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_del(e->wev);
|
||||
redisLibeventUpdate(privdata, EV_WRITE, 1);
|
||||
}
|
||||
|
||||
static void redisLibeventCleanup(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_free(e->rev);
|
||||
event_free(e->wev);
|
||||
free(e);
|
||||
if (!e) {
|
||||
return;
|
||||
}
|
||||
event_del(e->ev);
|
||||
event_free(e->ev);
|
||||
e->ev = NULL;
|
||||
|
||||
if (e->state & REDIS_LIBEVENT_ENTERED) {
|
||||
e->state |= REDIS_LIBEVENT_DELETED;
|
||||
} else {
|
||||
redisLibeventDestroy(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void redisLibeventSetTimeout(void *privdata, struct timeval tv) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents *)privdata;
|
||||
short flags = e->flags;
|
||||
e->flags = 0;
|
||||
e->tv = tv;
|
||||
redisLibeventUpdate(e, flags, 0);
|
||||
}
|
||||
|
||||
static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
|
||||
@@ -87,7 +152,7 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
|
||||
return REDIS_ERR;
|
||||
|
||||
/* Create container for context and r/w events */
|
||||
e = (redisLibeventEvents*)malloc(sizeof(*e));
|
||||
e = (redisLibeventEvents*)calloc(1, sizeof(*e));
|
||||
e->context = ac;
|
||||
|
||||
/* Register functions to start/stop listening for events */
|
||||
@@ -96,13 +161,12 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
|
||||
ac->ev.addWrite = redisLibeventAddWrite;
|
||||
ac->ev.delWrite = redisLibeventDelWrite;
|
||||
ac->ev.cleanup = redisLibeventCleanup;
|
||||
ac->ev.scheduleTimer = redisLibeventSetTimeout;
|
||||
ac->ev.data = e;
|
||||
|
||||
/* Initialize and install read/write events */
|
||||
e->rev = event_new(base, c->fd, EV_READ, redisLibeventReadEvent, e);
|
||||
e->wev = event_new(base, c->fd, EV_WRITE, redisLibeventWriteEvent, e);
|
||||
event_add(e->rev, NULL);
|
||||
event_add(e->wev, NULL);
|
||||
e->ev = event_new(base, c->fd, EV_READ | EV_WRITE, redisLibeventHandler, e);
|
||||
e->base = base;
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
Vendored
+4
-3
@@ -5,8 +5,9 @@ environment:
|
||||
CC: gcc
|
||||
- CYG_BASH: C:\cygwin\bin\bash
|
||||
CC: gcc
|
||||
TARGET: 32bit
|
||||
TARGET_VARS: 32bit-vars
|
||||
CFLAGS: -m32
|
||||
CXXFLAGS: -m32
|
||||
LDFLAGS: -m32
|
||||
|
||||
clone_depth: 1
|
||||
|
||||
@@ -20,4 +21,4 @@ install:
|
||||
|
||||
build_script:
|
||||
- 'echo building...'
|
||||
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make LDFLAGS=$LDFLAGS CC=$CC $TARGET CFLAGS=$CFLAGS && make LDFLAGS=$LDFLAGS CC=$CC $TARGET_VARS hiredis-example"'
|
||||
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; mkdir build && cd build && cmake .. -G \"Unix Makefiles\" && make VERBOSE=1"'
|
||||
Vendored
+113
-63
@@ -32,7 +32,9 @@
|
||||
#include "fmacros.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@@ -40,22 +42,9 @@
|
||||
#include "net.h"
|
||||
#include "dict.c"
|
||||
#include "sds.h"
|
||||
#include "win32.h"
|
||||
|
||||
#define _EL_ADD_READ(ctx) do { \
|
||||
if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_DEL_READ(ctx) do { \
|
||||
if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_ADD_WRITE(ctx) do { \
|
||||
if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_DEL_WRITE(ctx) do { \
|
||||
if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_CLEANUP(ctx) do { \
|
||||
if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \
|
||||
} while(0);
|
||||
#include "async_private.h"
|
||||
|
||||
/* Forward declaration of function in hiredis.c */
|
||||
int __redisAppendCommand(redisContext *c, const char *cmd, size_t len);
|
||||
@@ -126,6 +115,7 @@ static redisAsyncContext *redisAsyncInitialize(redisContext *c) {
|
||||
ac->ev.addWrite = NULL;
|
||||
ac->ev.delWrite = NULL;
|
||||
ac->ev.cleanup = NULL;
|
||||
ac->ev.scheduleTimer = NULL;
|
||||
|
||||
ac->onConnect = NULL;
|
||||
ac->onDisconnect = NULL;
|
||||
@@ -150,56 +140,52 @@ static void __redisAsyncCopyError(redisAsyncContext *ac) {
|
||||
ac->errstr = c->errstr;
|
||||
}
|
||||
|
||||
redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
|
||||
redisAsyncContext *redisAsyncConnectWithOptions(const redisOptions *options) {
|
||||
redisOptions myOptions = *options;
|
||||
redisContext *c;
|
||||
redisAsyncContext *ac;
|
||||
|
||||
c = redisConnectNonBlock(ip,port);
|
||||
if (c == NULL)
|
||||
myOptions.options |= REDIS_OPT_NONBLOCK;
|
||||
c = redisConnectWithOptions(&myOptions);
|
||||
if (c == NULL) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
ac = redisAsyncInitialize(c);
|
||||
if (ac == NULL) {
|
||||
redisFree(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
}
|
||||
|
||||
redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, ip, port);
|
||||
return redisAsyncConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisAsyncContext *redisAsyncConnectBind(const char *ip, int port,
|
||||
const char *source_addr) {
|
||||
redisContext *c = redisConnectBindNonBlock(ip,port,source_addr);
|
||||
redisAsyncContext *ac = redisAsyncInitialize(c);
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, ip, port);
|
||||
options.endpoint.tcp.source_addr = source_addr;
|
||||
return redisAsyncConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port,
|
||||
const char *source_addr) {
|
||||
redisContext *c = redisConnectBindNonBlockWithReuse(ip,port,source_addr);
|
||||
redisAsyncContext *ac = redisAsyncInitialize(c);
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, ip, port);
|
||||
options.options |= REDIS_OPT_REUSEADDR;
|
||||
options.endpoint.tcp.source_addr = source_addr;
|
||||
return redisAsyncConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisAsyncContext *redisAsyncConnectUnix(const char *path) {
|
||||
redisContext *c;
|
||||
redisAsyncContext *ac;
|
||||
|
||||
c = redisConnectUnixNonBlock(path);
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
ac = redisAsyncInitialize(c);
|
||||
if (ac == NULL) {
|
||||
redisFree(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_UNIX(&options, path);
|
||||
return redisAsyncConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) {
|
||||
@@ -328,7 +314,7 @@ void redisAsyncFree(redisAsyncContext *ac) {
|
||||
}
|
||||
|
||||
/* Helper function to make the disconnect happen and clean up. */
|
||||
static void __redisAsyncDisconnect(redisAsyncContext *ac) {
|
||||
void __redisAsyncDisconnect(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
|
||||
/* Make sure error is accessible if there is any */
|
||||
@@ -344,9 +330,15 @@ static void __redisAsyncDisconnect(redisAsyncContext *ac) {
|
||||
c->flags |= REDIS_DISCONNECTING;
|
||||
}
|
||||
|
||||
/* cleanup event library on disconnect.
|
||||
* this is safe to call multiple times */
|
||||
_EL_CLEANUP(ac);
|
||||
|
||||
/* For non-clean disconnects, __redisAsyncFree() will execute pending
|
||||
* callbacks with a NULL-reply. */
|
||||
__redisAsyncFree(ac);
|
||||
if (!(c->flags & REDIS_NO_AUTO_FREE)) {
|
||||
__redisAsyncFree(ac);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tries to do a clean disconnect from Redis, meaning it stops new commands
|
||||
@@ -358,6 +350,9 @@ static void __redisAsyncDisconnect(redisAsyncContext *ac) {
|
||||
void redisAsyncDisconnect(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
c->flags |= REDIS_DISCONNECTING;
|
||||
|
||||
/** unset the auto-free flag here, because disconnect undoes this */
|
||||
c->flags &= ~REDIS_NO_AUTO_FREE;
|
||||
if (!(c->flags & REDIS_IN_CALLBACK) && ac->replies.head == NULL)
|
||||
__redisAsyncDisconnect(ac);
|
||||
}
|
||||
@@ -408,7 +403,7 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply,
|
||||
assert(reply->element[2]->type == REDIS_REPLY_INTEGER);
|
||||
|
||||
/* Unset subscribed flag only when no pipelined pending subscribe. */
|
||||
if (reply->element[2]->integer == 0
|
||||
if (reply->element[2]->integer == 0
|
||||
&& dictSize(ac->sub.channels) == 0
|
||||
&& dictSize(ac->sub.patterns) == 0)
|
||||
c->flags &= ~REDIS_SUBSCRIBED;
|
||||
@@ -524,6 +519,18 @@ static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
|
||||
}
|
||||
}
|
||||
|
||||
void redisAsyncRead(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
|
||||
if (redisBufferRead(c) == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
} else {
|
||||
/* Always re-schedule reads */
|
||||
_EL_ADD_READ(ac);
|
||||
redisProcessCallbacks(ac);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function should be called when the socket is readable.
|
||||
* It processes all replies that can be read and executes their callbacks.
|
||||
*/
|
||||
@@ -539,28 +546,13 @@ void redisAsyncHandleRead(redisAsyncContext *ac) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (redisBufferRead(c) == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
} else {
|
||||
/* Always re-schedule reads */
|
||||
_EL_ADD_READ(ac);
|
||||
redisProcessCallbacks(ac);
|
||||
}
|
||||
c->funcs->async_read(ac);
|
||||
}
|
||||
|
||||
void redisAsyncHandleWrite(redisAsyncContext *ac) {
|
||||
void redisAsyncWrite(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
int done = 0;
|
||||
|
||||
if (!(c->flags & REDIS_CONNECTED)) {
|
||||
/* Abort connect was not successful. */
|
||||
if (__redisAsyncHandleConnect(ac) != REDIS_OK)
|
||||
return;
|
||||
/* Try again later when the context is still not connected. */
|
||||
if (!(c->flags & REDIS_CONNECTED))
|
||||
return;
|
||||
}
|
||||
|
||||
if (redisBufferWrite(c,&done) == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
} else {
|
||||
@@ -575,6 +567,51 @@ void redisAsyncHandleWrite(redisAsyncContext *ac) {
|
||||
}
|
||||
}
|
||||
|
||||
void redisAsyncHandleWrite(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
|
||||
if (!(c->flags & REDIS_CONNECTED)) {
|
||||
/* Abort connect was not successful. */
|
||||
if (__redisAsyncHandleConnect(ac) != REDIS_OK)
|
||||
return;
|
||||
/* Try again later when the context is still not connected. */
|
||||
if (!(c->flags & REDIS_CONNECTED))
|
||||
return;
|
||||
}
|
||||
|
||||
c->funcs->async_write(ac);
|
||||
}
|
||||
|
||||
void __redisSetError(redisContext *c, int type, const char *str);
|
||||
|
||||
void redisAsyncHandleTimeout(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
redisCallback cb;
|
||||
|
||||
if ((c->flags & REDIS_CONNECTED) && ac->replies.head == NULL) {
|
||||
/* Nothing to do - just an idle timeout */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c->err) {
|
||||
__redisSetError(c, REDIS_ERR_TIMEOUT, "Timeout");
|
||||
}
|
||||
|
||||
if (!(c->flags & REDIS_CONNECTED) && ac->onConnect) {
|
||||
ac->onConnect(ac, REDIS_ERR);
|
||||
}
|
||||
|
||||
while (__redisShiftCallback(&ac->replies, &cb) == REDIS_OK) {
|
||||
__redisRunCallback(ac, &cb, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Don't automatically sever the connection,
|
||||
* rather, allow to ignore <x> responses before the queue is clear
|
||||
*/
|
||||
__redisAsyncDisconnect(ac);
|
||||
}
|
||||
|
||||
/* Sets a pointer to the first argument and its length starting at p. Returns
|
||||
* the number of bytes to skip to get to the following argument. */
|
||||
static const char *nextArgument(const char *start, const char **str, size_t *len) {
|
||||
@@ -714,3 +751,16 @@ int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
|
||||
int status = __redisAsyncCommand(ac,fn,privdata,cmd,len);
|
||||
return status;
|
||||
}
|
||||
|
||||
void redisAsyncSetTimeout(redisAsyncContext *ac, struct timeval tv) {
|
||||
if (!ac->c.timeout) {
|
||||
ac->c.timeout = calloc(1, sizeof(tv));
|
||||
}
|
||||
|
||||
if (tv.tv_sec == ac->c.timeout->tv_sec &&
|
||||
tv.tv_usec == ac->c.timeout->tv_usec) {
|
||||
return;
|
||||
}
|
||||
|
||||
*ac->c.timeout = tv;
|
||||
}
|
||||
Vendored
+8
@@ -57,6 +57,7 @@ typedef struct redisCallbackList {
|
||||
/* Connection callback prototypes */
|
||||
typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);
|
||||
typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);
|
||||
typedef void(redisTimerCallback)(void *timer, void *privdata);
|
||||
|
||||
/* Context for an async connection to Redis */
|
||||
typedef struct redisAsyncContext {
|
||||
@@ -81,6 +82,7 @@ typedef struct redisAsyncContext {
|
||||
void (*addWrite)(void *privdata);
|
||||
void (*delWrite)(void *privdata);
|
||||
void (*cleanup)(void *privdata);
|
||||
void (*scheduleTimer)(void *privdata, struct timeval tv);
|
||||
} ev;
|
||||
|
||||
/* Called when either the connection is terminated due to an error or per
|
||||
@@ -106,6 +108,7 @@ typedef struct redisAsyncContext {
|
||||
} redisAsyncContext;
|
||||
|
||||
/* Functions that proxy to hiredis */
|
||||
redisAsyncContext *redisAsyncConnectWithOptions(const redisOptions *options);
|
||||
redisAsyncContext *redisAsyncConnect(const char *ip, int port);
|
||||
redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr);
|
||||
redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port,
|
||||
@@ -113,12 +116,17 @@ redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port,
|
||||
redisAsyncContext *redisAsyncConnectUnix(const char *path);
|
||||
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
|
||||
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
|
||||
|
||||
void redisAsyncSetTimeout(redisAsyncContext *ac, struct timeval tv);
|
||||
void redisAsyncDisconnect(redisAsyncContext *ac);
|
||||
void redisAsyncFree(redisAsyncContext *ac);
|
||||
|
||||
/* Handle read/write events */
|
||||
void redisAsyncHandleRead(redisAsyncContext *ac);
|
||||
void redisAsyncHandleWrite(redisAsyncContext *ac);
|
||||
void redisAsyncHandleTimeout(redisAsyncContext *ac);
|
||||
void redisAsyncRead(redisAsyncContext *ac);
|
||||
void redisAsyncWrite(redisAsyncContext *ac);
|
||||
|
||||
/* Command functions for an async context. Write the command to the
|
||||
* output buffer and register the provided callback. */
|
||||
|
||||
Vendored
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __HIREDIS_ASYNC_PRIVATE_H
|
||||
#define __HIREDIS_ASYNC_PRIVATE_H
|
||||
|
||||
#define _EL_ADD_READ(ctx) \
|
||||
do { \
|
||||
refreshTimeout(ctx); \
|
||||
if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
|
||||
} while (0)
|
||||
#define _EL_DEL_READ(ctx) do { \
|
||||
if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_ADD_WRITE(ctx) \
|
||||
do { \
|
||||
refreshTimeout(ctx); \
|
||||
if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \
|
||||
} while (0)
|
||||
#define _EL_DEL_WRITE(ctx) do { \
|
||||
if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_CLEANUP(ctx) do { \
|
||||
if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \
|
||||
ctx->ev.cleanup = NULL; \
|
||||
} while(0);
|
||||
|
||||
static inline void refreshTimeout(redisAsyncContext *ctx) {
|
||||
if (ctx->c.timeout && ctx->ev.scheduleTimer &&
|
||||
(ctx->c.timeout->tv_sec || ctx->c.timeout->tv_usec)) {
|
||||
ctx->ev.scheduleTimer(ctx->ev.data, *ctx->c.timeout);
|
||||
// } else {
|
||||
// printf("Not scheduling timer.. (tmo=%p)\n", ctx->c.timeout);
|
||||
// if (ctx->c.timeout){
|
||||
// printf("tv_sec: %u. tv_usec: %u\n", ctx->c.timeout->tv_sec,
|
||||
// ctx->c.timeout->tv_usec);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
void __redisAsyncDisconnect(redisAsyncContext *ac);
|
||||
void redisProcessCallbacks(redisAsyncContext *ac);
|
||||
|
||||
#endif /* __HIREDIS_ASYNC_PRIVATE_H */
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
INCLUDE(FindPkgConfig)
|
||||
# Check for GLib
|
||||
|
||||
PKG_CHECK_MODULES(GLIB2 glib-2.0)
|
||||
if (GLIB2_FOUND)
|
||||
INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS})
|
||||
LINK_DIRECTORIES(${GLIB2_LIBRARY_DIRS})
|
||||
ADD_EXECUTABLE(example-glib example-glib.c)
|
||||
TARGET_LINK_LIBRARIES(example-glib hiredis ${GLIB2_LIBRARIES})
|
||||
ENDIF(GLIB2_FOUND)
|
||||
|
||||
FIND_PATH(LIBEV ev.h
|
||||
HINTS /usr/local /usr/opt/local
|
||||
ENV LIBEV_INCLUDE_DIR)
|
||||
|
||||
if (LIBEV)
|
||||
# Just compile and link with libev
|
||||
ADD_EXECUTABLE(example-libev example-libev.c)
|
||||
TARGET_LINK_LIBRARIES(example-libev hiredis ev)
|
||||
ENDIF()
|
||||
|
||||
FIND_PATH(LIBEVENT event.h)
|
||||
if (LIBEVENT)
|
||||
ADD_EXECUTABLE(example-libevent example-libevent)
|
||||
TARGET_LINK_LIBRARIES(example-libevent hiredis event)
|
||||
ENDIF()
|
||||
|
||||
FIND_PATH(LIBUV uv.h)
|
||||
IF (LIBUV)
|
||||
ADD_EXECUTABLE(example-libuv example-libuv.c)
|
||||
TARGET_LINK_LIBRARIES(example-libuv hiredis uv)
|
||||
ENDIF()
|
||||
|
||||
IF (APPLE)
|
||||
FIND_LIBRARY(CF CoreFoundation)
|
||||
ADD_EXECUTABLE(example-macosx example-macosx.c)
|
||||
TARGET_LINK_LIBRARIES(example-macosx hiredis ${CF})
|
||||
ENDIF()
|
||||
|
||||
IF (ENABLE_SSL)
|
||||
ADD_EXECUTABLE(example-ssl example-ssl.c)
|
||||
TARGET_LINK_LIBRARIES(example-ssl hiredis hiredis_ssl)
|
||||
ENDIF()
|
||||
|
||||
ADD_EXECUTABLE(example example.c)
|
||||
TARGET_LINK_LIBRARIES(example hiredis)
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <hiredis.h>
|
||||
#include <hiredis_ssl.h>
|
||||
#include <async.h>
|
||||
#include <adapters/libevent.h>
|
||||
|
||||
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
redisReply *reply = r;
|
||||
if (reply == NULL) return;
|
||||
printf("argv[%s]: %s\n", (char*)privdata, reply->str);
|
||||
|
||||
/* Disconnect after receiving the reply to GET */
|
||||
redisAsyncDisconnect(c);
|
||||
}
|
||||
|
||||
void connectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Connected...\n");
|
||||
}
|
||||
|
||||
void disconnectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Disconnected...\n");
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
struct event_base *base = event_base_new();
|
||||
if (argc < 5) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <key> <host> <port> <cert> <certKey> [ca]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char *value = argv[1];
|
||||
size_t nvalue = strlen(value);
|
||||
|
||||
const char *hostname = argv[2];
|
||||
int port = atoi(argv[3]);
|
||||
|
||||
const char *cert = argv[4];
|
||||
const char *certKey = argv[5];
|
||||
const char *caCert = argc > 5 ? argv[6] : NULL;
|
||||
|
||||
redisAsyncContext *c = redisAsyncConnect(hostname, port);
|
||||
if (c->err) {
|
||||
/* Let *c leak for now... */
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return 1;
|
||||
}
|
||||
if (redisSecureConnection(&c->c, caCert, cert, certKey, "sni") != REDIS_OK) {
|
||||
printf("SSL Error!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
redisLibeventAttach(c,base);
|
||||
redisAsyncSetConnectCallback(c,connectCallback);
|
||||
redisAsyncSetDisconnectCallback(c,disconnectCallback);
|
||||
redisAsyncCommand(c, NULL, NULL, "SET key %b", value, nvalue);
|
||||
redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");
|
||||
event_base_dispatch(base);
|
||||
return 0;
|
||||
}
|
||||
+13
-2
@@ -9,7 +9,12 @@
|
||||
|
||||
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
redisReply *reply = r;
|
||||
if (reply == NULL) return;
|
||||
if (reply == NULL) {
|
||||
if (c->errstr) {
|
||||
printf("errstr: %s\n", c->errstr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
printf("argv[%s]: %s\n", (char*)privdata, reply->str);
|
||||
|
||||
/* Disconnect after receiving the reply to GET */
|
||||
@@ -35,8 +40,14 @@ void disconnectCallback(const redisAsyncContext *c, int status) {
|
||||
int main (int argc, char **argv) {
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
struct event_base *base = event_base_new();
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379);
|
||||
struct timeval tv = {0};
|
||||
tv.tv_sec = 1;
|
||||
options.timeout = &tv;
|
||||
|
||||
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
|
||||
|
||||
redisAsyncContext *c = redisAsyncConnectWithOptions(&options);
|
||||
if (c->err) {
|
||||
/* Let *c leak for now... */
|
||||
printf("Error: %s\n", c->errstr);
|
||||
|
||||
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <hiredis.h>
|
||||
#include <hiredis_ssl.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
unsigned int j;
|
||||
redisContext *c;
|
||||
redisReply *reply;
|
||||
if (argc < 4) {
|
||||
printf("Usage: %s <host> <port> <cert> <key> [ca]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1";
|
||||
int port = atoi(argv[2]);
|
||||
const char *cert = argv[3];
|
||||
const char *key = argv[4];
|
||||
const char *ca = argc > 4 ? argv[5] : NULL;
|
||||
|
||||
struct timeval tv = { 1, 500000 }; // 1.5 seconds
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, hostname, port);
|
||||
options.timeout = &tv;
|
||||
c = redisConnectWithOptions(&options);
|
||||
|
||||
if (c == NULL || c->err) {
|
||||
if (c) {
|
||||
printf("Connection error: %s\n", c->errstr);
|
||||
redisFree(c);
|
||||
} else {
|
||||
printf("Connection error: can't allocate redis context\n");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (redisSecureConnection(c, ca, cert, key, "sni") != REDIS_OK) {
|
||||
printf("Couldn't initialize SSL!\n");
|
||||
printf("Error: %s\n", c->errstr);
|
||||
redisFree(c);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* PING server */
|
||||
reply = redisCommand(c,"PING");
|
||||
printf("PING: %s\n", reply->str);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Set a key */
|
||||
reply = redisCommand(c,"SET %s %s", "foo", "hello world");
|
||||
printf("SET: %s\n", reply->str);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Set a key using binary safe API */
|
||||
reply = redisCommand(c,"SET %b %b", "bar", (size_t) 3, "hello", (size_t) 5);
|
||||
printf("SET (binary API): %s\n", reply->str);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Try a GET and two INCR */
|
||||
reply = redisCommand(c,"GET foo");
|
||||
printf("GET foo: %s\n", reply->str);
|
||||
freeReplyObject(reply);
|
||||
|
||||
reply = redisCommand(c,"INCR counter");
|
||||
printf("INCR counter: %lld\n", reply->integer);
|
||||
freeReplyObject(reply);
|
||||
/* again ... */
|
||||
reply = redisCommand(c,"INCR counter");
|
||||
printf("INCR counter: %lld\n", reply->integer);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Create a list of numbers, from 0 to 9 */
|
||||
reply = redisCommand(c,"DEL mylist");
|
||||
freeReplyObject(reply);
|
||||
for (j = 0; j < 10; j++) {
|
||||
char buf[64];
|
||||
|
||||
snprintf(buf,64,"%u",j);
|
||||
reply = redisCommand(c,"LPUSH mylist element-%s", buf);
|
||||
freeReplyObject(reply);
|
||||
}
|
||||
|
||||
/* Let's check what we have inside the list */
|
||||
reply = redisCommand(c,"LRANGE mylist 0 -1");
|
||||
if (reply->type == REDIS_REPLY_ARRAY) {
|
||||
for (j = 0; j < reply->elements; j++) {
|
||||
printf("%u) %s\n", j, reply->element[j]->str);
|
||||
}
|
||||
}
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Disconnects and frees the context */
|
||||
redisFree(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Vendored
+15
-2
@@ -5,14 +5,27 @@
|
||||
#include <hiredis.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
unsigned int j;
|
||||
unsigned int j, isunix = 0;
|
||||
redisContext *c;
|
||||
redisReply *reply;
|
||||
const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1";
|
||||
|
||||
if (argc > 2) {
|
||||
if (*argv[2] == 'u' || *argv[2] == 'U') {
|
||||
isunix = 1;
|
||||
/* in this case, host is the path to the unix socket */
|
||||
printf("Will connect to unix socket @%s\n", hostname);
|
||||
}
|
||||
}
|
||||
|
||||
int port = (argc > 2) ? atoi(argv[2]) : 6379;
|
||||
|
||||
struct timeval timeout = { 1, 500000 }; // 1.5 seconds
|
||||
c = redisConnectWithTimeout(hostname, port, timeout);
|
||||
if (isunix) {
|
||||
c = redisConnectUnixWithTimeout(hostname, timeout);
|
||||
} else {
|
||||
c = redisConnectWithTimeout(hostname, port, timeout);
|
||||
}
|
||||
if (c == NULL || c->err) {
|
||||
if (c) {
|
||||
printf("Connection error: %s\n", c->errstr);
|
||||
|
||||
Vendored
+134
-122
@@ -34,7 +34,6 @@
|
||||
#include "fmacros.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
@@ -42,10 +41,20 @@
|
||||
#include "hiredis.h"
|
||||
#include "net.h"
|
||||
#include "sds.h"
|
||||
#include "async.h"
|
||||
#include "win32.h"
|
||||
|
||||
static redisContextFuncs redisContextDefaultFuncs = {
|
||||
.free_privdata = NULL,
|
||||
.async_read = redisAsyncRead,
|
||||
.async_write = redisAsyncWrite,
|
||||
.read = redisNetRead,
|
||||
.write = redisNetWrite
|
||||
};
|
||||
|
||||
static redisReply *createReplyObject(int type);
|
||||
static void *createStringObject(const redisReadTask *task, char *str, size_t len);
|
||||
static void *createArrayObject(const redisReadTask *task, int elements);
|
||||
static void *createArrayObject(const redisReadTask *task, size_t elements);
|
||||
static void *createIntegerObject(const redisReadTask *task, long long value);
|
||||
static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len);
|
||||
static void *createNilObject(const redisReadTask *task);
|
||||
@@ -112,21 +121,34 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
|
||||
if (r == NULL)
|
||||
return NULL;
|
||||
|
||||
buf = malloc(len+1);
|
||||
if (buf == NULL) {
|
||||
freeReplyObject(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(task->type == REDIS_REPLY_ERROR ||
|
||||
task->type == REDIS_REPLY_STATUS ||
|
||||
task->type == REDIS_REPLY_STRING);
|
||||
task->type == REDIS_REPLY_STRING ||
|
||||
task->type == REDIS_REPLY_VERB);
|
||||
|
||||
/* Copy string value */
|
||||
memcpy(buf,str,len);
|
||||
buf[len] = '\0';
|
||||
if (task->type == REDIS_REPLY_VERB) {
|
||||
buf = malloc(len-4+1); /* Skip 4 bytes of verbatim type header. */
|
||||
if (buf == NULL) {
|
||||
freeReplyObject(r);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(r->vtype,str,3);
|
||||
r->vtype[3] = '\0';
|
||||
memcpy(buf,str+4,len-4);
|
||||
buf[len-4] = '\0';
|
||||
r->len = len-4;
|
||||
} else {
|
||||
buf = malloc(len+1);
|
||||
if (buf == NULL) {
|
||||
freeReplyObject(r);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(buf,str,len);
|
||||
buf[len] = '\0';
|
||||
r->len = len;
|
||||
}
|
||||
r->str = buf;
|
||||
r->len = len;
|
||||
|
||||
if (task->parent) {
|
||||
parent = task->parent->obj;
|
||||
@@ -138,7 +160,7 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
|
||||
return r;
|
||||
}
|
||||
|
||||
static void *createArrayObject(const redisReadTask *task, int elements) {
|
||||
static void *createArrayObject(const redisReadTask *task, size_t elements) {
|
||||
redisReply *r, *parent;
|
||||
|
||||
r = createReplyObject(task->type);
|
||||
@@ -649,29 +671,30 @@ redisReader *redisReaderCreate(void) {
|
||||
return redisReaderCreateWithFunctions(&defaultFunctions);
|
||||
}
|
||||
|
||||
static redisContext *redisContextInit(void) {
|
||||
static redisContext *redisContextInit(const redisOptions *options) {
|
||||
redisContext *c;
|
||||
|
||||
c = calloc(1,sizeof(redisContext));
|
||||
c = calloc(1, sizeof(*c));
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->funcs = &redisContextDefaultFuncs;
|
||||
c->obuf = sdsempty();
|
||||
c->reader = redisReaderCreate();
|
||||
c->fd = REDIS_INVALID_FD;
|
||||
|
||||
if (c->obuf == NULL || c->reader == NULL) {
|
||||
redisFree(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(void)options; /* options are used in other functions */
|
||||
return c;
|
||||
}
|
||||
|
||||
void redisFree(redisContext *c) {
|
||||
if (c == NULL)
|
||||
return;
|
||||
if (c->fd > 0)
|
||||
close(c->fd);
|
||||
redisNetClose(c);
|
||||
|
||||
sdsfree(c->obuf);
|
||||
redisReaderFree(c->reader);
|
||||
@@ -680,12 +703,16 @@ void redisFree(redisContext *c) {
|
||||
free(c->unix_sock.path);
|
||||
free(c->timeout);
|
||||
free(c->saddr);
|
||||
if (c->funcs->free_privdata) {
|
||||
c->funcs->free_privdata(c->privdata);
|
||||
}
|
||||
memset(c, 0xff, sizeof(*c));
|
||||
free(c);
|
||||
}
|
||||
|
||||
int redisFreeKeepFd(redisContext *c) {
|
||||
int fd = c->fd;
|
||||
c->fd = -1;
|
||||
redisFD redisFreeKeepFd(redisContext *c) {
|
||||
redisFD fd = c->fd;
|
||||
c->fd = REDIS_INVALID_FD;
|
||||
redisFree(c);
|
||||
return fd;
|
||||
}
|
||||
@@ -694,10 +721,13 @@ int redisReconnect(redisContext *c) {
|
||||
c->err = 0;
|
||||
memset(c->errstr, '\0', strlen(c->errstr));
|
||||
|
||||
if (c->fd > 0) {
|
||||
close(c->fd);
|
||||
if (c->privdata && c->funcs->free_privdata) {
|
||||
c->funcs->free_privdata(c->privdata);
|
||||
c->privdata = NULL;
|
||||
}
|
||||
|
||||
redisNetClose(c);
|
||||
|
||||
sdsfree(c->obuf);
|
||||
redisReaderFree(c->reader);
|
||||
|
||||
@@ -718,112 +748,107 @@ int redisReconnect(redisContext *c) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
redisContext *redisConnectWithOptions(const redisOptions *options) {
|
||||
redisContext *c = redisContextInit(options);
|
||||
if (c == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(options->options & REDIS_OPT_NONBLOCK)) {
|
||||
c->flags |= REDIS_BLOCK;
|
||||
}
|
||||
if (options->options & REDIS_OPT_REUSEADDR) {
|
||||
c->flags |= REDIS_REUSEADDR;
|
||||
}
|
||||
if (options->options & REDIS_OPT_NOAUTOFREE) {
|
||||
c->flags |= REDIS_NO_AUTO_FREE;
|
||||
}
|
||||
|
||||
if (options->type == REDIS_CONN_TCP) {
|
||||
redisContextConnectBindTcp(c, options->endpoint.tcp.ip,
|
||||
options->endpoint.tcp.port, options->timeout,
|
||||
options->endpoint.tcp.source_addr);
|
||||
} else if (options->type == REDIS_CONN_UNIX) {
|
||||
redisContextConnectUnix(c, options->endpoint.unix_socket,
|
||||
options->timeout);
|
||||
} else if (options->type == REDIS_CONN_USERFD) {
|
||||
c->fd = options->endpoint.fd;
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
} else {
|
||||
// Unknown type - FIXME - FREE
|
||||
return NULL;
|
||||
}
|
||||
if (options->timeout != NULL && (c->flags & REDIS_BLOCK) && c->fd != REDIS_INVALID_FD) {
|
||||
redisContextSetTimeout(c, *options->timeout);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Connect to a Redis instance. On error the field error in the returned
|
||||
* context will be set to the return value of the error function.
|
||||
* When no set of reply functions is given, the default set will be used. */
|
||||
redisContext *redisConnect(const char *ip, int port) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags |= REDIS_BLOCK;
|
||||
redisContextConnectTcp(c,ip,port,NULL);
|
||||
return c;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, ip, port);
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags |= REDIS_BLOCK;
|
||||
redisContextConnectTcp(c,ip,port,&tv);
|
||||
return c;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, ip, port);
|
||||
options.timeout = &tv;
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisContext *redisConnectNonBlock(const char *ip, int port) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags &= ~REDIS_BLOCK;
|
||||
redisContextConnectTcp(c,ip,port,NULL);
|
||||
return c;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, ip, port);
|
||||
options.options |= REDIS_OPT_NONBLOCK;
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisContext *redisConnectBindNonBlock(const char *ip, int port,
|
||||
const char *source_addr) {
|
||||
redisContext *c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
c->flags &= ~REDIS_BLOCK;
|
||||
redisContextConnectBindTcp(c,ip,port,NULL,source_addr);
|
||||
return c;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, ip, port);
|
||||
options.endpoint.tcp.source_addr = source_addr;
|
||||
options.options |= REDIS_OPT_NONBLOCK;
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
|
||||
const char *source_addr) {
|
||||
redisContext *c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
c->flags &= ~REDIS_BLOCK;
|
||||
c->flags |= REDIS_REUSEADDR;
|
||||
redisContextConnectBindTcp(c,ip,port,NULL,source_addr);
|
||||
return c;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_TCP(&options, ip, port);
|
||||
options.endpoint.tcp.source_addr = source_addr;
|
||||
options.options |= REDIS_OPT_NONBLOCK|REDIS_OPT_REUSEADDR;
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisContext *redisConnectUnix(const char *path) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags |= REDIS_BLOCK;
|
||||
redisContextConnectUnix(c,path,NULL);
|
||||
return c;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_UNIX(&options, path);
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags |= REDIS_BLOCK;
|
||||
redisContextConnectUnix(c,path,&tv);
|
||||
return c;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_UNIX(&options, path);
|
||||
options.timeout = &tv;
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisContext *redisConnectUnixNonBlock(const char *path) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags &= ~REDIS_BLOCK;
|
||||
redisContextConnectUnix(c,path,NULL);
|
||||
return c;
|
||||
redisOptions options = {0};
|
||||
REDIS_OPTIONS_SET_UNIX(&options, path);
|
||||
options.options |= REDIS_OPT_NONBLOCK;
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
redisContext *redisConnectFd(int fd) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->fd = fd;
|
||||
c->flags |= REDIS_BLOCK | REDIS_CONNECTED;
|
||||
return c;
|
||||
redisContext *redisConnectFd(redisFD fd) {
|
||||
redisOptions options = {0};
|
||||
options.type = REDIS_CONN_USERFD;
|
||||
options.endpoint.fd = fd;
|
||||
return redisConnectWithOptions(&options);
|
||||
}
|
||||
|
||||
/* Set read/write timeout on a blocking socket. */
|
||||
@@ -853,22 +878,15 @@ int redisBufferRead(redisContext *c) {
|
||||
if (c->err)
|
||||
return REDIS_ERR;
|
||||
|
||||
nread = read(c->fd,buf,sizeof(buf));
|
||||
if (nread == -1) {
|
||||
if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
|
||||
/* Try again later */
|
||||
nread = c->funcs->read(c, buf, sizeof(buf));
|
||||
if (nread > 0) {
|
||||
if (redisReaderFeed(c->reader, buf, nread) != REDIS_OK) {
|
||||
__redisSetError(c, c->reader->err, c->reader->errstr);
|
||||
return REDIS_ERR;
|
||||
} else {
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
} else if (nread == 0) {
|
||||
__redisSetError(c,REDIS_ERR_EOF,"Server closed the connection");
|
||||
} else if (nread < 0) {
|
||||
return REDIS_ERR;
|
||||
} else {
|
||||
if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) {
|
||||
__redisSetError(c,c->reader->err,c->reader->errstr);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
@@ -883,21 +901,15 @@ int redisBufferRead(redisContext *c) {
|
||||
* c->errstr to hold the appropriate error string.
|
||||
*/
|
||||
int redisBufferWrite(redisContext *c, int *done) {
|
||||
int nwritten;
|
||||
|
||||
/* Return early when the context has seen an error. */
|
||||
if (c->err)
|
||||
return REDIS_ERR;
|
||||
|
||||
if (sdslen(c->obuf) > 0) {
|
||||
nwritten = write(c->fd,c->obuf,sdslen(c->obuf));
|
||||
if (nwritten == -1) {
|
||||
if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
|
||||
/* Try again later */
|
||||
} else {
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
int nwritten = c->funcs->write(c);
|
||||
if (nwritten < 0) {
|
||||
return REDIS_ERR;
|
||||
} else if (nwritten > 0) {
|
||||
if (nwritten == (signed)sdslen(c->obuf)) {
|
||||
sdsfree(c->obuf);
|
||||
|
||||
Vendored
+99
-4
@@ -35,7 +35,11 @@
|
||||
#define __HIREDIS_H
|
||||
#include "read.h"
|
||||
#include <stdarg.h> /* for va_list */
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/time.h> /* for struct timeval */
|
||||
#else
|
||||
struct timeval; /* forward declaration */
|
||||
#endif
|
||||
#include <stdint.h> /* uintXX_t, etc */
|
||||
#include "sds.h" /* for sds */
|
||||
|
||||
@@ -74,6 +78,12 @@
|
||||
/* Flag that is set when we should set SO_REUSEADDR before calling bind() */
|
||||
#define REDIS_REUSEADDR 0x80
|
||||
|
||||
/**
|
||||
* Flag that indicates the user does not want the context to
|
||||
* be automatically freed upon error
|
||||
*/
|
||||
#define REDIS_NO_AUTO_FREE 0x200
|
||||
|
||||
#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */
|
||||
|
||||
/* number of times we retry to connect in the case of EADDRNOTAVAIL and
|
||||
@@ -92,6 +102,8 @@ typedef struct redisReply {
|
||||
size_t len; /* Length of string */
|
||||
char *str; /* Used for REDIS_REPLY_ERROR, REDIS_REPLY_STRING
|
||||
and REDIS_REPLY_DOUBLE (in additionl to dval). */
|
||||
char vtype[4]; /* Used for REDIS_REPLY_VERB, contains the null
|
||||
terminated 3 character content type, such as "txt". */
|
||||
size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
|
||||
struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
|
||||
} redisReply;
|
||||
@@ -111,14 +123,93 @@ void redisFreeSdsCommand(sds cmd);
|
||||
|
||||
enum redisConnectionType {
|
||||
REDIS_CONN_TCP,
|
||||
REDIS_CONN_UNIX
|
||||
REDIS_CONN_UNIX,
|
||||
REDIS_CONN_USERFD
|
||||
};
|
||||
|
||||
struct redisSsl;
|
||||
|
||||
#define REDIS_OPT_NONBLOCK 0x01
|
||||
#define REDIS_OPT_REUSEADDR 0x02
|
||||
|
||||
/**
|
||||
* Don't automatically free the async object on a connection failure,
|
||||
* or other implicit conditions. Only free on an explicit call to disconnect() or free()
|
||||
*/
|
||||
#define REDIS_OPT_NOAUTOFREE 0x04
|
||||
|
||||
/* In Unix systems a file descriptor is a regular signed int, with -1
|
||||
* representing an invalid descriptor. In Windows it is a SOCKET
|
||||
* (32- or 64-bit unsigned integer depending on the architecture), where
|
||||
* all bits set (~0) is INVALID_SOCKET. */
|
||||
#ifndef _WIN32
|
||||
typedef int redisFD;
|
||||
#define REDIS_INVALID_FD -1
|
||||
#else
|
||||
#ifdef _WIN64
|
||||
typedef unsigned long long redisFD; /* SOCKET = 64-bit UINT_PTR */
|
||||
#else
|
||||
typedef unsigned long redisFD; /* SOCKET = 32-bit UINT_PTR */
|
||||
#endif
|
||||
#define REDIS_INVALID_FD ((redisFD)(~0)) /* INVALID_SOCKET */
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* the type of connection to use. This also indicates which
|
||||
* `endpoint` member field to use
|
||||
*/
|
||||
int type;
|
||||
/* bit field of REDIS_OPT_xxx */
|
||||
int options;
|
||||
/* timeout value. if NULL, no timeout is used */
|
||||
const struct timeval *timeout;
|
||||
union {
|
||||
/** use this field for tcp/ip connections */
|
||||
struct {
|
||||
const char *source_addr;
|
||||
const char *ip;
|
||||
int port;
|
||||
} tcp;
|
||||
/** use this field for unix domain sockets */
|
||||
const char *unix_socket;
|
||||
/**
|
||||
* use this field to have hiredis operate an already-open
|
||||
* file descriptor */
|
||||
redisFD fd;
|
||||
} endpoint;
|
||||
} redisOptions;
|
||||
|
||||
/**
|
||||
* Helper macros to initialize options to their specified fields.
|
||||
*/
|
||||
#define REDIS_OPTIONS_SET_TCP(opts, ip_, port_) \
|
||||
(opts)->type = REDIS_CONN_TCP; \
|
||||
(opts)->endpoint.tcp.ip = ip_; \
|
||||
(opts)->endpoint.tcp.port = port_;
|
||||
|
||||
#define REDIS_OPTIONS_SET_UNIX(opts, path) \
|
||||
(opts)->type = REDIS_CONN_UNIX; \
|
||||
(opts)->endpoint.unix_socket = path;
|
||||
|
||||
struct redisAsyncContext;
|
||||
struct redisContext;
|
||||
|
||||
typedef struct redisContextFuncs {
|
||||
void (*free_privdata)(void *);
|
||||
void (*async_read)(struct redisAsyncContext *);
|
||||
void (*async_write)(struct redisAsyncContext *);
|
||||
int (*read)(struct redisContext *, char *, size_t);
|
||||
int (*write)(struct redisContext *);
|
||||
} redisContextFuncs;
|
||||
|
||||
/* Context for a connection to Redis */
|
||||
typedef struct redisContext {
|
||||
const redisContextFuncs *funcs; /* Function table */
|
||||
|
||||
int err; /* Error flags, 0 when there is no error */
|
||||
char errstr[128]; /* String representation of error when applicable */
|
||||
int fd;
|
||||
redisFD fd;
|
||||
int flags;
|
||||
char *obuf; /* Write buffer */
|
||||
redisReader *reader; /* Protocol reader */
|
||||
@@ -139,8 +230,12 @@ typedef struct redisContext {
|
||||
/* For non-blocking connect */
|
||||
struct sockadr *saddr;
|
||||
size_t addrlen;
|
||||
|
||||
/* Additional private data for hiredis addons such as SSL */
|
||||
void *privdata;
|
||||
} redisContext;
|
||||
|
||||
redisContext *redisConnectWithOptions(const redisOptions *options);
|
||||
redisContext *redisConnect(const char *ip, int port);
|
||||
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
|
||||
redisContext *redisConnectNonBlock(const char *ip, int port);
|
||||
@@ -151,7 +246,7 @@ redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
|
||||
redisContext *redisConnectUnix(const char *path);
|
||||
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
|
||||
redisContext *redisConnectUnixNonBlock(const char *path);
|
||||
redisContext *redisConnectFd(int fd);
|
||||
redisContext *redisConnectFd(redisFD fd);
|
||||
|
||||
/**
|
||||
* Reconnect the given context using the saved information.
|
||||
@@ -167,7 +262,7 @@ int redisReconnect(redisContext *c);
|
||||
int redisSetTimeout(redisContext *c, const struct timeval tv);
|
||||
int redisEnableKeepAlive(redisContext *c);
|
||||
void redisFree(redisContext *c);
|
||||
int redisFreeKeepFd(redisContext *c);
|
||||
redisFD redisFreeKeepFd(redisContext *c);
|
||||
int redisBufferRead(redisContext *c);
|
||||
int redisBufferWrite(redisContext *c, int *done);
|
||||
|
||||
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
pkgincludedir=${includedir}/hiredis
|
||||
|
||||
Name: hiredis
|
||||
Description: Minimalistic C client library for Redis.
|
||||
Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lhiredis
|
||||
Cflags: -I${pkgincludedir} -D_FILE_OFFSET_BITS=64
|
||||
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019, Redis Labs
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __HIREDIS_SSL_H
|
||||
#define __HIREDIS_SSL_H
|
||||
|
||||
/* This is the underlying struct for SSL in ssl.h, which is not included to
|
||||
* keep build dependencies short here.
|
||||
*/
|
||||
struct ssl_st;
|
||||
|
||||
/**
|
||||
* Secure the connection using SSL. This should be done before any command is
|
||||
* executed on the connection.
|
||||
*/
|
||||
int redisSecureConnection(redisContext *c, const char *capath, const char *certpath,
|
||||
const char *keypath, const char *servername);
|
||||
|
||||
/**
|
||||
* Initiate SSL/TLS negotiation on a provided context.
|
||||
*/
|
||||
|
||||
int redisInitiateSSL(redisContext *c, struct ssl_st *ssl);
|
||||
|
||||
#endif /* __HIREDIS_SSL_H */
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
pkgincludedir=${includedir}/hiredis
|
||||
|
||||
Name: hiredis_ssl
|
||||
Description: SSL Support for hiredis.
|
||||
Version: @PROJECT_VERSION@
|
||||
Requires: hiredis
|
||||
Libs: -L${libdir} -lhiredis_ssl
|
||||
Libs.private: -lssl -lcrypto
|
||||
Vendored
+87
-35
@@ -34,36 +34,64 @@
|
||||
|
||||
#include "fmacros.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "sds.h"
|
||||
#include "sockcompat.h"
|
||||
#include "win32.h"
|
||||
|
||||
/* Defined in hiredis.c */
|
||||
void __redisSetError(redisContext *c, int type, const char *str);
|
||||
|
||||
static void redisContextCloseFd(redisContext *c) {
|
||||
if (c && c->fd >= 0) {
|
||||
void redisNetClose(redisContext *c) {
|
||||
if (c && c->fd != REDIS_INVALID_FD) {
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
c->fd = REDIS_INVALID_FD;
|
||||
}
|
||||
}
|
||||
|
||||
int redisNetRead(redisContext *c, char *buf, size_t bufcap) {
|
||||
int nread = recv(c->fd, buf, bufcap, 0);
|
||||
if (nread == -1) {
|
||||
if ((errno == EWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
|
||||
/* Try again later */
|
||||
return 0;
|
||||
} else if(errno == ETIMEDOUT && (c->flags & REDIS_BLOCK)) {
|
||||
/* especially in windows */
|
||||
__redisSetError(c, REDIS_ERR_TIMEOUT, "recv timeout");
|
||||
return -1;
|
||||
} else {
|
||||
__redisSetError(c, REDIS_ERR_IO, NULL);
|
||||
return -1;
|
||||
}
|
||||
} else if (nread == 0) {
|
||||
__redisSetError(c, REDIS_ERR_EOF, "Server closed the connection");
|
||||
return -1;
|
||||
} else {
|
||||
return nread;
|
||||
}
|
||||
}
|
||||
|
||||
int redisNetWrite(redisContext *c) {
|
||||
int nwritten = send(c->fd, c->obuf, sdslen(c->obuf), 0);
|
||||
if (nwritten < 0) {
|
||||
if ((errno == EWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
|
||||
/* Try again later */
|
||||
} else {
|
||||
__redisSetError(c, REDIS_ERR_IO, NULL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
|
||||
int errorno = errno; /* snprintf() may change errno */
|
||||
char buf[128] = { 0 };
|
||||
@@ -79,15 +107,15 @@ static int redisSetReuseAddr(redisContext *c) {
|
||||
int on = 1;
|
||||
if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static int redisCreateSocket(redisContext *c, int type) {
|
||||
int s;
|
||||
if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
|
||||
redisFD s;
|
||||
if ((s = socket(type, SOCK_STREAM, 0)) == REDIS_INVALID_FD) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
@@ -101,6 +129,7 @@ static int redisCreateSocket(redisContext *c, int type) {
|
||||
}
|
||||
|
||||
static int redisSetBlocking(redisContext *c, int blocking) {
|
||||
#ifndef _WIN32
|
||||
int flags;
|
||||
|
||||
/* Set the socket nonblocking.
|
||||
@@ -108,7 +137,7 @@ static int redisSetBlocking(redisContext *c, int blocking) {
|
||||
* interrupted by a signal. */
|
||||
if ((flags = fcntl(c->fd, F_GETFL)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
@@ -119,15 +148,23 @@ static int redisSetBlocking(redisContext *c, int blocking) {
|
||||
|
||||
if (fcntl(c->fd, F_SETFL, flags) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#else
|
||||
u_long mode = blocking ? 0 : 1;
|
||||
if (ioctl(c->fd, FIONBIO, &mode) == -1) {
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "ioctl(FIONBIO)");
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisKeepAlive(redisContext *c, int interval) {
|
||||
int val = 1;
|
||||
int fd = c->fd;
|
||||
redisFD fd = c->fd;
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
@@ -170,7 +207,7 @@ static int redisSetTcpNoDelay(redisContext *c) {
|
||||
int yes = 1;
|
||||
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
@@ -212,12 +249,12 @@ static int redisContextWaitReady(redisContext *c, long msec) {
|
||||
|
||||
if ((res = poll(wfd, 1, msec)) == -1) {
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
} else if (res == 0) {
|
||||
errno = ETIMEDOUT;
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
@@ -230,7 +267,7 @@ static int redisContextWaitReady(redisContext *c, long msec) {
|
||||
}
|
||||
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
@@ -277,11 +314,18 @@ int redisCheckSocketError(redisContext *c) {
|
||||
}
|
||||
|
||||
int redisContextSetTimeout(redisContext *c, const struct timeval tv) {
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
|
||||
const void *to_ptr = &tv;
|
||||
size_t to_sz = sizeof(tv);
|
||||
#ifdef _WIN32
|
||||
DWORD timeout_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
to_ptr = &timeout_msec;
|
||||
to_sz = sizeof(timeout_msec);
|
||||
#endif
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,to_ptr,to_sz) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,to_ptr,to_sz) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
@@ -291,7 +335,8 @@ int redisContextSetTimeout(redisContext *c, const struct timeval tv) {
|
||||
static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
||||
const struct timeval *timeout,
|
||||
const char *source_addr) {
|
||||
int s, rv, n;
|
||||
redisFD s;
|
||||
int rv, n;
|
||||
char _port[6]; /* strlen("65535"); */
|
||||
struct addrinfo hints, *servinfo, *bservinfo, *p, *b;
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
@@ -360,7 +405,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
||||
}
|
||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||
addrretry:
|
||||
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
|
||||
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == REDIS_INVALID_FD)
|
||||
continue;
|
||||
|
||||
c->fd = s;
|
||||
@@ -401,16 +446,14 @@ addrretry:
|
||||
}
|
||||
|
||||
/* For repeat connection */
|
||||
if (c->saddr) {
|
||||
free(c->saddr);
|
||||
}
|
||||
free(c->saddr);
|
||||
c->saddr = malloc(p->ai_addrlen);
|
||||
memcpy(c->saddr, p->ai_addr, p->ai_addrlen);
|
||||
c->addrlen = p->ai_addrlen;
|
||||
|
||||
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
||||
if (errno == EHOSTUNREACH) {
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
continue;
|
||||
} else if (errno == EINPROGRESS) {
|
||||
if (blocking) {
|
||||
@@ -424,7 +467,7 @@ addrretry:
|
||||
if (++reuses >= REDIS_CONNECT_RETRIES) {
|
||||
goto error;
|
||||
} else {
|
||||
redisContextCloseFd(c);
|
||||
redisNetClose(c);
|
||||
goto addrretry;
|
||||
}
|
||||
} else {
|
||||
@@ -471,8 +514,9 @@ int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
|
||||
}
|
||||
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
||||
#ifndef _WIN32
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
struct sockaddr_un sa;
|
||||
struct sockaddr_un *sa;
|
||||
long timeout_msec = -1;
|
||||
|
||||
if (redisCreateSocket(c,AF_UNIX) < 0)
|
||||
@@ -499,9 +543,11 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time
|
||||
if (redisContextTimeoutMsec(c,&timeout_msec) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
sa.sun_family = AF_UNIX;
|
||||
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
|
||||
if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
|
||||
sa = (struct sockaddr_un*)(c->saddr = malloc(sizeof(struct sockaddr_un)));
|
||||
c->addrlen = sizeof(struct sockaddr_un);
|
||||
sa->sun_family = AF_UNIX;
|
||||
strncpy(sa->sun_path, path, sizeof(sa->sun_path) - 1);
|
||||
if (connect(c->fd, (struct sockaddr*)sa, sizeof(*sa)) == -1) {
|
||||
if (errno == EINPROGRESS && !blocking) {
|
||||
/* This is ok. */
|
||||
} else {
|
||||
@@ -516,4 +562,10 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time
|
||||
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
return REDIS_OK;
|
||||
#else
|
||||
/* We currently do not support Unix sockets for Windows. */
|
||||
/* TODO(m): https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ */
|
||||
errno = EPROTONOSUPPORT;
|
||||
return REDIS_ERR;
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
Vendored
+4
@@ -37,6 +37,10 @@
|
||||
|
||||
#include "hiredis.h"
|
||||
|
||||
void redisNetClose(redisContext *c);
|
||||
int redisNetRead(redisContext *c, char *buf, size_t bufcap);
|
||||
int redisNetWrite(redisContext *c);
|
||||
|
||||
int redisCheckSocketError(redisContext *c);
|
||||
int redisContextSetTimeout(redisContext *c, const struct timeval tv);
|
||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);
|
||||
|
||||
Vendored
+22
-6
@@ -31,10 +31,10 @@
|
||||
|
||||
#include "fmacros.h"
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include "read.h"
|
||||
#include "sds.h"
|
||||
#include "win32.h"
|
||||
|
||||
static void __redisReaderSetError(redisReader *r, int type, const char *str) {
|
||||
size_t len;
|
||||
@@ -294,9 +295,9 @@ static int processLineItem(redisReader *r) {
|
||||
buf[len] = '\0';
|
||||
|
||||
if (strcasecmp(buf,",inf") == 0) {
|
||||
d = 1.0/0.0; /* Positive infinite. */
|
||||
d = INFINITY; /* Positive infinite. */
|
||||
} else if (strcasecmp(buf,",-inf") == 0) {
|
||||
d = -1.0/0.0; /* Nevative infinite. */
|
||||
d = -INFINITY; /* Nevative infinite. */
|
||||
} else {
|
||||
d = strtod((char*)buf,&eptr);
|
||||
if (buf[0] == '\0' || eptr[0] != '\0' || isnan(d)) {
|
||||
@@ -379,10 +380,18 @@ static int processBulkItem(redisReader *r) {
|
||||
/* Only continue when the buffer contains the entire bulk item. */
|
||||
bytelen += len+2; /* include \r\n */
|
||||
if (r->pos+bytelen <= r->len) {
|
||||
if ((cur->type == REDIS_REPLY_VERB && len < 4) ||
|
||||
(cur->type == REDIS_REPLY_VERB && s[5] != ':'))
|
||||
{
|
||||
__redisReaderSetError(r,REDIS_ERR_PROTOCOL,
|
||||
"Verbatim string 4 bytes of content type are "
|
||||
"missing or incorrectly encoded.");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
if (r->fn && r->fn->createString)
|
||||
obj = r->fn->createString(cur,s+2,len);
|
||||
else
|
||||
obj = (void*)REDIS_REPLY_STRING;
|
||||
obj = (void*)(long)cur->type;
|
||||
success = 1;
|
||||
}
|
||||
}
|
||||
@@ -430,7 +439,7 @@ static int processAggregateItem(redisReader *r) {
|
||||
|
||||
root = (r->ridx == 0);
|
||||
|
||||
if (elements < -1 || elements > INT_MAX) {
|
||||
if (elements < -1 || (LLONG_MAX > SIZE_MAX && elements > SIZE_MAX)) {
|
||||
__redisReaderSetError(r,REDIS_ERR_PROTOCOL,
|
||||
"Multi-bulk length out of range");
|
||||
return REDIS_ERR;
|
||||
@@ -523,6 +532,9 @@ static int processItem(redisReader *r) {
|
||||
case '#':
|
||||
cur->type = REDIS_REPLY_BOOL;
|
||||
break;
|
||||
case '=':
|
||||
cur->type = REDIS_REPLY_VERB;
|
||||
break;
|
||||
default:
|
||||
__redisReaderSetErrorProtocolByte(r,*p);
|
||||
return REDIS_ERR;
|
||||
@@ -543,6 +555,7 @@ static int processItem(redisReader *r) {
|
||||
case REDIS_REPLY_BOOL:
|
||||
return processLineItem(r);
|
||||
case REDIS_REPLY_STRING:
|
||||
case REDIS_REPLY_VERB:
|
||||
return processBulkItem(r);
|
||||
case REDIS_REPLY_ARRAY:
|
||||
case REDIS_REPLY_MAP:
|
||||
@@ -657,8 +670,11 @@ int redisReaderGetReply(redisReader *r, void **reply) {
|
||||
|
||||
/* Emit a reply when there is one. */
|
||||
if (r->ridx == -1) {
|
||||
if (reply != NULL)
|
||||
if (reply != NULL) {
|
||||
*reply = r->reply;
|
||||
} else if (r->reply != NULL && r->fn && r->fn->freeObject) {
|
||||
r->fn->freeObject(r->reply);
|
||||
}
|
||||
r->reply = NULL;
|
||||
}
|
||||
return REDIS_OK;
|
||||
|
||||
Vendored
+3
-2
@@ -45,6 +45,7 @@
|
||||
#define REDIS_ERR_EOF 3 /* End of file */
|
||||
#define REDIS_ERR_PROTOCOL 4 /* Protocol error */
|
||||
#define REDIS_ERR_OOM 5 /* Out of memory */
|
||||
#define REDIS_ERR_TIMEOUT 6 /* Timed out */
|
||||
#define REDIS_ERR_OTHER 2 /* Everything else... */
|
||||
|
||||
#define REDIS_REPLY_STRING 1
|
||||
@@ -55,12 +56,12 @@
|
||||
#define REDIS_REPLY_ERROR 6
|
||||
#define REDIS_REPLY_DOUBLE 7
|
||||
#define REDIS_REPLY_BOOL 8
|
||||
#define REDIS_REPLY_VERB 9
|
||||
#define REDIS_REPLY_MAP 9
|
||||
#define REDIS_REPLY_SET 10
|
||||
#define REDIS_REPLY_ATTR 11
|
||||
#define REDIS_REPLY_PUSH 12
|
||||
#define REDIS_REPLY_BIGNUM 13
|
||||
#define REDIS_REPLY_VERB 14
|
||||
|
||||
#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */
|
||||
|
||||
@@ -79,7 +80,7 @@ typedef struct redisReadTask {
|
||||
|
||||
typedef struct redisReplyObjectFunctions {
|
||||
void *(*createString)(const redisReadTask*, char*, size_t);
|
||||
void *(*createArray)(const redisReadTask*, int);
|
||||
void *(*createArray)(const redisReadTask*, size_t);
|
||||
void *(*createInteger)(const redisReadTask*, long long);
|
||||
void *(*createDouble)(const redisReadTask*, double, char*, size_t);
|
||||
void *(*createNil)(const redisReadTask*);
|
||||
|
||||
Vendored
+1
-1
@@ -1035,7 +1035,7 @@ sds *sdssplitargs(const char *line, int *argc) {
|
||||
s_free(vector);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
vector = new_vector;
|
||||
vector[*argc] = current;
|
||||
(*argc)++;
|
||||
|
||||
Vendored
+17
-14
@@ -34,6 +34,9 @@
|
||||
#define __SDS_H
|
||||
|
||||
#define SDS_MAX_PREALLOC (1024*1024)
|
||||
#ifdef _MSC_VER
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
@@ -143,20 +146,20 @@ static inline void sdssetlen(sds s, size_t newlen) {
|
||||
case SDS_TYPE_5:
|
||||
{
|
||||
unsigned char *fp = ((unsigned char*)s)-1;
|
||||
*fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);
|
||||
*fp = (unsigned char)(SDS_TYPE_5 | (newlen << SDS_TYPE_BITS));
|
||||
}
|
||||
break;
|
||||
case SDS_TYPE_8:
|
||||
SDS_HDR(8,s)->len = newlen;
|
||||
SDS_HDR(8,s)->len = (uint8_t)newlen;
|
||||
break;
|
||||
case SDS_TYPE_16:
|
||||
SDS_HDR(16,s)->len = newlen;
|
||||
SDS_HDR(16,s)->len = (uint16_t)newlen;
|
||||
break;
|
||||
case SDS_TYPE_32:
|
||||
SDS_HDR(32,s)->len = newlen;
|
||||
SDS_HDR(32,s)->len = (uint32_t)newlen;
|
||||
break;
|
||||
case SDS_TYPE_64:
|
||||
SDS_HDR(64,s)->len = newlen;
|
||||
SDS_HDR(64,s)->len = (uint64_t)newlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -167,21 +170,21 @@ static inline void sdsinclen(sds s, size_t inc) {
|
||||
case SDS_TYPE_5:
|
||||
{
|
||||
unsigned char *fp = ((unsigned char*)s)-1;
|
||||
unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc;
|
||||
unsigned char newlen = SDS_TYPE_5_LEN(flags)+(unsigned char)inc;
|
||||
*fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);
|
||||
}
|
||||
break;
|
||||
case SDS_TYPE_8:
|
||||
SDS_HDR(8,s)->len += inc;
|
||||
SDS_HDR(8,s)->len += (uint8_t)inc;
|
||||
break;
|
||||
case SDS_TYPE_16:
|
||||
SDS_HDR(16,s)->len += inc;
|
||||
SDS_HDR(16,s)->len += (uint16_t)inc;
|
||||
break;
|
||||
case SDS_TYPE_32:
|
||||
SDS_HDR(32,s)->len += inc;
|
||||
SDS_HDR(32,s)->len += (uint32_t)inc;
|
||||
break;
|
||||
case SDS_TYPE_64:
|
||||
SDS_HDR(64,s)->len += inc;
|
||||
SDS_HDR(64,s)->len += (uint64_t)inc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -211,16 +214,16 @@ static inline void sdssetalloc(sds s, size_t newlen) {
|
||||
/* Nothing to do, this type has no total allocation info. */
|
||||
break;
|
||||
case SDS_TYPE_8:
|
||||
SDS_HDR(8,s)->alloc = newlen;
|
||||
SDS_HDR(8,s)->alloc = (uint8_t)newlen;
|
||||
break;
|
||||
case SDS_TYPE_16:
|
||||
SDS_HDR(16,s)->alloc = newlen;
|
||||
SDS_HDR(16,s)->alloc = (uint16_t)newlen;
|
||||
break;
|
||||
case SDS_TYPE_32:
|
||||
SDS_HDR(32,s)->alloc = newlen;
|
||||
SDS_HDR(32,s)->alloc = (uint32_t)newlen;
|
||||
break;
|
||||
case SDS_TYPE_64:
|
||||
SDS_HDR(64,s)->alloc = newlen;
|
||||
SDS_HDR(64,s)->alloc = (uint64_t)newlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+248
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Marcus Geelnard <m at bitsnbites dot eu>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define REDIS_SOCKCOMPAT_IMPLEMENTATION
|
||||
#include "sockcompat.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
static int _wsaErrorToErrno(int err) {
|
||||
switch (err) {
|
||||
case WSAEWOULDBLOCK:
|
||||
return EWOULDBLOCK;
|
||||
case WSAEINPROGRESS:
|
||||
return EINPROGRESS;
|
||||
case WSAEALREADY:
|
||||
return EALREADY;
|
||||
case WSAENOTSOCK:
|
||||
return ENOTSOCK;
|
||||
case WSAEDESTADDRREQ:
|
||||
return EDESTADDRREQ;
|
||||
case WSAEMSGSIZE:
|
||||
return EMSGSIZE;
|
||||
case WSAEPROTOTYPE:
|
||||
return EPROTOTYPE;
|
||||
case WSAENOPROTOOPT:
|
||||
return ENOPROTOOPT;
|
||||
case WSAEPROTONOSUPPORT:
|
||||
return EPROTONOSUPPORT;
|
||||
case WSAEOPNOTSUPP:
|
||||
return EOPNOTSUPP;
|
||||
case WSAEAFNOSUPPORT:
|
||||
return EAFNOSUPPORT;
|
||||
case WSAEADDRINUSE:
|
||||
return EADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL:
|
||||
return EADDRNOTAVAIL;
|
||||
case WSAENETDOWN:
|
||||
return ENETDOWN;
|
||||
case WSAENETUNREACH:
|
||||
return ENETUNREACH;
|
||||
case WSAENETRESET:
|
||||
return ENETRESET;
|
||||
case WSAECONNABORTED:
|
||||
return ECONNABORTED;
|
||||
case WSAECONNRESET:
|
||||
return ECONNRESET;
|
||||
case WSAENOBUFS:
|
||||
return ENOBUFS;
|
||||
case WSAEISCONN:
|
||||
return EISCONN;
|
||||
case WSAENOTCONN:
|
||||
return ENOTCONN;
|
||||
case WSAETIMEDOUT:
|
||||
return ETIMEDOUT;
|
||||
case WSAECONNREFUSED:
|
||||
return ECONNREFUSED;
|
||||
case WSAELOOP:
|
||||
return ELOOP;
|
||||
case WSAENAMETOOLONG:
|
||||
return ENAMETOOLONG;
|
||||
case WSAEHOSTUNREACH:
|
||||
return EHOSTUNREACH;
|
||||
case WSAENOTEMPTY:
|
||||
return ENOTEMPTY;
|
||||
default:
|
||||
/* We just return a generic I/O error if we could not find a relevant error. */
|
||||
return EIO;
|
||||
}
|
||||
}
|
||||
|
||||
static void _updateErrno(int success) {
|
||||
errno = success ? 0 : _wsaErrorToErrno(WSAGetLastError());
|
||||
}
|
||||
|
||||
static int _initWinsock() {
|
||||
static int s_initialized = 0;
|
||||
if (!s_initialized) {
|
||||
static WSADATA wsadata;
|
||||
int err = WSAStartup(MAKEWORD(2,2), &wsadata);
|
||||
if (err != 0) {
|
||||
errno = _wsaErrorToErrno(err);
|
||||
return 0;
|
||||
}
|
||||
s_initialized = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int win32_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
|
||||
/* Note: This function is likely to be called before other functions, so run init here. */
|
||||
if (!_initWinsock()) {
|
||||
return EAI_FAIL;
|
||||
}
|
||||
|
||||
switch (getaddrinfo(node, service, hints, res)) {
|
||||
case 0: return 0;
|
||||
case WSATRY_AGAIN: return EAI_AGAIN;
|
||||
case WSAEINVAL: return EAI_BADFLAGS;
|
||||
case WSAEAFNOSUPPORT: return EAI_FAMILY;
|
||||
case WSA_NOT_ENOUGH_MEMORY: return EAI_MEMORY;
|
||||
case WSAHOST_NOT_FOUND: return EAI_NONAME;
|
||||
case WSATYPE_NOT_FOUND: return EAI_SERVICE;
|
||||
case WSAESOCKTNOSUPPORT: return EAI_SOCKTYPE;
|
||||
default: return EAI_FAIL; /* Including WSANO_RECOVERY */
|
||||
}
|
||||
}
|
||||
|
||||
const char *win32_gai_strerror(int errcode) {
|
||||
switch (errcode) {
|
||||
case 0: errcode = 0; break;
|
||||
case EAI_AGAIN: errcode = WSATRY_AGAIN; break;
|
||||
case EAI_BADFLAGS: errcode = WSAEINVAL; break;
|
||||
case EAI_FAMILY: errcode = WSAEAFNOSUPPORT; break;
|
||||
case EAI_MEMORY: errcode = WSA_NOT_ENOUGH_MEMORY; break;
|
||||
case EAI_NONAME: errcode = WSAHOST_NOT_FOUND; break;
|
||||
case EAI_SERVICE: errcode = WSATYPE_NOT_FOUND; break;
|
||||
case EAI_SOCKTYPE: errcode = WSAESOCKTNOSUPPORT; break;
|
||||
default: errcode = WSANO_RECOVERY; break; /* Including EAI_FAIL */
|
||||
}
|
||||
return gai_strerror(errcode);
|
||||
}
|
||||
|
||||
void win32_freeaddrinfo(struct addrinfo *res) {
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
||||
SOCKET win32_socket(int domain, int type, int protocol) {
|
||||
SOCKET s;
|
||||
|
||||
/* Note: This function is likely to be called before other functions, so run init here. */
|
||||
if (!_initWinsock()) {
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
_updateErrno((s = socket(domain, type, protocol)) != INVALID_SOCKET);
|
||||
return s;
|
||||
}
|
||||
|
||||
int win32_ioctl(SOCKET fd, unsigned long request, unsigned long *argp) {
|
||||
int ret = ioctlsocket(fd, (long)request, argp);
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
|
||||
int win32_bind(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
int ret = bind(sockfd, addr, addrlen);
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
|
||||
int win32_connect(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
int ret = connect(sockfd, addr, addrlen);
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
|
||||
/* For Winsock connect(), the WSAEWOULDBLOCK error means the same thing as
|
||||
* EINPROGRESS for POSIX connect(), so we do that translation to keep POSIX
|
||||
* logic consistent. */
|
||||
if (errno == EWOULDBLOCK) {
|
||||
errno = EINPROGRESS;
|
||||
}
|
||||
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
|
||||
int win32_getsockopt(SOCKET sockfd, int level, int optname, void *optval, socklen_t *optlen) {
|
||||
int ret = 0;
|
||||
if ((level == SOL_SOCKET) && ((optname == SO_RCVTIMEO) || (optname == SO_SNDTIMEO))) {
|
||||
if (*optlen >= sizeof (struct timeval)) {
|
||||
struct timeval *tv = optval;
|
||||
DWORD timeout = 0;
|
||||
socklen_t dwlen = 0;
|
||||
ret = getsockopt(sockfd, level, optname, (char *)&timeout, &dwlen);
|
||||
tv->tv_sec = timeout / 1000;
|
||||
tv->tv_usec = (timeout * 1000) % 1000000;
|
||||
} else {
|
||||
ret = WSAEFAULT;
|
||||
}
|
||||
*optlen = sizeof (struct timeval);
|
||||
} else {
|
||||
ret = getsockopt(sockfd, level, optname, (char*)optval, optlen);
|
||||
}
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
|
||||
int win32_setsockopt(SOCKET sockfd, int level, int optname, const void *optval, socklen_t optlen) {
|
||||
int ret = 0;
|
||||
if ((level == SOL_SOCKET) && ((optname == SO_RCVTIMEO) || (optname == SO_SNDTIMEO))) {
|
||||
struct timeval *tv = optval;
|
||||
DWORD timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;
|
||||
ret = setsockopt(sockfd, level, optname, (const char*)&timeout, sizeof(DWORD));
|
||||
} else {
|
||||
ret = setsockopt(sockfd, level, optname, (const char*)optval, optlen);
|
||||
}
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
|
||||
int win32_close(SOCKET fd) {
|
||||
int ret = closesocket(fd);
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
|
||||
ssize_t win32_recv(SOCKET sockfd, void *buf, size_t len, int flags) {
|
||||
int ret = recv(sockfd, (char*)buf, (int)len, flags);
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
|
||||
ssize_t win32_send(SOCKET sockfd, const void *buf, size_t len, int flags) {
|
||||
int ret = send(sockfd, (const char*)buf, (int)len, flags);
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
|
||||
int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
|
||||
int ret = WSAPoll(fds, nfds, timeout);
|
||||
_updateErrno(ret != SOCKET_ERROR);
|
||||
return ret != SOCKET_ERROR ? ret : -1;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
Vendored
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Marcus Geelnard <m at bitsnbites dot eu>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __SOCKCOMPAT_H
|
||||
#define __SOCKCOMPAT_H
|
||||
|
||||
#ifndef _WIN32
|
||||
/* For POSIX systems we use the standard BSD socket API. */
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <poll.h>
|
||||
#else
|
||||
/* For Windows we use winsock. */
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600 /* To get WSAPoll etc. */
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef signed long ssize_t;
|
||||
#endif
|
||||
|
||||
/* Emulate the parts of the BSD socket API that we need (override the winsock signatures). */
|
||||
int win32_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
|
||||
const char *win32_gai_strerror(int errcode);
|
||||
void win32_freeaddrinfo(struct addrinfo *res);
|
||||
SOCKET win32_socket(int domain, int type, int protocol);
|
||||
int win32_ioctl(SOCKET fd, unsigned long request, unsigned long *argp);
|
||||
int win32_bind(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int win32_connect(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int win32_getsockopt(SOCKET sockfd, int level, int optname, void *optval, socklen_t *optlen);
|
||||
int win32_setsockopt(SOCKET sockfd, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int win32_close(SOCKET fd);
|
||||
ssize_t win32_recv(SOCKET sockfd, void *buf, size_t len, int flags);
|
||||
ssize_t win32_send(SOCKET sockfd, const void *buf, size_t len, int flags);
|
||||
typedef ULONG nfds_t;
|
||||
int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout);
|
||||
|
||||
#ifndef REDIS_SOCKCOMPAT_IMPLEMENTATION
|
||||
#define getaddrinfo(node, service, hints, res) win32_getaddrinfo(node, service, hints, res)
|
||||
#undef gai_strerror
|
||||
#define gai_strerror(errcode) win32_gai_strerror(errcode)
|
||||
#define freeaddrinfo(res) win32_freeaddrinfo(res)
|
||||
#define socket(domain, type, protocol) win32_socket(domain, type, protocol)
|
||||
#define ioctl(fd, request, argp) win32_ioctl(fd, request, argp)
|
||||
#define bind(sockfd, addr, addrlen) win32_bind(sockfd, addr, addrlen)
|
||||
#define connect(sockfd, addr, addrlen) win32_connect(sockfd, addr, addrlen)
|
||||
#define getsockopt(sockfd, level, optname, optval, optlen) win32_getsockopt(sockfd, level, optname, optval, optlen)
|
||||
#define setsockopt(sockfd, level, optname, optval, optlen) win32_setsockopt(sockfd, level, optname, optval, optlen)
|
||||
#define close(fd) win32_close(fd)
|
||||
#define recv(sockfd, buf, len, flags) win32_recv(sockfd, buf, len, flags)
|
||||
#define send(sockfd, buf, len, flags) win32_send(sockfd, buf, len, flags)
|
||||
#define poll(fds, nfds, timeout) win32_poll(fds, nfds, timeout)
|
||||
#endif /* REDIS_SOCKCOMPAT_IMPLEMENTATION */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* __SOCKCOMPAT_H */
|
||||
Vendored
+448
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
* Copyright (c) 2019, Redis Labs
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "hiredis.h"
|
||||
#include "async.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "async_private.h"
|
||||
|
||||
void __redisSetError(redisContext *c, int type, const char *str);
|
||||
|
||||
/* The SSL context is attached to SSL/TLS connections as a privdata. */
|
||||
typedef struct redisSSLContext {
|
||||
/**
|
||||
* OpenSSL SSL_CTX; It is optional and will not be set when using
|
||||
* user-supplied SSL.
|
||||
*/
|
||||
SSL_CTX *ssl_ctx;
|
||||
|
||||
/**
|
||||
* OpenSSL SSL object.
|
||||
*/
|
||||
SSL *ssl;
|
||||
|
||||
/**
|
||||
* SSL_write() requires to be called again with the same arguments it was
|
||||
* previously called with in the event of an SSL_read/SSL_write situation
|
||||
*/
|
||||
size_t lastLen;
|
||||
|
||||
/** Whether the SSL layer requires read (possibly before a write) */
|
||||
int wantRead;
|
||||
|
||||
/**
|
||||
* Whether a write was requested prior to a read. If set, the write()
|
||||
* should resume whenever a read takes place, if possible
|
||||
*/
|
||||
int pendingWrite;
|
||||
} redisSSLContext;
|
||||
|
||||
/* Forward declaration */
|
||||
redisContextFuncs redisContextSSLFuncs;
|
||||
|
||||
#ifdef HIREDIS_SSL_TRACE
|
||||
/**
|
||||
* Callback used for debugging
|
||||
*/
|
||||
static void sslLogCallback(const SSL *ssl, int where, int ret) {
|
||||
const char *retstr = "";
|
||||
int should_log = 1;
|
||||
/* Ignore low-level SSL stuff */
|
||||
|
||||
if (where & SSL_CB_ALERT) {
|
||||
should_log = 1;
|
||||
}
|
||||
if (where == SSL_CB_HANDSHAKE_START || where == SSL_CB_HANDSHAKE_DONE) {
|
||||
should_log = 1;
|
||||
}
|
||||
if ((where & SSL_CB_EXIT) && ret == 0) {
|
||||
should_log = 1;
|
||||
}
|
||||
|
||||
if (!should_log) {
|
||||
return;
|
||||
}
|
||||
|
||||
retstr = SSL_alert_type_string(ret);
|
||||
printf("ST(0x%x). %s. R(0x%x)%s\n", where, SSL_state_string_long(ssl), ret, retstr);
|
||||
|
||||
if (where == SSL_CB_HANDSHAKE_DONE) {
|
||||
printf("Using SSL version %s. Cipher=%s\n", SSL_get_version(ssl), SSL_get_cipher_name(ssl));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* OpenSSL global initialization and locking handling callbacks.
|
||||
* Note that this is only required for OpenSSL < 1.1.0.
|
||||
*/
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
#define HIREDIS_USE_CRYPTO_LOCKS
|
||||
#endif
|
||||
|
||||
#ifdef HIREDIS_USE_CRYPTO_LOCKS
|
||||
typedef pthread_mutex_t sslLockType;
|
||||
static void sslLockInit(sslLockType *l) {
|
||||
pthread_mutex_init(l, NULL);
|
||||
}
|
||||
static void sslLockAcquire(sslLockType *l) {
|
||||
pthread_mutex_lock(l);
|
||||
}
|
||||
static void sslLockRelease(sslLockType *l) {
|
||||
pthread_mutex_unlock(l);
|
||||
}
|
||||
static pthread_mutex_t *ossl_locks;
|
||||
|
||||
static void opensslDoLock(int mode, int lkid, const char *f, int line) {
|
||||
sslLockType *l = ossl_locks + lkid;
|
||||
|
||||
if (mode & CRYPTO_LOCK) {
|
||||
sslLockAcquire(l);
|
||||
} else {
|
||||
sslLockRelease(l);
|
||||
}
|
||||
|
||||
(void)f;
|
||||
(void)line;
|
||||
}
|
||||
|
||||
static void initOpensslLocks(void) {
|
||||
unsigned ii, nlocks;
|
||||
if (CRYPTO_get_locking_callback() != NULL) {
|
||||
/* Someone already set the callback before us. Don't destroy it! */
|
||||
return;
|
||||
}
|
||||
nlocks = CRYPTO_num_locks();
|
||||
ossl_locks = malloc(sizeof(*ossl_locks) * nlocks);
|
||||
for (ii = 0; ii < nlocks; ii++) {
|
||||
sslLockInit(ossl_locks + ii);
|
||||
}
|
||||
CRYPTO_set_locking_callback(opensslDoLock);
|
||||
}
|
||||
#endif /* HIREDIS_USE_CRYPTO_LOCKS */
|
||||
|
||||
/**
|
||||
* SSL Connection initialization.
|
||||
*/
|
||||
|
||||
static int redisSSLConnect(redisContext *c, SSL_CTX *ssl_ctx, SSL *ssl) {
|
||||
if (c->privdata) {
|
||||
__redisSetError(c, REDIS_ERR_OTHER, "redisContext was already associated");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
c->privdata = calloc(1, sizeof(redisSSLContext));
|
||||
|
||||
c->funcs = &redisContextSSLFuncs;
|
||||
redisSSLContext *rssl = c->privdata;
|
||||
|
||||
rssl->ssl_ctx = ssl_ctx;
|
||||
rssl->ssl = ssl;
|
||||
|
||||
SSL_set_mode(rssl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
SSL_set_fd(rssl->ssl, c->fd);
|
||||
SSL_set_connect_state(rssl->ssl);
|
||||
|
||||
ERR_clear_error();
|
||||
int rv = SSL_connect(rssl->ssl);
|
||||
if (rv == 1) {
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
rv = SSL_get_error(rssl->ssl, rv);
|
||||
if (((c->flags & REDIS_BLOCK) == 0) &&
|
||||
(rv == SSL_ERROR_WANT_READ || rv == SSL_ERROR_WANT_WRITE)) {
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
if (c->err == 0) {
|
||||
char err[512];
|
||||
if (rv == SSL_ERROR_SYSCALL)
|
||||
snprintf(err,sizeof(err)-1,"SSL_connect failed: %s",strerror(errno));
|
||||
else {
|
||||
unsigned long e = ERR_peek_last_error();
|
||||
snprintf(err,sizeof(err)-1,"SSL_connect failed: %s",
|
||||
ERR_reason_error_string(e));
|
||||
}
|
||||
__redisSetError(c, REDIS_ERR_IO, err);
|
||||
}
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
int redisInitiateSSL(redisContext *c, SSL *ssl) {
|
||||
return redisSSLConnect(c, NULL, ssl);
|
||||
}
|
||||
|
||||
int redisSecureConnection(redisContext *c, const char *capath,
|
||||
const char *certpath, const char *keypath, const char *servername) {
|
||||
|
||||
SSL_CTX *ssl_ctx = NULL;
|
||||
SSL *ssl = NULL;
|
||||
|
||||
/* Initialize global OpenSSL stuff */
|
||||
static int isInit = 0;
|
||||
if (!isInit) {
|
||||
isInit = 1;
|
||||
SSL_library_init();
|
||||
#ifdef HIREDIS_USE_CRYPTO_LOCKS
|
||||
initOpensslLocks();
|
||||
#endif
|
||||
}
|
||||
|
||||
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
if (!ssl_ctx) {
|
||||
__redisSetError(c, REDIS_ERR_OTHER, "Failed to create SSL_CTX");
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef HIREDIS_SSL_TRACE
|
||||
SSL_CTX_set_info_callback(ssl_ctx, sslLogCallback);
|
||||
#endif
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
||||
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
|
||||
if ((certpath != NULL && keypath == NULL) || (keypath != NULL && certpath == NULL)) {
|
||||
__redisSetError(c, REDIS_ERR_OTHER, "certpath and keypath must be specified together");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (capath) {
|
||||
if (!SSL_CTX_load_verify_locations(ssl_ctx, capath, NULL)) {
|
||||
__redisSetError(c, REDIS_ERR_OTHER, "Invalid CA certificate");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (certpath) {
|
||||
if (!SSL_CTX_use_certificate_chain_file(ssl_ctx, certpath)) {
|
||||
__redisSetError(c, REDIS_ERR_OTHER, "Invalid client certificate");
|
||||
goto error;
|
||||
}
|
||||
if (!SSL_CTX_use_PrivateKey_file(ssl_ctx, keypath, SSL_FILETYPE_PEM)) {
|
||||
__redisSetError(c, REDIS_ERR_OTHER, "Invalid client key");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ssl = SSL_new(ssl_ctx);
|
||||
if (!ssl) {
|
||||
__redisSetError(c, REDIS_ERR_OTHER, "Couldn't create new SSL instance");
|
||||
goto error;
|
||||
}
|
||||
if (servername) {
|
||||
if (!SSL_set_tlsext_host_name(ssl, servername)) {
|
||||
__redisSetError(c, REDIS_ERR_OTHER, "Couldn't set server name indication");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return redisSSLConnect(c, ssl_ctx, ssl);
|
||||
|
||||
error:
|
||||
if (ssl) SSL_free(ssl);
|
||||
if (ssl_ctx) SSL_CTX_free(ssl_ctx);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
static int maybeCheckWant(redisSSLContext *rssl, int rv) {
|
||||
/**
|
||||
* If the error is WANT_READ or WANT_WRITE, the appropriate flags are set
|
||||
* and true is returned. False is returned otherwise
|
||||
*/
|
||||
if (rv == SSL_ERROR_WANT_READ) {
|
||||
rssl->wantRead = 1;
|
||||
return 1;
|
||||
} else if (rv == SSL_ERROR_WANT_WRITE) {
|
||||
rssl->pendingWrite = 1;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of redisContextFuncs for SSL connections.
|
||||
*/
|
||||
|
||||
static void redisSSLFreeContext(void *privdata){
|
||||
redisSSLContext *rsc = privdata;
|
||||
|
||||
if (!rsc) return;
|
||||
if (rsc->ssl) {
|
||||
SSL_free(rsc->ssl);
|
||||
rsc->ssl = NULL;
|
||||
}
|
||||
if (rsc->ssl_ctx) {
|
||||
SSL_CTX_free(rsc->ssl_ctx);
|
||||
rsc->ssl_ctx = NULL;
|
||||
}
|
||||
free(rsc);
|
||||
}
|
||||
|
||||
static int redisSSLRead(redisContext *c, char *buf, size_t bufcap) {
|
||||
redisSSLContext *rssl = c->privdata;
|
||||
|
||||
int nread = SSL_read(rssl->ssl, buf, bufcap);
|
||||
if (nread > 0) {
|
||||
return nread;
|
||||
} else if (nread == 0) {
|
||||
__redisSetError(c, REDIS_ERR_EOF, "Server closed the connection");
|
||||
return -1;
|
||||
} else {
|
||||
int err = SSL_get_error(rssl->ssl, nread);
|
||||
if (c->flags & REDIS_BLOCK) {
|
||||
/**
|
||||
* In blocking mode, we should never end up in a situation where
|
||||
* we get an error without it being an actual error, except
|
||||
* in the case of EINTR, which can be spuriously received from
|
||||
* debuggers or whatever.
|
||||
*/
|
||||
if (errno == EINTR) {
|
||||
return 0;
|
||||
} else {
|
||||
const char *msg = NULL;
|
||||
if (errno == EAGAIN) {
|
||||
msg = "Resource temporarily unavailable";
|
||||
}
|
||||
__redisSetError(c, REDIS_ERR_IO, msg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We can very well get an EWOULDBLOCK/EAGAIN, however
|
||||
*/
|
||||
if (maybeCheckWant(rssl, err)) {
|
||||
return 0;
|
||||
} else {
|
||||
__redisSetError(c, REDIS_ERR_IO, NULL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int redisSSLWrite(redisContext *c) {
|
||||
redisSSLContext *rssl = c->privdata;
|
||||
|
||||
size_t len = rssl->lastLen ? rssl->lastLen : sdslen(c->obuf);
|
||||
int rv = SSL_write(rssl->ssl, c->obuf, len);
|
||||
|
||||
if (rv > 0) {
|
||||
rssl->lastLen = 0;
|
||||
} else if (rv < 0) {
|
||||
rssl->lastLen = len;
|
||||
|
||||
int err = SSL_get_error(rssl->ssl, rv);
|
||||
if ((c->flags & REDIS_BLOCK) == 0 && maybeCheckWant(rssl, err)) {
|
||||
return 0;
|
||||
} else {
|
||||
__redisSetError(c, REDIS_ERR_IO, NULL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void redisSSLAsyncRead(redisAsyncContext *ac) {
|
||||
int rv;
|
||||
redisSSLContext *rssl = ac->c.privdata;
|
||||
redisContext *c = &ac->c;
|
||||
|
||||
rssl->wantRead = 0;
|
||||
|
||||
if (rssl->pendingWrite) {
|
||||
int done;
|
||||
|
||||
/* This is probably just a write event */
|
||||
rssl->pendingWrite = 0;
|
||||
rv = redisBufferWrite(c, &done);
|
||||
if (rv == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
return;
|
||||
} else if (!done) {
|
||||
_EL_ADD_WRITE(ac);
|
||||
}
|
||||
}
|
||||
|
||||
rv = redisBufferRead(c);
|
||||
if (rv == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
} else {
|
||||
_EL_ADD_READ(ac);
|
||||
redisProcessCallbacks(ac);
|
||||
}
|
||||
}
|
||||
|
||||
static void redisSSLAsyncWrite(redisAsyncContext *ac) {
|
||||
int rv, done = 0;
|
||||
redisSSLContext *rssl = ac->c.privdata;
|
||||
redisContext *c = &ac->c;
|
||||
|
||||
rssl->pendingWrite = 0;
|
||||
rv = redisBufferWrite(c, &done);
|
||||
if (rv == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
if (rssl->wantRead) {
|
||||
/* Need to read-before-write */
|
||||
rssl->pendingWrite = 1;
|
||||
_EL_DEL_WRITE(ac);
|
||||
} else {
|
||||
/* No extra reads needed, just need to write more */
|
||||
_EL_ADD_WRITE(ac);
|
||||
}
|
||||
} else {
|
||||
/* Already done! */
|
||||
_EL_DEL_WRITE(ac);
|
||||
}
|
||||
|
||||
/* Always reschedule a read */
|
||||
_EL_ADD_READ(ac);
|
||||
}
|
||||
|
||||
redisContextFuncs redisContextSSLFuncs = {
|
||||
.free_privdata = redisSSLFreeContext,
|
||||
.async_read = redisSSLAsyncRead,
|
||||
.async_write = redisSSLAsyncWrite,
|
||||
.read = redisSSLRead,
|
||||
.write = redisSSLWrite
|
||||
};
|
||||
|
||||
Vendored
+83
-10
@@ -13,12 +13,16 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "hiredis.h"
|
||||
#ifdef HIREDIS_TEST_SSL
|
||||
#include "hiredis_ssl.h"
|
||||
#endif
|
||||
#include "net.h"
|
||||
|
||||
enum connection_type {
|
||||
CONN_TCP,
|
||||
CONN_UNIX,
|
||||
CONN_FD
|
||||
CONN_FD,
|
||||
CONN_SSL
|
||||
};
|
||||
|
||||
struct config {
|
||||
@@ -33,6 +37,14 @@ struct config {
|
||||
struct {
|
||||
const char *path;
|
||||
} unix_sock;
|
||||
|
||||
struct {
|
||||
const char *host;
|
||||
int port;
|
||||
const char *ca_cert;
|
||||
const char *cert;
|
||||
const char *key;
|
||||
} ssl;
|
||||
};
|
||||
|
||||
/* The following lines make up our testing "framework" :) */
|
||||
@@ -93,11 +105,27 @@ static int disconnect(redisContext *c, int keep_fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void do_ssl_handshake(redisContext *c, struct config config) {
|
||||
#ifdef HIREDIS_TEST_SSL
|
||||
redisSecureConnection(c, config.ssl.ca_cert, config.ssl.cert, config.ssl.key, NULL);
|
||||
if (c->err) {
|
||||
printf("SSL error: %s\n", c->errstr);
|
||||
redisFree(c);
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
(void) c;
|
||||
(void) config;
|
||||
#endif
|
||||
}
|
||||
|
||||
static redisContext *do_connect(struct config config) {
|
||||
redisContext *c = NULL;
|
||||
|
||||
if (config.type == CONN_TCP) {
|
||||
c = redisConnect(config.tcp.host, config.tcp.port);
|
||||
} else if (config.type == CONN_SSL) {
|
||||
c = redisConnect(config.ssl.host, config.ssl.port);
|
||||
} else if (config.type == CONN_UNIX) {
|
||||
c = redisConnectUnix(config.unix_sock.path);
|
||||
} else if (config.type == CONN_FD) {
|
||||
@@ -121,9 +149,21 @@ static redisContext *do_connect(struct config config) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (config.type == CONN_SSL) {
|
||||
do_ssl_handshake(c, config);
|
||||
}
|
||||
|
||||
return select_database(c);
|
||||
}
|
||||
|
||||
static void do_reconnect(redisContext *c, struct config config) {
|
||||
redisReconnect(c);
|
||||
|
||||
if (config.type == CONN_SSL) {
|
||||
do_ssl_handshake(c, config);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_format_commands(void) {
|
||||
char *cmd;
|
||||
int len;
|
||||
@@ -360,7 +400,8 @@ static void test_reply_reader(void) {
|
||||
freeReplyObject(reply);
|
||||
redisReaderFree(reader);
|
||||
|
||||
test("Set error when array > INT_MAX: ");
|
||||
#if LLONG_MAX > SIZE_MAX
|
||||
test("Set error when array > SIZE_MAX: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader, "*9223372036854775807\r\n+asdf\r\n",29);
|
||||
ret = redisReaderGetReply(reader,&reply);
|
||||
@@ -369,7 +410,6 @@ static void test_reply_reader(void) {
|
||||
freeReplyObject(reply);
|
||||
redisReaderFree(reader);
|
||||
|
||||
#if LLONG_MAX > SIZE_MAX
|
||||
test("Set error when bulk > SIZE_MAX: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader, "$9223372036854775807\r\nasdf\r\n",28);
|
||||
@@ -434,22 +474,23 @@ static void test_free_null(void) {
|
||||
test_cond(reply == NULL);
|
||||
}
|
||||
|
||||
#define HIREDIS_BAD_DOMAIN "idontexist-noreally.com"
|
||||
static void test_blocking_connection_errors(void) {
|
||||
redisContext *c;
|
||||
struct addrinfo hints = {.ai_family = AF_INET};
|
||||
struct addrinfo *ai_tmp = NULL;
|
||||
const char *bad_domain = "idontexist.com";
|
||||
|
||||
int rv = getaddrinfo(bad_domain, "6379", &hints, &ai_tmp);
|
||||
int rv = getaddrinfo(HIREDIS_BAD_DOMAIN, "6379", &hints, &ai_tmp);
|
||||
if (rv != 0) {
|
||||
// Address does *not* exist
|
||||
test("Returns error when host cannot be resolved: ");
|
||||
// First see if this domain name *actually* resolves to NXDOMAIN
|
||||
c = redisConnect("dontexist.com", 6379);
|
||||
c = redisConnect(HIREDIS_BAD_DOMAIN, 6379);
|
||||
test_cond(
|
||||
c->err == REDIS_ERR_OTHER &&
|
||||
(strcmp(c->errstr, "Name or service not known") == 0 ||
|
||||
strcmp(c->errstr, "Can't resolve: sadkfjaskfjsa.com") == 0 ||
|
||||
strcmp(c->errstr, "Can't resolve: " HIREDIS_BAD_DOMAIN) == 0 ||
|
||||
strcmp(c->errstr, "Name does not resolve") == 0 ||
|
||||
strcmp(c->errstr,
|
||||
"nodename nor servname provided, or not known") == 0 ||
|
||||
strcmp(c->errstr, "No address associated with hostname") == 0 ||
|
||||
@@ -574,7 +615,8 @@ static void test_blocking_connection_timeouts(struct config config) {
|
||||
|
||||
c = do_connect(config);
|
||||
test("Does not return a reply when the command times out: ");
|
||||
s = write(c->fd, cmd, strlen(cmd));
|
||||
redisAppendFormattedCommand(c, cmd, strlen(cmd));
|
||||
s = c->funcs->write(c);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
redisSetTimeout(c, tv);
|
||||
@@ -583,7 +625,7 @@ static void test_blocking_connection_timeouts(struct config config) {
|
||||
freeReplyObject(reply);
|
||||
|
||||
test("Reconnect properly reconnects after a timeout: ");
|
||||
redisReconnect(c);
|
||||
do_reconnect(c, config);
|
||||
reply = redisCommand(c, "PING");
|
||||
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
|
||||
freeReplyObject(reply);
|
||||
@@ -591,7 +633,7 @@ static void test_blocking_connection_timeouts(struct config config) {
|
||||
test("Reconnect properly uses owned parameters: ");
|
||||
config.tcp.host = "foo";
|
||||
config.unix_sock.path = "foo";
|
||||
redisReconnect(c);
|
||||
do_reconnect(c, config);
|
||||
reply = redisCommand(c, "PING");
|
||||
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
|
||||
freeReplyObject(reply);
|
||||
@@ -894,6 +936,23 @@ int main(int argc, char **argv) {
|
||||
throughput = 0;
|
||||
} else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
|
||||
test_inherit_fd = 0;
|
||||
#ifdef HIREDIS_TEST_SSL
|
||||
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-port")) {
|
||||
argv++; argc--;
|
||||
cfg.ssl.port = atoi(argv[0]);
|
||||
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-host")) {
|
||||
argv++; argc--;
|
||||
cfg.ssl.host = argv[0];
|
||||
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-ca-cert")) {
|
||||
argv++; argc--;
|
||||
cfg.ssl.ca_cert = argv[0];
|
||||
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-cert")) {
|
||||
argv++; argc--;
|
||||
cfg.ssl.cert = argv[0];
|
||||
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-key")) {
|
||||
argv++; argc--;
|
||||
cfg.ssl.key = argv[0];
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
||||
exit(1);
|
||||
@@ -922,6 +981,20 @@ int main(int argc, char **argv) {
|
||||
test_blocking_io_errors(cfg);
|
||||
if (throughput) test_throughput(cfg);
|
||||
|
||||
#ifdef HIREDIS_TEST_SSL
|
||||
if (cfg.ssl.port && cfg.ssl.host) {
|
||||
printf("\nTesting against SSL connection (%s:%d):\n", cfg.ssl.host, cfg.ssl.port);
|
||||
cfg.type = CONN_SSL;
|
||||
|
||||
test_blocking_connection(cfg);
|
||||
test_blocking_connection_timeouts(cfg);
|
||||
test_blocking_io_errors(cfg);
|
||||
test_invalid_timeout_errors(cfg);
|
||||
test_append_formatted_commands(cfg);
|
||||
if (throughput) test_throughput(cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (test_inherit_fd) {
|
||||
printf("\nTesting against inherited fd (%s):\n", cfg.unix_sock.path);
|
||||
cfg.type = CONN_FD;
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
#!/bin/sh -ue
|
||||
|
||||
REDIS_SERVER=${REDIS_SERVER:-redis-server}
|
||||
REDIS_PORT=${REDIS_PORT:-56379}
|
||||
REDIS_SSL_PORT=${REDIS_SSL_PORT:-56443}
|
||||
TEST_SSL=${TEST_SSL:-0}
|
||||
SSL_TEST_ARGS=
|
||||
|
||||
tmpdir=$(mktemp -d)
|
||||
PID_FILE=${tmpdir}/hiredis-test-redis.pid
|
||||
SOCK_FILE=${tmpdir}/hiredis-test-redis.sock
|
||||
|
||||
if [ "$TEST_SSL" = "1" ]; then
|
||||
SSL_CA_CERT=${tmpdir}/ca.crt
|
||||
SSL_CA_KEY=${tmpdir}/ca.key
|
||||
SSL_CERT=${tmpdir}/redis.crt
|
||||
SSL_KEY=${tmpdir}/redis.key
|
||||
|
||||
openssl genrsa -out ${tmpdir}/ca.key 4096
|
||||
openssl req \
|
||||
-x509 -new -nodes -sha256 \
|
||||
-key ${SSL_CA_KEY} \
|
||||
-days 3650 \
|
||||
-subj '/CN=Hiredis Test CA' \
|
||||
-out ${SSL_CA_CERT}
|
||||
openssl genrsa -out ${SSL_KEY} 2048
|
||||
openssl req \
|
||||
-new -sha256 \
|
||||
-key ${SSL_KEY} \
|
||||
-subj '/CN=Hiredis Test Cert' | \
|
||||
openssl x509 \
|
||||
-req -sha256 \
|
||||
-CA ${SSL_CA_CERT} \
|
||||
-CAkey ${SSL_CA_KEY} \
|
||||
-CAserial ${tmpdir}/ca.txt \
|
||||
-CAcreateserial \
|
||||
-days 365 \
|
||||
-out ${SSL_CERT}
|
||||
|
||||
SSL_TEST_ARGS="--ssl-host 127.0.0.1 --ssl-port ${REDIS_SSL_PORT} --ssl-ca-cert ${SSL_CA_CERT} --ssl-cert ${SSL_CERT} --ssl-key ${SSL_KEY}"
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
set +e
|
||||
kill $(cat ${PID_FILE})
|
||||
rm -rf ${tmpdir}
|
||||
}
|
||||
trap cleanup INT TERM EXIT
|
||||
|
||||
cat > ${tmpdir}/redis.conf <<EOF
|
||||
daemonize yes
|
||||
pidfile ${PID_FILE}
|
||||
port ${REDIS_PORT}
|
||||
bind 127.0.0.1
|
||||
unixsocket ${SOCK_FILE}
|
||||
EOF
|
||||
|
||||
if [ "$TEST_SSL" = "1" ]; then
|
||||
cat >> ${tmpdir}/redis.conf <<EOF
|
||||
tls-port ${REDIS_SSL_PORT}
|
||||
tls-ca-cert-file ${SSL_CA_CERT}
|
||||
tls-cert-file ${SSL_CERT}
|
||||
tls-key-file ${SSL_KEY}
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat ${tmpdir}/redis.conf
|
||||
${REDIS_SERVER} ${tmpdir}/redis.conf
|
||||
|
||||
${TEST_PREFIX:-} ./hiredis-test -h 127.0.0.1 -p ${REDIS_PORT} -s ${SOCK_FILE} ${SSL_TEST_ARGS}
|
||||
Vendored
+16
-2
@@ -2,10 +2,20 @@
|
||||
#define _WIN32_HELPER_INCLUDE
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include <winsock2.h> /* for struct timeval */
|
||||
|
||||
#ifndef inline
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#ifndef strcasecmp
|
||||
#define strcasecmp stricmp
|
||||
#endif
|
||||
|
||||
#ifndef strncasecmp
|
||||
#define strncasecmp strnicmp
|
||||
#endif
|
||||
|
||||
#ifndef va_copy
|
||||
#define va_copy(d,s) ((d) = (s))
|
||||
#endif
|
||||
@@ -37,6 +47,10 @@ __inline int c99_snprintf(char* str, size_t size, const char* format, ...)
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#define strerror_r(errno,buf,len) strerror_s(buf,len,errno)
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* _WIN32_HELPER_INCLUDE */
|
||||
@@ -216,7 +216,7 @@ ixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE int
|
||||
iget_defrag_hint(tsdn_t *tsdn, void* ptr, int *bin_util, int *run_util) {
|
||||
iget_defrag_hint(tsdn_t *tsdn, void* ptr) {
|
||||
int defrag = 0;
|
||||
rtree_ctx_t rtree_ctx_fallback;
|
||||
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
||||
@@ -232,11 +232,22 @@ iget_defrag_hint(tsdn_t *tsdn, void* ptr, int *bin_util, int *run_util) {
|
||||
malloc_mutex_lock(tsdn, &bin->lock);
|
||||
/* don't bother moving allocations from the slab currently used for new allocations */
|
||||
if (slab != bin->slabcur) {
|
||||
const bin_info_t *bin_info = &bin_infos[binind];
|
||||
size_t availregs = bin_info->nregs * bin->stats.curslabs;
|
||||
*bin_util = ((long long)bin->stats.curregs<<16) / availregs;
|
||||
*run_util = ((long long)(bin_info->nregs - extent_nfree_get(slab))<<16) / bin_info->nregs;
|
||||
defrag = 1;
|
||||
int free_in_slab = extent_nfree_get(slab);
|
||||
if (free_in_slab) {
|
||||
const bin_info_t *bin_info = &bin_infos[binind];
|
||||
int curslabs = bin->stats.curslabs;
|
||||
size_t curregs = bin->stats.curregs;
|
||||
if (bin->slabcur) {
|
||||
/* remove slabcur from the overall utilization */
|
||||
curregs -= bin_info->nregs - extent_nfree_get(bin->slabcur);
|
||||
curslabs -= 1;
|
||||
}
|
||||
/* Compare the utilization ratio of the slab in question to the total average,
|
||||
* to avoid precision lost and division, we do that by extrapolating the usage
|
||||
* of the slab as if all slabs have the same usage. If this slab is less used
|
||||
* than the average, we'll prefer to evict the data to hopefully more used ones */
|
||||
defrag = (bin_info->nregs - free_in_slab) * curslabs <= curregs;
|
||||
}
|
||||
}
|
||||
malloc_mutex_unlock(tsdn, &bin->lock);
|
||||
}
|
||||
|
||||
+7
-1
@@ -787,7 +787,13 @@ background_thread_stats_read(tsdn_t *tsdn, background_thread_stats_t *stats) {
|
||||
nstime_init(&stats->run_interval, 0);
|
||||
for (unsigned i = 0; i < max_background_threads; i++) {
|
||||
background_thread_info_t *info = &background_thread_info[i];
|
||||
malloc_mutex_lock(tsdn, &info->mtx);
|
||||
if (malloc_mutex_trylock(tsdn, &info->mtx)) {
|
||||
/*
|
||||
* Each background thread run may take a long time;
|
||||
* avoid waiting on the stats if the thread is active.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (info->state != background_thread_stopped) {
|
||||
num_runs += info->tot_n_runs;
|
||||
nstime_add(&stats->run_interval, &info->tot_sleep_time);
|
||||
|
||||
Vendored
+3
-5
@@ -3326,12 +3326,10 @@ jemalloc_postfork_child(void) {
|
||||
/******************************************************************************/
|
||||
|
||||
/* Helps the application decide if a pointer is worth re-allocating in order to reduce fragmentation.
|
||||
* returns 0 if the allocation is in the currently active run,
|
||||
* or when it is not causing any frag issue (large or huge bin)
|
||||
* returns the bin utilization and run utilization both in fixed point 16:16.
|
||||
* returns 1 if the allocation should be moved, and 0 if the allocation be kept.
|
||||
* If the application decides to re-allocate it should use MALLOCX_TCACHE_NONE when doing so. */
|
||||
JEMALLOC_EXPORT int JEMALLOC_NOTHROW
|
||||
get_defrag_hint(void* ptr, int *bin_util, int *run_util) {
|
||||
get_defrag_hint(void* ptr) {
|
||||
assert(ptr != NULL);
|
||||
return iget_defrag_hint(TSDN_NULL, ptr, bin_util, run_util);
|
||||
return iget_defrag_hint(TSDN_NULL, ptr);
|
||||
}
|
||||
Vendored
+24
-1
@@ -21,7 +21,7 @@ So what usually happens is either:
|
||||
|
||||
The result is a pollution of binaries without line editing support.
|
||||
|
||||
So I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporing line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to Linenoise if not.
|
||||
So I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporting line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to Linenoise if not.
|
||||
|
||||
## Terminals, in 2010.
|
||||
|
||||
@@ -126,6 +126,24 @@ Linenoise has direct support for persisting the history into an history
|
||||
file. The functions `linenoiseHistorySave` and `linenoiseHistoryLoad` do
|
||||
just that. Both functions return -1 on error and 0 on success.
|
||||
|
||||
## Mask mode
|
||||
|
||||
Sometimes it is useful to allow the user to type passwords or other
|
||||
secrets that should not be displayed. For such situations linenoise supports
|
||||
a "mask mode" that will just replace the characters the user is typing
|
||||
with `*` characters, like in the following example:
|
||||
|
||||
$ ./linenoise_example
|
||||
hello> get mykey
|
||||
echo: 'get mykey'
|
||||
hello> /mask
|
||||
hello> *********
|
||||
|
||||
You can enable and disable mask mode using the following two functions:
|
||||
|
||||
void linenoiseMaskModeEnable(void);
|
||||
void linenoiseMaskModeDisable(void);
|
||||
|
||||
## Completion
|
||||
|
||||
Linenoise supports completion, which is the ability to complete the user
|
||||
@@ -222,3 +240,8 @@ Sometimes you may want to clear the screen as a result of something the
|
||||
user typed. You can do this by calling the following function:
|
||||
|
||||
void linenoiseClearScreen(void);
|
||||
|
||||
## Related projects
|
||||
|
||||
* [Linenoise NG](https://github.com/arangodb/linenoise-ng) is a fork of Linenoise that aims to add more advanced features like UTF-8 support, Windows support and other features. Uses C++ instead of C as development language.
|
||||
* [Linenoise-swift](https://github.com/andybest/linenoise-swift) is a reimplementation of Linenoise written in Swift.
|
||||
Vendored
+5
@@ -55,6 +55,7 @@ int main(int argc, char **argv) {
|
||||
*
|
||||
* The typed string is returned as a malloc() allocated string by
|
||||
* linenoise, so the user needs to free() it. */
|
||||
|
||||
while((line = linenoise("hello> ")) != NULL) {
|
||||
/* Do something with the string. */
|
||||
if (line[0] != '\0' && line[0] != '/') {
|
||||
@@ -65,6 +66,10 @@ int main(int argc, char **argv) {
|
||||
/* The "/historylen" command will change the history len. */
|
||||
int len = atoi(line+11);
|
||||
linenoiseHistorySetMaxLen(len);
|
||||
} else if (!strncmp(line, "/mask", 5)) {
|
||||
linenoiseMaskModeEnable();
|
||||
} else if (!strncmp(line, "/unmask", 7)) {
|
||||
linenoiseMaskModeDisable();
|
||||
} else if (line[0] == '/') {
|
||||
printf("Unreconized command: %s\n", line);
|
||||
}
|
||||
|
||||
Vendored
+31
-5
@@ -125,6 +125,7 @@ static linenoiseHintsCallback *hintsCallback = NULL;
|
||||
static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
|
||||
|
||||
static struct termios orig_termios; /* In order to restore at exit.*/
|
||||
static int maskmode = 0; /* Show "***" instead of input. For passwords. */
|
||||
static int rawmode = 0; /* For atexit() function to check if restore is needed*/
|
||||
static int mlmode = 0; /* Multi line mode. Default is single line. */
|
||||
static int atexit_registered = 0; /* Register atexit just 1 time. */
|
||||
@@ -197,6 +198,19 @@ FILE *lndebug_fp = NULL;
|
||||
|
||||
/* ======================= Low level terminal handling ====================== */
|
||||
|
||||
/* Enable "mask mode". When it is enabled, instead of the input that
|
||||
* the user is typing, the terminal will just display a corresponding
|
||||
* number of asterisks, like "****". This is useful for passwords and other
|
||||
* secrets that should not be displayed. */
|
||||
void linenoiseMaskModeEnable(void) {
|
||||
maskmode = 1;
|
||||
}
|
||||
|
||||
/* Disable mask mode. */
|
||||
void linenoiseMaskModeDisable(void) {
|
||||
maskmode = 0;
|
||||
}
|
||||
|
||||
/* Set if to use or not the multi line mode. */
|
||||
void linenoiseSetMultiLine(int ml) {
|
||||
mlmode = ml;
|
||||
@@ -485,6 +499,8 @@ void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
|
||||
if (bold == 1 && color == -1) color = 37;
|
||||
if (color != -1 || bold != 0)
|
||||
snprintf(seq,64,"\033[%d;%d;49m",bold,color);
|
||||
else
|
||||
seq[0] = '\0';
|
||||
abAppend(ab,seq,strlen(seq));
|
||||
abAppend(ab,hint,hintlen);
|
||||
if (color != -1 || bold != 0)
|
||||
@@ -523,7 +539,11 @@ static void refreshSingleLine(struct linenoiseState *l) {
|
||||
abAppend(&ab,seq,strlen(seq));
|
||||
/* Write the prompt and the current buffer content */
|
||||
abAppend(&ab,l->prompt,strlen(l->prompt));
|
||||
abAppend(&ab,buf,len);
|
||||
if (maskmode == 1) {
|
||||
while (len--) abAppend(&ab,"*",1);
|
||||
} else {
|
||||
abAppend(&ab,buf,len);
|
||||
}
|
||||
/* Show hits if any. */
|
||||
refreshShowHints(&ab,l,plen);
|
||||
/* Erase to right */
|
||||
@@ -577,7 +597,12 @@ static void refreshMultiLine(struct linenoiseState *l) {
|
||||
|
||||
/* Write the prompt and the current buffer content */
|
||||
abAppend(&ab,l->prompt,strlen(l->prompt));
|
||||
abAppend(&ab,l->buf,l->len);
|
||||
if (maskmode == 1) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < l->len; i++) abAppend(&ab,"*",1);
|
||||
} else {
|
||||
abAppend(&ab,l->buf,l->len);
|
||||
}
|
||||
|
||||
/* Show hits if any. */
|
||||
refreshShowHints(&ab,l,plen);
|
||||
@@ -600,7 +625,7 @@ static void refreshMultiLine(struct linenoiseState *l) {
|
||||
rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */
|
||||
lndebug("rpos2 %d", rpos2);
|
||||
|
||||
/* Go up till we reach the expected positon. */
|
||||
/* Go up till we reach the expected position. */
|
||||
if (rows-rpos2 > 0) {
|
||||
lndebug("go-up %d", rows-rpos2);
|
||||
snprintf(seq,64,"\x1b[%dA", rows-rpos2);
|
||||
@@ -645,7 +670,8 @@ int linenoiseEditInsert(struct linenoiseState *l, char c) {
|
||||
if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
|
||||
/* Avoid a full update of the line in the
|
||||
* trivial case. */
|
||||
if (write(l->ofd,&c,1) == -1) return -1;
|
||||
char d = (maskmode==1) ? '*' : c;
|
||||
if (write(l->ofd,&d,1) == -1) return -1;
|
||||
} else {
|
||||
refreshLine(l);
|
||||
}
|
||||
@@ -741,7 +767,7 @@ void linenoiseEditBackspace(struct linenoiseState *l) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the previosu word, maintaining the cursor at the start of the
|
||||
/* Delete the previous word, maintaining the cursor at the start of the
|
||||
* current word. */
|
||||
void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
|
||||
size_t old_pos = l->pos;
|
||||
|
||||
Vendored
+2
@@ -65,6 +65,8 @@ int linenoiseHistoryLoad(const char *filename);
|
||||
void linenoiseClearScreen(void);
|
||||
void linenoiseSetMultiLine(int ml);
|
||||
void linenoisePrintKeyCodes(void);
|
||||
void linenoiseMaskModeEnable(void);
|
||||
void linenoiseMaskModeDisable(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
CallInfo *ci;
|
||||
StkId st, base;
|
||||
Proto *p = cl->p;
|
||||
luaD_checkstack(L, p->maxstacksize);
|
||||
luaD_checkstack(L, p->maxstacksize + p->numparams);
|
||||
func = restorestack(L, funcr);
|
||||
if (!p->is_vararg) { /* no varargs? */
|
||||
base = func + 1;
|
||||
|
||||
Vendored
+6
-4
@@ -89,12 +89,14 @@ typedef struct Header {
|
||||
} Header;
|
||||
|
||||
|
||||
static int getnum (const char **fmt, int df) {
|
||||
static int getnum (lua_State *L, const char **fmt, int df) {
|
||||
if (!isdigit(**fmt)) /* no number? */
|
||||
return df; /* return default value */
|
||||
else {
|
||||
int a = 0;
|
||||
do {
|
||||
if (a > (INT_MAX / 10) || a * 10 > (INT_MAX - (**fmt - '0')))
|
||||
luaL_error(L, "integral size overflow");
|
||||
a = a*10 + *((*fmt)++) - '0';
|
||||
} while (isdigit(**fmt));
|
||||
return a;
|
||||
@@ -115,9 +117,9 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) {
|
||||
case 'f': return sizeof(float);
|
||||
case 'd': return sizeof(double);
|
||||
case 'x': return 1;
|
||||
case 'c': return getnum(fmt, 1);
|
||||
case 'c': return getnum(L, fmt, 1);
|
||||
case 'i': case 'I': {
|
||||
int sz = getnum(fmt, sizeof(int));
|
||||
int sz = getnum(L, fmt, sizeof(int));
|
||||
if (sz > MAXINTSIZE)
|
||||
luaL_error(L, "integral size %d is larger than limit of %d",
|
||||
sz, MAXINTSIZE);
|
||||
@@ -150,7 +152,7 @@ static void controloptions (lua_State *L, int opt, const char **fmt,
|
||||
case '>': h->endian = BIG; return;
|
||||
case '<': h->endian = LITTLE; return;
|
||||
case '!': {
|
||||
int a = getnum(fmt, MAXALIGN);
|
||||
int a = getnum(L, fmt, MAXALIGN);
|
||||
if (!isp2(a))
|
||||
luaL_error(L, "alignment %d is not a power of 2", a);
|
||||
h->align = a;
|
||||
|
||||
+429
-163
@@ -24,7 +24,7 @@
|
||||
# to customize a few per-server settings. Include files can include
|
||||
# other files, so use this wisely.
|
||||
#
|
||||
# Notice option "include" won't be rewritten by command "CONFIG REWRITE"
|
||||
# Note that option "include" won't be rewritten by command "CONFIG REWRITE"
|
||||
# from admin or KeyDB Sentinel. Since KeyDB always uses the last processed
|
||||
# line as value of a configuration directive, you'd better put includes
|
||||
# at the beginning of this file to avoid overwriting config change at runtime.
|
||||
@@ -46,7 +46,7 @@
|
||||
################################## NETWORK #####################################
|
||||
|
||||
# By default, if no "bind" configuration directive is specified, KeyDB listens
|
||||
# for connections from all the network interfaces available on the server.
|
||||
# for connections from all available network interfaces on the host machine.
|
||||
# It is possible to listen to just one or multiple selected interfaces using
|
||||
# the "bind" configuration directive, followed by one or more IP addresses.
|
||||
#
|
||||
@@ -58,13 +58,12 @@
|
||||
# ~~~ WARNING ~~~ If the computer running KeyDB is directly exposed to the
|
||||
# internet, binding to all the interfaces is dangerous and will expose the
|
||||
# instance to everybody on the internet. So by default we uncomment the
|
||||
# following bind directive, that will force KeyDB to listen only into
|
||||
# the IPv4 loopback interface address (this means KeyDB will be able to
|
||||
# accept connections only from clients running into the same computer it
|
||||
# is running).
|
||||
# following bind directive, that will force KeyDB to listen only on the
|
||||
# IPv4 loopback interface address (this means KeyDB will only be able to
|
||||
# accept client connections from the same host that it is running on).
|
||||
#
|
||||
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
|
||||
# JUST COMMENT THE FOLLOWING LINE.
|
||||
# JUST COMMENT OUT THE FOLLOWING LINE.
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bind 127.0.0.1
|
||||
|
||||
@@ -93,8 +92,8 @@ port 6379
|
||||
|
||||
# TCP listen() backlog.
|
||||
#
|
||||
# In high requests-per-second environments you need an high backlog in order
|
||||
# to avoid slow clients connections issues. Note that the Linux kernel
|
||||
# In high requests-per-second environments you need a high backlog in order
|
||||
# to avoid slow clients connection issues. Note that the Linux kernel
|
||||
# will silently truncate it to the value of /proc/sys/net/core/somaxconn so
|
||||
# make sure to raise both the value of somaxconn and tcp_max_syn_backlog
|
||||
# in order to get the desired effect.
|
||||
@@ -118,8 +117,8 @@ timeout 0
|
||||
# of communication. This is useful for two reasons:
|
||||
#
|
||||
# 1) Detect dead peers.
|
||||
# 2) Take the connection alive from the point of view of network
|
||||
# equipment in the middle.
|
||||
# 2) Force network equipment in the middle to consider the connection to be
|
||||
# alive.
|
||||
#
|
||||
# On Linux, the specified value (in seconds) is the period used to send ACKs.
|
||||
# Note that to close the connection the double of the time is needed.
|
||||
@@ -129,6 +128,95 @@ timeout 0
|
||||
# KeyDB default starting with Redis 3.2.1.
|
||||
tcp-keepalive 300
|
||||
|
||||
################################# TLS/SSL #####################################
|
||||
|
||||
# By default, TLS/SSL is disabled. To enable it, the "tls-port" configuration
|
||||
# directive can be used to define TLS-listening ports. To enable TLS on the
|
||||
# default port, use:
|
||||
#
|
||||
# port 0
|
||||
# tls-port 6379
|
||||
|
||||
# Configure a X.509 certificate and private key to use for authenticating the
|
||||
# server to connected clients, masters or cluster peers. These files should be
|
||||
# PEM formatted.
|
||||
#
|
||||
# tls-cert-file redis.crt
|
||||
# tls-key-file redis.key
|
||||
|
||||
# Configure a DH parameters file to enable Diffie-Hellman (DH) key exchange:
|
||||
#
|
||||
# tls-dh-params-file redis.dh
|
||||
|
||||
# Configure a CA certificate(s) bundle or directory to authenticate TLS/SSL
|
||||
# clients and peers. Redis requires an explicit configuration of at least one
|
||||
# of these, and will not implicitly use the system wide configuration.
|
||||
#
|
||||
# tls-ca-cert-file ca.crt
|
||||
# tls-ca-cert-dir /etc/ssl/certs
|
||||
|
||||
# By default, clients (including replica servers) on a TLS port are required
|
||||
# to authenticate using valid client side certificates.
|
||||
#
|
||||
# If "no" is specified, client certificates are not required and not accepted.
|
||||
# If "optional" is specified, client certificates are accepted and must be
|
||||
# valid if provided, but are not required.
|
||||
#
|
||||
# tls-auth-clients no
|
||||
# tls-auth-clients optional
|
||||
|
||||
# By default, a KeyDB replica does not attempt to establish a TLS connection
|
||||
# with its master.
|
||||
#
|
||||
# Use the following directive to enable TLS on replication links.
|
||||
#
|
||||
# tls-replication yes
|
||||
|
||||
# By default, the Redis Cluster bus uses a plain TCP connection. To enable
|
||||
# TLS for the bus protocol, use the following directive:
|
||||
#
|
||||
# tls-cluster yes
|
||||
|
||||
# Explicitly specify TLS versions to support. Allowed values are case insensitive
|
||||
# and include "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" (OpenSSL >= 1.1.1) or
|
||||
# any combination. To enable only TLSv1.2 and TLSv1.3, use:
|
||||
#
|
||||
# tls-protocols "TLSv1.2 TLSv1.3"
|
||||
|
||||
# Configure allowed ciphers. See the ciphers(1ssl) manpage for more information
|
||||
# about the syntax of this string.
|
||||
#
|
||||
# Note: this configuration applies only to <= TLSv1.2.
|
||||
#
|
||||
# tls-ciphers DEFAULT:!MEDIUM
|
||||
|
||||
# Configure allowed TLSv1.3 ciphersuites. See the ciphers(1ssl) manpage for more
|
||||
# information about the syntax of this string, and specifically for TLSv1.3
|
||||
# ciphersuites.
|
||||
#
|
||||
# tls-ciphersuites TLS_CHACHA20_POLY1305_SHA256
|
||||
|
||||
# When choosing a cipher, use the server's preference instead of the client
|
||||
# preference. By default, the server follows the client's preference.
|
||||
#
|
||||
# tls-prefer-server-ciphers yes
|
||||
|
||||
# By default, TLS session caching is enabled to allow faster and less expensive
|
||||
# reconnections by clients that support it. Use the following directive to disable
|
||||
# caching.
|
||||
#
|
||||
# tls-session-caching no
|
||||
|
||||
# Change the default number of TLS sessions cached. A zero value sets the cache
|
||||
# to unlimited size. The default size is 20480.
|
||||
#
|
||||
# tls-session-cache-size 5000
|
||||
|
||||
# Change the default timeout of cached TLS sessions. The default timeout is 300
|
||||
# seconds.
|
||||
#
|
||||
# tls-session-cache-timeout 60
|
||||
|
||||
################################# GENERAL #####################################
|
||||
|
||||
# By default KeyDB does not run as a daemon. Use 'yes' if you need it.
|
||||
@@ -139,11 +227,12 @@ daemonize no
|
||||
# supervision tree. Options:
|
||||
# supervised no - no supervision interaction
|
||||
# supervised upstart - signal upstart by putting KeyDB into SIGSTOP mode
|
||||
# requires "expect stop" in your upstart job config
|
||||
# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
|
||||
# supervised auto - detect upstart or systemd method based on
|
||||
# UPSTART_JOB or NOTIFY_SOCKET environment variables
|
||||
# Note: these supervision methods only signal "process is ready."
|
||||
# They do not enable continuous liveness pings back to your supervisor.
|
||||
# They do not enable continuous pings back to your supervisor.
|
||||
supervised no
|
||||
|
||||
# If a pid file is specified, KeyDB writes it where specified at startup
|
||||
@@ -193,6 +282,9 @@ databases 16
|
||||
# ASCII art logo in startup logs by setting the following option to yes.
|
||||
always-show-logo yes
|
||||
|
||||
# Retrieving "message of today" using CURL requests.
|
||||
#enable-motd yes
|
||||
|
||||
################################ SNAPSHOTTING ################################
|
||||
#
|
||||
# Save the DB on disk:
|
||||
@@ -202,7 +294,7 @@ always-show-logo yes
|
||||
# Will save the DB if both the given number of seconds and the given
|
||||
# number of write operations against the DB occurred.
|
||||
#
|
||||
# In the example below the behaviour will be to save:
|
||||
# In the example below the behavior will be to save:
|
||||
# after 900 sec (15 min) if at least 1 key changed
|
||||
# after 300 sec (5 min) if at least 10 keys changed
|
||||
# after 60 sec if at least 10000 keys changed
|
||||
@@ -235,7 +327,7 @@ save 60 10000
|
||||
stop-writes-on-bgsave-error yes
|
||||
|
||||
# Compress string objects using LZF when dump .rdb databases?
|
||||
# For default that's set to 'yes' as it's almost always a win.
|
||||
# By default compression is enabled as it's almost always a win.
|
||||
# If you want to save some CPU in the saving child set it to 'no' but
|
||||
# the dataset will likely be bigger if you have compressible values or keys.
|
||||
rdbcompression yes
|
||||
@@ -252,6 +344,19 @@ rdbchecksum yes
|
||||
# The filename where to dump the DB
|
||||
dbfilename dump.rdb
|
||||
|
||||
# Remove RDB files used by replication in instances without persistence
|
||||
# enabled. By default this option is disabled, however there are environments
|
||||
# where for regulations or other security concerns, RDB files persisted on
|
||||
# disk by masters in order to feed replicas, or stored on disk by replicas
|
||||
# in order to load them for the initial synchronization, should be deleted
|
||||
# ASAP. Note that this option ONLY WORKS in instances that have both AOF
|
||||
# and RDB persistence disabled, otherwise is completely ignored.
|
||||
#
|
||||
# An alternative (and sometimes better) way to obtain the same effect is
|
||||
# to use diskless replication on both master and replicas instances. However
|
||||
# in the case of replicas, diskless is not always an option.
|
||||
rdb-del-sync-files no
|
||||
|
||||
# The working directory.
|
||||
#
|
||||
# The DB will be written inside this directory, with the filename specified
|
||||
@@ -294,9 +399,9 @@ dir ./
|
||||
#
|
||||
# However this is not enough if you are using KeyDB ACLs (for Redis version
|
||||
# 6 or greater), and the default user is not capable of running the PSYNC
|
||||
# command and/or other commands needed for replication. In this case it's
|
||||
# better to configure a special user to use with replication, and specify the
|
||||
# masteruser configuration as such:
|
||||
# command and/or other commands needed for replication (gathered in the
|
||||
# @replication group). In this case it's better to configure a special user to
|
||||
# use with replication, and specify the masteruser configuration as such:
|
||||
#
|
||||
# masteruser <username>
|
||||
#
|
||||
@@ -310,14 +415,28 @@ dir ./
|
||||
# still reply to client requests, possibly with out of date data, or the
|
||||
# data set may just be empty if this is the first synchronization.
|
||||
#
|
||||
# 2) if replica-serve-stale-data is set to 'no' the replica will reply with
|
||||
# an error "SYNC with master in progress" to all the kind of commands
|
||||
# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,
|
||||
# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB,
|
||||
# COMMAND, POST, HOST: and LATENCY.
|
||||
# 2) If replica-serve-stale-data is set to 'no' the replica will reply with
|
||||
# an error "SYNC with master in progress" to all commands except:
|
||||
# INFO, REPLICAOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG, SUBSCRIBE,
|
||||
# UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, COMMAND, POST,
|
||||
# HOST and LATENCY.
|
||||
#
|
||||
replica-serve-stale-data yes
|
||||
|
||||
# Active Replicas will allow read only data access while loading remote RDBs
|
||||
# provided they are permitted to serve stale data. As an option you may also
|
||||
# permit them to accept write commands. This is an EXPERIMENTAL feature and
|
||||
# may result in commands not being fully synchronized
|
||||
#
|
||||
# allow-write-during-load no
|
||||
|
||||
# You can modify the number of masters necessary to form a replica quorum when
|
||||
# multi-master is enabled and replica-serve-stale-data is "no". By default
|
||||
# this is set to -1 which implies the number of known masters (e.g. those
|
||||
# you added with replicaof)
|
||||
#
|
||||
# replica-quorum -1
|
||||
|
||||
# You can configure a replica instance to accept writes or not. Writing against
|
||||
# a replica instance may be useful to store some ephemeral data (because data
|
||||
# written on a replica will be easily deleted after resync with the master) but
|
||||
@@ -336,13 +455,11 @@ replica-read-only yes
|
||||
|
||||
# Replication SYNC strategy: disk or socket.
|
||||
#
|
||||
# -------------------------------------------------------
|
||||
# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY
|
||||
# -------------------------------------------------------
|
||||
# New replicas and reconnecting replicas that are not able to continue the
|
||||
# replication process just receiving differences, need to do what is called a
|
||||
# "full synchronization". An RDB file is transmitted from the master to the
|
||||
# replicas.
|
||||
#
|
||||
# New replicas and reconnecting replicas that are not able to continue the replication
|
||||
# process just receiving differences, need to do what is called a "full
|
||||
# synchronization". An RDB file is transmitted from the master to the replicas.
|
||||
# The transmission can happen in two different ways:
|
||||
#
|
||||
# 1) Disk-backed: The KeyDB master creates a new process that writes the RDB
|
||||
@@ -352,14 +469,14 @@ replica-read-only yes
|
||||
# RDB file to replica sockets, without touching the disk at all.
|
||||
#
|
||||
# With disk-backed replication, while the RDB file is generated, more replicas
|
||||
# can be queued and served with the RDB file as soon as the current child producing
|
||||
# the RDB file finishes its work. With diskless replication instead once
|
||||
# the transfer starts, new replicas arriving will be queued and a new transfer
|
||||
# will start when the current one terminates.
|
||||
# can be queued and served with the RDB file as soon as the current child
|
||||
# producing the RDB file finishes its work. With diskless replication instead
|
||||
# once the transfer starts, new replicas arriving will be queued and a new
|
||||
# transfer will start when the current one terminates.
|
||||
#
|
||||
# When diskless replication is used, the master waits a configurable amount of
|
||||
# time (in seconds) before starting the transfer in the hope that multiple replicas
|
||||
# will arrive and the transfer can be parallelized.
|
||||
# time (in seconds) before starting the transfer in the hope that multiple
|
||||
# replicas will arrive and the transfer can be parallelized.
|
||||
#
|
||||
# With slow disks and fast (large bandwidth) networks, diskless replication
|
||||
# works better.
|
||||
@@ -370,16 +487,42 @@ repl-diskless-sync no
|
||||
# to the replicas.
|
||||
#
|
||||
# This is important since once the transfer starts, it is not possible to serve
|
||||
# new replicas arriving, that will be queued for the next RDB transfer, so the server
|
||||
# waits a delay in order to let more replicas arrive.
|
||||
# new replicas arriving, that will be queued for the next RDB transfer, so the
|
||||
# server waits a delay in order to let more replicas arrive.
|
||||
#
|
||||
# The delay is specified in seconds, and by default is 5 seconds. To disable
|
||||
# it entirely just set it to 0 seconds and the transfer will start ASAP.
|
||||
repl-diskless-sync-delay 5
|
||||
|
||||
# Replicas send PINGs to server in a predefined interval. It's possible to change
|
||||
# this interval with the repl_ping_replica_period option. The default value is 10
|
||||
# seconds.
|
||||
# -----------------------------------------------------------------------------
|
||||
# WARNING: RDB diskless load is experimental. Since in this setup the replica
|
||||
# does not immediately store an RDB on disk, it may cause data loss during
|
||||
# failovers. RDB diskless load + KeyDB modules not handling I/O reads may also
|
||||
# cause KeyDB to abort in case of I/O errors during the initial synchronization
|
||||
# stage with the master. Use only if your do what you are doing.
|
||||
# -----------------------------------------------------------------------------
|
||||
#
|
||||
# Replica can load the RDB it reads from the replication link directly from the
|
||||
# socket, or store the RDB to a file and read that file after it was completely
|
||||
# received from the master.
|
||||
#
|
||||
# In many cases the disk is slower than the network, and storing and loading
|
||||
# the RDB file may increase replication time (and even increase the master's
|
||||
# Copy on Write memory and salve buffers).
|
||||
# However, parsing the RDB file directly from the socket may mean that we have
|
||||
# to flush the contents of the current database before the full rdb was
|
||||
# received. For this reason we have the following options:
|
||||
#
|
||||
# "disabled" - Don't use diskless load (store the rdb file to the disk first)
|
||||
# "on-empty-db" - Use diskless load only when it is completely safe.
|
||||
# "swapdb" - Keep a copy of the current db contents in RAM while parsing
|
||||
# the data directly from the socket. note that this requires
|
||||
# sufficient memory, if you don't have it, you risk an OOM kill.
|
||||
repl-diskless-load disabled
|
||||
|
||||
# Replicas send PINGs to server in a predefined interval. It's possible to
|
||||
# change this interval with the repl_ping_replica_period option. The default
|
||||
# value is 10 seconds.
|
||||
#
|
||||
# repl-ping-replica-period 10
|
||||
|
||||
@@ -391,7 +534,8 @@ repl-diskless-sync-delay 5
|
||||
#
|
||||
# It is important to make sure that this value is greater than the value
|
||||
# specified for repl-ping-replica-period otherwise a timeout will be detected
|
||||
# every time there is low traffic between the master and the replica.
|
||||
# every time there is low traffic between the master and the replica. The default
|
||||
# value is 60 seconds.
|
||||
#
|
||||
# repl-timeout 60
|
||||
|
||||
@@ -411,38 +555,38 @@ repl-diskless-sync-delay 5
|
||||
repl-disable-tcp-nodelay no
|
||||
|
||||
# Set the replication backlog size. The backlog is a buffer that accumulates
|
||||
# replica data when replicas are disconnected for some time, so that when a replica
|
||||
# wants to reconnect again, often a full resync is not needed, but a partial
|
||||
# resync is enough, just passing the portion of data the replica missed while
|
||||
# disconnected.
|
||||
# replica data when replicas are disconnected for some time, so that when a
|
||||
# replica wants to reconnect again, often a full resync is not needed, but a
|
||||
# partial resync is enough, just passing the portion of data the replica
|
||||
# missed while disconnected.
|
||||
#
|
||||
# The bigger the replication backlog, the longer the time the replica can be
|
||||
# disconnected and later be able to perform a partial resynchronization.
|
||||
# The bigger the replication backlog, the longer the replica can endure the
|
||||
# disconnect and later be able to perform a partial resynchronization.
|
||||
#
|
||||
# The backlog is only allocated once there is at least a replica connected.
|
||||
# The backlog is only allocated if there is at least one replica connected.
|
||||
#
|
||||
# repl-backlog-size 1mb
|
||||
|
||||
# After a master has no longer connected replicas for some time, the backlog
|
||||
# will be freed. The following option configures the amount of seconds that
|
||||
# need to elapse, starting from the time the last replica disconnected, for
|
||||
# the backlog buffer to be freed.
|
||||
# After a master has no connected replicas for some time, the backlog will be
|
||||
# freed. The following option configures the amount of seconds that need to
|
||||
# elapse, starting from the time the last replica disconnected, for the backlog
|
||||
# buffer to be freed.
|
||||
#
|
||||
# Note that replicas never free the backlog for timeout, since they may be
|
||||
# promoted to masters later, and should be able to correctly "partially
|
||||
# resynchronize" with the replicas: hence they should always accumulate backlog.
|
||||
# resynchronize" with other replicas: hence they should always accumulate backlog.
|
||||
#
|
||||
# A value of 0 means to never release the backlog.
|
||||
#
|
||||
# repl-backlog-ttl 3600
|
||||
|
||||
# The replica priority is an integer number published by KeyDB in the INFO output.
|
||||
# It is used by KeyDB Sentinel in order to select a replica to promote into a
|
||||
# master if the master is no longer working correctly.
|
||||
# The replica priority is an integer number published by KeyDB in the INFO
|
||||
# output. It is used by KeyDB Sentinel in order to select a replica to promote
|
||||
# into a master if the master is no longer working correctly.
|
||||
#
|
||||
# A replica with a low priority number is considered better for promotion, so
|
||||
# for instance if there are three replicas with priority 10, 100, 25 Sentinel will
|
||||
# pick the one with priority 10, that is the lowest.
|
||||
# for instance if there are three replicas with priority 10, 100, 25 Sentinel
|
||||
# will pick the one with priority 10, that is the lowest.
|
||||
#
|
||||
# However a special priority of 0 marks the replica as not able to perform the
|
||||
# role of master, so a replica with priority of 0 will never be selected by
|
||||
@@ -480,8 +624,8 @@ replica-priority 100
|
||||
# Another place where this info is available is in the output of the
|
||||
# "ROLE" command of a master.
|
||||
#
|
||||
# The listed IP and address normally reported by a replica is obtained
|
||||
# in the following way:
|
||||
# The listed IP address and port normally reported by a replica is
|
||||
# obtained in the following way:
|
||||
#
|
||||
# IP: The address is auto detected by checking the peer address
|
||||
# of the socket used by the replica to connect with the master.
|
||||
@@ -491,7 +635,7 @@ replica-priority 100
|
||||
# listen for connections.
|
||||
#
|
||||
# However when port forwarding or Network Address Translation (NAT) is
|
||||
# used, the replica may be actually reachable via different IP and port
|
||||
# used, the replica may actually be reachable via different IP and port
|
||||
# pairs. The following two options can be used by a replica in order to
|
||||
# report to its master a specific set of IP and port, so that both INFO
|
||||
# and ROLE will report those values.
|
||||
@@ -502,9 +646,45 @@ replica-priority 100
|
||||
# replica-announce-ip 5.5.5.5
|
||||
# replica-announce-port 1234
|
||||
|
||||
############################### KEYS TRACKING #################################
|
||||
|
||||
# KeyDB implements server assisted support for client side caching of values.
|
||||
# This is implemented using an invalidation table that remembers, using
|
||||
# 16 millions of slots, what clients may have certain subsets of keys. In turn
|
||||
# this is used in order to send invalidation messages to clients. Please
|
||||
# check this page to understand more about the feature:
|
||||
#
|
||||
# https://redis.io/topics/client-side-caching
|
||||
#
|
||||
# When tracking is enabled for a client, all the read only queries are assumed
|
||||
# to be cached: this will force KeyDB to store information in the invalidation
|
||||
# table. When keys are modified, such information is flushed away, and
|
||||
# invalidation messages are sent to the clients. However if the workload is
|
||||
# heavily dominated by reads, KeyDB could use more and more memory in order
|
||||
# to track the keys fetched by many clients.
|
||||
#
|
||||
# For this reason it is possible to configure a maximum fill value for the
|
||||
# invalidation table. By default it is set to 1M of keys, and once this limit
|
||||
# is reached, KeyDB will start to evict keys in the invalidation table
|
||||
# even if they were not modified, just to reclaim memory: this will in turn
|
||||
# force the clients to invalidate the cached values. Basically the table
|
||||
# maximum size is a trade off between the memory you want to spend server
|
||||
# side to track information about who cached what, and the ability of clients
|
||||
# to retain cached objects in memory.
|
||||
#
|
||||
# If you set the value to 0, it means there are no limits, and KeyDB will
|
||||
# retain as many keys as needed in the invalidation table.
|
||||
# In the "stats" INFO section, you can find information about the number of
|
||||
# keys in the invalidation table at every given moment.
|
||||
#
|
||||
# Note: when key tracking is used in broadcasting mode, no memory is used
|
||||
# in the server side so this setting is useless.
|
||||
#
|
||||
# tracking-table-max-keys 1000000
|
||||
|
||||
################################## SECURITY ###################################
|
||||
|
||||
# Warning: since KeyDB is pretty fast an outside user can try up to
|
||||
# Warning: since KeyDB is pretty fast, an outside user can try up to
|
||||
# 1 million passwords per second against a modern box. This means that you
|
||||
# should use very strong passwords, otherwise they will be very easy to break.
|
||||
# Note that because the password is really a shared secret between the client
|
||||
@@ -528,7 +708,7 @@ replica-priority 100
|
||||
# AUTH (or the HELLO command AUTH option) in order to be authenticated and
|
||||
# start to work.
|
||||
#
|
||||
# The ACL rules that describe what an user can do are the following:
|
||||
# The ACL rules that describe what a user can do are the following:
|
||||
#
|
||||
# on Enable the user: it is possible to authenticate as this user.
|
||||
# off Disable the user: it's no longer possible to authenticate
|
||||
@@ -538,7 +718,7 @@ replica-priority 100
|
||||
# -<command> Disallow the execution of that command
|
||||
# +@<category> Allow the execution of all the commands in such category
|
||||
# with valid categories are like @admin, @set, @sortedset, ...
|
||||
# and so forth, see the full list in the server.c file where
|
||||
# and so forth, see the full list in the server.cpp file where
|
||||
# the KeyDB command table is described and defined.
|
||||
# The special category @all means all the commands, but currently
|
||||
# present in the server, and that will be loaded in the future
|
||||
@@ -556,7 +736,7 @@ replica-priority 100
|
||||
# It is possible to specify multiple patterns.
|
||||
# allkeys Alias for ~*
|
||||
# resetkeys Flush the list of allowed keys patterns.
|
||||
# ><password> Add this passowrd to the list of valid password for the user.
|
||||
# ><password> Add this password to the list of valid password for the user.
|
||||
# For example >mypass will add "mypass" to the list.
|
||||
# This directive clears the "nopass" flag (see later).
|
||||
# <<password> Remove this password from the list of valid passwords.
|
||||
@@ -598,11 +778,19 @@ replica-priority 100
|
||||
# For more information about ACL configuration please refer to
|
||||
# the Redis web site at https://redis.io/topics/acl
|
||||
|
||||
# ACL LOG
|
||||
#
|
||||
# The ACL Log tracks failed commands and authentication events associated
|
||||
# with ACLs. The ACL Log is useful to troubleshoot failed commands blocked
|
||||
# by ACLs. The ACL Log is stored in memory. You can reclaim memory with
|
||||
# ACL LOG RESET. Define the maximum entry length of the ACL Log below.
|
||||
acllog-max-len 128
|
||||
|
||||
# Using an external ACL file
|
||||
#
|
||||
# Instead of configuring users here in this file, it is possible to use
|
||||
# a stand-alone file just listing users. The two methods cannot be mixed:
|
||||
# if you configure users here and at the same time you activate the exteranl
|
||||
# if you configure users here and at the same time you activate the external
|
||||
# ACL file, the server will refuse to start.
|
||||
#
|
||||
# The format of the external ACL user file is exactly the same as the
|
||||
@@ -610,7 +798,7 @@ replica-priority 100
|
||||
#
|
||||
# aclfile /etc/keydb/users.acl
|
||||
|
||||
# IMPORTANT NOTE: starting with Redis 6 "requirepass" is just a compatiblity
|
||||
# IMPORTANT NOTE: starting with Redis 6 "requirepass" is just a compatibility
|
||||
# layer on top of the new ACL system. The option effect will be just setting
|
||||
# the password for the default user. Clients will still authenticate using
|
||||
# AUTH <password> as usually, or more explicitly with AUTH default <password>
|
||||
@@ -654,6 +842,11 @@ replica-priority 100
|
||||
# Once the limit is reached KeyDB will close all the new connections sending
|
||||
# an error 'max number of clients reached'.
|
||||
#
|
||||
# IMPORTANT: When Redis Cluster is used, the max number of connections is also
|
||||
# shared with the cluster bus: every node in the cluster will use two
|
||||
# connections, one incoming and another outgoing. It is important to size the
|
||||
# limit accordingly in case of very large clusters.
|
||||
#
|
||||
# maxclients 10000
|
||||
|
||||
############################## MEMORY MANAGEMENT ################################
|
||||
@@ -684,13 +877,13 @@ replica-priority 100
|
||||
# maxmemory <bytes>
|
||||
|
||||
# MAXMEMORY POLICY: how KeyDB will select what to remove when maxmemory
|
||||
# is reached. You can select among five behaviors:
|
||||
# is reached. You can select one from the following behaviors:
|
||||
#
|
||||
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
|
||||
# volatile-lru -> Evict using approximated LRU, only keys with an expire set.
|
||||
# allkeys-lru -> Evict any key using approximated LRU.
|
||||
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
|
||||
# volatile-lfu -> Evict using approximated LFU, only keys with an expire set.
|
||||
# allkeys-lfu -> Evict any key using approximated LFU.
|
||||
# volatile-random -> Remove a random key among the ones with an expire set.
|
||||
# volatile-random -> Remove a random key having an expire set.
|
||||
# allkeys-random -> Remove a random key, any key.
|
||||
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
|
||||
# noeviction -> Don't evict anything, just return an error on write operations.
|
||||
@@ -716,8 +909,8 @@ replica-priority 100
|
||||
|
||||
# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated
|
||||
# algorithms (in order to save memory), so you can tune it for speed or
|
||||
# accuracy. For default KeyDB will check five keys and pick the one that was
|
||||
# used less recently, you can change the sample size using the following
|
||||
# accuracy. By default KeyDB will check five keys and pick the one that was
|
||||
# used least recently, you can change the sample size using the following
|
||||
# configuration directive.
|
||||
#
|
||||
# The default of 5 produces good enough results. 10 Approximates very closely
|
||||
@@ -731,20 +924,37 @@ replica-priority 100
|
||||
# DEL commands to the replica as keys evict in the master side.
|
||||
#
|
||||
# This behavior ensures that masters and replicas stay consistent, and is usually
|
||||
# what you want, however if your replica is writable, or you want the replica to have
|
||||
# a different memory setting, and you are sure all the writes performed to the
|
||||
# replica are idempotent, then you may change this default (but be sure to understand
|
||||
# what you are doing).
|
||||
# what you want, however if your replica is writable, or you want the replica
|
||||
# to have a different memory setting, and you are sure all the writes performed
|
||||
# to the replica are idempotent, then you may change this default (but be sure
|
||||
# to understand what you are doing).
|
||||
#
|
||||
# Note that since the replica by default does not evict, it may end using more
|
||||
# memory than the one set via maxmemory (there are certain buffers that may
|
||||
# be larger on the replica, or data structures may sometimes take more memory and so
|
||||
# forth). So make sure you monitor your replicas and make sure they have enough
|
||||
# memory to never hit a real out-of-memory condition before the master hits
|
||||
# the configured maxmemory setting.
|
||||
# be larger on the replica, or data structures may sometimes take more memory
|
||||
# and so forth). So make sure you monitor your replicas and make sure they
|
||||
# have enough memory to never hit a real out-of-memory condition before the
|
||||
# master hits the configured maxmemory setting.
|
||||
#
|
||||
# replica-ignore-maxmemory yes
|
||||
|
||||
# KeyDB reclaims expired keys in two ways: upon access when those keys are
|
||||
# found to be expired, and also in background, in what is called the
|
||||
# "active expire key". The key space is slowly and interactively scanned
|
||||
# looking for expired keys to reclaim, so that it is possible to free memory
|
||||
# of keys that are expired and will never be accessed again in a short time.
|
||||
#
|
||||
# The default effort of the expire cycle will try to avoid having more than
|
||||
# ten percent of expired keys still in memory, and will try to avoid consuming
|
||||
# more than 25% of total memory and to add latency to the system. However
|
||||
# it is possible to increase the expire "effort" that is normally set to
|
||||
# "1", to a greater value, up to the value "10". At its maximum value the
|
||||
# system will use more CPU, longer cycles (and technically may introduce
|
||||
# more latency), and will tolerate less already expired keys still present
|
||||
# in the system. It's a tradeoff between memory, CPU and latency.
|
||||
#
|
||||
# active-expire-effort 1
|
||||
|
||||
############################# LAZY FREEING ####################################
|
||||
|
||||
# KeyDB has two primitives to delete keys. One is called DEL and is a blocking
|
||||
@@ -787,13 +997,51 @@ replica-priority 100
|
||||
# In all the above cases the default is to delete objects in a blocking way,
|
||||
# like if DEL was called. However you can configure each case specifically
|
||||
# in order to instead release memory in a non-blocking way like if UNLINK
|
||||
# was called, using the following configuration directives:
|
||||
# was called, using the following configuration directives.
|
||||
|
||||
lazyfree-lazy-eviction no
|
||||
lazyfree-lazy-expire no
|
||||
lazyfree-lazy-server-del no
|
||||
replica-lazy-flush no
|
||||
|
||||
# It is also possible, for the case when to replace the user code DEL calls
|
||||
# with UNLINK calls is not easy, to modify the default behavior of the DEL
|
||||
# command to act exactly like UNLINK, using the following configuration
|
||||
# directive:
|
||||
|
||||
lazyfree-lazy-user-del no
|
||||
|
||||
############################ KERNEL OOM CONTROL ##############################
|
||||
|
||||
# On Linux, it is possible to hint the kernel OOM killer on what processes
|
||||
# should be killed first when out of memory.
|
||||
#
|
||||
# Enabling this feature makes KeyDB actively control the oom_score_adj value
|
||||
# for all its processes, depending on their role. The default scores will
|
||||
# attempt to have background child processes killed before all others, and
|
||||
# replicas killed before masters.
|
||||
#
|
||||
# KeyDB supports three options:
|
||||
#
|
||||
# no: Don't make changes to oom-score-adj (default).
|
||||
# yes: Alias to "relative" see below.
|
||||
# absolute: Values in oom-score-adj-values are written as is to the kernel.
|
||||
# relative: Values are used relative to the initial value of oom_score_adj when
|
||||
# the server starts and are then clamped to a range of -1000 to 1000.
|
||||
# Because typically the initial value is 0, they will often match the
|
||||
# absolute values.
|
||||
oom-score-adj no
|
||||
|
||||
# When oom-score-adj is used, this directive controls the specific values used
|
||||
# for master, replica and background child processes. Values range -2000 to
|
||||
# 2000 (higher means more likely to be killed).
|
||||
#
|
||||
# Unprivileged processes (not root, and without CAP_SYS_RESOURCE capabilities)
|
||||
# can freely increase their value, but not decrease it below its initial
|
||||
# settings. This means that setting oom-score-adj to "relative" and setting the
|
||||
# oom-score-adj-values to positive values will always succeed.
|
||||
oom-score-adj-values 0 200 800
|
||||
|
||||
############################## APPEND ONLY MODE ###############################
|
||||
|
||||
# By default KeyDB asynchronously dumps the dataset on disk. This mode is
|
||||
@@ -918,8 +1166,8 @@ aof-load-truncated yes
|
||||
#
|
||||
# [RDB file][AOF tail]
|
||||
#
|
||||
# When loading KeyDB recognizes that the AOF file starts with the "REDIS"
|
||||
# string and loads the prefixed RDB file, and continues loading the AOF
|
||||
# When loading, KeyDB recognizes that the AOF file starts with the "REDIS"
|
||||
# string and loads the prefixed RDB file, then continues loading the AOF
|
||||
# tail.
|
||||
aof-use-rdb-preamble yes
|
||||
|
||||
@@ -933,7 +1181,7 @@ aof-use-rdb-preamble yes
|
||||
#
|
||||
# When a long running script exceeds the maximum execution time only the
|
||||
# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be
|
||||
# used to stop a script that did not yet called write commands. The second
|
||||
# used to stop a script that did not yet call any write commands. The second
|
||||
# is the only way to shut down the server in the case a write command was
|
||||
# already issued by the script but the user doesn't want to wait for the natural
|
||||
# termination of the script.
|
||||
@@ -959,7 +1207,7 @@ lua-time-limit 5000
|
||||
|
||||
# Cluster node timeout is the amount of milliseconds a node must be unreachable
|
||||
# for it to be considered in failure state.
|
||||
# Most other internal time limits are multiple of the node timeout.
|
||||
# Most other internal time limits are a multiple of the node timeout.
|
||||
#
|
||||
# cluster-node-timeout 15000
|
||||
|
||||
@@ -986,18 +1234,18 @@ lua-time-limit 5000
|
||||
# the failover if, since the last interaction with the master, the time
|
||||
# elapsed is greater than:
|
||||
#
|
||||
# (node-timeout * replica-validity-factor) + repl-ping-replica-period
|
||||
# (node-timeout * cluster-replica-validity-factor) + repl-ping-replica-period
|
||||
#
|
||||
# So for example if node-timeout is 30 seconds, and the replica-validity-factor
|
||||
# So for example if node-timeout is 30 seconds, and the cluster-replica-validity-factor
|
||||
# is 10, and assuming a default repl-ping-replica-period of 10 seconds, the
|
||||
# replica will not try to failover if it was not able to talk with the master
|
||||
# for longer than 310 seconds.
|
||||
#
|
||||
# A large replica-validity-factor may allow replicas with too old data to failover
|
||||
# A large cluster-replica-validity-factor may allow replicas with too old data to failover
|
||||
# a master, while a too small value may prevent the cluster from being able to
|
||||
# elect a replica at all.
|
||||
#
|
||||
# For maximum availability, it is possible to set the replica-validity-factor
|
||||
# For maximum availability, it is possible to set the cluster-replica-validity-factor
|
||||
# to a value of 0, which means, that replicas will always try to failover the
|
||||
# master regardless of the last time they interacted with the master.
|
||||
# (However they'll always try to apply a delay proportional to their
|
||||
@@ -1028,7 +1276,7 @@ lua-time-limit 5000
|
||||
# cluster-migration-barrier 1
|
||||
|
||||
# By default KeyDB Cluster nodes stop accepting queries if they detect there
|
||||
# is at least an hash slot uncovered (no available node is serving it).
|
||||
# is at least a hash slot uncovered (no available node is serving it).
|
||||
# This way if the cluster is partially down (for example a range of hash slots
|
||||
# are no longer covered) all the cluster becomes, eventually, unavailable.
|
||||
# It automatically returns available as soon as all the slots are covered again.
|
||||
@@ -1050,6 +1298,22 @@ lua-time-limit 5000
|
||||
#
|
||||
# cluster-replica-no-failover no
|
||||
|
||||
# This option, when set to yes, allows nodes to serve read traffic while the
|
||||
# the cluster is in a down state, as long as it believes it owns the slots.
|
||||
#
|
||||
# This is useful for two cases. The first case is for when an application
|
||||
# doesn't require consistency of data during node failures or network partitions.
|
||||
# One example of this is a cache, where as long as the node has the data it
|
||||
# should be able to serve it.
|
||||
#
|
||||
# The second use case is for configurations that don't meet the recommended
|
||||
# three shards but want to enable cluster mode and scale later. A
|
||||
# master outage in a 1 or 2 shard configuration causes a read/write outage to the
|
||||
# entire cluster without this option set, with it set there is only a write outage.
|
||||
# Without a quorum of masters, slot ownership will not change automatically.
|
||||
#
|
||||
# cluster-allow-reads-when-down no
|
||||
|
||||
# In order to setup your cluster make sure to read the documentation
|
||||
# available at http://redis.io web site.
|
||||
|
||||
@@ -1067,7 +1331,7 @@ lua-time-limit 5000
|
||||
# * cluster-announce-port
|
||||
# * cluster-announce-bus-port
|
||||
#
|
||||
# Each instruct the node about its address, client port, and cluster message
|
||||
# Each instructs the node about its address, client port, and cluster message
|
||||
# bus port. The information is then published in the header of the bus packets
|
||||
# so that other nodes will be able to correctly map the address of the node
|
||||
# publishing the information.
|
||||
@@ -1078,7 +1342,7 @@ lua-time-limit 5000
|
||||
# Note that when remapped, the bus port may not be at the fixed offset of
|
||||
# clients port + 10000, so you can specify any port and bus-port depending
|
||||
# on how they get remapped. If the bus-port is not set, a fixed offset of
|
||||
# 10000 will be used as usually.
|
||||
# 10000 will be used as usual.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
@@ -1156,7 +1420,11 @@ latency-monitor-threshold 0
|
||||
# z Sorted set commands
|
||||
# x Expired events (events generated every time a key expires)
|
||||
# e Evicted events (events generated when a key is evicted for maxmemory)
|
||||
# A Alias for g$lshzxe, so that the "AKE" string means all the events.
|
||||
# t Stream commands
|
||||
# m Key-miss events (Note: It is not included in the 'A' class)
|
||||
# A Alias for g$lshzxet, so that the "AKE" string means all the events
|
||||
# (Except key-miss events which are excluded from 'A' due to their
|
||||
# unique nature).
|
||||
#
|
||||
# The "notify-keyspace-events" takes as argument a string that is composed
|
||||
# of zero or multiple characters. The empty string means that notifications
|
||||
@@ -1177,61 +1445,6 @@ latency-monitor-threshold 0
|
||||
# specify at least one of K or E, no events will be delivered.
|
||||
notify-keyspace-events ""
|
||||
|
||||
############################### GOPHER SERVER #################################
|
||||
|
||||
# KeyDB contains an implementation of the Gopher protocol, as specified in
|
||||
# the RFC 1436 (https://www.ietf.org/rfc/rfc1436.txt).
|
||||
#
|
||||
# The Gopher protocol was very popular in the late '90s. It is an alternative
|
||||
# to the web, and the implementation both server and client side is so simple
|
||||
# that the KeyDB server has just 100 lines of code in order to implement this
|
||||
# support.
|
||||
#
|
||||
# What do you do with Gopher nowadays? Well Gopher never *really* died, and
|
||||
# lately there is a movement in order for the Gopher more hierarchical content
|
||||
# composed of just plain text documents to be resurrected. Some want a simpler
|
||||
# internet, others believe that the mainstream internet became too much
|
||||
# controlled, and it's cool to create an alternative space for people that
|
||||
# want a bit of fresh air.
|
||||
#
|
||||
# Anyway for the 10nth birthday of the KeyDB, we gave it the Gopher protocol
|
||||
# as a gift.
|
||||
#
|
||||
# --- HOW IT WORKS? ---
|
||||
#
|
||||
# The KeyDB Gopher support uses the inline protocol of KeyDB, and specifically
|
||||
# two kind of inline requests that were anyway illegal: an empty request
|
||||
# or any request that starts with "/" (there are no KeyDB commands starting
|
||||
# with such a slash). Normal RESP2/RESP3 requests are completely out of the
|
||||
# path of the Gopher protocol implementation and are served as usually as well.
|
||||
#
|
||||
# If you open a connection to KeyDB when Gopher is enabled and send it
|
||||
# a string like "/foo", if there is a key named "/foo" it is served via the
|
||||
# Gopher protocol.
|
||||
#
|
||||
# In order to create a real Gopher "hole" (the name of a Gopher site in Gopher
|
||||
# talking), you likely need a script like the following:
|
||||
#
|
||||
# https://github.com/antirez/gopher2redis
|
||||
#
|
||||
# --- SECURITY WARNING ---
|
||||
#
|
||||
# If you plan to put KeyDB on the internet in a publicly accessible address
|
||||
# to server Gopher pages MAKE SURE TO SET A PASSWORD to the instance.
|
||||
# Once a password is set:
|
||||
#
|
||||
# 1. The Gopher server (when enabled, not by default) will kill serve
|
||||
# content via Gopher.
|
||||
# 2. However other commands cannot be called before the client will
|
||||
# authenticate.
|
||||
#
|
||||
# So use the 'requirepass' option to protect your instance.
|
||||
#
|
||||
# To enable Gopher support uncomment the following line and set
|
||||
# the option from no (the default) to yes.
|
||||
#
|
||||
# gopher-enabled no
|
||||
|
||||
############################### ADVANCED CONFIG ###############################
|
||||
|
||||
# Hashes are encoded using a memory efficient data structure when they have a
|
||||
@@ -1375,8 +1588,8 @@ client-output-buffer-limit pubsub 32mb 8mb 60
|
||||
# client-query-buffer-limit 1gb
|
||||
|
||||
# In the KeyDB protocol, bulk requests, that are, elements representing single
|
||||
# strings, are normally limited ot 512 mb. However you can change this limit
|
||||
# here.
|
||||
# strings, are normally limited to 512 mb. However you can change this limit
|
||||
# here, but must be 1mb or greater
|
||||
#
|
||||
# proto-max-bulk-len 512mb
|
||||
|
||||
@@ -1404,9 +1617,9 @@ hz 10
|
||||
#
|
||||
# Since the default HZ value by default is conservatively set to 10, KeyDB
|
||||
# offers, and enables by default, the ability to use an adaptive HZ value
|
||||
# which will temporary raise when there are many connected clients.
|
||||
# which will temporarily raise when there are many connected clients.
|
||||
#
|
||||
# When dynamic HZ is enabled, the actual configured HZ will be used as
|
||||
# When dynamic HZ is enabled, the actual configured HZ will be used
|
||||
# as a baseline, but multiples of the configured HZ value will be actually
|
||||
# used as needed once more clients are connected. In this way an idle
|
||||
# instance will use very little CPU time while a busy instance will be
|
||||
@@ -1471,7 +1684,7 @@ rdb-save-incremental-fsync yes
|
||||
# for the key counter to be divided by two (or decremented if it has a value
|
||||
# less <= 10).
|
||||
#
|
||||
# The default value for the lfu-decay-time is 1. A Special value of 0 means to
|
||||
# The default value for the lfu-decay-time is 1. A special value of 0 means to
|
||||
# decay the counter every time it happens to be scanned.
|
||||
#
|
||||
# lfu-log-factor 10
|
||||
@@ -1479,10 +1692,6 @@ rdb-save-incremental-fsync yes
|
||||
|
||||
########################### ACTIVE DEFRAGMENTATION #######################
|
||||
#
|
||||
# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested
|
||||
# even in production and manually tested by multiple engineers for some
|
||||
# time.
|
||||
#
|
||||
# What is active defragmentation?
|
||||
# -------------------------------
|
||||
#
|
||||
@@ -1495,7 +1704,7 @@ rdb-save-incremental-fsync yes
|
||||
# restart is needed in order to lower the fragmentation, or at least to flush
|
||||
# away all the data and create it again. However thanks to this feature
|
||||
# implemented by Oran Agra for Redis 4.0 this process can happen at runtime
|
||||
# in an "hot" way, while the server is running.
|
||||
# in a "hot" way, while the server is running.
|
||||
#
|
||||
# Basically when the fragmentation is over a certain level (see the
|
||||
# configuration options below) KeyDB will start to create new copies of the
|
||||
@@ -1522,7 +1731,7 @@ rdb-save-incremental-fsync yes
|
||||
# a good idea to leave the defaults untouched.
|
||||
|
||||
# Enabled active defragmentation
|
||||
# activedefrag yes
|
||||
# activedefrag no
|
||||
|
||||
# Minimum amount of fragmentation waste to start active defrag
|
||||
# active-defrag-ignore-bytes 100mb
|
||||
@@ -1533,16 +1742,71 @@ rdb-save-incremental-fsync yes
|
||||
# Maximum percentage of fragmentation at which we use maximum effort
|
||||
# active-defrag-threshold-upper 100
|
||||
|
||||
# Minimal effort for defrag in CPU percentage
|
||||
# active-defrag-cycle-min 5
|
||||
# Minimal effort for defrag in CPU percentage, to be used when the lower
|
||||
# threshold is reached
|
||||
# active-defrag-cycle-min 1
|
||||
|
||||
# Maximal effort for defrag in CPU percentage
|
||||
# active-defrag-cycle-max 75
|
||||
# Maximal effort for defrag in CPU percentage, to be used when the upper
|
||||
# threshold is reached
|
||||
# active-defrag-cycle-max 25
|
||||
|
||||
# Maximum number of set/hash/zset/list fields that will be processed from
|
||||
# the main dictionary scan
|
||||
# active-defrag-max-scan-fields 1000
|
||||
|
||||
# Jemalloc background thread for purging will be enabled by default
|
||||
jemalloc-bg-thread yes
|
||||
|
||||
# It is possible to pin different threads and processes of KeyDB to specific
|
||||
# CPUs in your system, in order to maximize the performances of the server.
|
||||
# This is useful both in order to pin different KeyDB threads in different
|
||||
# CPUs, but also in order to make sure that multiple KeyDB instances running
|
||||
# in the same host will be pinned to different CPUs.
|
||||
#
|
||||
# Normally you can do this using the "taskset" command, however it is also
|
||||
# possible to this via KeyDB configuration directly, both in Linux and FreeBSD.
|
||||
#
|
||||
# You can pin the server/IO threads, bio threads, aof rewrite child process, and
|
||||
# the bgsave child process. The syntax to specify the cpu list is the same as
|
||||
# the taskset command:
|
||||
#
|
||||
# Set redis server/io threads to cpu affinity 0,2,4,6:
|
||||
# server_cpulist 0-7:2
|
||||
#
|
||||
# Set bio threads to cpu affinity 1,3:
|
||||
# bio_cpulist 1,3
|
||||
#
|
||||
# Set aof rewrite child process to cpu affinity 8,9,10,11:
|
||||
# aof_rewrite_cpulist 8-11
|
||||
#
|
||||
# Set bgsave child process to cpu affinity 1,10,11
|
||||
# bgsave_cpulist 1,10-11
|
||||
|
||||
# In some cases KeyDB will emit warnings and even refuse to start if it detects
|
||||
# that the system is in bad state, it is possible to suppress these warnings
|
||||
# by setting the following config which takes a space delimited list of warnings
|
||||
# to suppress
|
||||
#
|
||||
# ignore-warnings ARM64-COW-BUG
|
||||
|
||||
# The minimum number of clients on a thread before KeyDB assigns new connections to a different thread
|
||||
# Tuning this parameter is a tradeoff between locking overhead and distributing the workload over multiple cores
|
||||
# min-clients-per-thread 50
|
||||
|
||||
# How often to run RDB load progress callback?
|
||||
# The callback runs during key load to ping other servers and prevent timeouts.
|
||||
# It also updates load time estimates.
|
||||
# Change these values to run it more or less often. It will run when either condition is true.
|
||||
# Either when x bytes have been processed, or when x keys have been loaded.
|
||||
# loading-process-events-interval-bytes 2097152
|
||||
# loading-process-events-interval-keys 8192
|
||||
|
||||
# Avoid forwarding RREPLAY messages to other masters?
|
||||
# WARNING: This setting is dangerous! You must be certain all masters are connected to each
|
||||
# other in a true mesh topology or data loss will occur!
|
||||
# This command can be used to reduce multimaster bus traffic
|
||||
# multi-master-no-forward no
|
||||
|
||||
# Path to directory for file backed scratchpad. The file backed scratchpad
|
||||
# reduces memory requirements by storing rarely accessed data on disk
|
||||
# instead of RAM. A temporary file will be created in this directory.
|
||||
@@ -1551,6 +1815,8 @@ rdb-save-incremental-fsync yes
|
||||
# Number of worker threads serving requests. This number should be related to the performance
|
||||
# of your network hardware, not the number of cores on your machine. We don't recommend going
|
||||
# above 4 at this time. By default this is set 1.
|
||||
#
|
||||
# Note: KeyDB does not use io-threads, but io-threads is a config alias for server-threads
|
||||
server-threads 2
|
||||
|
||||
# Should KeyDB pin threads to CPUs? By default this is disabled, and KeyDB will not bind threads.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
### KeyDB Packaging
|
||||
|
||||
The following directories contain packaging code used to create rpm and deb packages as well as docker images.
|
||||
@@ -0,0 +1,21 @@
|
||||
### KeyDB DEB Package Source Builds
|
||||
|
||||
This directory contains scripts and components needed to generate debian packages on different distributions/architectures from source
|
||||
|
||||
The 'debian' directory contains debian source code for bionic, buster and later distributions as it uses functions only available with debhelper11+. 'debian_dh9' is used for xenial, stretch and earlier distributions using debhelper9.
|
||||
|
||||
You will need to install pbuilder `sudo apt install pbuilder` along with other distribution specific dependancies
|
||||
|
||||
Generate deb packages with the following script command run from this directory:
|
||||
|
||||
```
|
||||
$ ./deb-buildsource.sh
|
||||
```
|
||||
|
||||
This generates a directory structure, .dsc file, original.tar.gz, and new changelog for the distribution and architecture installed.
|
||||
|
||||
When complete the produced debian packages will be located in deb_files_generated directory.
|
||||
|
||||
Arguments for the deb-buildsource.sh script that can be passed are either 'None' or '"your custom comments"'. 'None' assumes a permanent changelog entry has been made listing the correct build for the version. If you quote and enter your own comment string, it will be appended to the changelog for that deb package. If no argument is passed a default comment is generated saying that this deb package was generated by this script.
|
||||
|
||||
This script has been tested on xenial/bionic/stretch/buster
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,244 @@
|
||||
# Example sentinel.conf
|
||||
|
||||
# *** IMPORTANT ***
|
||||
#
|
||||
# By default Sentinel will not be reachable from interfaces different than
|
||||
# localhost, either use the 'bind' directive to bind to a list of network
|
||||
# interfaces, or disable protected mode with "protected-mode no" by
|
||||
# adding it to this configuration file.
|
||||
#
|
||||
# Before doing that MAKE SURE the instance is protected from the outside
|
||||
# world via firewalling or other means.
|
||||
#
|
||||
# For example you may use one of the following:
|
||||
#
|
||||
# bind 127.0.0.1 192.168.1.1
|
||||
#
|
||||
# protected-mode no
|
||||
|
||||
# port <sentinel-port>
|
||||
# The port that this sentinel instance will run on
|
||||
port 26379
|
||||
|
||||
# By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it.
|
||||
# Note that Redis will write a pid file in /var/run/keydb-sentinel.pid when
|
||||
# daemonized.
|
||||
daemonize yes
|
||||
|
||||
# When running daemonized, Redis Sentinel writes a pid file in
|
||||
# /var/run/keydb-sentinel.pid by default. You can specify a custom pid file
|
||||
# location here.
|
||||
pidfile /var/run/sentinel/keydb-sentinel.pid
|
||||
|
||||
# Specify the log file name. Also the empty string can be used to force
|
||||
# Sentinel to log on the standard output. Note that if you use standard
|
||||
# output for logging but daemonize, logs will be sent to /dev/null
|
||||
logfile /var/log/keydb/keydb-sentinel.log
|
||||
|
||||
# sentinel announce-ip <ip>
|
||||
# sentinel announce-port <port>
|
||||
#
|
||||
# The above two configuration directives are useful in environments where,
|
||||
# because of NAT, Sentinel is reachable from outside via a non-local address.
|
||||
#
|
||||
# When announce-ip is provided, the Sentinel will claim the specified IP address
|
||||
# in HELLO messages used to gossip its presence, instead of auto-detecting the
|
||||
# local address as it usually does.
|
||||
#
|
||||
# Similarly when announce-port is provided and is valid and non-zero, Sentinel
|
||||
# will announce the specified TCP port.
|
||||
#
|
||||
# The two options don't need to be used together, if only announce-ip is
|
||||
# provided, the Sentinel will announce the specified IP and the server port
|
||||
# as specified by the "port" option. If only announce-port is provided, the
|
||||
# Sentinel will announce the auto-detected local IP and the specified port.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# sentinel announce-ip 1.2.3.4
|
||||
|
||||
# dir <working-directory>
|
||||
# Every long running process should have a well-defined working directory.
|
||||
# For Redis Sentinel to chdir to /tmp at startup is the simplest thing
|
||||
# for the process to don't interfere with administrative tasks such as
|
||||
# unmounting filesystems.
|
||||
dir /var/lib/keydb
|
||||
|
||||
# sentinel monitor <master-name> <ip> <keydb-port> <quorum>
|
||||
#
|
||||
# Tells Sentinel to monitor this master, and to consider it in O_DOWN
|
||||
# (Objectively Down) state only if at least <quorum> sentinels agree.
|
||||
#
|
||||
# Note that whatever is the ODOWN quorum, a Sentinel will require to
|
||||
# be elected by the majority of the known Sentinels in order to
|
||||
# start a failover, so no failover can be performed in minority.
|
||||
#
|
||||
# Replicas are auto-discovered, so you don't need to specify replicas in
|
||||
# any way. Sentinel itself will rewrite this configuration file adding
|
||||
# the replicas using additional configuration options.
|
||||
# Also note that the configuration file is rewritten when a
|
||||
# replica is promoted to master.
|
||||
#
|
||||
# Note: master name should not include special characters or spaces.
|
||||
# The valid charset is A-z 0-9 and the three characters ".-_".
|
||||
sentinel monitor mymaster 127.0.0.1 6379 2
|
||||
|
||||
# sentinel auth-pass <master-name> <password>
|
||||
#
|
||||
# Set the password to use to authenticate with the master and replicas.
|
||||
# Useful if there is a password set in the Redis instances to monitor.
|
||||
#
|
||||
# Note that the master password is also used for replicas, so it is not
|
||||
# possible to set a different password in masters and replicas instances
|
||||
# if you want to be able to monitor these instances with Sentinel.
|
||||
#
|
||||
# However you can have Redis instances without the authentication enabled
|
||||
# mixed with Redis instances requiring the authentication (as long as the
|
||||
# password set is the same for all the instances requiring the password) as
|
||||
# the AUTH command will have no effect in Redis instances with authentication
|
||||
# switched off.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
|
||||
|
||||
# sentinel down-after-milliseconds <master-name> <milliseconds>
|
||||
#
|
||||
# Number of milliseconds the master (or any attached replica or sentinel) should
|
||||
# be unreachable (as in, not acceptable reply to PING, continuously, for the
|
||||
# specified period) in order to consider it in S_DOWN state (Subjectively
|
||||
# Down).
|
||||
#
|
||||
# Default is 30 seconds.
|
||||
sentinel down-after-milliseconds mymaster 30000
|
||||
|
||||
# sentinel parallel-syncs <master-name> <numreplicas>
|
||||
#
|
||||
# How many replicas we can reconfigure to point to the new replica simultaneously
|
||||
# during the failover. Use a low number if you use the replicas to serve query
|
||||
# to avoid that all the replicas will be unreachable at about the same
|
||||
# time while performing the synchronization with the master.
|
||||
sentinel parallel-syncs mymaster 1
|
||||
|
||||
# sentinel failover-timeout <master-name> <milliseconds>
|
||||
#
|
||||
# Specifies the failover timeout in milliseconds. It is used in many ways:
|
||||
#
|
||||
# - The time needed to re-start a failover after a previous failover was
|
||||
# already tried against the same master by a given Sentinel, is two
|
||||
# times the failover timeout.
|
||||
#
|
||||
# - The time needed for a replica replicating to a wrong master according
|
||||
# to a Sentinel current configuration, to be forced to replicate
|
||||
# with the right master, is exactly the failover timeout (counting since
|
||||
# the moment a Sentinel detected the misconfiguration).
|
||||
#
|
||||
# - The time needed to cancel a failover that is already in progress but
|
||||
# did not produced any configuration change (SLAVEOF NO ONE yet not
|
||||
# acknowledged by the promoted replica).
|
||||
#
|
||||
# - The maximum time a failover in progress waits for all the replicas to be
|
||||
# reconfigured as replicas of the new master. However even after this time
|
||||
# the replicas will be reconfigured by the Sentinels anyway, but not with
|
||||
# the exact parallel-syncs progression as specified.
|
||||
#
|
||||
# Default is 3 minutes.
|
||||
sentinel failover-timeout mymaster 180000
|
||||
|
||||
# SCRIPTS EXECUTION
|
||||
#
|
||||
# sentinel notification-script and sentinel reconfig-script are used in order
|
||||
# to configure scripts that are called to notify the system administrator
|
||||
# or to reconfigure clients after a failover. The scripts are executed
|
||||
# with the following rules for error handling:
|
||||
#
|
||||
# If script exits with "1" the execution is retried later (up to a maximum
|
||||
# number of times currently set to 10).
|
||||
#
|
||||
# If script exits with "2" (or an higher value) the script execution is
|
||||
# not retried.
|
||||
#
|
||||
# If script terminates because it receives a signal the behavior is the same
|
||||
# as exit code 1.
|
||||
#
|
||||
# A script has a maximum running time of 60 seconds. After this limit is
|
||||
# reached the script is terminated with a SIGKILL and the execution retried.
|
||||
|
||||
# NOTIFICATION SCRIPT
|
||||
#
|
||||
# sentinel notification-script <master-name> <script-path>
|
||||
#
|
||||
# Call the specified notification script for any sentinel event that is
|
||||
# generated in the WARNING level (for instance -sdown, -odown, and so forth).
|
||||
# This script should notify the system administrator via email, SMS, or any
|
||||
# other messaging system, that there is something wrong with the monitored
|
||||
# Redis systems.
|
||||
#
|
||||
# The script is called with just two arguments: the first is the event type
|
||||
# and the second the event description.
|
||||
#
|
||||
# The script must exist and be executable in order for sentinel to start if
|
||||
# this option is provided.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# sentinel notification-script mymaster /var/redis/notify.sh
|
||||
|
||||
# CLIENTS RECONFIGURATION SCRIPT
|
||||
#
|
||||
# sentinel client-reconfig-script <master-name> <script-path>
|
||||
#
|
||||
# When the master changed because of a failover a script can be called in
|
||||
# order to perform application-specific tasks to notify the clients that the
|
||||
# configuration has changed and the master is at a different address.
|
||||
#
|
||||
# The following arguments are passed to the script:
|
||||
#
|
||||
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
|
||||
#
|
||||
# <state> is currently always "failover"
|
||||
# <role> is either "leader" or "observer"
|
||||
#
|
||||
# The arguments from-ip, from-port, to-ip, to-port are used to communicate
|
||||
# the old address of the master and the new address of the elected replica
|
||||
# (now a master).
|
||||
#
|
||||
# This script should be resistant to multiple invocations.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
|
||||
|
||||
# SECURITY
|
||||
#
|
||||
# By default SENTINEL SET will not be able to change the notification-script
|
||||
# and client-reconfig-script at runtime. This avoids a trivial security issue
|
||||
# where clients can set the script to anything and trigger a failover in order
|
||||
# to get the program executed.
|
||||
|
||||
sentinel deny-scripts-reconfig yes
|
||||
|
||||
# REDIS COMMANDS RENAMING
|
||||
#
|
||||
# Sometimes the Redis server has certain commands, that are needed for Sentinel
|
||||
# to work correctly, renamed to unguessable strings. This is often the case
|
||||
# of CONFIG and SLAVEOF in the context of providers that provide Redis as
|
||||
# a service, and don't want the customers to reconfigure the instances outside
|
||||
# of the administration console.
|
||||
#
|
||||
# In such case it is possible to tell Sentinel to use different command names
|
||||
# instead of the normal ones. For example if the master "mymaster", and the
|
||||
# associated replicas, have "CONFIG" all renamed to "GUESSME", I could use:
|
||||
#
|
||||
# SENTINEL rename-command mymaster CONFIG GUESSME
|
||||
#
|
||||
# After such configuration is set, every time Sentinel would use CONFIG it will
|
||||
# use GUESSME instead. Note that there is no actual need to respect the command
|
||||
# case, so writing "config guessme" is the same in the example above.
|
||||
#
|
||||
# SENTINEL SET can also be used in order to perform this configuration at runtime.
|
||||
#
|
||||
# In order to set a command back to its original name (undo the renaming), it
|
||||
# is possible to just rename a command to itsef:
|
||||
#
|
||||
# SENTINEL rename-command mymaster CONFIG CONFIG
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#! /bin/bash
|
||||
|
||||
# define parameters used in this deb package build
|
||||
# enter comments as an argument string quoted. If you do not want comments to be added (ie. you have updated in git repo) type None
|
||||
if [ $# -eq 0 ]; then
|
||||
changelog_comments="This is a new source build generated from the deb_build_source.sh script"
|
||||
else
|
||||
changelog_comments=$1
|
||||
fi
|
||||
echo $changelog_comments
|
||||
build=1 #change if updated build number required. Default is 1 as convention for keydb is to update minor version
|
||||
version=$(grep KEYDB_REAL_VERSION ../../src/version.h | awk '{ printf $3 }' | tr -d \")
|
||||
majorv="${version:0:1}"
|
||||
distributor=$(lsb_release --id --short)
|
||||
if [ "$distributor" == "Debian" ]; then
|
||||
distname=+deb$(lsb_release --release --short | cut -d. -f1)u1
|
||||
elif [ "$distributor" == "Ubuntu" ]; then
|
||||
distname=~$(lsb_release --codename --short)1
|
||||
fi
|
||||
codename=$(lsb_release --codename --short)
|
||||
date=$(date +%a," "%d" "%b" "%Y" "%T)
|
||||
pkg_name=keydb-$majorv:$version$distname
|
||||
|
||||
# create build tree
|
||||
cd ../../../
|
||||
tar -czvf keydb_$version.orig.tar.gz --force-local KeyDB
|
||||
cd KeyDB/pkg/deb/
|
||||
mkdir -p $pkg_name/tmp
|
||||
if [[ "$codename" == "xenial" ]] || [[ "$codename" == "stretch" ]]; then
|
||||
cp -r debian_dh9 $pkg_name/tmp/debian
|
||||
else
|
||||
cp -r debian $pkg_name/tmp
|
||||
fi
|
||||
cp master_changelog $pkg_name/tmp/debian/changelog
|
||||
mv ../../../keydb_$version.orig.tar.gz ./$pkg_name
|
||||
cd $pkg_name/tmp
|
||||
changelog_str="keydb ($majorv:$version-$build$distname) $codename; urgency=medium\n\n * $version $changelog_comments \n\n -- Ben Schermel <ben@eqalpha.com> $date +0000\n\n"
|
||||
if [ $# -eq 0 ]; then
|
||||
sed -i "1s/^/$changelog_str\n/" debian/changelog
|
||||
elif [ $# -eq 1 ] && [ "$1" != "None" ]; then
|
||||
sed -i "1s/^/$changelog_str\n/" debian/changelog
|
||||
fi
|
||||
sed -i "s/distribution_placeholder/$distname/g" debian/changelog
|
||||
sed -i "s/codename_placeholder/$codename/g" debian/changelog
|
||||
|
||||
# generate required files and structure for pbuilder including .dsc file
|
||||
debuild -S -sa
|
||||
cd ../
|
||||
|
||||
# create pbuilder chrooted environment and build the deb package
|
||||
if [ "$codename" == "xenial" ]; then
|
||||
sudo pbuilder create --distribution $codename --othermirror "deb http://archive.ubuntu.com/ubuntu $codename universe multiverse"
|
||||
else
|
||||
sudo pbuilder create --distribution $codename
|
||||
fi
|
||||
sudo pbuilder --update
|
||||
sudo pbuilder --build *.dsc
|
||||
|
||||
# move new packages to deb_files_generated and clean up
|
||||
cp /var/cache/pbuilder/result/*$version*.deb ../deb_files_generated
|
||||
sudo pbuilder clean
|
||||
cd ../
|
||||
rm -rf $pkg_name
|
||||
Whitespace-only changes.
@@ -0,0 +1,30 @@
|
||||
# -*- sh -*-
|
||||
#
|
||||
# Bash completion function for the 'keydb-cli' command.
|
||||
#
|
||||
# Steve
|
||||
# --
|
||||
# http://www.steve.org.uk
|
||||
#
|
||||
|
||||
_keydb-cli()
|
||||
{
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
#
|
||||
# All known commands accepted. Sorted.
|
||||
#
|
||||
opts='bgrewriteaof bgsave dbsize debug decr decrby del echo exists expire expireat flushall flushdb get getset incr incrby info keys lastsave lindex llen lpop lpush lrange lrem lset ltrim mget move mset msetnx ping randomkey rename renamenx rewriteaof rpop rpoplpush rpush sadd save scard sdiff sdiffstore select set setnx shutdown sinter sinterstore sismember slaveof smembers smove sort spop srandmember srem sunion sunionstore ttl type zadd zcard zincrby zrange zrangebyscore zrem zremrangebyscore zrevrange zscore'
|
||||
|
||||
#
|
||||
# Only complete on the first term.
|
||||
#
|
||||
if [ $COMP_CWORD -eq 1 ]; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
}
|
||||
complete -F _keydb-cli keydb-cli
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
#!/bin/sh
|
||||
|
||||
SYSTEMD_VER=$(systemctl --version | head -1 | cut -d' ' -f2)
|
||||
|
||||
if [ ${SYSTEMD_VER} -lt 237 ]
|
||||
then
|
||||
SYSTEMD_EXTRA=""
|
||||
else
|
||||
SYSTEMD_EXTRA=$(cat <<EOF
|
||||
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
#MemoryDenyWriteExecute=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectControlGroups=true
|
||||
RestrictRealtime=true
|
||||
RestrictNamespaces=true
|
||||
EOF
|
||||
)
|
||||
fi
|
||||
|
||||
for BINARY in keydb-server keydb-sentinel
|
||||
do
|
||||
for MODE in default templated
|
||||
do
|
||||
case "${BINARY}" in
|
||||
keydb-server)
|
||||
NAME="keydb"
|
||||
;;
|
||||
keydb-sentinel)
|
||||
NAME="sentinel"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${MODE}" in
|
||||
default)
|
||||
EXTRA="Alias=${NAME}.service"
|
||||
TARGET="debian/${BINARY}.service"
|
||||
NAMESPACED="${NAME}"
|
||||
DESCRIPTION="Advanced key-value store"
|
||||
;;
|
||||
templated)
|
||||
EXTRA=""
|
||||
TARGET="debian/${BINARY}@.service"
|
||||
NAMESPACED="${NAME}-%i"
|
||||
DESCRIPTION="Advanced key-value store (%I)"
|
||||
;;
|
||||
esac
|
||||
|
||||
: >${TARGET}
|
||||
|
||||
if [ "${MODE}" = "templated" ]
|
||||
then
|
||||
cat >> ${TARGET} <<EOF
|
||||
# Templated service file for ${BINARY}(1)
|
||||
#
|
||||
# Each instance of ${BINARY} requires its own configuration file:
|
||||
#
|
||||
# $ cp /etc/keydb/${NAME}.conf /etc/keydb/${NAME}-myname.conf
|
||||
# $ chown keydb:keydb /etc/keydb/${NAME}-myname.conf
|
||||
#
|
||||
# Ensure each instance is using their own database:
|
||||
#
|
||||
# $ sed -i -e 's@^dbfilename .*@dbfilename dump-myname.rdb@' /etc/keydb/${NAME}-myname.conf
|
||||
#
|
||||
# We then listen exlusively on UNIX sockets to avoid TCP port collisions:
|
||||
#
|
||||
# $ sed -i -e 's@^port .*@port 0@' /etc/keydb/${NAME}-myname.conf
|
||||
# $ sed -i -e 's@^\\(# \\)\\{0,1\\}unixsocket .*@unixsocket /var/run/${NAME}-myname/${BINARY}.sock@' /etc/keydb/${NAME}-myname.conf
|
||||
#
|
||||
# ... and ensure we are logging, etc. in a unique location:
|
||||
#
|
||||
# $ sed -i -e 's@^logfile .*@logfile /var/log/keydb/${BINARY}-myname.log@' /etc/keydb/${NAME}-myname.conf
|
||||
# $ sed -i -e 's@^pidfile .*@pidfile /var/run/keydb-myname/${BINARY}.pid@' /etc/keydb/${NAME}-myname.conf
|
||||
#
|
||||
# We can then start the service as follows, validating we are using our own
|
||||
# configuration:
|
||||
#
|
||||
# $ systemctl start ${BINARY}@myname.service
|
||||
# $ keydb-cli -s /var/run/${NAME}-myname/${BINARY}.sock info | grep config_file
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat >> ${TARGET} <<EOF
|
||||
[Unit]
|
||||
Description=${DESCRIPTION}
|
||||
After=network.target
|
||||
Documentation=https://docs.keydb.dev, man:${BINARY}(1)
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=/usr/bin/${BINARY} /etc/keydb/${NAMESPACED}.conf
|
||||
ExecStop=/bin/kill -s TERM \$MAINPID
|
||||
PIDFile=/var/run/${NAMESPACED}/${BINARY}.pid
|
||||
TimeoutStopSec=0
|
||||
Restart=always
|
||||
User=keydb
|
||||
Group=keydb
|
||||
RuntimeDirectory=${NAMESPACED}
|
||||
RuntimeDirectoryMode=2755
|
||||
|
||||
UMask=007
|
||||
PrivateTmp=yes
|
||||
LimitNOFILE=65535
|
||||
PrivateDevices=yes
|
||||
ProtectHome=yes
|
||||
ReadOnlyDirectories=/
|
||||
ReadWriteDirectories=-/var/lib/keydb
|
||||
ReadWriteDirectories=-/var/log/keydb
|
||||
ReadWriteDirectories=-/var/run/${NAMESPACED}
|
||||
|
||||
NoNewPrivileges=true
|
||||
CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE${SYSTEMD_EXTRA}
|
||||
|
||||
# ${BINARY} can write to its own config file when in cluster mode so we
|
||||
# permit writing there by default. If you are not using this feature, it is
|
||||
# recommended that you replace the following lines with "ProtectSystem=full".
|
||||
ProtectSystem=true
|
||||
ReadWriteDirectories=-/etc/keydb
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
if [ "${EXTRA}" != "" ]
|
||||
then
|
||||
echo "${EXTRA}" >> "${TARGET}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
@@ -0,0 +1,32 @@
|
||||
keydb (5:5.3.3-1~bionic1) bionic; urgency=medium
|
||||
|
||||
* 5.3.3 Updating deb source package and naming convention.
|
||||
|
||||
-- Ben Schermel <ben@eqalpha.com> Fri, 25 Oct 2019 8:00:37 +0000
|
||||
|
||||
keydb (5:5.1.12-1chl1~bionic1) bionic; urgency=medium
|
||||
|
||||
* 5.1.1 update. This update fixes several rare deadlock scenarios. Deadlock detection is also added.
|
||||
|
||||
-- Ben Schermel <ben@eqalpha.com> Fri, 25 Oct 2019 8:00:37 +0000
|
||||
|
||||
|
||||
keydb (5:5.1.11-1chl1~bionic1) bionic; urgency=medium
|
||||
|
||||
* 5.1 release. This release includes subkey expires (EXPIREMEMBER/EXPIREMEMBERAT), with updates to PTTL/TTL accordingly. New OBJECT LASTMODIFIED, BITIOP LSHIFT & BITOP RSHIFT commands. See https://docs.keydb.dev/blog/2019/10/20/blog-post/ for detailed review of release.
|
||||
|
||||
-- Ben Schermel <ben@eqalpha.com> Mon, 21 Oct 2019 8:00:37 +0000
|
||||
|
||||
|
||||
keydb (5:5.0.1-1chl1~bionic1) bionic; urgency=medium
|
||||
|
||||
* Arm build now included for bionic package
|
||||
|
||||
-- Ben Schermel <ben@eqalpha.com> Wed, 21 Aug 2019 22:58:37 +0000
|
||||
|
||||
|
||||
keydb (5:5.0.0-1chl1~bionic1) bionic; urgency=medium
|
||||
|
||||
* Initial release of KeyDB PPA. This PPA was originally derived from https://launchpad.net/~chris-lea/+archive/ubuntu/redis-server
|
||||
|
||||
-- Ben Schermel <ben@eqalpha.com> Wed, 21 Aug 2019 2:58:37 +0000
|
||||
@@ -0,0 +1 @@
|
||||
9
|
||||
@@ -0,0 +1,77 @@
|
||||
Source: keydb
|
||||
Section: database
|
||||
Priority: optional
|
||||
Maintainer: Ben Schermel <ben@eqalpha.com>
|
||||
Build-Depends:
|
||||
debhelper (>= 9~),
|
||||
dpkg-dev (>= 1.17.5),
|
||||
systemd,
|
||||
procps <!nocheck>,
|
||||
build-essential <!nocheck>,
|
||||
tcl <!nocheck>,
|
||||
tcl-dev <!nocheck>,
|
||||
uuid-dev <!nocheck>,
|
||||
libcurl4-openssl-dev <!nocheck>,
|
||||
nasm <!nocheck>,
|
||||
autotools-dev <!nocheck>,
|
||||
autoconf <!nocheck>,
|
||||
libjemalloc-dev <!nocheck>,
|
||||
libssl-dev <!nocheck>
|
||||
Standards-Version: 4.2.1
|
||||
Homepage: https://docs.keydb.dev/
|
||||
Vcs-Git: https://github.com/JohnSully/KeyDB.git
|
||||
Vcs-Browser: https://github.com/JohnSully/KeyDB
|
||||
|
||||
Package: keydb
|
||||
Architecture: all
|
||||
Depends:
|
||||
keydb-server (<< ${binary:Version}.1~),
|
||||
keydb-server (>= ${binary:Version}),
|
||||
${misc:Depends},
|
||||
Description: Persistent key-value database with network interface (metapackage)
|
||||
keydb is a key-value database in a similar vein to memcache but the dataset
|
||||
is non-volatile. keydb additionally provides native support for atomically
|
||||
manipulating and querying data structures such as lists and sets.
|
||||
.
|
||||
The dataset is stored entirely in memory and periodically flushed to disk.
|
||||
.
|
||||
This package depends on the keydb-server package.
|
||||
|
||||
Package: keydb-sentinel
|
||||
Architecture: any
|
||||
Depends:
|
||||
lsb-base (>= 3.2-14),
|
||||
keydb-tools (= ${binary:Version}),
|
||||
${misc:Depends},
|
||||
Description: Persistent key-value database with network interface (monitoring)
|
||||
keydb is a key-value database in a similar vein to memcache but the dataset
|
||||
is non-volatile. keydb additionally provides native support for atomically
|
||||
manipulating and querying data structures such as lists and sets.
|
||||
.
|
||||
This package contains the keydb Sentinel monitoring software.
|
||||
|
||||
Package: keydb-server
|
||||
Architecture: any
|
||||
Depends:
|
||||
lsb-base (>= 3.2-14),
|
||||
keydb-tools (= ${binary:Version}),
|
||||
${misc:Depends},
|
||||
Description: Persistent key-value database with network interface
|
||||
keydb is a key-value database in a similar vein to memcache but the dataset
|
||||
is non-volatile. keydb additionally provides native support for atomically
|
||||
manipulating and querying data structures such as lists and sets.
|
||||
.
|
||||
The dataset is stored entirely in memory and periodically flushed to disk.
|
||||
|
||||
Package: keydb-tools
|
||||
Architecture: any
|
||||
Depends:
|
||||
adduser,
|
||||
${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
Description: Persistent key-value database with network interface (client)
|
||||
keydb is a key-value database in a similar vein to memcache but the dataset
|
||||
is non-volatile. keydb additionally provides native support for atomically
|
||||
manipulating and querying data structures such as lists and sets.
|
||||
.
|
||||
This package contains the command line client and other tools.
|
||||
@@ -0,0 +1,61 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Contact: John Sully <john@eqalpha.com>
|
||||
Upstream-Name: keydb-pro
|
||||
Source: https://github.com/JohnSully/KeyDB-Pro
|
||||
|
||||
Files: *
|
||||
Copyright: © 2006-2014 Salvatore Sanfilippo <antirez@gmail.com>
|
||||
Copyright © 2019, John Sully
|
||||
License: Proprietary
|
||||
|
||||
|
||||
Files: debian/*
|
||||
Copyright: © 2009 Chris Lamb <lamby@debian.org>
|
||||
License: BSD-3-clause
|
||||
|
||||
License: BSD-2-clause
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
.
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
License: BSD-3-clause
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Redis nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,68 @@
|
||||
.TH KEYDB-BENCHMARK 1 "August 17, 2019"
|
||||
.SH NAME
|
||||
keydb-benchmark \- Benchmark a KeyDB instance
|
||||
.SH SYNOPSIS
|
||||
.B redis-benchmark
|
||||
[\-h <host>] [\-p <port>] [\-c <clients>] [\-n <requests]> [\-k <boolean>]
|
||||
.SH DESCRIPTION
|
||||
KeyDB is a key-value database. It is similar to memcached but the dataset is
|
||||
not volatile and other datatypes (such as lists and sets) are natively
|
||||
supported.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\-h hostname
|
||||
Server hostname (default 127.0.0.1)
|
||||
.TP
|
||||
\-p port
|
||||
Server port (default 6379)
|
||||
.TP
|
||||
\-s socket
|
||||
Server socket (overrides host and port)
|
||||
.TP
|
||||
\-a password
|
||||
Password for KeyDB Auth
|
||||
.TP
|
||||
\-c clients
|
||||
Number of parallel connections (default 50)
|
||||
.TP
|
||||
\-n requests
|
||||
Total number of requests (default 100000)
|
||||
.TP
|
||||
\-d size
|
||||
Data size of SET/GET value in bytes (default 2)
|
||||
.TP
|
||||
\-dbnum db
|
||||
SELECT the specified db number (default 0)
|
||||
.TP
|
||||
\-k boolean
|
||||
1=keep alive 0=reconnect (default 1)
|
||||
.TP
|
||||
\-r keyspacelen
|
||||
Use random keys for SET/GET/INCR, random values for SADD Using this option the
|
||||
benchmark will get/set keys in the form mykey_rand000000012456 instead of
|
||||
constant keys, the <keyspacelen> argument determines the max number of values
|
||||
for the random number. For instance if set to 10 only rand000000000000 -
|
||||
rand000000000009 range will be allowed.
|
||||
.TP
|
||||
\-P numreq
|
||||
Pipeline <numreq> requests. Default 1 (no pipeline).
|
||||
.TP
|
||||
\-q
|
||||
Quiet. Just show query/sec values
|
||||
.TP
|
||||
\-\-csv
|
||||
Ourput in CSV format
|
||||
.TP
|
||||
\-l
|
||||
Loop. Run the tests forever
|
||||
.TP
|
||||
\-I
|
||||
Idle mode. Just open N idle connections and wait.
|
||||
.TP
|
||||
\-D
|
||||
Debug mode. more verbose.
|
||||
.SH AUTHOR
|
||||
\fBkeydb-benchmark\fP was written by John Sully, originating as a fork of Redis. Redis was written by Salvatore Sanfilippo.
|
||||
.PP
|
||||
This manual page was written by Chris Lamb <lamby@debian.org> for the Debian
|
||||
project (but may be used by others). Modified by Ben Schermel <ben@eqalpha.com>
|
||||
@@ -0,0 +1,17 @@
|
||||
.TH KEYDB-CHECK-AOF 1 "August 17, 2019"
|
||||
.SH NAME
|
||||
keydb-check-aof \- Check integrity of a KeyDB .AOF file
|
||||
.SH SYNOPSIS
|
||||
.B keydb-check-aof
|
||||
filename
|
||||
.SH DESCRIPTION
|
||||
KeyDB is a key-value database. It is similar to memcached but the dataset is
|
||||
not volatile and other datatypes (such as lists and sets) are natively
|
||||
supported.
|
||||
.PP
|
||||
This utility checks the integrity of a dumped .AOF file.
|
||||
.SH AUTHOR
|
||||
\fBkeydb-check-aof\fP was written by John Sully, originating as a fork of Redis. Redis was written by Salvatore Sanfilippo.
|
||||
.PP
|
||||
This manual page was written by Chris Lamb <lamby@debian.org> for the Debian
|
||||
project (but may be used by others). Modified by Ben Schermel <ben@eqalpha.com>
|
||||
@@ -0,0 +1,17 @@
|
||||
.TH KEYDB-CHECK-RDB 1 "August 17, 2019"
|
||||
.SH NAME
|
||||
keydb-check-rdb \- Check integrity of KeyDB dumped database file
|
||||
.SH SYNOPSIS
|
||||
.B keydb-check-rdb
|
||||
filename
|
||||
.SH DESCRIPTION
|
||||
KeyDB is a key-value database. It is similar to memcached but the dataset is
|
||||
not volatile and other datatypes (such as lists and sets) are natively
|
||||
supported.
|
||||
.PP
|
||||
This utility checks the integrity of a dumped database file.
|
||||
.SH AUTHOR
|
||||
\fBredis-check-rdb\fP was written by John Sully, originating as a fork of Redis. Redis was written by Salvatore Sanfilippo.
|
||||
.PP
|
||||
This manual page was written by Chris Lamb <lamby@debian.org> for the Debian
|
||||
project (but may be used by others). Modified by Ben Schermel <ben@eqalpha.com>
|
||||
@@ -0,0 +1,19 @@
|
||||
.TH KEYDB-CLI 1 "August 17, 2019"
|
||||
.SH NAME
|
||||
keydb-cli \- Command-line client to keydb-server
|
||||
.SH SYNOPSIS
|
||||
.B keydb-cli
|
||||
.RI [options]
|
||||
.SH DESCRIPTION
|
||||
KeyDB is a key-value database. It is similar to memcached but the dataset is
|
||||
not volatile and other datatypes (such as lists and sets) are natively
|
||||
supported.
|
||||
.PP
|
||||
\fBkeydb-cli\fP provides a simple command-line interface to a KeyDB server.
|
||||
.SH OPTIONS
|
||||
See \fBkeydb-doc\fP for more information on the commands KeyDB accepts.
|
||||
.SH AUTHOR
|
||||
\fBkeydb-cli\fP was written by John Sully, originating as a fork of Redis. Redis was written by Salvatore Sanfilippo.
|
||||
.PP
|
||||
This manual page was written by Chris Lamb <lamby@debian.org> for the Debian
|
||||
project (but may be used by others). Modified by Ben Schermel <ben@eqalpha.com>
|
||||
@@ -0,0 +1,23 @@
|
||||
.TH KEYDB-SENTINEL 1 "August 17, 2019"
|
||||
.SH NAME
|
||||
keydb-sentinel \- Persistent key-value database (cluster mode)
|
||||
.SH SYNOPSIS
|
||||
.B keydb-sentinel
|
||||
.RI configfile
|
||||
.SH DESCRIPTION
|
||||
KeyDB is a key-value database. It is similar to memcached but the dataset is
|
||||
not volatile and other datatypes (such as lists and sets) are natively
|
||||
supported.
|
||||
.PP
|
||||
.SH OPTIONS
|
||||
.IP "configfile"
|
||||
Read options from specified configuration file.
|
||||
.SH NOTES
|
||||
On Debian GNU/Linux systems, \fBkeydb-sentinel\fP is typically started via the
|
||||
\fB/etc/init.d/keydb-sentinel\fP initscript, not manually. This defaults to using
|
||||
\fB/etc/keydb/sentinel.conf\fP as a configuration file.
|
||||
.SH AUTHOR
|
||||
\fBkeydb-sentinel\fP was written by John Sully, originating as a fork of Redis. Redis was written by Salvatore Sanfilippo.
|
||||
.PP
|
||||
This manual page was written by Chris Lamb <lamby@debian.org> for the Debian
|
||||
project (but may be used by others). Modified by Ben Schermel <ben@eqalpha.com>
|
||||
@@ -0,0 +1,2 @@
|
||||
debian/keydb-sentinel.service /lib/systemd/system/
|
||||
pkg/deb/conf/sentinel.conf /etc/keydb
|
||||
@@ -0,0 +1,7 @@
|
||||
/var/log/keydb/keydb-sentinel*.log {
|
||||
weekly
|
||||
missingok
|
||||
rotate 12
|
||||
compress
|
||||
notifempty
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
debian/keydb-sentinel.1
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
USER="keydb"
|
||||
GROUP="$USER"
|
||||
CONFFILE="/etc/keydb/sentinel.conf"
|
||||
|
||||
if [ "$1" = "configure" ]
|
||||
then
|
||||
if ! dpkg-statoverride --list ${CONFFILE} >/dev/null 2>&1
|
||||
then
|
||||
dpkg-statoverride --update --add ${USER} ${GROUP} 640 ${CONFFILE}
|
||||
fi
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
if [ "$1" = "configure" ]
|
||||
then
|
||||
find /etc/keydb -maxdepth 1 -type d -name 'keydb-sentinel.*.d' -empty -delete
|
||||
fi
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
CONFFILE="/etc/keydb/sentinel.conf"
|
||||
|
||||
if [ "$1" = "purge" ]
|
||||
then
|
||||
dpkg-statoverride --remove ${CONFFILE} || test $? -eq 2
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,23 @@
|
||||
.TH KEYDB-SERVER 1 "August 17, 2019"
|
||||
.SH NAME
|
||||
keydb-server \- Persistent key-value database
|
||||
.SH SYNOPSIS
|
||||
.B keydb-server
|
||||
.RI configfile
|
||||
.SH DESCRIPTION
|
||||
KeyDB is a key-value database. It is similar to memcached but the dataset is
|
||||
not volatile and other datatypes (such as lists and sets) are natively
|
||||
supported.
|
||||
.PP
|
||||
.SH OPTIONS
|
||||
.IP "configfile"
|
||||
Read options from specified configuration file.
|
||||
.SH NOTES
|
||||
On Debian GNU/Linux systems, \fBkeydb-server\fP is typically started via the
|
||||
\fB/etc/init.d/keydb-server\fP initscript, not manually. This defaults to using
|
||||
\fB/etc/keydb/keydb.conf\fP as a configuration file.
|
||||
.SH AUTHOR
|
||||
\fBkeydb-server\fP was written by John Sully, originating as a fork of Redis. Redis was written by Salvatore Sanfilippo.
|
||||
.PP
|
||||
This manual page was written by Chris Lamb <lamby@debian.org> for the Debian
|
||||
project (but may be used by others). Modified by Ben Schermel <ben@eqalpha.com>
|
||||
@@ -0,0 +1 @@
|
||||
README.md
|
||||
@@ -0,0 +1,2 @@
|
||||
debian/keydb-server.service /lib/systemd/system/
|
||||
pkg/deb/conf/keydb.conf /etc/keydb
|
||||
@@ -0,0 +1,7 @@
|
||||
/var/log/keydb/keydb-server*.log {
|
||||
weekly
|
||||
missingok
|
||||
rotate 12
|
||||
compress
|
||||
notifempty
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
debian/keydb-server.1
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
USER="keydb"
|
||||
GROUP="$USER"
|
||||
CONFFILE="/etc/keydb/keydb.conf"
|
||||
|
||||
if [ "$1" = "configure" ]
|
||||
then
|
||||
if ! dpkg-statoverride --list ${CONFFILE} >/dev/null 2>&1
|
||||
then
|
||||
dpkg-statoverride --update --add ${USER} ${GROUP} 640 ${CONFFILE}
|
||||
fi
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
if [ "$1" = "configure" ]
|
||||
then
|
||||
find /etc/keydb -maxdepth 1 -type d -name 'keydb-server.*.d' -empty -delete
|
||||
fi
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
CONFFILE="/etc/keydb/keydb.conf"
|
||||
|
||||
if [ "${1}" = "purge" ]
|
||||
then
|
||||
dpkg-statoverride --remove ${CONFFILE} || test $? -eq 2
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,2 @@
|
||||
src/redis-trib.rb
|
||||
utils/lru
|
||||
@@ -0,0 +1,7 @@
|
||||
debian/bash_completion.d/* /usr/share/bash-completion/completions
|
||||
src/keydb-benchmark /usr/bin
|
||||
src/keydb-check-aof /usr/bin
|
||||
src/keydb-check-rdb /usr/bin
|
||||
src/keydb-cli /usr/bin
|
||||
src/keydb-server /usr/bin
|
||||
src/keydb-sentinel /usr/bin
|
||||
@@ -0,0 +1,4 @@
|
||||
debian/keydb-benchmark.1
|
||||
debian/keydb-check-aof.1
|
||||
debian/keydb-check-rdb.1
|
||||
debian/keydb-cli.1
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
USER="keydb"
|
||||
|
||||
Setup_dir () {
|
||||
DIR="${1}"
|
||||
MODE="${2}"
|
||||
GROUP="${3}"
|
||||
|
||||
mkdir -p ${DIR}
|
||||
|
||||
case "${DIR}" in
|
||||
/var/log/keydb)
|
||||
MODE="02750"
|
||||
GROUP="adm"
|
||||
;;
|
||||
*)
|
||||
MODE="750"
|
||||
GROUP="${USER}"
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! dpkg-statoverride --list ${DIR} >/dev/null 2>&1
|
||||
then
|
||||
chown ${USER}:${GROUP} ${DIR}
|
||||
chmod ${MODE} ${DIR}
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$1" = "configure" ]
|
||||
then
|
||||
adduser \
|
||||
--system \
|
||||
--home /var/lib/keydb \
|
||||
--quiet \
|
||||
--group \
|
||||
${USER} || true
|
||||
|
||||
Setup_dir /var/log/keydb ${USER}:adm 2750
|
||||
Setup_dir /var/lib/keydb ${USER}:${USER} 750
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
if [ "${1}" = "purge" ]
|
||||
then
|
||||
userdel keydb || true
|
||||
rm -rf /var/lib/keydb /var/log/keydb
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
include /usr/share/dpkg/buildflags.mk
|
||||
|
||||
export BUILD_TLS=yes
|
||||
export CFLAGS CPPFLAGS LDFLAGS
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_LDFLAGS_MAINT_APPEND = -ldl -latomic $(LUA_LDFLAGS)
|
||||
|
||||
ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
|
||||
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
|
||||
MAKEFLAGS += -j$(NUMJOBS)
|
||||
export MAKEFLAGS
|
||||
endif
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_install:
|
||||
debian/bin/generate-systemd-service-files
|
||||
dh_installsystemd --restart-after-upgrade
|
||||
|
||||
override_dh_auto_test:
|
||||
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
|
||||
# Avoid race conditions in upstream testsuite.
|
||||
./runtest || true
|
||||
./runtest-cluster || true
|
||||
./runtest-sentinel || true
|
||||
endif
|
||||
|
||||
override_dh_auto_clean:
|
||||
dh_auto_clean
|
||||
rm -f src/release.h debian/*.service
|
||||
|
||||
override_dh_compress:
|
||||
dh_compress -Xredis-trib.rb
|
||||
|
||||
override_dh_installchangelogs:
|
||||
dh_installchangelogs --keep 00-RELEASENOTES
|
||||
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
||||
@@ -0,0 +1,2 @@
|
||||
# Upstream do not provide signed tarballs.
|
||||
keydb-pro source: debian-watch-does-not-check-gpg-signature
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Show the INFO from "keydb-cli"
|
||||
|
||||
set -eu
|
||||
|
||||
keydb-cli INFO
|
||||
keydb-cli LOLWUT
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Run the benchmarking
|
||||
|
||||
set -eu
|
||||
|
||||
keydb-benchmark -P 10
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Smoke test keydb-check-aof
|
||||
|
||||
keydb-check-aof 2>&1 | grep -qsi usage:
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Test keydb-check-rdb
|
||||
|
||||
set -eu
|
||||
|
||||
# Perform a synchronous save to ensure .rdb file eixsts
|
||||
keydb-cli SAVE
|
||||
|
||||
keydb-check-rdb /var/lib/keydb/dump.rdb
|
||||
@@ -0,0 +1,8 @@
|
||||
Tests: 0001-keydb-cli
|
||||
|
||||
Tests: 0002-benchmark
|
||||
|
||||
Tests: 0003-keydb-check-aof
|
||||
|
||||
Tests: 0004-keydb-check-rdb
|
||||
Restrictions: needs-root
|
||||
Loaded 100 of 441 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user