1
0
Fork 0
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:
King_DuckZ 2016-06-21 14:19:59 +01:00
parent 7957a94980
commit c61619eb38
5 changed files with 130 additions and 0 deletions

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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;
};

View 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