diff --git a/src/backends/redis/CMakeLists.txt b/src/backends/redis/CMakeLists.txt index 634774d..8a614df 100644 --- a/src/backends/redis/CMakeLists.txt +++ b/src/backends/redis/CMakeLists.txt @@ -4,6 +4,7 @@ find_package(hiredis 0.11.0 REQUIRED) add_library(${PROJECT_NAME} SHARED backend_redis.cpp + command.cpp ) target_include_directories(${PROJECT_NAME} SYSTEM diff --git a/src/backends/redis/backend_redis.cpp b/src/backends/redis/backend_redis.cpp index 7c9ccc6..ec02fe0 100644 --- a/src/backends/redis/backend_redis.cpp +++ b/src/backends/redis/backend_redis.cpp @@ -20,18 +20,10 @@ #include "backends/exposed_functions.hpp" #include "backends/backend_version.hpp" #include -#include -#include -#include -#include -#include -#include #include namespace dindb { namespace { - using RedisReply = std::unique_ptr; - struct RedisConnectionSettings { std::string address; uint16_t port; @@ -62,42 +54,20 @@ namespace YAML { } //namespace YAML namespace dindb { - BackendRedis::BackendRedis(std::string &&parAddress, uint16_t parPort, - bool parConnect) : - m_conn(nullptr, &redisFree), - m_address(std::move(parAddress)), - m_port(parPort) { - if (parConnect) - this->connect(); + BackendRedis::BackendRedis(std::string &&parAddress, uint16_t parPort, bool parConnect) : + m_redis(std::move(parAddress), parPort, parConnect) + { } BackendRedis::~BackendRedis() noexcept { } void BackendRedis::connect() { - if (not m_conn) { - struct timeval timeout = {5, 500000}; //5.5 seconds? - RedisConnection conn( - redisConnectWithTimeout(m_address.c_str(), m_port, timeout), - &redisFree - ); - if (not conn) { - std::ostringstream oss; - oss << "Unable to connect to Redis server at " << m_address << ':' << m_port; - throw std::runtime_error(oss.str()); - } - if (conn->err) { - std::ostringstream oss; - oss << "Unable to connect to Redis server at " << m_address << ':' << m_port << - ": " << conn->errstr; - throw std::runtime_error(oss.str()); - } - std::swap(conn, m_conn); - } - } + m_redis.connect(); + } void BackendRedis::disconnect() { - m_conn.reset(); + m_redis.disconnect(); } void BackendRedis::tag_files (const std::vector& parFiles, const std::vector& parTags, GroupIDType parSet) { @@ -122,30 +92,7 @@ namespace dindb { } void BackendRedis::write_files (const std::vector& parData, const mchlib::SetRecordDataFull& parSetData, const std::string& parSignature) { - assert(is_connected()); - std::string key; - { - std::ostringstream key_oss; - RedisReply incr_reply(static_cast(redisCommand(m_conn.get(), "incr set_counter")), &freeReplyObject); - key_oss << "sets:" << incr_reply->integer; - key = key_oss.str(); - } - - RedisReply insert_reply( - static_cast(redisCommand( - m_conn.get(), - "hmset %b name %b disk_label %b fs_uuid %b", - key.data(), - key.size(), - parSetData.name.data(), - parSetData.name.size(), - parSetData.disk_label.data(), - parSetData.disk_label.size(), - parSetData.fs_uuid.data(), - parSetData.fs_uuid.size() - )), - &freeReplyObject - ); + //TODO: run command } bool BackendRedis::search_file_by_hash (mchlib::FileRecordData& parItem, mchlib::SetRecordDataFull& parSet, const mchlib::TigerHash& parHash) { @@ -183,10 +130,6 @@ namespace dindb { std::vector BackendRedis::find_paths_starting_by (GroupIDType parGroupID, uint16_t parLevel, boost::string_ref parPath) { return std::vector(); } - - bool BackendRedis::is_connected() const { - return m_conn and not m_conn->err; - } } //namespace dindb extern "C" dindb::Backend* dindexer_create_backend (const YAML::Node* parConfig) { diff --git a/src/backends/redis/backend_redis.hpp b/src/backends/redis/backend_redis.hpp index 3ab92a0..1e32ba9 100644 --- a/src/backends/redis/backend_redis.hpp +++ b/src/backends/redis/backend_redis.hpp @@ -19,12 +19,10 @@ #define idB2F92EE07A004D5293FD0657EEE8F75B #include "backends/db_backend.hpp" -#include +#include "command.hpp" #include #include -struct redisContext; - namespace dindb { class BackendRedis : public Backend { public: @@ -58,13 +56,7 @@ namespace dindb { virtual std::vector find_paths_starting_by ( GroupIDType parGroupID, uint16_t parLevel, boost::string_ref parPath ) override; private: - using RedisConnection = std::unique_ptr; - - bool is_connected ( void ) const; - - RedisConnection m_conn; - std::string m_address; - uint16_t m_port; + redis::Command m_redis; }; } //namespace dindb diff --git a/src/backends/redis/command.cpp b/src/backends/redis/command.cpp new file mode 100644 index 0000000..5b53b64 --- /dev/null +++ b/src/backends/redis/command.cpp @@ -0,0 +1,105 @@ +/* Copyright 2015, 2016, Michele Santullo + * This file is part of "dindexer". + * + * "dindexer" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "dindexer" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "dindexer". If not, see . + */ + +#include "command.hpp" +#include +#include +#include +#include +#include +#include + +namespace redis { + namespace { + using RedisReply = std::unique_ptr; + } //unnamed namespace + + Command::Command (std::string&& parAddress, uint16_t parPort, bool parConnect) : + m_conn(nullptr, &redisFree), + m_address(std::move(parAddress)), + m_port(parPort) + { + if (parConnect) + this->connect(); + } + + Command::~Command() noexcept { + } + + void Command::connect() { + if (not m_conn) { + struct timeval timeout = {5, 500000}; //5.5 seconds? + RedisConnection conn( + redisConnectWithTimeout(m_address.c_str(), m_port, timeout), + &redisFree + ); + if (not conn) { + std::ostringstream oss; + oss << "Unable to connect to Redis server at " << m_address << ':' << m_port; + throw std::runtime_error(oss.str()); + } + if (conn->err) { + std::ostringstream oss; + oss << "Unable to connect to Redis server at " << m_address << ':' << m_port << + ": " << conn->errstr; + throw std::runtime_error(oss.str()); + } + std::swap(conn, m_conn); + } + } + + void Command::disconnect() { + m_conn.reset(); + } + + void Command::run (const char* parCommand, int parArgc, const char** parArgv, std::size_t* parLengths) { + assert(is_connected()); + + RedisReply reply( + static_cast(redisCommandArgv(m_conn.get(), parArgc, parArgv, parLengths)), + &freeReplyObject + ); + + //std::string key; + //{ + // std::ostringstream key_oss; + // RedisReply incr_reply(static_cast(redisCommand(m_conn.get(), "incr set_counter")), &freeReplyObject); + // key_oss << "sets:" << incr_reply->integer; + // key = key_oss.str(); + //} + + //RedisReply insert_reply( + // static_cast(redisCommand( + // m_conn.get(), + // "hmset %b name %b disk_label %b fs_uuid %b", + // key.data(), + // key.size(), + // parSetData.name.data(), + // parSetData.name.size(), + // parSetData.disk_label.data(), + // parSetData.disk_label.size(), + // parSetData.fs_uuid.data(), + // parSetData.fs_uuid.size() + // )), + // &freeReplyObject + //); + } + + bool Command::is_connected() const { + return m_conn and not m_conn->err; + } +} //namespace redis diff --git a/src/backends/redis/command.hpp b/src/backends/redis/command.hpp new file mode 100644 index 0000000..fe327ed --- /dev/null +++ b/src/backends/redis/command.hpp @@ -0,0 +1,73 @@ +/* Copyright 2015, 2016, Michele Santullo + * This file is part of "dindexer". + * + * "dindexer" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "dindexer" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "dindexer". If not, see . + */ + +#ifndef idD83EEBFC927840C6B9F32D61A1D1E582 +#define idD83EEBFC927840C6B9F32D61A1D1E582 + +#include +#include +#include +#include +#include +#include + +struct redisContext; + +namespace redis { + class Command { + public: + Command ( std::string&& parAddress, uint16_t parPort, bool parConnect ); + ~Command ( void ) noexcept; + + void connect ( void ); + void disconnect ( void ); + + bool is_connected ( void ) const; + + template + void run ( const char* parCommand, Args&&... parArgs ); + + private: + using RedisConnection = std::unique_ptr; + + void run ( const char* parCommand, int parArgc, const char** parArgv, std::size_t* parLengths ); + + RedisConnection m_conn; + std::string m_address; + uint16_t m_port; + }; + + template + void Command::run (const char* parCommand, Args&&... parArgs) { + constexpr const std::size_t arg_count = sizeof...(Args); + using CharPointerArray = std::array; + using LengthArray = std::array; + + CharPointerArray arguments; + LengthArray lengths; + assert(false); //TODO write implementation + + this->run( + parCommand, + static_cast(arg_count), + arguments.data(), + lengths.data() + ); + } +} //namespace redis + +#endif