Redis C 客户端例子(使用Siren)

启动Redis服务器

docker run --name redis -p 6379:6379 -d redis

初始化数据库

docker exec -it redis redis-cli
SET foo bar
quit

客户端代码(redis_client.cc)

#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 

#include 

#include 
#include 
#include 
#include 
#include 
#include 


#define HIREDIS_DL_FILE_NAME "libhiredis.so"


extern siren::Loop *siren_loop;
extern siren::Async *siren_async;


namespace {

auto elf_hooks = std::make_tuple(
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "open", siren_open),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "read", maybe_siren_read),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "write", maybe_siren_write),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "readv", maybe_siren_readv),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "writev", maybe_siren_writev),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "lseek", siren_lseek),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "close", maybe_siren_close),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "usleep", siren_usleep),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "socket", siren_socket),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "getsockopt", siren_getsockopt),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "setsockopt", siren_setsockopt),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "accept", siren_accept),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "accept4", siren_accept4),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "connect", siren_connect),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "recv", siren_recv),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "send", siren_send),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "recvfrom", siren_recvfrom),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "sendto", siren_sendto),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "getaddrinfo", siren_getaddrinfo),
    // siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "getnameinfo", siren_getnameinfo),
    siren::MakeELFHook(HIREDIS_DL_FILE_NAME, "poll", siren_poll)
);


class RedisError
  : public std::exception
{
public:
    explicit RedisError(redisContext *redis) {
        description_ = "RedisError: ";
        description_ += redis->errstr;
    }

    const char *what() const noexcept override {
        return description_.c_str();
    }

private:
    std::string description_;
};

}


int
real_main(int fiberID)
{
    redisContext *redis = redisConnect("192.168.11.101", 6379);

    if (redis == nullptr) {
       throw std::bad_alloc();
    }

    auto scopeGuard = siren::MakeScopeGuard([&] () -> void {
        redisFree(redis);
    });

    if (redis->err != 0) {
        throw RedisError(redis);
    }

    // 增、改
    {
        redisReply *reply = static_cast(redisCommand(redis, "SET hello world%d", fiberID));

        if (reply == nullptr) {
            throw RedisError(redis);
        }

        auto scopeGuard = siren::MakeScopeGuard([&] () -> void {
            freeReplyObject(reply);
        });

        std::printf("[%d] SET FOO: %s\n", fiberID, reply->str);
    }

    // 查
    {
        redisReply *reply = static_cast(redisCommand(redis, "GET hello"));

        if (reply == nullptr) {
            throw RedisError(redis);
        }

        auto scopeGuard = siren::MakeScopeGuard([&] () -> void {
            freeReplyObject(reply);
        });

        std::printf("[%d] GET FOO: %s\n", fiberID, reply->str);
    }
}


int
main()
{
    siren::IterateTuple(elf_hooks, [] (auto &&elf_hook) { elf_hook.toggle(); });
    siren::Loop loop(16 * 1024);
    siren::Async async(&loop);
    siren_loop = &loop;
    siren_async = &async;
    int result;

    for (int i = 0; i < 10; ++i) {
        loop.createFiber([&, i(i)] () {
            result = real_main(i);
        }, 32 * 1024);
    }

    try {
        loop.run();
    } catch (const std::exception &exception) {
        std::fprintf(stderr, "%s\n", exception.what());
        return 1;
    }

    return result;
}

编译运行

g++ -std=c++14 redis_client.cc -lsiren -pthread -lhiredis -ldl && ./a.out

你可能感兴趣的:(Redis C 客户端例子(使用Siren))