Giter VIP home page Giter VIP logo

hiredis-vip's People

Contributors

deep011 avatar fortrue avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hiredis-vip's Issues

使用wiki页面example-1, 直接core

#include <stdio.h>
#include <hircluster.h>
int main()
{
    char *key="key-a";
    char *field="field-1";
    char *key1="key1";
    char *value1="value-1";
    char *key2="key1";
    char *value2="value-1";
    redisClusterContext *cc = redisClusterConnect("127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7004",
        HIRCLUSTER_FLAG_NULL);
    if(cc == NULL || cc->err)
    {
        printf("connect error : %s\n", cc == NULL ? "NULL" : cc->errstr);
        return -1;
    }

    redisReply *reply = redisClusterCommand(cc, "hmget %s %s", key, field);
    if(reply == NULL)
    {
        printf("reply is null[%s]\n", cc->errstr);
        redisClusterFree(cc);
        return -1;
    }

    printf("reply->type:%d", reply->type);

    freeReplyObject(reply);

    reply = redisClusterCommand(cc, "mset %s %s %s %s", key1, value1, key2, value2);
    if(reply == NULL)
    {
        printf("reply is null[%s]\n", cc->errstr);
        redisClusterFree(cc);
        return -1;
    }

    printf("reply->str:%s", reply->str);

    freeReplyObject(reply);
    redisClusterFree(cc);
    return 0;
}

gcc example3.c -o a3 -lhiredis_vip -L/usr/local/lib -I/usr/local/include/hiredis-vip -g -ggdb

$ ./a3 
*** glibc detected *** ./a3: double free or corruption (fasttop): 0x00000000054d5040 ***
段错误 (core dumped)
(gdb) bt
#0  0x0000003a4ca6f34e in malloc_consolidate () from /lib64/libc.so.6
#1  0x0000003a4ca71a7c in _int_malloc () from /lib64/libc.so.6
#2  0x0000003a4ca73a7d in calloc () from /lib64/libc.so.6
#3  0x0000003a4c609f8b in _dl_new_object () from /lib64/ld-linux-x86-64.so.2
#4  0x0000003a4c605a9c in _dl_map_object_from_fd () from /lib64/ld-linux-x86-64.so.2
#5  0x0000003a4c607863 in _dl_map_object () from /lib64/ld-linux-x86-64.so.2
#6  0x0000003a4c610ea2 in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
#7  0x0000003a4c60d136 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#8  0x0000003a4c6108bc in _dl_open () from /lib64/ld-linux-x86-64.so.2
#9  0x0000003a4cb09fc0 in do_dlopen () from /lib64/libc.so.6
#10 0x0000003a4c60d136 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#11 0x0000003a4cb0a127 in __libc_dlopen_mode () from /lib64/libc.so.6
#12 0x0000003a4cae734f in backtrace () from /lib64/libc.so.6
#13 0x0000003a4ca6995f in __libc_message () from /lib64/libc.so.6
#14 0x0000003a4ca714af in _int_free () from /lib64/libc.so.6
#15 0x0000003a4ca757ab in free () from /lib64/libc.so.6
#16 0x00002b5dceb0dbf3 in command_destroy (command=0x54d5d30) at command.c:1678
#17 0x00002b5dceb11b27 in listDelNode (list=0x54d6090, node=0x54d51e0) at adlist.c:169
#18 0x00002b5dceb13719 in command_pre_fragment (cc=0x2b5dced20010, command=0x54d5110, commands=0x54d6090)
    at hircluster.c:3191
#19 command_format_by_slot (cc=0x2b5dced20010, command=0x54d5110, commands=0x54d6090) at hircluster.c:3376
#20 0x00002b5dceb183c3 in redisClusterFormattedCommand (cc=0x2b5dced20010, 
    cmd=0x54d6180 "*5\r\n$4\r\nmset\r\n$4\r\nkey1\r\n$7\r\nvalue-1\r\n$4\r\nkey1\r\n$7\r\nvalue-1\r\n", 
    len=<value optimized out>) at hircluster.c:3432
#21 0x00002b5dceb192a2 in redisClustervCommand (cc=0x2b5dced20010, format=<value optimized out>, 
    ap=<value optimized out>) at hircluster.c:3535
#22 0x00002b5dceb19388 in redisClusterCommand (cc=0x3a4cd549e0, format=0x496 <Address 0x496 out of bounds>)
    at hircluster.c:3547
#23 0x000000000040081c in main () at example3.c:31

请问我这是什么原因? 万分感谢

连接redis4.0.1版本构建的集群,出现段错误

使用接口为同步接口
测试环境 ubuntu 16.04

hiredis-vip master 0.3.0

redis 4.0.1 官网直接下载

gcc 5.4.0
初步诊断,错误发生的原因应在redisContext *ctx_get_by_node(redisClusterContext *cc, cluster_node *node)内部,node->host ==NULL , node->port<=0

Invalid read of size

Valgrind shows some Invalid read of size and Invalid free cases.

