1
0
Fork 0
mirror of https://github.com/KingDuckZ/dindexer.git synced 2025-02-17 11:45:50 +00:00

Use boost::regex and implement delete_all_tags by regex.

std::regex doesn't understand the (?i) modifier, which makes it
throw an exception on regex generated by the frontend. I can't
change the frontend, or the postgre plugin would break... thankfully
boost comes to the rescue :)
This commit is contained in:
King_DuckZ 2016-07-11 11:58:52 +01:00
parent 83fe7c75d6
commit 016f357704
2 changed files with 61 additions and 6 deletions

View file

@ -5,6 +5,7 @@ set(DINDEXER_REDIS_SCRIPTS_PATH "${CMAKE_INSTALL_PREFIX}/${bare_name}/redis" CAC
find_package(hiredis 0.11.0 REQUIRED)
find_package(CryptoPP 5.6)
find_package(libev 4.0 REQUIRED)
find_package(Boost 1.53.0 REQUIRED COMPONENTS regex)
add_library(${PROJECT_NAME} SHARED
backend_redis.cpp
@ -23,6 +24,7 @@ target_include_directories(${PROJECT_NAME} SYSTEM
PRIVATE ${HIREDIS_INCLUDE_DIRS}
PRIVATE ${CMAKE_SOURCE_DIR}/lib/better-enums
PRIVATE ${LIBEV_INCLUDE_DIRS}
PRIVATE ${Boost_INCLUDE_DIRS}
)
target_include_directories(${PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
@ -33,6 +35,7 @@ target_link_libraries(${PROJECT_NAME}
PUBLIC ${bare_name}-core
PRIVATE ${HIREDIS_LIBRARIES}
PRIVATE ${LIBEV_LIBRARIES}
PRIVATE ${Boost_LIBRARIES}
)
target_compile_definitions(${PROJECT_NAME}

View file

@ -22,7 +22,7 @@
#include "dindexer-core/split_tags.hpp"
#include <sstream>
#include <tuple>
#include <regex>
#include <boost/regex.hpp>
#include <unordered_set>
#include <boost/functional/hash.hpp>
@ -41,13 +41,13 @@ namespace dindb {
return PROGRAM_NAME ":file:" + dinhelp::lexical_cast<std::string>(parID);
}
std::vector<std::regex> compile_regexes (const std::vector<std::string>& parRegexes) {
std::vector<std::regex> retval;
std::vector<boost::regex> compile_regexes (const std::vector<std::string>& parRegexes) {
std::vector<boost::regex> retval;
retval.reserve(parRegexes.size());
for (const auto& str : parRegexes) {
retval.emplace_back(std::regex(
retval.emplace_back(boost::regex(
str,
std::regex_constants::optimize | std::regex_constants::nosubs | std::regex_constants::ECMAScript
boost::regex_constants::optimize | boost::regex_constants::nosubs | boost::regex_constants::perl
));
}
assert(retval.size() == parRegexes.size());
@ -83,7 +83,7 @@ namespace dindb {
auto batch = parRedis.make_batch();
for (const auto &regex : regexes) {
if (not std::regex_search(path, regex))
if (not boost::regex_search(path, regex))
continue;
for (const auto &tag : parTags) {
@ -92,10 +92,17 @@ namespace dindb {
const std::string tag_key = oss.str();
parTagIfInSet.run(batch, std::make_tuple(tag_key, file_key), std::make_tuple(set_key));
}
break;
}
batch.throw_if_failed();
}
}
template <typename T>
T id_from_redis_key (const std::string& parKey) {
assert(not parKey.empty());
return dinhelp::lexical_cast<T>(dincore::split_and_trim(parKey, ':').back());
}
} //unnamed namespace
void tag_files (redis::Command& parRedis, redis::Script& parTagIfInSet, const std::vector<uint64_t>& parFiles, const std::vector<boost::string_ref>& parTags, GroupIDType parSet) {
@ -135,6 +142,51 @@ namespace dindb {
}
void delete_all_tags (redis::Command& parRedis, redis::Script& parDeleIfInSet, const std::vector<std::string>& parRegexes, GroupIDType parSet) {
using dinhelp::lexical_cast;
const std::string set_key = (parSet != InvalidGroupID ? PROGRAM_NAME ":set:" + lexical_cast<std::string>(parSet) : "");
const auto regexes = compile_regexes(parRegexes);
std::set<std::string> dele_tags;
std::vector<uint64_t> ids;
for (const auto& itm : parRedis.scan(PROGRAM_NAME ":file:*")) {
const auto& file_key = itm;
auto file_reply = parRedis.run("HMGET", file_key, "path", "tags", "group_id");
auto& file_replies = redis::get_array(file_reply);
assert(file_replies.size() == 3);
const auto group_id = id_from_redis_key<GroupIDType>(redis::get_string(file_replies[2]));
if (parSet != InvalidGroupID and parSet != group_id)
continue;
const auto path = redis::get_string(file_replies[0]);
const auto tags_str = (file_replies[1].which() == redis::RedisVariantType_Nil ? std::string() : redis::get_string(file_replies[1]));
const auto tags = dincore::split_tags(tags_str);
const auto file_id = id_from_redis_key<FileIDType>(file_key);
for (const auto &regex : regexes) {
if (not boost::regex_search(path, regex))
continue;
ids.push_back(file_id);
for (const auto &tag : tags) {
dele_tags.insert(std::string(tag.data(), tag.size()));
}
break;
}
}
std::vector<boost::string_ref> dele_tags_vec;
dele_tags_vec.reserve(dele_tags.size());
std::transform(
dele_tags.begin(),
dele_tags.end(),
std::back_inserter(dele_tags_vec),
[](const std::string& parS) { return boost::string_ref(parS); }
);
delete_tags(parRedis, parDeleIfInSet, ids, dele_tags_vec, parSet);
}
} //namespace dindb