啟動(dòng)Redis服務(wù)器
docker run --name redis -p 6379:6379 -d redis
初始化數(shù)據(jù)庫
docker exec -it redis redis-cli
SET foo bar
quit
客戶端代碼(redis_client.cc)
#include <cstdio>
#include <exception>
#include <new>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/poll.h>
#include <hiredis/hiredis.h>
#include <siren/async.h>
#include <siren/c_library.h>
#include <siren/elf_hook.h>
#include <siren/loop.h>
#include <siren/scope_guard.h>
#include <siren/utility.h>
#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<redisReply *>(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<redisReply *>(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;
}
編譯運(yùn)行
g++ -std=c++14 redis_client.cc -lsiren -pthread -lhiredis -ldl && ./a.out