==17525== Invalid read of size 8
==17525==    at 0x6B5EF0: redisClusterAsyncDisconnect (hircluster.c:4934)
==17525==    by 0x57DA73: redis::ClusterConnection::OnReply(redisClusterAsyncContext*, void*, void*) (cluster_connection.cpp:242)
==17525==    by 0x6B5068: redisClusterAsyncCallback (hircluster.c:4664)
==17525==    by 0x6ACB98: __redisRunCallback (async.c:270)
==17525==    by 0x6ACB98: __redisAsyncFree (async.c:284)
==17525==    by 0x6AEA36: cluster_node_deinit (hircluster.c:303)
==17525==    by 0x6AEB6B: dictClusterNodeDestructor (hircluster.c:92)
==17525==    by 0x6AE754: _dictClear (dict.c:224)
==17525==    by 0x6B2C28: dictRelease (dict.c:239)
==17525==    by 0x6B2C28: redisClusterFree (hircluster.c:2072)
==17525==    by 0x6B5F40: redisClusterAsyncFree (hircluster.c:4960)
==17525==    by 0x57C84E: redis::ClusterConnection::~ClusterConnection() (cluster_connection.cpp:62)
==17525==    by 0x577054: _M_release (shared_ptr_base.h:144)
==17525==    by 0x577054: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x577054: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> > (stl_construct.h:93)
==17525==    by 0x577054: __destroy<std::shared_ptr<redis::ConnectionBase> *> (stl_construct.h:103)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> *> (stl_construct.h:126)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> *, std::shared_ptr<redis::ConnectionBase> > (stl_construct.h:151)
==17525==    by 0x577054: _M_erase_at_end (stl_vector.h:1352)
==17525==    by 0x577054: clear (stl_vector.h:1126)
==17525==    by 0x577054: redis::ConnectionPool::~ConnectionPool() (cpool.cpp:67)
==17525==    by 0x502188: _M_release (shared_ptr_base.h:144)
==17525==    by 0x502188: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x502188: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x502188: ~pair (stl_pair.h:96)
==17525==    by 0x502188: ~_Hash_node (hashtable_policy.h:170)
==17525==    by 0x502188: void __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true> >::destroy<std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true> >(std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true>*) (new_allocator.h:124)
==17525==  Address 0xc717478 is 8 bytes inside a block of size 24 free'd
==17525==    at 0x4C2ACDD: free (vg_replace_malloc.c:530)
==17525==    by 0x6AE75C: _dictClear (dict.c:225)
==17525==    by 0x6B2C28: dictRelease (dict.c:239)
==17525==    by 0x6B2C28: redisClusterFree (hircluster.c:2072)
==17525==    by 0x6B5F40: redisClusterAsyncFree (hircluster.c:4960)
==17525==    by 0x57C84E: redis::ClusterConnection::~ClusterConnection() (cluster_connection.cpp:62)
==17525==    by 0x577054: _M_release (shared_ptr_base.h:144)
==17525==    by 0x577054: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x577054: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> > (stl_construct.h:93)
==17525==    by 0x577054: __destroy<std::shared_ptr<redis::ConnectionBase> *> (stl_construct.h:103)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> *> (stl_construct.h:126)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> *, std::shared_ptr<redis::ConnectionBase> > (stl_construct.h:151)
==17525==    by 0x577054: _M_erase_at_end (stl_vector.h:1352)
==17525==    by 0x577054: clear (stl_vector.h:1126)
==17525==    by 0x577054: redis::ConnectionPool::~ConnectionPool() (cpool.cpp:67)
==17525==    by 0x502188: _M_release (shared_ptr_base.h:144)
==17525==    by 0x502188: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x502188: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x502188: ~pair (stl_pair.h:96)
==17525==    by 0x502188: ~_Hash_node (hashtable_policy.h:170)
==17525==    by 0x502188: void __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true> >::destroy<std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true> >(std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true>*) (new_allocator.h:124)
==17525==    by 0x50639D: _M_deallocate_node (hashtable.h:746)
==17525==    by 0x50639D: _M_begin (hashtable.h:763)
==17525==    by 0x50639D: clear (hashtable.h:1641)
==17525==    by 0x50639D: ~_Hashtable (hashtable.h:958)
==17525==    by 0x50639D: ~unordered_map (unordered_map.h:97)
==17525==    by 0x50639D: destroy<std::unordered_map<std::basic_string<char>, std::shared_ptr<redis::ConnectionPool>, std::hash<string>, std::equal_to<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, std::shared_ptr<redis::ConnectionPool> > > > > (new_allocator.h:124)
==17525==    by 0x50639D: _S_destroy<std::unordered_map<std::basic_string<char>, std::shared_ptr<redis::ConnectionPool>, std::hash<string>, std::equal_to<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, std::shared_ptr<redis::ConnectionPool> > > > > (alloc_traits.h:281)
==17525==    by 0x50639D: destroy<std::unordered_map<std::basic_string<char>, std::shared_ptr<redis::ConnectionPool>, std::hash<string>, std::equal_to<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, std::shared_ptr<redis::ConnectionPool> > > > > (alloc_traits.h:405)
==17525==    by 0x50639D: std::_Sp_counted_ptr_inplace<std::unordered_map<std::string, std::shared_ptr<redis::ConnectionPool>, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> > > >, std::allocator<std::unordered_map<std::string, std::shared_ptr<redis::ConnectionPool>, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> > > > >, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:407)
==17525==    by 0x4FBC5A: _M_release (shared_ptr_base.h:144)
==17525==    by 0x4FBC5A: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x4FBC5A: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x4FBC5A: external_services::~external_services() (peer.hpp:162)
==17525==    by 0x5369BE: server::peer_base<AsyncExtendQueue<server::context> >::~peer_base() (peer_impl.hpp:156)
==17525==    by 0x5500FE: ~basic_resolver_query (tcp_peer.hpp:39)
==17525==    by 0x5500FE: server::tcp_client::~tcp_client() (tcp_client.hpp:57)
==17525==    by 0x99C168E: _M_release (shared_ptr_base.h:144)
==17525==    by 0x99C168E: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x99C168E: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x99C168E: ~endpoint (peer.hpp:80)
==17525==    by 0x99C168E: client_lobby::~client_lobby() (client_lobby.hpp:22)
==17525==  Block was alloc'd at
==17525==    at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
==17525==    by 0x6AE63A: dictAdd (dict.c:145)
==17525==    by 0x6B1610: parse_cluster_nodes (hircluster.c:1046)
==17525==    by 0x6B235F: cluster_update_route_by_addr (hircluster.c:1348)
==17525==    by 0x6B29A0: cluster_update_route (hircluster.c:1927)
==17525==    by 0x6B325F: _redisClusterConnect (hircluster.c:2111)
==17525==    by 0x6B325F: redisClusterConnectNonBlock (hircluster.c:2181)
==17525==    by 0x6B56E5: redisClusterAsyncConnect (hircluster.c:4429)
==17525==    by 0x57CC98: redis::ClusterConnection::Connect() (cluster_connection.cpp:89)
==17525==    by 0x581F35: redis::ConnectionBase::CreateCommandResult() (connection_base.cpp:96)
==17525==    by 0x57DAF3: redis::ClusterConnection::CommandV(char const*, ...) (cluster_connection.cpp:204)
==17525==    by 0x9AC46ED: operator-> (connection_base.hpp:83)
==17525==    by 0x9AC46ED: _M_get_pointer (cpool.hpp:89)
==17525==    by 0x9AC46ED: std::_Function_handler<std::shared_ptr<redis::CommandResult> (redis::ConnectionPool::ScopedConnection&), std::shared_ptr<redis::CommandResult> redis::ConnectionPool::Command<char const*&, unsigned int const&, int, unsigned long, unsigned long>(std::string const&, char const*&, unsigned int const&, int&&, unsigned long&&, unsigned long&&)::{lambda(redis::ConnectionPool::ScopedConnection&)#1}>::_M_invoke(std::_Any_data const&, redis::ConnectionPool::ScopedConnection&) (functional:2056)
==17525==    by 0x57774D: operator() (functional:2471)
==17525==    by 0x57774D: redis::ConnectionPool::Run(std::function<std::shared_ptr<redis::CommandResult> (redis::ConnectionPool::ScopedConnection&)>) (cpool.cpp:127)
==17525== Invalid read of size 8
==17525==    at 0x6B5EF4: dictNext (dict.c:281)
==17525==    by 0x6B5EF4: redisClusterAsyncDisconnect (hircluster.c:4932)
==17525==    by 0x57DA73: redis::ClusterConnection::OnReply(redisClusterAsyncContext*, void*, void*) (cluster_connection.cpp:242)
==17525==    by 0x6B5068: redisClusterAsyncCallback (hircluster.c:4664)
==17525==    by 0x6ACB98: __redisRunCallback (async.c:270)
==17525==    by 0x6ACB98: __redisAsyncFree (async.c:284)
==17525==    by 0x6AEA36: cluster_node_deinit (hircluster.c:303)
==17525==    by 0x6AEB6B: dictClusterNodeDestructor (hircluster.c:92)
==17525==    by 0x6AE754: _dictClear (dict.c:224)
==17525==    by 0x6B2C28: dictRelease (dict.c:239)
==17525==    by 0x6B2C28: redisClusterFree (hircluster.c:2072)
==17525==    by 0x6B5F40: redisClusterAsyncFree (hircluster.c:4960)
==17525==    by 0x57C84E: redis::ClusterConnection::~ClusterConnection() (cluster_connection.cpp:62)
==17525==    by 0x577054: _M_release (shared_ptr_base.h:144)
==17525==    by 0x577054: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x577054: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> > (stl_construct.h:93)
==17525==    by 0x577054: __destroy<std::shared_ptr<redis::ConnectionBase> *> (stl_construct.h:103)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> *> (stl_construct.h:126)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> *, std::shared_ptr<redis::ConnectionBase> > (stl_construct.h:151)
==17525==    by 0x577054: _M_erase_at_end (stl_vector.h:1352)
==17525==    by 0x577054: clear (stl_vector.h:1126)
==17525==    by 0x577054: redis::ConnectionPool::~ConnectionPool() (cpool.cpp:67)
==17525==    by 0x502188: _M_release (shared_ptr_base.h:144)
==17525==    by 0x502188: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x502188: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x502188: ~pair (stl_pair.h:96)
==17525==    by 0x502188: ~_Hash_node (hashtable_policy.h:170)
==17525==    by 0x502188: void __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true> >::destroy<std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true> >(std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true>*) (new_allocator.h:124)
==17525==  Address 0xc717480 is 16 bytes inside a block of size 24 free'd
==17525==    at 0x4C2ACDD: free (vg_replace_malloc.c:530)
==17525==    by 0x6AE75C: _dictClear (dict.c:225)
==17525==    by 0x6B2C28: dictRelease (dict.c:239)
==17525==    by 0x6B2C28: redisClusterFree (hircluster.c:2072)
==17525==    by 0x6B5F40: redisClusterAsyncFree (hircluster.c:4960)
==17525==    by 0x57C84E: redis::ClusterConnection::~ClusterConnection() (cluster_connection.cpp:62)
==17525==    by 0x577054: _M_release (shared_ptr_base.h:144)
==17525==    by 0x577054: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x577054: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> > (stl_construct.h:93)
==17525==    by 0x577054: __destroy<std::shared_ptr<redis::ConnectionBase> *> (stl_construct.h:103)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> *> (stl_construct.h:126)
==17525==    by 0x577054: _Destroy<std::shared_ptr<redis::ConnectionBase> *, std::shared_ptr<redis::ConnectionBase> > (stl_construct.h:151)
==17525==    by 0x577054: _M_erase_at_end (stl_vector.h:1352)
==17525==    by 0x577054: clear (stl_vector.h:1126)
==17525==    by 0x577054: redis::ConnectionPool::~ConnectionPool() (cpool.cpp:67)
==17525==    by 0x502188: _M_release (shared_ptr_base.h:144)
==17525==    by 0x502188: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x502188: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x502188: ~pair (stl_pair.h:96)
==17525==    by 0x502188: ~_Hash_node (hashtable_policy.h:170)
==17525==    by 0x502188: void __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true> >::destroy<std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true> >(std::__detail::_Hash_node<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> >, true>*) (new_allocator.h:124)
==17525==    by 0x50639D: _M_deallocate_node (hashtable.h:746)
==17525==    by 0x50639D: _M_begin (hashtable.h:763)
==17525==    by 0x50639D: clear (hashtable.h:1641)
==17525==    by 0x50639D: ~_Hashtable (hashtable.h:958)
==17525==    by 0x50639D: ~unordered_map (unordered_map.h:97)
==17525==    by 0x50639D: destroy<std::unordered_map<std::basic_string<char>, std::shared_ptr<redis::ConnectionPool>, std::hash<string>, std::equal_to<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, std::shared_ptr<redis::ConnectionPool> > > > > (new_allocator.h:124)
==17525==    by 0x50639D: _S_destroy<std::unordered_map<std::basic_string<char>, std::shared_ptr<redis::ConnectionPool>, std::hash<string>, std::equal_to<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, std::shared_ptr<redis::ConnectionPool> > > > > (alloc_traits.h:281)
==17525==    by 0x50639D: destroy<std::unordered_map<std::basic_string<char>, std::shared_ptr<redis::ConnectionPool>, std::hash<string>, std::equal_to<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, std::shared_ptr<redis::ConnectionPool> > > > > (alloc_traits.h:405)
==17525==    by 0x50639D: std::_Sp_counted_ptr_inplace<std::unordered_map<std::string, std::shared_ptr<redis::ConnectionPool>, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> > > >, std::allocator<std::unordered_map<std::string, std::shared_ptr<redis::ConnectionPool>, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::shared_ptr<redis::ConnectionPool> > > > >, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:407)
==17525==    by 0x4FBC5A: _M_release (shared_ptr_base.h:144)
==17525==    by 0x4FBC5A: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x4FBC5A: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x4FBC5A: external_services::~external_services() (peer.hpp:162)
==17525==    by 0x5369BE: server::peer_base<AsyncExtendQueue<server::context> >::~peer_base() (peer_impl.hpp:156)
==17525==    by 0x5500FE: ~basic_resolver_query (tcp_peer.hpp:39)
==17525==    by 0x5500FE: server::tcp_client::~tcp_client() (tcp_client.hpp:57)
==17525==    by 0x99C168E: _M_release (shared_ptr_base.h:144)
==17525==    by 0x99C168E: ~__shared_count (shared_ptr_base.h:546)
==17525==    by 0x99C168E: ~__shared_ptr (shared_ptr_base.h:781)
==17525==    by 0x99C168E: ~endpoint (peer.hpp:80)
==17525==    by 0x99C168E: client_lobby::~client_lobby() (client_lobby.hpp:22)
==17525==  Block was alloc'd at
==17525==    at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
==17525==    by 0x6AE63A: dictAdd (dict.c:145)
==17525==    by 0x6B1610: parse_cluster_nodes (hircluster.c:1046)
==17525==    by 0x6B235F: cluster_update_route_by_addr (hircluster.c:1348)
==17525==    by 0x6B29A0: cluster_update_route (hircluster.c:1927)
==17525==    by 0x6B325F: _redisClusterConnect (hircluster.c:2111)
==17525==    by 0x6B325F: redisClusterConnectNonBlock (hircluster.c:2181)
==17525==    by 0x6B56E5: redisClusterAsyncConnect (hircluster.c:4429)
==17525==    by 0x57CC98: redis::ClusterConnection::Connect() (cluster_connection.cpp:89)
==17525==    by 0x581F35: redis::ConnectionBase::CreateCommandResult() (connection_base.cpp:96)
==17525==    by 0x57DAF3: redis::ClusterConnection::CommandV(char const*, ...) (cluster_connection.cpp:204)
==17525==    by 0x9AC46ED: operator-> (connection_base.hpp:83)
==17525==    by 0x9AC46ED: _M_get_pointer (cpool.hpp:89)
==17525==    by 0x9AC46ED: std::_Function_handler<std::shared_ptr<redis::CommandResult> (redis::ConnectionPool::ScopedConnection&), std::shared_ptr<redis::CommandResult> redis::ConnectionPool::Command<char const*&, unsigned int const&, int, unsigned long, unsigned long>(std::string const&, char const*&, unsigned int const&, int&&, unsigned long&&, unsigned long&&)::{lambda(redis::ConnectionPool::ScopedConnection&)#1}>::_M_invoke(std::_Any_data const&, redis::ConnectionPool::ScopedConnection&) (functional:2056)
==17525==    by 0x57774D: operator() (functional:2471)
==17525==    by 0x57774D: redis::ConnectionPool::Run(std::function<std::shared_ptr<redis::CommandResult> (redis::ConnectionPool::ScopedConnection&)>) (cpool.cpp:127)
==17525== Invalid free() / delete / delete[] / realloc()
==17525==    at 0x4C2ACDD: free (vg_replace_malloc.c:530)
==17525==    by 0x7143BDB: __libc_freeres (in /usr/lib64/libc-2.17.so)
==17525==    by 0x4A24749: _vgnU_freeres (vg_preloaded.c:77)
==17525==    by 0x7018E2A: __run_exit_handlers (exit.c:92)
==17525==    by 0x7018EB4: exit (exit.c:99)
==17525==    by 0x7001B1B: (below main) (libc-start.c:308)
==17525==  Address 0x739a3d0 is 0 bytes inside data symbol "noai6ai_cached"

redis服务端主动断开链接后异步发送请求会导致coredump

#0 0x00007ffff67e1d16 in strlen () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff7345d34 in __redisClusterAsyncSetError (str=0xffffffff00000001 <error: Cannot access memory at address 0xffffffff00000001>, type=-1, acc=0x1020300) at hircluster.c:3971
#2 redisClusterAsyncFormattedCommand (acc=acc@entry=0x1020300, fn=fn@entry=0x52f5a2 <UserFeature::GetFeatureForRedis(redisClusterAsyncContext*, void*, void*)>, privdata=privdata@entry=0xfb03b0, cmd=, len=40) at hircluster.c:4535
#3 0x00007ffff7346017 in redisClustervAsyncCommand (acc=0x1020300, fn=0x52f5a2 <UserFeature::GetFeatureForRedis(redisClusterAsyncContext*, void*, void*)>, privdata=0xfb03b0, format=, ap=) at hircluster.c:4602
#4 0x00007ffff734614a in redisClusterAsyncCommand (acc=, fn=, privdata=, format=) at hircluster.c:4615
#5 0x000000000052f4f2 in UserFeature::GetFeature (this=0xfd4960, tmpData=0x807ee000, server=...) at /home/wciq1208/ClionProjects/online-server-cpp/src/index/UserFeature.cpp:22
#6 0x00000000004fbd2b in Server::Handler (this=0xfd1a48, req=0x807dc000, arg=...) at /home/wciq1208/ClionProjects/online-server-cpp/src/process/Server.cpp:93
#7 0x00000000004fb81d in Server::EvHandler (req=0x807dc000, arg=0xfd1a48) at /home/wciq1208/ClionProjects/online-server-cpp/src/process/Server.cpp:43
#8 0x00007ffff799cd74 in evhttp_handle_request (req=0x807dc000, arg=) at http.c:3039
#9 0x00007ffff799afbd in evhttp_read_body (evcon=evcon@entry=0x7ff6a3c0, req=req@entry=0x807dc000) at http.c:1028
#10 0x00007ffff799b4da in evhttp_get_body (evcon=0x7ff6a3c0, req=0x807dc000) at http.c:1969
#11 0x00007ffff798c16a in bufferevent_readcb (fd=3, event=, arg=0xfcd400) at bufferevent_sock.c:186
#12 0x00007ffff7980252 in event_persist_closure (ev=, base=0x1038000) at event.c:1319
#13 event_process_active_single_queue (activeq=0xfb0140, base=0x1038000) at event.c:1363
#14 event_process_active (base=) at event.c:1438
#15 event_base_loop (base=0x1038000, flags=0) at event.c:1639
#16 0x0000000000551270 in HttpServer::createThread (this=0xfd1a48) at /home/wciq1208/ClionProjects/online-server-cpp/src/process/HttpServer.cpp:67
#17 0x000000000052efd8 in std::_Mem_fn_base<signed char (HttpServer::)(), true>::_M_call<Server&> (this=0xfc2470, __object=...) at /usr/include/c++/5/functional:628
#18 0x000000000052ef60 in std::_Mem_fn_base<signed char (HttpServer::
)(), true>::operator()<Server&, , void>(Server&) const (this=0xfc2470, __object=...) at /usr/include/c++/5/functional:610
#19 0x000000000052ef08 in std::_Mem_fn_base<signed char (HttpServer::)(), true>::operator()<Server, , void>(std::reference_wrapper) const (this=0xfc2470, __ref=...) at /usr/include/c++/5/functional:619
#20 0x000000000052eed3 in std::_Bind_simple<std::_Mem_fn<signed char (HttpServer::
)()> (std::reference_wrapper)>::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0xfc2468) at /usr/include/c++/5/functional:1531
#21 0x000000000052ed70 in std::_Bind_simple<std::_Mem_fn<signed char (HttpServer::)()> (std::reference_wrapper)>::operator()() (this=0xfc2468) at /usr/include/c++/5/functional:1520
#22 0x000000000052ecc0 in std::thread::_Impl<std::_Bind_simple<std::_Mem_fn<signed char (HttpServer::
)()> (std::reference_wrapper)> >::_M_run() (this=0xfc2450) at /usr/include/c++/5/thread:115
#23 0x00007ffff6deec80 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#24 0x00007ffff7bc16fa in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0

本来想尝试在disconnectcallback当中重连,但是发现回调函数只提供ac作为参数而没有acc,导致不能使用异步适配器

不支持 RENAME 命令 - -!

1 QS DBG 2016-12-27 17:33:49.974 20829 20829 cluster_client.cpp:80:check_redis_reply: private_data=[sadd {a}1 1],type=[3:REDIS_REPLY_INTEGER],integer=[1],len=[0],str=[(null)],elements=[0]

2 QS ERR 2016-12-27 17:33:49.974 20829 20829 cluster_client.cpp:62:check_redis_reply: exec cmd which private_data=[rename {a}1 {a}2], reply is null

测试发现, RENAME 一个存在的 key 到另一个 处于同一个 slot 的新 key 失败

是不是不支持 KEYS 命令?

QS ERR 2016-12-23 11:24:05.239 30257 30257 cluster_client.cpp:56:check_redis_reply: exec cmd=[KEYS a*] reply is null
QS DBG 2016-12-23 11:24:05.239 30257 30257 cluster_client.cpp:72:check_redis_reply: cmd=[del a#2],type=[3:REDIS_REPLY_INTEGER],integer=[1],len=[0],str = [(null)],elements=[0]

KEYS a* 匹配不到结果, 但其实是有的, 有个使用场景是想删除指定模式的 key 需要 keys 命令匹配所有的 key 然后全部删除,可以支持吗大哥?或者有别的变通方法吗?求指教,谢谢!

incr命令不支持吗? example.c例子运行incr未起效

运行examples/example.c,INCR未起效
`[root@localhost_ hiredis-vip-master]# ./examples/hiredis-example
PING: PONG
SET: MOVED 12182 192.168.119.136:7002
SET (binary API): OK
GET foo: MOVED 12182 192.168.119.136:7002
INCR counter: 0
INCR counter: 0
0) element-9

  1. element-8
  2. element-7
  3. element-6
  4. element-5
  5. element-4
  6. element-3
  7. element-2
  8. element-1
  9. element-0
    `

pipelining的问题

现在的管道命令只能这样么:
redisClusterAppendCommand(cc, "set key1 value1");
redisClusterAppendCommand(cc, "get key1");
redisClusterAppendCommand(cc, "mset key2 value2 key3 value3");
redisClusterAppendCommand(cc, "mget key2 key3");

redisClusterGetReply(cc, &reply); //for "set key1 value1"
freeReplyObject(reply);
redisClusterGetReply(cc, &reply); //for "get key1"
freeReplyObject(reply);
redisClusterGetReply(cc, &reply); //for "mset key2 value2 key3 value3"
freeReplyObject(reply);
redisClusterGetReply(cc, &reply); //for "mget key2 key3"
freeReplyObject(reply);
能否像python一次返回所有结果?

how to call publish/subscribe ?

There is code in hiredis README:
reply = redisCommand(context,"SUBSCRIBE foo");
and I tried to call subscribe command with following code:
redisReply *reply = redisClusterCommand(cc,"SUBSCRIBE test");
but reply is null and , cc->errstr is "parse command error"
I think this isn't the right way.
is there another function for publish/subscribe or they're not supported now ?

master/slave

Hi,
I was wondering if this library automatically recognises failover between master and slave nodes for a clustered node? Documentation doesn't seem to cover that.

regards,

PING not allowed

Hi!

As I see for now, the library does not support issuing "PING" commands at a cluster node as an error occurs client side: "No keys in command(must have keys for redis cluster mode)".

While I see the intention of client-side-hashing on keys, the "PING" command is useful to check the connection of the redis client OR the availability of the redis cluster (server).

I could of course issue a "PING" on every node contained in the redisClusterContext->table, but then again I think there are too much restrictions in general in this lib (Several redis commands are not supported as they are not defined in the client lib).

Thanks in advance for the reply!

Balázs

Add redisClustervCommand

Hi,
I'm going to create a c++ wrapper.Would you like to add APIs like redisvCommand in hiredis then I could pass the va_list.
thanks.

example-libuv.c bug

hi,when redis don't work.example-libuv.c don't right run.
After redisAsyncConnect,it don't call connectCallback function or call disconnectCallback

But example-libevent.c can work.
It call connectCallback status == REDIS_ERROR,Very Good!

SET command not work when I use NonBlock connection

redisContext *c = redisConnectNonBlock(hostname,port);
redisReply *reply = redisCommand(c,"set %d %d",1,2);
printf("set: %s\n",reply->str);

these code raise a segmentation fault,reply is a NULL pointer

使用 master 分支最新代码的异步接口时,写入大量命令时会 coredump,请帮忙看下啥原因导致的,谢谢!

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <hircluster.h>
#include <adapters/libevent.h>

const char* get_redis_reply_type(int type)
{
    static const char *REDIS_REPLY_TYPE[] = {
        "ERROR_UNDEFINED_REDIS_REPLY_TYPE",
        "REDIS_REPLY_STRING",
        "REDIS_REPLY_ARRAY",
        "REDIS_REPLY_INTEGER",
        "REDIS_REPLY_NIL",
        "REDIS_REPLY_STATUS",
        "REDIS_REPLY_ERROR"
    };

    if(type >= REDIS_REPLY_STRING && type <= REDIS_REPLY_ERROR)
    {
        return REDIS_REPLY_TYPE[type];
    }
    else
        return REDIS_REPLY_TYPE[0];
}

void check_redis_reply(redisReply *reply, const char *cmd, int free)
{
    if(reply == NULL)
    {
        printf("exec : [%s] reply is null\n", cmd == NULL ? "NULL" : cmd);
    }
    else
    {
        printf("exec : [%s], reply->type = [%d:%s], reply->str = [%s]\n", 
                cmd == NULL ? "NULL" : cmd, reply->type, get_redis_reply_type(reply->type), reply->str);
        if(free)
            freeReplyObject(reply);
    }
}

void connectCallback(const redisAsyncContext *c, int status)
{
    if(status != REDIS_OK)
    {
        printf("connect error : [%s]\n", c->errstr);
        return;
    }
    else
    {
        printf("connect ok !\n");
    }
}

void disconnectCallback(const redisAsyncContext *c, int status)
{
    if(status != REDIS_OK)
    {
        printf("disconnect error : [%s]\n", c->errstr);
        return;
    }
    else
    {
        printf("disconnect ok !\n");
    }
}

void getCallback(redisClusterAsyncContext *acc, void *reply, void *cmd)
{
    // 会自动 free reply, 不要手动 free
    check_redis_reply(reply, cmd, 0);
}

void* event_loop_thread(void* c)
{
    struct event_base *base = event_base_new();

    redisClusterAsyncContext *acc = redisClusterAsyncConnect("127.0.0.1:6380", HIRCLUSTER_FLAG_NULL);

    if (acc->err) {
        printf("async connect error : [%s]\n", acc->errstr);
        return NULL;
    }

    redisClusterLibeventAttach(acc, base);
    redisClusterAsyncSetConnectCallback(acc, connectCallback);
    redisClusterAsyncSetDisconnectCallback(acc, disconnectCallback);

    // 必须先任意注册一个事件再 event_base_dispatch ,不然 event_base_dispatch 会失败
    if(redisClusterAsyncCommand(acc, getCallback, "first", "set %d %d", 0, 0) != REDIS_OK)
        printf("redisClusterAsyncCommand error : [%d:%s]\n", acc->err, acc->errstr);

    *(redisClusterAsyncContext**)c = acc;

    int ret = event_base_dispatch(base);
    printf("event loop error ! [%d]\n", ret);
}

int main()
{
    printf("------test async------\n");

    pthread_t tid;
    redisClusterAsyncContext *acc = NULL;
    if(pthread_create(&tid, NULL, event_loop_thread, &acc) != 0)
    {
        printf("pthread_create error : [%s]\n", strerror(errno));
        return -1;
    }

    while(acc == NULL)
    {
        sleep(1);
    }

    unsigned int i=0;
    while(1)
    {
        if(redisClusterAsyncCommand(acc, getCallback, NULL, "set %d %d", i, i) != REDIS_OK)
            printf("redisClusterAsyncCommand error !\n");
        ++i;
        usleep(1000);
    }
    
    pause();
    return 0;
}

运行大概30s后内存就开始暴涨了 --!

执行redisClusterGetReply收到MOVED语句以及redisClusterCommand没有断线重连机制

你好:
1. redisClusterCommand没有断线重连机制,而redisClusterAppendCommand有.
2. 在测试主从切换后执行redisClusterGetReply,收到MOVED语句,以下是测试过程:

  • 测试代码:
while(true) {

        // reply = (redisReply *)redisClusterCommand(cluster_ctx, "GET a");
        // if (!reply) {
        //     printf("Execute fail.\n");
        // } else {
        //     printf("%s\n", reply->str);
        //     freeReplyObject(reply);
        // }
        //
        // reply = (redisReply *)redisClusterCommand(cluster_ctx, "GET b");
        // if (!reply) {
        //     printf("Execute fail.\n");
        // } else {
        //     printf("%s\n", reply->str);
        //     freeReplyObject(reply);
        // }
        //
        // reply = (redisReply *)redisClusterCommand(cluster_ctx, "GET c");
        // if (!reply) {
        //     printf("Execute fail.\n");
        // } else {
        //     printf("%s\n", reply->str);
        //     freeReplyObject(reply);
        // }
        //
        // printf("Done\n");
        // getchar();
        // continue;

        int rc;
        rc = redisClusterAppendCommand(cluster_ctx, "GET a");
        if (REDIS_OK != rc) {
            printf("Append fail.[%s]\n", cluster_ctx->errstr);
        }

        rc = redisClusterAppendCommand(cluster_ctx, "GET b");
        if (REDIS_OK != rc) {
            printf("Append fail.[%s]\n", cluster_ctx->errstr);
        }

        rc = redisClusterAppendCommand(cluster_ctx, "GET c");
        if (REDIS_OK != rc) {
            printf("Append fail.[%s]\n", cluster_ctx->errstr);
        }

        reply = NULL;
        rc = redisClusterGetReply(cluster_ctx, (void **)&reply);
        if (REDIS_OK != rc || !reply) {
            printf("Get reply fail.\n");
        } else {
            printf("%s\n", reply->str);
        }
        if (reply) {
            freeReplyObject(reply);
        }

        reply = NULL;
        rc = redisClusterGetReply(cluster_ctx, (void **)&reply);
        if (REDIS_OK != rc || !reply) {
            printf("Get reply fail.\n");
        } else {
            printf("%s\n", reply->str);
        }
        if (reply) {
            freeReplyObject(reply);
        }

        reply = NULL;
        rc = redisClusterGetReply(cluster_ctx, (void **)&reply);
        if (REDIS_OK != rc || !reply) {
            printf("Get reply fail.\n");
        } else {
            printf("%s\n", reply->str);
        }
        if (reply) {
            freeReplyObject(reply);
        }

        printf("Done\n");
        getchar();
    }
  1. 执行程序连接redis并正确获得GET a,b,c的内容
  2. 所有从库执行cluster failover接替主库
  3. 输入回车再次获取,收到MOVED语句

reply is null[route update error, please recreate redisClusterContext!]

复制的例子代码,返回标题的错误,是什么情况呢
`
redisClusterContext *cc = redisClusterConnect("172.18.33.6:7000,172.18.33.6:7001,172.18.33.6:7002", HIRCLUSTER_FLAG_NULL);
if(cc == NULL || cc->err)
{
printf("connect error : %s\n", cc == NULL ? "NULL" : cc->errstr);
return -1;
}

redisReply *reply = (redisReply*)redisClusterCommand(cc, "get  %s", "tttt");
if(reply == NULL)
{
    printf("reply is null[%s]\n", cc->errstr);
    redisClusterFree(cc);
    return -1;
}

`

build不过,出现对......未定义引用

/opt/workspace/connRedis/Debug/../test.cpp:15:对‘redisClusterConnect’未定义的引用
/opt/workspace/connRedis/Debug/../test.cpp:24:对‘redisClusterCommand’未定义的引用
/opt/workspace/connRedis/Debug/../test.cpp:28:对‘redisClusterFree’未定义的引用
/opt/workspace/connRedis/Debug/../test.cpp:32:对‘freeReplyObject’未定义的引用
/opt/workspace/connRedis/Debug/../test.cpp:35:对‘redisClusterCommand’未定义的引用
/opt/workspace/connRedis/Debug/../test.cpp:38:对‘redisClusterFree’未定义的引用
/opt/workspace/connRedis/Debug/../test.cpp:42:对‘freeReplyObject’未定义的引用
/opt/workspace/connRedis/Debug/../test.cpp:45:对‘redisClusterFree’未定义的引用

这情况是怎么一回事牙?

When I try to do hmset/hmget facing error "no reachable node in cluster"

I am able to connect to cluster withou any issue. Its not throwing any error. But whenever I try to do hmset/hmget its failing and throwing me the error "no reachable node in cluster"

Here is my code. In below code redis_config is string and its value is ":"

g_redis_cc = redisClusterConnect(redis_config, HIRCLUSTER_FLAG_NULL);
if (g_redis_cc == NULL || g_redis_cc->err) {
    if (g_redis_cc) {
        REDIS_DEBUG("Connection error: %s\n", g_redis_cc->errstr);
        redisFree(g_redis_cc);
    } else {
        REDIS_DEBUG("Connection error: can't allocate redis context\n");
    }
    return NULL;

}

reply = redisClusterCommand(g_redis_cc, "hmset %s %s %s", "keyname", "fieldname", "valuename");
if (reply == NULL) {
    printf("reply is NULL err %s \n", g_redis_cc->errstr);
}

Redis config is as below
redis-host:6379> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:1
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0

redisClusterGetReply获取的reply为NULL

通过pipeline发送命令后,采用redisClusterGetReply获取结果时错误。c->errstr结果为:Server closed the connection。redisClusterGetReply内部是有重连的,为什么还会出现这个问题呢? 另外, redisCLusterReset函数中调用redisClusterGetReply的话貌似会阻塞!

redisClusterAsyncDisconnect does not frees redisClusterAsyncContext

I am using the hiredis vip async api to connect to a 3 node cluster redis and my program is leaking
some memory.
It looks like the redisClusterAsyncContext structure is not being freed after calling the redisClusterAsyncDisconnect on it.

I have just made a simple example in order to reproduce the memory leak.

#include <iostream>
#include <sstream>
#include <event.h>
#include <hiredis-vip/adapters/libevent.h>
#include <hiredis-vip/hircluster.h>

void connect_cluster_cb(const redisAsyncContext *c, int status){
    std::cout << "Connected to redis cluster node " << c->c.tcp.host << ":" << c->c.tcp.port << std::endl;
}

void disconnect_cluster_cb(const redisAsyncContext *c, int status){
    if( status != REDIS_OK){
        std::cout << "Error : Disconnected from redis cluster node " << c->c.tcp.host << ":" << c->c.tcp.port << std::endl;
        exit(1);
    }
    std::cout << "Disconnected from redis cluster node " << c->c.tcp.host << ":" << c->c.tcp.port << std::endl;
}

void get_response_cluster_cb(redisClusterAsyncContext *c, void *r, void *data)
{
    static int count = 0;
    std::cout << "get_response_cluster_cb " << count << std::endl;
    redisClusterAsyncContext* rac = static_cast<redisClusterAsyncContext*>(data);

    if ( count > 8 ){
        std::cout << "Lets disconnect " << std::endl;
        redisClusterAsyncDisconnect(rac);
        // redisClusterAsyncFree(rac); Can't free structure here
    } else {
        count ++;
        std::stringstream ss;
        ss << "key" << count ;
        redisClusterAsyncCommand(c, get_response_cluster_cb, c, "GET %s", ss.str().c_str());
    }
}

int main(){
    std::string host = "localhost:7000";
    struct event_base *base = event_base_new();

    std::cout << "Connecting to redis " << host << std::endl;
    redisClusterAsyncContext *c = redisClusterAsyncConnect(host.c_str(), HIRCLUSTER_FLAG_NULL);
    if (c->err) {
        std::cout << "Redis problem when creating async context : " << c->errstr << std::endl;
    }

    redisClusterLibeventAttach(c, base);
    redisClusterAsyncSetConnectCallback(c, connect_cluster_cb);
    redisClusterAsyncSetDisconnectCallback(c, disconnect_cluster_cb);

    int status = redisClusterAsyncCommand(c, get_response_cluster_cb, c, "GET %s", "dummyping");
    if ( status == REDIS_OK){
        std::cout << "status ok" << std::endl;
    } else {
        std::cout << "status not ok" << std::endl;
    }

    event_base_dispatch(base);

    event_base_free(base);
    // redisClusterAsyncFree(c); If I add this, the program do not leak.
    return 0;
}

Use this line to compile it :

g++ leak_example.cpp  -O0 -g3 -std=c++11 -levent -lhiredis_vip

And when running it with valgrind, i get this :

==5900== Memcheck, a memory error detector
==5900== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5900== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==5900== Command: ./a.out
==5900== 
Connecting to redis localhost:7000
status ok
Connected to redis cluster node 172.20.0.10:7000
get_response_cluster_cb 0
Connected to redis cluster node 172.20.0.10:7001
get_response_cluster_cb 1
get_response_cluster_cb 2
get_response_cluster_cb 3
Connected to redis cluster node 172.20.0.10:7002
get_response_cluster_cb 4
get_response_cluster_cb 5
get_response_cluster_cb 6
get_response_cluster_cb 7
get_response_cluster_cb 8
get_response_cluster_cb 9
Lets disconnect 
Disconnected from redis cluster node 172.20.0.10:7000
Disconnected from redis cluster node 172.20.0.10:7002
Disconnected from redis cluster node 172.20.0.10:7001
==5900== 
==5900== HEAP SUMMARY:
==5900==     in use at exit: 205,309 bytes in 34 blocks
==5900==   total heap usage: 433 allocs, 399 frees, 250,066 bytes allocated
==5900== 
==5900== 132,605 (184 direct, 132,421 indirect) bytes in 1 blocks are definitely lost in loss record 15 of 15
==5900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5900==    by 0x4E54337: redisClusterAsyncInitialize (hircluster.c:4256)
==5900==    by 0x4E54337: redisClusterAsyncConnect (hircluster.c:4435)
==5900==    by 0x401B67: main (leak_example.cpp:43)
==5900== 
==5900== LEAK SUMMARY:
==5900==    definitely lost: 184 bytes in 1 blocks
==5900==    indirectly lost: 132,421 bytes in 32 blocks
==5900==      possibly lost: 0 bytes in 0 blocks
==5900==    still reachable: 72,704 bytes in 1 blocks
==5900==         suppressed: 0 bytes in 0 blocks
==5900== Reachable blocks (those to which a pointer was found) are not shown.
==5900== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==5900== 
==5900== For counts of detected and suppressed errors, rerun with: -v
==5900== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

As I commented in the last part of my code, calling the redisClusterAsyncFree at the end of the main solves the memory leak. However, in my program, this is not possible ( i am connecting and disconnecting from the cluster from time to time).
Doing the redisClusterAsyncFree right after calling the redisClusterAsyncDisconnect is not possible also because it generates invalid reads and writes.

One idea i have is to count the connects and disconnects for a redis cluster and call redisClusterAsyncFree after all disconnects callbacks are called. However i am not able to pass any data to the connect and disconnect callbacks in order to do some counting for a particular connection.

Probably the redisClusterAsyncDisconnect should free the redisClusterAsyncContext ? This is the behaviour of the redisAsyncDisconnect of the hirerdis library.

Thanks in advance,
pablo

redisContextConnectTcp is blocked in the poll

HI,
I am trying to redisClusterAsyncConnect to connect to cluster. But looks like cluster context flags are ignored when we create redisContext and which leads to blocking connect. If route to destination exist then connect gets blocked forever.

cluster_update_route_by_addr
{
<>
if(cc->timeout){
c = redisConnectWithTimeout(ip, port, *cc->timeout);
}else{
c = redisConnect(ip, port); <<< this is always blockig even if cc has blocking flag reset.
}
<>
}

集群模式下从节点连接问题

你好,我的redis服务器使用集群,配置文件设置了slave-read-only yes。通过hiredis_vip redisClusterConnectWithTimeout 连接集群,但是发现实际的读操作中只是使用了主节点,没有使用从节点。在主节点正常的情况下没有和从节点的连接,这样效率低一半。请问怎么使用vip才能连接到从节点?

Lua脚本的支持

你好,我使用hiredis-vip进行Lua脚本的执行的时候,发现即使使用{}保证键在一个slot内,也会出现lua脚本的异常,但是直接在终端上执行就没有问题,请问后面会考虑添加对Lua脚本的一些有限支持吗?

compile error

/usr/local/hiredis-vip/include/adlist.h:73: 错误:对‘list’的引用有歧义
/usr/local/hiredis-vip/include/adlist.h:54: 错误:candidates are: typedef struct list list
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:417: 错误: template<class _Tp, class _Alloc> class std::list
/usr/local/hiredis-vip/include/adlist.h:73: 错误:expected constructor, destructor, or type conversion before ‘*’ token
/usr/local/hiredis-vip/include/adlist.h:74: 错误:对‘list’的引用有歧义
/usr/local/hiredis-vip/include/adlist.h:54: 错误:candidates are: typedef struct list list
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:417: 错误: template<class _Tp, class _Alloc> class std::list
/usr/local/hiredis-vip/include/adlist.h:74: 错误:变量或字段‘listRelease’声明为 void
/usr/local/hiredis-vip/include/adlist.h:74: 错误:对‘list’的引用有歧义
/usr/local/hiredis-vip/include/adlist.h:54: 错误:candidates are: typedef struct list list
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:417: 错误: template<class _Tp, class _Alloc> class std::list

看下吧,兄弟!

Parse Error

After spending quite a while trying to trace a parse error it has come to my attention that it would be really nice to be able to see the state of the parser when the error occurred.

In order to do this I had to break out GDB.

Even if its just the state and current position (token position), this could be extremely useful.

基础hiredis是否升级到1.0.0版本

现在用的是0.13.1版本,还是代码直接copy过来的,这样hiredis和hiredis-vip演进会有问题。是否支持hiredis1.0.0版本,并且把代码分开?

reply is null[no reachable node in cluster]

Hi, I set up redis cluster(3 nodes) and test it with hiredis-vip example code
redisClusterContext *cc = redisClusterConnect("192.168.0.5:7001,192.168.0.5:7002,192.168.0.5:7003",HIRCLUSTER_FLAG_NULL);
redisReply *reply;
reply = redisClusterCommand(cc, "set key1 value1");
if(reply == NULL){
printf("reply is null[%s]\n", cc->errstr);
redisClusterFree(cc);
return -1;
}

Result: reply is null[no reachable node in cluster]

Cluster info:
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:3
cluster_size:3
cluster_current_epoch:3
cluster_my_epoch:1
cluster_stats_messages_sent:29821
cluster_stats_messages_received:29821

redis_version:3.2.8

请问下,支不支持pub/sub功能?

This API can also be used to implement a blocking subscriber:

reply = redisClusterCommand(clusterContext,"SUBSCRIBE foo");
freeReplyObject(reply);
while(redisClusterGetReply(clusterContext,&reply) == REDIS_OK) {
// consume message
freeReplyObject(reply);
}
redisClusterReset(clusterContext);

测试结果输出:
Parse command error. Cmd type: 0, state: 5, break position: 17.

你好,关于redis-cluster-c-client的一个问题

我们存储的value是若干个struct的内存字节拷贝,然后转换为字符串。我遇到了一个问题,当字符串中某个byte是0时,value会被截断,看了代码,应该是redisvFormatCommand这个函数中是已'\0'判断字符串结束的,如下:while(*c != '\0')。我想请问作者,这个可以改成传入字符串字节长度,代替'\0'标记结束吗? 因为我发现网上一些其他的主从client是可以支持包含'\0'字节的value设置的。
谢谢!

关于redisCLusterReset函数的问题

该函数在hircluster.c源码中的第3925行执行了redisReaderFree(c->reader);
但是c这个指针在上面是被置为空而且在后续代码中也未被修改的,这样写的用意是什么呢?

make test not works

How to run test case?

#01 Format command without interpolation: PASSED
#02 Format command with %s string interpolation: PASSED
#03 Format command with %s and an empty string: PASSED
#04 Format command with an empty string in between proper interpolations: PASSED
#05 Format command with %b string interpolation: PASSED
#06 Format command with %b and an empty string: PASSED
#07 Format command with literal %: PASSED
#08 Format command with printf-delegation (int): PASSED
#09 Format command with printf-delegation (char): PASSED
#10 Format command with printf-delegation (short): PASSED
#11 Format command with printf-delegation (long): PASSED
#12 Format command with printf-delegation (long long): PASSED
#13 Format command with printf-delegation (unsigned int): PASSED
#14 Format command with printf-delegation (unsigned char): PASSED
#15 Format command with printf-delegation (unsigned short): PASSED
#16 Format command with printf-delegation (unsigned long): PASSED
#17 Format command with printf-delegation (unsigned long long): PASSED
#18 Format command with printf-delegation (float): PASSED
#19 Format command with printf-delegation (double): PASSED
#20 Format command with invalid printf format: PASSED
#21 Format command by passing argc/argv without lengths: PASSED
#22 Format command by passing argc/argv with lengths: PASSED
#23 Error handling in reply parser: PASSED
#24 Memory cleanup in reply parser: PASSED
#25 Set error on nested multi bulks with depth > 7: PASSED
#26 Works with NULL functions for reply: PASSED
#27 Works when a single newline (\r\n) covers two calls to feed: PASSED
#28 Don't reset state after protocol error: PASSED
#29 Don't do empty allocation for empty multi bulk: PASSED
#30 Returns error when host cannot be resolved: PASSED
#31 Returns error when the port is not open: PASSED
#32 Returns error when the unix socket path doesn't accept connections: PASSED
#33 Don't fail when redisFree is passed a NULL value: PASSED
#34 Don't fail when freeReplyObject is passed a NULL value: PASSED

Testing against TCP connection (127.0.0.1:6380):
Database #9 is not empty, test can not continue
make: *** [test] Error 1

请教一下批量操作问题

1.在使用libevent作为异步框架时进行mget操作没触发回调函数,请问怎么解决?
2.没有针对异步模式的pipeline么?

error: [ctx get by node is null], 4.0rc3 cluster with one slave,all slot port is -1

4.0rc3 cluster with one slave,all slot port is -1

in node_get_with_nodes() node_infos[1] value is 192.168.100.10:33003@43003
node->port = hi_atoi(ip_port[1], sdslen(ip_port[1]));
this line convert failed.

slots info:

f71188687317ab3d38b2a71f3746ea51c118b794 192.168.100.10:33003@43003 master - 0 1495769813746 3 connected 10923-16383
f5f98cc7313640b7de905eadba330f4c8e3eaccd 192.168.100.10:33002@43002 master - 0 1495769814047 2 connected 5461-10922
95132622d6f9a3a4e1e0452686d0370474b57e48 192.168.100.10:33001@43001 myself,master - 0 1495769813000 1 connected 0-5460
d71c2bff2878335ceb15e3eab7426f0a846baedd 192.168.100.10:33005@43005 slave f5f98cc7313640b7de905eadba330f4c8e3eaccd 0 1495769814047 5 con
nected
3ecd7994c8e533040312095eaab3b31b5c396ad8 192.168.100.10:33004@43004 slave 95132622d6f9a3a4e1e0452686d0370474b57e48 0 1495769814047 4 con
nected
1387547ec9df054fb1b3a46822676f0873b3e92b 192.168.100.10:33006@43006 slave f71188687317ab3d38b2a71f3746ea51c118b794 0 1495769814047 6 con
nected

hello,a question about redis-cluster muti operation.

我看了README.md中的cluster的pipeline操作,没有问题,但是现在的场景我需要执行原子操作的muti函数,看test.c中对于非cluster有如下操作,然后我尝试着用于cluster中,结果执行时“Segmentation fault”了,请问目前客户端可以支持cluster的事物操作吗?谢谢!
freeReplyObject(redisClusterCommand(c,"MULTI"));
freeReplyObject(redisClusterCommand(c,"LRANGE mylist 0 -1"));
freeReplyObject(redisClusterCommand(c,"PING"));
reply = (redisClusterCommand(c,"EXEC"));

谢谢!

请教一个redis-cluster的问题

你好,我想请教一个问题。我部署了一台6主6从的redis-cluster(版本3.0.7),在调用c++客户端执行get操作不断加压时,发现有1个节点的cpu利用率飙到了100%,而剩下的11个节点cpu利用率不到10%。对redis-cluster的读取操作不是均衡分布的吗?我想请教下这个是不是和redis-cluster的运行机制有关系啊?还是和我们的client设计有关系?(ps:get操作的key是int64的,value是30-40k的字符串)。谢谢!

Deleting Multiple Keys

How can I delete Multiple keys in a single command. The following syntax does not work. I am guessing cluster does not support when the keys are distributed across the slots!!

The following didn't work!!

redisClusterAsyncCommand(redisCtxt, redisDeleteCallback, trans, "DEL %s %s %s %s", k1, k2, k3,k4)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.