mirror of
https://github.com/KingDuckZ/dindexer.git
synced 2025-07-02 14:04:22 +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)
|
project(${bare_name}-backend-redis CXX)
|
||||||
|
|
||||||
find_package(hiredis 0.11.0 REQUIRED)
|
find_package(hiredis 0.11.0 REQUIRED)
|
||||||
|
find_package(CryptoPP 5.6)
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} SHARED
|
add_library(${PROJECT_NAME} SHARED
|
||||||
backend_redis.cpp
|
backend_redis.cpp
|
||||||
|
@ -15,6 +16,9 @@ target_include_directories(${PROJECT_NAME} SYSTEM
|
||||||
PRIVATE ${HIREDIS_INCLUDE_DIRS}
|
PRIVATE ${HIREDIS_INCLUDE_DIRS}
|
||||||
PRIVATE ${CMAKE_SOURCE_DIR}/lib/better-enums
|
PRIVATE ${CMAKE_SOURCE_DIR}/lib/better-enums
|
||||||
)
|
)
|
||||||
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE ${bare_name}-inc
|
PRIVATE ${bare_name}-inc
|
||||||
|
@ -22,6 +26,19 @@ target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE ${HIREDIS_LIBRARIES}
|
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}
|
install(TARGETS ${PROJECT_NAME}
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
RUNTIME DESTINATION bin
|
RUNTIME DESTINATION bin
|
||||||
|
|
|
@ -65,6 +65,7 @@ namespace redis {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
void hiredis_run_callback (redisAsyncContext*, void* parReply, void* parPrivData) {
|
void hiredis_run_callback (redisAsyncContext*, void* parReply, void* parPrivData) {
|
||||||
assert(parPrivData);
|
assert(parPrivData);
|
||||||
auto* data = static_cast<HiredisCallbackData*>(parPrivData);
|
auto* data = static_cast<HiredisCallbackData*>(parPrivData);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
|
#include "helpers/lexical_cast.hpp"
|
||||||
#include <hiredis/hiredis.h>
|
#include <hiredis/hiredis.h>
|
||||||
#include <hiredis/async.h>
|
#include <hiredis/async.h>
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
|
@ -23,9 +24,23 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#if defined(WITH_CRYPTOPP)
|
||||||
|
# include <crypto++/sha.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace redis {
|
namespace redis {
|
||||||
namespace {
|
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
|
} //unnamed namespace
|
||||||
|
|
||||||
Command::Command (std::string&& parAddress, uint16_t parPort) :
|
Command::Command (std::string&& parAddress, uint16_t parPort) :
|
||||||
|
@ -87,4 +102,57 @@ namespace redis {
|
||||||
assert(is_connected());
|
assert(is_connected());
|
||||||
return Batch(m_conn.get());
|
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
|
} //namespace redis
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "scan_iterator.hpp"
|
#include "scan_iterator.hpp"
|
||||||
#include "reply.hpp"
|
#include "reply.hpp"
|
||||||
#include "batch.hpp"
|
#include "batch.hpp"
|
||||||
|
#include "redisConfig.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -32,6 +33,12 @@
|
||||||
#include <boost/range/iterator_range_core.hpp>
|
#include <boost/range/iterator_range_core.hpp>
|
||||||
#include <boost/utility/string_ref.hpp>
|
#include <boost/utility/string_ref.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#if defined(WITH_CRYPTOPP)
|
||||||
|
# include <set>
|
||||||
|
#else
|
||||||
|
# include <map>
|
||||||
|
#endif
|
||||||
|
#include <boost/utility/string_ref.hpp>
|
||||||
|
|
||||||
struct redisAsyncContext;
|
struct redisAsyncContext;
|
||||||
|
|
||||||
|
@ -66,10 +73,20 @@ namespace redis {
|
||||||
sscan_range sscan ( boost::string_ref parKey );
|
sscan_range sscan ( boost::string_ref parKey );
|
||||||
zscan_range zscan ( boost::string_ref parKey );
|
zscan_range zscan ( boost::string_ref parKey );
|
||||||
|
|
||||||
|
void submit_lua_script ( const std::string& parScript );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using RedisConnection = std::unique_ptr<redisAsyncContext, void(*)(redisAsyncContext*)>;
|
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;
|
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;
|
std::string m_address;
|
||||||
uint16_t m_port;
|
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
Add a link
Reference in a new issue