mirror of
https://github.com/KingDuckZ/dindexer.git
synced 2025-02-17 11:45:50 +00:00
Add code to submit scripts to Redis.
This is untested, but I can't test it until I implement other things first. I also need to do some refactoring, so I need to commit and make a checkpoint now. Consider this code as good as if didn't exist.
This commit is contained in:
parent
7957a94980
commit
c61619eb38
5 changed files with 130 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
project(${bare_name}-backend-redis CXX)
|
||||
|
||||
find_package(hiredis 0.11.0 REQUIRED)
|
||||
find_package(CryptoPP 5.6)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
backend_redis.cpp
|
||||
|
@ -15,6 +16,9 @@ target_include_directories(${PROJECT_NAME} SYSTEM
|
|||
PRIVATE ${HIREDIS_INCLUDE_DIRS}
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/lib/better-enums
|
||||
)
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE ${bare_name}-inc
|
||||
|
@ -22,6 +26,19 @@ target_link_libraries(${PROJECT_NAME}
|
|||
PRIVATE ${HIREDIS_LIBRARIES}
|
||||
)
|
||||
|
||||
if (CryptoPP_FOUND)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${CryptoPP_LIBRARIES})
|
||||
target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE ${CryptoPP_INCLUDE_DIRS})
|
||||
set (has_cryptopp_lib ON)
|
||||
else()
|
||||
set (has_cryptopp_lib OFF)
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
redisConfig.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/redisConfig.h
|
||||
)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace redis {
|
|||
};
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void hiredis_run_callback (redisAsyncContext*, void* parReply, void* parPrivData) {
|
||||
assert(parPrivData);
|
||||
auto* data = static_cast<HiredisCallbackData*>(parPrivData);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
|
||||
#include "command.hpp"
|
||||
#include "helpers/lexical_cast.hpp"
|
||||
#include <hiredis/hiredis.h>
|
||||
#include <hiredis/async.h>
|
||||
#include <ciso646>
|
||||
|
@ -23,9 +24,23 @@
|
|||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#if defined(WITH_CRYPTOPP)
|
||||
# include <crypto++/sha.h>
|
||||
#endif
|
||||
|
||||
namespace redis {
|
||||
namespace {
|
||||
#if defined(WITH_CRYPTOPP)
|
||||
struct LuaScriptHash {
|
||||
union {
|
||||
struct {
|
||||
uint64_t part_a, part_b;
|
||||
uint32_t part_c;
|
||||
};
|
||||
uint8_t raw_bytes[20];
|
||||
};
|
||||
};
|
||||
#endif
|
||||
} //unnamed namespace
|
||||
|
||||
Command::Command (std::string&& parAddress, uint16_t parPort) :
|
||||
|
@ -87,4 +102,57 @@ namespace redis {
|
|||
assert(is_connected());
|
||||
return Batch(m_conn.get());
|
||||
}
|
||||
|
||||
#if defined(WITH_CRYPTOPP)
|
||||
boost::string_ref Command::add_lua_script_ifn (const std::string& parScript) {
|
||||
if (parScript.empty())
|
||||
return boost::string_ref();
|
||||
|
||||
using dinhelp::lexical_cast;
|
||||
|
||||
static_assert(20 == CryptoPP::SHA1::DIGESTSIZE, "Unexpected SHA1 digest size");
|
||||
static_assert(sizeof(LuaScriptHash) >= CryptoPP::SHA1::DIGESTSIZE, "Wrong SHA1 struct size");
|
||||
static_assert(Sha1Array().size() == CryptoPP::SHA1::DIGESTSIZE, "Wrong array size");
|
||||
|
||||
LuaScriptHash digest;
|
||||
CryptoPP::SHA1().CalculateDigest(digest.raw_bytes, reinterpret_cast<const uint8_t*>(parScript.data()), parScript.size());
|
||||
//TODO: change when lexical_cast will support arrays
|
||||
const std::string sha1_str = lexical_cast<std::string>(digest.part_a) + lexical_cast<std::string>(digest.part_b) + lexical_cast<std::string>(digest.part_c);
|
||||
Sha1Array sha1_array;
|
||||
std::copy(sha1_str.begin(), sha1_str.end(), sha1_array.begin());
|
||||
|
||||
auto it_found = m_known_hashes.find(sha1_array);
|
||||
const bool was_present = (m_known_hashes.end() != it_found);
|
||||
if (was_present) {
|
||||
return boost::string_ref(it_found->data(), it_found->size());
|
||||
}
|
||||
|
||||
auto reply = this->run("SCRIPT", "LOAD", parScript);
|
||||
assert(not was_present);
|
||||
|
||||
assert(get_string(reply) == sha1_str);
|
||||
const auto it_inserted = m_known_hashes.insert(it_found, sha1_array);
|
||||
(void)reply;
|
||||
|
||||
return boost::string_ref(it_inserted->data(), it_inserted->size());
|
||||
}
|
||||
#else
|
||||
boost::string_ref Command::add_lua_script_ifn (const std::string& parScript) {
|
||||
auto it_found = m_known_hashes.find(parScript);
|
||||
const bool was_present = (m_known_hashes.end() != it_found);
|
||||
if (was_present) {
|
||||
return boost::string_ref(it_found->second.data(), it_found->second.size());
|
||||
}
|
||||
|
||||
auto reply = this->run("SCRIPT", "LOAD", parScript);
|
||||
assert(not was_present);
|
||||
|
||||
const auto sha1_str = get_string(reply);
|
||||
Sha1Array sha1_array;
|
||||
std::copy(sha1_str.begin(), sha1_str.end(), sha1_array.begin());
|
||||
auto it_inserted = m_known_hashes.insert(it_found, std::make_pair(parScript, sha1_array));
|
||||
|
||||
return boost::string_ref(it_inserted->second.data(), it_inserted->second.size());
|
||||
}
|
||||
#endif
|
||||
} //namespace redis
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "scan_iterator.hpp"
|
||||
#include "reply.hpp"
|
||||
#include "batch.hpp"
|
||||
#include "redisConfig.h"
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -32,6 +33,12 @@
|
|||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <stdexcept>
|
||||
#if defined(WITH_CRYPTOPP)
|
||||
# include <set>
|
||||
#else
|
||||
# include <map>
|
||||
#endif
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
struct redisAsyncContext;
|
||||
|
||||
|
@ -66,10 +73,20 @@ namespace redis {
|
|||
sscan_range sscan ( boost::string_ref parKey );
|
||||
zscan_range zscan ( boost::string_ref parKey );
|
||||
|
||||
void submit_lua_script ( const std::string& parScript );
|
||||
|
||||
private:
|
||||
using RedisConnection = std::unique_ptr<redisAsyncContext, void(*)(redisAsyncContext*)>;
|
||||
using Sha1Array = std::array<char, 20>;
|
||||
|
||||
boost::string_ref add_lua_script_ifn ( const std::string& parScript );
|
||||
|
||||
RedisConnection m_conn;
|
||||
#if defined(WITH_CRYPTOPP)
|
||||
std::set<Sha1Array> m_known_hashes;
|
||||
#else
|
||||
std::map<std::string, Sha1Array> m_known_scripts;
|
||||
#endif
|
||||
std::string m_address;
|
||||
uint16_t m_port;
|
||||
};
|
||||
|
|
27
src/backends/redis/redisConfig.h.in
Normal file
27
src/backends/redis/redisConfig.h.in
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef idB3E2F339E3B64378B66342550C4D2089
|
||||
#define idB3E2F339E3B64378B66342550C4D2089
|
||||
|
||||
#include "helpers/cmake_on_off.h"
|
||||
|
||||
#if CMAKE_@has_cryptopp_lib@
|
||||
# define WITH_CRYPTOPP
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue