107 lines
2.5 KiB
C++
107 lines
2.5 KiB
C++
|
|
#include "config.h"
|
|
#ifdef USE_REDIS
|
|
|
|
#include <stdexcept>
|
|
#include <sstream>
|
|
#include <fstream>
|
|
#include "db-redis.h"
|
|
#include "Settings.h"
|
|
|
|
static inline int64_t stoi64(const std::string &s)
|
|
{
|
|
std::stringstream tmp(s);
|
|
int64_t t;
|
|
tmp >> t;
|
|
return t;
|
|
}
|
|
|
|
|
|
#if 0
|
|
static inline std::string i64tos(int64_t i)
|
|
{
|
|
std::ostringstream os;
|
|
os << i;
|
|
return os.str();
|
|
}
|
|
#endif
|
|
|
|
DBRedis::DBRedis(const std::string &mapdir) :
|
|
m_blocksReadCount(0),
|
|
m_blocksQueriedCount(0)
|
|
{
|
|
Settings world_mt(mapdir + "/world.mt");
|
|
std::string address;
|
|
if (!world_mt.check("redis_address", address) || !world_mt.check("redis_hash", hash)) {
|
|
throw std::runtime_error("Set redis_address and redis_hash in world.mt to use the redis backend");
|
|
}
|
|
int port = stoi64(world_mt.get("redis_port", "6379"));
|
|
ctx = redisConnect(address.c_str(), port);
|
|
if(!ctx)
|
|
throw std::runtime_error("Cannot allocate redis context");
|
|
else if(ctx->err) {
|
|
std::string err = std::string("Connection error: ") + ctx->errstr;
|
|
redisFree(ctx);
|
|
throw std::runtime_error(err);
|
|
}
|
|
}
|
|
|
|
|
|
DBRedis::~DBRedis()
|
|
{
|
|
redisFree(ctx);
|
|
}
|
|
|
|
|
|
int DBRedis::getBlocksReadCount(void)
|
|
{
|
|
return m_blocksReadCount;
|
|
}
|
|
|
|
int DBRedis::getBlocksQueriedCount(void)
|
|
{
|
|
return m_blocksQueriedCount;
|
|
}
|
|
|
|
|
|
const DB::BlockPosList &DBRedis::getBlockPosList()
|
|
{
|
|
redisReply *reply;
|
|
reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str());
|
|
if(!reply)
|
|
throw std::runtime_error(std::string("redis command 'HKEYS %s' failed: ") + ctx->errstr);
|
|
if(reply->type != REDIS_REPLY_ARRAY)
|
|
throw std::runtime_error("Failed to get keys from database");
|
|
for(size_t i = 0; i < reply->elements; i++) {
|
|
if(reply->element[i]->type != REDIS_REPLY_STRING)
|
|
throw std::runtime_error("Got wrong response to 'HKEYS %s' command");
|
|
m_blockPosList.push_back(BlockPos(reply->element[i]->str));
|
|
}
|
|
|
|
freeReplyObject(reply);
|
|
return m_blockPosList;
|
|
}
|
|
|
|
|
|
const DB::Block DBRedis::getBlockOnPos(const BlockPos &pos)
|
|
{
|
|
redisReply *reply;
|
|
std::string tmp;
|
|
Block block(pos, {});
|
|
|
|
m_blocksQueriedCount++;
|
|
|
|
reply = (redisReply*) redisCommand(ctx, "HGET %s %s", hash.c_str(), pos.databasePosStr().c_str());
|
|
if(!reply)
|
|
throw std::runtime_error(std::string("redis command 'HGET %s %s' failed: ") + ctx->errstr);
|
|
if (reply->type == REDIS_REPLY_STRING && reply->len != 0) {
|
|
m_blocksReadCount++;
|
|
block = Block(pos, reinterpret_cast<const unsigned char *>(reply->str), reply->len);
|
|
} else
|
|
throw std::runtime_error("Got wrong response to 'HGET %s %s' command");
|
|
freeReplyObject(reply);
|
|
|
|
return block;
|
|
}
|
|
#endif // USE_REDIS
|