diff options
Diffstat (limited to 'searchlib')
16 files changed, 225 insertions, 282 deletions
diff --git a/searchlib/src/tests/attribute/comparator/comparator_test.cpp b/searchlib/src/tests/attribute/comparator/comparator_test.cpp index 7bd6f3ca013..0b709d44900 100644 --- a/searchlib/src/tests/attribute/comparator/comparator_test.cpp +++ b/searchlib/src/tests/attribute/comparator/comparator_test.cpp @@ -1,9 +1,10 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include <vespa/log/log.h> LOG_SETUP("comparator_test"); -#include <vespa/vespalib/testkit/testapp.h> + #include <vespa/searchlib/attribute/enumcomparator.h> #include <vespa/vespalib/btree/btreeroot.h> +#include <vespa/vespalib/testkit/testapp.h> #include <vespa/searchlib/attribute/enumstore.hpp> #include <vespa/vespalib/btree/btreenode.hpp> @@ -14,22 +15,16 @@ namespace search { using namespace btree; -typedef EnumStoreT<NumericEntryType<int32_t> > NumericEnumStore; -typedef EnumStoreComparatorT<NumericEntryType<int32_t> > NumericComparator; - -typedef EnumStoreT<NumericEntryType<float> > FloatEnumStore; -typedef EnumStoreComparatorT<NumericEntryType<float> > FloatComparator; - -typedef EnumStoreT<StringEntryType> StringEnumStore; -typedef EnumStoreComparatorT<StringEntryType> StringComparator; -typedef EnumStoreFoldedComparatorT<StringEntryType> FoldedStringComparator; +using NumericEnumStore = EnumStoreT<NumericEntryType<int32_t> >; +using FloatEnumStore = EnumStoreT<NumericEntryType<float> >; +using StringEnumStore = EnumStoreT<StringEntryType>; -typedef IEnumStore::Index EnumIndex; +using EnumIndex = IEnumStore::Index; -typedef BTreeRoot<EnumIndex, BTreeNoLeafData, - btree::NoAggregated, - const datastore::EntryComparatorWrapper> TreeType; -typedef TreeType::NodeAllocatorType NodeAllocator; +using TreeType = BTreeRoot<EnumIndex, BTreeNoLeafData, + btree::NoAggregated, + const datastore::EntryComparatorWrapper>; +using NodeAllocator = TreeType::NodeAllocatorType; class Test : public vespalib::TestApp { private: @@ -51,11 +46,11 @@ Test::requireThatNumericComparatorIsWorking() EnumIndex e1, e2; es.addEnum(10, e1); es.addEnum(30, e2); - NumericComparator cmp1(es); + auto cmp1 = es.make_comparator(); EXPECT_TRUE(cmp1(e1, e2)); EXPECT_TRUE(!cmp1(e2, e1)); EXPECT_TRUE(!cmp1(e1, e1)); - NumericComparator cmp2(es, 20); + auto cmp2 = es.make_comparator(20); EXPECT_TRUE(cmp2(EnumIndex(), e2)); EXPECT_TRUE(!cmp2(e2, EnumIndex())); } @@ -68,14 +63,14 @@ Test::requireThatFloatComparatorIsWorking() es.addEnum(10.5, e1); es.addEnum(30.5, e2); es.addEnum(std::numeric_limits<float>::quiet_NaN(), e3); - FloatComparator cmp1(es); + auto cmp1 = es.make_comparator(); EXPECT_TRUE(cmp1(e1, e2)); EXPECT_TRUE(!cmp1(e2, e1)); EXPECT_TRUE(!cmp1(e1, e1)); EXPECT_TRUE(cmp1(e3, e1)); // nan EXPECT_TRUE(!cmp1(e1, e3)); // nan EXPECT_TRUE(!cmp1(e3, e3)); // nan - FloatComparator cmp2(es, 20.5); + auto cmp2 = es.make_comparator(20.5); EXPECT_TRUE(cmp2(EnumIndex(), e2)); EXPECT_TRUE(!cmp2(e2, EnumIndex())); } @@ -88,13 +83,13 @@ Test::requireThatStringComparatorIsWorking() es.addEnum("Aa", e1); es.addEnum("aa", e2); es.addEnum("aB", e3); - StringComparator cmp1(es); + auto cmp1 = es.make_comparator(); EXPECT_TRUE(cmp1(e1, e2)); // similar folded, fallback to regular EXPECT_TRUE(!cmp1(e2, e1)); EXPECT_TRUE(!cmp1(e1, e1)); EXPECT_TRUE(cmp1(e2, e3)); // folded compare EXPECT_TRUE(strcmp("aa", "aB") > 0); // regular - StringComparator cmp2(es, "AB"); + auto cmp2 = es.make_comparator("AB"); EXPECT_TRUE(cmp2(EnumIndex(), e3)); EXPECT_TRUE(!cmp2(e3, EnumIndex())); } @@ -108,7 +103,7 @@ Test::requireThatComparatorWithTreeIsWorking() NodeAllocator m; EnumIndex ei; for (int32_t v = 100; v > 0; --v) { - NumericComparator cmp(es, v); + auto cmp = es.make_comparator(v); EXPECT_TRUE(!t.find(EnumIndex(), m, cmp).valid()); es.addEnum(v, ei); t.insert(ei, BTreeNoLeafData(), m, cmp); @@ -135,13 +130,13 @@ Test::requireThatFoldedComparatorIsWorking() es.addEnum("aa", e2); es.addEnum("aB", e3); es.addEnum("Folded", e4); - FoldedStringComparator cmp1(es); + auto cmp1 = es.make_folded_comparator(); EXPECT_TRUE(!cmp1(e1, e2)); // similar folded EXPECT_TRUE(!cmp1(e2, e1)); // similar folded EXPECT_TRUE(cmp1(e2, e3)); // folded compare EXPECT_TRUE(!cmp1(e3, e2)); // folded compare - FoldedStringComparator cmp2(es, "fol", false); - FoldedStringComparator cmp3(es, "fol", true); + auto cmp2 = es.make_folded_comparator("fol", false); + auto cmp3 = es.make_folded_comparator("fol", true); EXPECT_TRUE(cmp2(EnumIndex(), e4)); EXPECT_TRUE(!cmp2(e4, EnumIndex())); EXPECT_TRUE(!cmp3(EnumIndex(), e4)); // similar when prefix diff --git a/searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp b/searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp index 505394b20ce..e94279ddb72 100644 --- a/searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp +++ b/searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp @@ -453,7 +453,7 @@ PostingListAttributeTest::checkPostingList(const VectorType & vec, const std::ve const uint32_t docEnd = range.getEnd(i); auto itr = dict.find(typename VectorType::EnumIndex(), - typename VectorType::ComparatorType(enumStore, values[i])); + enumStore.make_comparator(values[i])); ASSERT_TRUE(itr.valid()); typename VectorType::PostingList::Iterator postings; @@ -672,7 +672,7 @@ PostingListAttributeTest::checkPostingList(AttributeType & vec, ValueType value, const typename AttributeType::Dictionary & dict = enumStore.getPostingDictionary(); const typename AttributeType::PostingList & postingList = vec.getPostingList(); auto itr = dict.find(typename AttributeType::EnumIndex(), - typename AttributeType::ComparatorType(vec.getEnumStore(), value)); + vec.getEnumStore().make_comparator(value)); ASSERT_TRUE(itr.valid()); typename AttributeType::PostingList::Iterator postings; @@ -692,7 +692,7 @@ PostingListAttributeTest::checkNonExistantPostingList(AttributeType & vec, Value { const typename AttributeType::Dictionary & dict = vec.getEnumStore().getPostingDictionary(); auto itr = dict.find(typename AttributeType::EnumIndex(), - typename AttributeType::ComparatorType(vec.getEnumStore(), value)); + vec.getEnumStore().make_comparator(value)); EXPECT_TRUE(!itr.valid()); } diff --git a/searchlib/src/vespa/searchlib/attribute/enumattribute.hpp b/searchlib/src/vespa/searchlib/attribute/enumattribute.hpp index e3e2943351e..76a9fc91916 100644 --- a/searchlib/src/vespa/searchlib/attribute/enumattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/enumattribute.hpp @@ -35,7 +35,7 @@ void EnumAttribute<B>::load_enum_store(LoadedVector& loaded) EnumIndex index = loader.insert(value.getValue(), value._pidx.ref()); for (size_t i(0), m(loaded.size()); i < m; ++i, loaded.next()) { value = loaded.read(); - if (EnumStore::ComparatorType::compare(prev, value.getValue()) != 0) { + if (!EnumStore::ComparatorType::equal(prev, value.getValue())) { loader.set_ref_count_for_last_value(prevRefCount); index = loader.insert(value.getValue(), value._pidx.ref()); prev = value.getValue(); diff --git a/searchlib/src/vespa/searchlib/attribute/enumcomparator.cpp b/searchlib/src/vespa/searchlib/attribute/enumcomparator.cpp index bf323d56245..817a3037a9a 100644 --- a/searchlib/src/vespa/searchlib/attribute/enumcomparator.cpp +++ b/searchlib/src/vespa/searchlib/attribute/enumcomparator.cpp @@ -1,12 +1,8 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "enumcomparator.h" -#include "enumstore.hpp" #include <vespa/searchlib/util/foldedstringcompare.h> -#include <vespa/log/log.h> -LOG_SETUP(".searchlib.attribute.enum_comparator"); - namespace search { namespace { @@ -15,71 +11,82 @@ FoldedStringCompare _strCmp; } -template <> -int -EnumStoreComparatorT<NumericEntryType<float> >::compare(EntryValue lhs, EntryValue rhs) +template <typename EntryT> +EnumStoreComparator<EntryT>::EnumStoreComparator(const DataStoreType& data_store, const EntryT& fallback_value, bool prefix) + : ParentType(data_store, fallback_value) { - return FloatingPointCompareHelper::compare(lhs, rhs); + (void) prefix; } -template <> -int -EnumStoreComparatorT<NumericEntryType<double> >::compare(EntryValue lhs, EntryValue rhs) +template <typename EntryT> +EnumStoreComparator<EntryT>::EnumStoreComparator(const DataStoreType& data_store) + : ParentType(data_store) +{ +} + +template <typename EntryT> +bool +EnumStoreComparator<EntryT>::equal(const EntryT& lhs, const EntryT& rhs) +{ + return !datastore::UniqueStoreComparatorHelper<EntryT>::less(lhs, rhs) && + !datastore::UniqueStoreComparatorHelper<EntryT>::less(rhs, lhs); +} + +EnumStoreStringComparator::EnumStoreStringComparator(const DataStoreType& data_store) + : ParentType(data_store, nullptr) { - return FloatingPointCompareHelper::compare(lhs, rhs); } -template <> -EnumStoreFoldedComparatorT<StringEntryType>:: -EnumStoreFoldedComparatorT(const EnumStoreType & enumStore, - EntryValue value, bool prefix) - : ParentType(enumStore, value), +EnumStoreStringComparator::EnumStoreStringComparator(const DataStoreType& data_store, const char* fallback_value) + : ParentType(data_store, fallback_value) +{ +} + +EnumStoreFoldedStringComparator::EnumStoreFoldedStringComparator(const DataStoreType& data_store, bool prefix) + : ParentType(data_store, nullptr), _prefix(prefix), - _prefixLen(0u) + _prefix_len(0u) { - if (getUsePrefix()) - _prefixLen = _strCmp.size(value); } -template <> +EnumStoreFoldedStringComparator::EnumStoreFoldedStringComparator(const DataStoreType& data_store, + const char* fallback_value, bool prefix) + : ParentType(data_store, fallback_value), + _prefix(prefix), + _prefix_len(0u) +{ + if (use_prefix()) { + _prefix_len = _strCmp.size(fallback_value); + } +} + int -EnumStoreComparatorT<StringEntryType>::compare(EntryValue lhs, EntryValue rhs) +EnumStoreStringComparator::compare(const char* lhs, const char* rhs) { return _strCmp.compare(lhs, rhs); } -template <> int -EnumStoreFoldedComparatorT<StringEntryType>::compareFolded(EntryValue lhs, - EntryValue rhs) +EnumStoreFoldedStringComparator::compare_folded(const char* lhs, const char* rhs) { return _strCmp.compareFolded(lhs, rhs); } -template <> int -EnumStoreFoldedComparatorT<StringEntryType>:: -compareFoldedPrefix(EntryValue lhs, - EntryValue rhs, - size_t prefixLen) +EnumStoreFoldedStringComparator::compare_folded_prefix(const char* lhs, + const char* rhs, + size_t prefix_len) { - return _strCmp.compareFoldedPrefix(lhs, rhs, prefixLen); + return _strCmp.compareFoldedPrefix(lhs, rhs, prefix_len); } -template class EnumStoreComparatorT<StringEntryType>; -template class EnumStoreComparatorT<NumericEntryType<int8_t> >; -template class EnumStoreComparatorT<NumericEntryType<int16_t> >; -template class EnumStoreComparatorT<NumericEntryType<int32_t> >; -template class EnumStoreComparatorT<NumericEntryType<int64_t> >; -template class EnumStoreComparatorT<NumericEntryType<float> >; -template class EnumStoreComparatorT<NumericEntryType<double> >; -template class EnumStoreFoldedComparatorT<StringEntryType>; -template class EnumStoreFoldedComparatorT<NumericEntryType<int8_t> >; -template class EnumStoreFoldedComparatorT<NumericEntryType<int16_t> >; -template class EnumStoreFoldedComparatorT<NumericEntryType<int32_t> >; -template class EnumStoreFoldedComparatorT<NumericEntryType<int64_t> >; -template class EnumStoreFoldedComparatorT<NumericEntryType<float> >; -template class EnumStoreFoldedComparatorT<NumericEntryType<double> >; - -} // namespace search +template class EnumStoreComparator<int8_t>; +template class EnumStoreComparator<int16_t>; +template class EnumStoreComparator<int32_t>; +template class EnumStoreComparator<uint32_t>; +template class EnumStoreComparator<int64_t>; +template class EnumStoreComparator<float>; +template class EnumStoreComparator<double>; + +} diff --git a/searchlib/src/vespa/searchlib/attribute/enumcomparator.h b/searchlib/src/vespa/searchlib/attribute/enumcomparator.h index 66dd9dd5e6c..9a691e3b4e4 100644 --- a/searchlib/src/vespa/searchlib/attribute/enumcomparator.h +++ b/searchlib/src/vespa/searchlib/attribute/enumcomparator.h @@ -2,173 +2,114 @@ #pragma once -#include "enumstore.h" +#include "i_enum_store.h" #include <vespa/vespalib/datastore/entry_comparator.h> +#include <vespa/vespalib/datastore/unique_store_comparator.h> +#include <vespa/vespalib/datastore/unique_store_string_comparator.h> namespace search { /** - * Template comparator class for the various entry types. - **/ -template <typename EntryType> -class EnumStoreComparatorT : public datastore::EntryComparator { + * Less-than comparator used for comparing values of type EntryT stored in an enum store. + */ +template <typename EntryT> +class EnumStoreComparator : public datastore::UniqueStoreComparator<EntryT, IEnumStore::InternalIndex> { public: - using EnumStoreType = EnumStoreT<EntryType>; + using ParentType = datastore::UniqueStoreComparator<EntryT, IEnumStore::InternalIndex>; + using DataStoreType = typename ParentType::DataStoreType; + + EnumStoreComparator(const DataStoreType& data_store, const EntryT& fallback_value, bool prefix = false); + EnumStoreComparator(const DataStoreType& data_store); + + static bool equal(const EntryT& lhs, const EntryT& rhs); +}; + +/** + * Less-than comparator used for comparing strings stored in an enum store. + * + * The input string values are first folded, then compared. + * If they are equal, then it falls back to comparing without folding. + */ +class EnumStoreStringComparator : public datastore::UniqueStoreStringComparator<IEnumStore::InternalIndex> { protected: - using EntryValue = typename EntryType::Type; - using EnumIndex = typename EnumStoreType::Index; - - const EnumStoreType & _enumStore; - EntryValue _value; - EntryValue getValue(const datastore::EntryRef ref) const { - EnumIndex idx(ref); - if (idx.valid()) { - return _enumStore.getValue(idx); - } - return _value; - } + using ParentType = datastore::UniqueStoreStringComparator<IEnumStore::InternalIndex>; + using DataStoreType = ParentType::DataStoreType; + using ParentType::get; + + static int compare(const char* lhs, const char* rhs); + public: + EnumStoreStringComparator(const DataStoreType& data_store); + /** - * Creates a comparator using the given enum store. - **/ - EnumStoreComparatorT(const EnumStoreType & enumStore) - : _enumStore(enumStore), - _value() - {} - /** - * Creates a comparator using the given enum store and that uses the + * Creates a comparator using the given low-level data store and that uses the * given value during compare if the enum index is invalid. - **/ - EnumStoreComparatorT(const EnumStoreType & enumStore, EntryValue value) - : _enumStore(enumStore), - _value(value) - {} - - static int compare(EntryValue lhs, EntryValue rhs) { - if (lhs < rhs) { - return -1; - } else if (lhs == rhs) { - return 0; - } - return 1; + */ + EnumStoreStringComparator(const DataStoreType& data_store, const char* fallback_value); + + static bool equal(const char* lhs, const char* rhs) { + return compare(lhs, rhs) == 0; } + bool operator() (const datastore::EntryRef lhs, const datastore::EntryRef rhs) const override { - return compare(getValue(lhs), getValue(rhs)) < 0; + return compare(get(lhs), get(rhs)) < 0; } }; /** - * Template comparator class for the various entry types that uses folded compare. - **/ -template <typename EntryType> -class EnumStoreFoldedComparatorT : public EnumStoreComparatorT<EntryType> { + * Less-than comparator used for folded-only comparing strings stored in an enum store. + * + * The input string values are first folded, then compared. + * There is NO fallback if they are equal. + */ +class EnumStoreFoldedStringComparator : public EnumStoreStringComparator { private: - typedef EnumStoreComparatorT<EntryType> ParentType; - typedef typename ParentType::EnumStoreType EnumStoreType; - typedef typename ParentType::EnumIndex EnumIndex; - typedef typename ParentType::EntryValue EntryValue; - using ParentType::getValue; + using ParentType = EnumStoreStringComparator; + bool _prefix; - size_t _prefixLen; + size_t _prefix_len; + + inline bool use_prefix() const { return _prefix; } + static int compare_folded(const char* lhs, const char* rhs); + static int compare_folded_prefix(const char* lhs, const char* rhs, size_t prefix_len); + public: /** - * Creates a comparator using the given enum store. + * Creates a comparator using the given low-level data store. + * * @param prefix whether we should perform prefix compare. - **/ - EnumStoreFoldedComparatorT(const EnumStoreType & enumStore, bool prefix = false); + */ + EnumStoreFoldedStringComparator(const DataStoreType& data_store, bool prefix = false); + /** - * Creates a comparator using the given enum store and that uses the + * Creates a comparator using the given low-level data store and that uses the * given value during compare if the enum index is invalid. + * * @param prefix whether we should perform prefix compare. - **/ - EnumStoreFoldedComparatorT(const EnumStoreType & enumStore, - EntryValue value, bool prefix = false); - inline bool getUsePrefix() const { return false; } - static int compareFolded(EntryValue lhs, EntryValue rhs) { return ParentType::compare(lhs, rhs); } - static int compareFoldedPrefix(EntryValue lhs, EntryValue rhs, size_t prefixLen) { - (void) prefixLen; - return ParentType::compare(lhs, rhs); + */ + EnumStoreFoldedStringComparator(const DataStoreType& data_store, + const char* fallback_value, bool prefix = false); + + static bool equal(const char* lhs, const char* rhs) { + return compare_folded(lhs, rhs) == 0; } bool operator() (const datastore::EntryRef lhs, const datastore::EntryRef rhs) const override { - if (getUsePrefix()) { - return compareFoldedPrefix(getValue(lhs), - getValue(rhs), _prefixLen) < 0; + if (use_prefix()) { + return compare_folded_prefix(get(lhs), get(rhs), _prefix_len) < 0; } - return compareFolded(getValue(lhs), getValue(rhs)) < 0; + return compare_folded(get(lhs), get(rhs)) < 0; } }; -template <> -int -EnumStoreComparatorT<NumericEntryType<float> >::compare(EntryValue lhs, EntryValue rhs); - -template <> -int -EnumStoreComparatorT<NumericEntryType<double> >::compare(EntryValue lhs, EntryValue rhs); - -template <> -int -EnumStoreComparatorT<StringEntryType>::compare(EntryValue lhs, EntryValue rhs); +extern template class EnumStoreComparator<int8_t>; +extern template class EnumStoreComparator<int16_t>; +extern template class EnumStoreComparator<int32_t>; +extern template class EnumStoreComparator<uint32_t>; +extern template class EnumStoreComparator<int64_t>; +extern template class EnumStoreComparator<float>; +extern template class EnumStoreComparator<double>; - -template <typename EntryType> -EnumStoreFoldedComparatorT<EntryType>:: -EnumStoreFoldedComparatorT(const EnumStoreType & enumStore, bool prefix) - : ParentType(enumStore), - _prefix(prefix), - _prefixLen(0u) -{ -} - -template <typename EntryType> -EnumStoreFoldedComparatorT<EntryType>:: -EnumStoreFoldedComparatorT(const EnumStoreType & enumStore, - EntryValue value, bool prefix) - : ParentType(enumStore, value), - _prefix(prefix), - _prefixLen(0u) -{ } -template <> -EnumStoreFoldedComparatorT<StringEntryType>:: -EnumStoreFoldedComparatorT(const EnumStoreType & enumStore, - EntryValue value, bool prefix); - -template <> -int -EnumStoreFoldedComparatorT<StringEntryType>::compareFolded(EntryValue lhs, - EntryValue rhs); - -template <> -int -EnumStoreFoldedComparatorT<StringEntryType>:: -compareFoldedPrefix(EntryValue lhs, EntryValue rhs, size_t prefixLen); - -template <> -inline bool -EnumStoreFoldedComparatorT<StringEntryType>::getUsePrefix() const -{ - return _prefix; -} - - -extern template class EnumStoreComparatorT<StringEntryType>; -extern template class EnumStoreComparatorT<NumericEntryType<int8_t> >; -extern template class EnumStoreComparatorT<NumericEntryType<int16_t> >; -extern template class EnumStoreComparatorT<NumericEntryType<int32_t> >; -extern template class EnumStoreComparatorT<NumericEntryType<int64_t> >; -extern template class EnumStoreComparatorT<NumericEntryType<float> >; -extern template class EnumStoreComparatorT<NumericEntryType<double> >; -extern template class EnumStoreFoldedComparatorT<StringEntryType>; -extern template class EnumStoreFoldedComparatorT<NumericEntryType<int8_t> >; -extern template class EnumStoreFoldedComparatorT<NumericEntryType<int16_t> >; -extern template class EnumStoreFoldedComparatorT<NumericEntryType<int32_t> >; -extern template class EnumStoreFoldedComparatorT<NumericEntryType<int64_t> >; -extern template class EnumStoreFoldedComparatorT<NumericEntryType<float> >; -extern template class EnumStoreFoldedComparatorT<NumericEntryType<double> >; - -} // namespace search - diff --git a/searchlib/src/vespa/searchlib/attribute/enumstore.cpp b/searchlib/src/vespa/searchlib/attribute/enumstore.cpp index ddd5f8540d1..a0f9df3979a 100644 --- a/searchlib/src/vespa/searchlib/attribute/enumstore.cpp +++ b/searchlib/src/vespa/searchlib/attribute/enumstore.cpp @@ -37,7 +37,8 @@ EnumStoreT<StringEntryType>::load_unique_value(const void* src, idx = _store.get_allocator().allocate(value); if (prev_idx.valid()) { - assert(ComparatorType::compare(getValue(prev_idx), value) < 0); + auto cmp = make_comparator(value); + assert(cmp(prev_idx, Index())); } return sz; } diff --git a/searchlib/src/vespa/searchlib/attribute/enumstore.h b/searchlib/src/vespa/searchlib/attribute/enumstore.h index d5fd4904d26..2b1413e26c9 100644 --- a/searchlib/src/vespa/searchlib/attribute/enumstore.h +++ b/searchlib/src/vespa/searchlib/attribute/enumstore.h @@ -4,6 +4,7 @@ #include "enum_store_dictionary.h" #include "enum_store_loaders.h" +#include "enumcomparator.h" #include "i_enum_store.h" #include "loadedenumvalue.h" #include <vespa/searchlib/util/foldedstringcompare.h> @@ -21,9 +22,6 @@ namespace search { -template <typename> class EnumStoreComparatorT; -template <typename> class EnumStoreFoldedComparatorT; - /** * Class representing a numeric entry type in a enum store. * Used as template argument for EnumStoreT. @@ -51,29 +49,6 @@ public: }; -/** - * Used to determine the ordering between two floating point values that can be NAN. - **/ -struct FloatingPointCompareHelper -{ - template <typename T> - static int compare(T a, T b) { - if (std::isnan(a) && std::isnan(b)) { - return 0; - } else if (std::isnan(a)) { - return -1; - } else if (std::isnan(b)) { - return 1; - } else if (a < b) { - return -1; - } else if (a == b) { - return 0; - } - return 1; - } -}; - - //----------------------------------------------------------------------------- // EnumStoreT //----------------------------------------------------------------------------- @@ -83,18 +58,20 @@ class EnumStoreT : public IEnumStore friend class EnumStoreTest; public: using DataType = typename EntryType::Type; - using ComparatorType = EnumStoreComparatorT<EntryType>; + using ComparatorType = std::conditional_t<std::is_same_v<DataType, const char *>, + EnumStoreStringComparator, + EnumStoreComparator<DataType>>; using AllocatorType = std::conditional_t<std::is_same_v<DataType, const char *>, datastore::UniqueStoreStringAllocator<InternalIndex>, datastore::UniqueStoreAllocator<DataType, InternalIndex>>; - using UniqueStoreType = datastore::UniqueStore<DataType, InternalIndex, ComparatorType, AllocatorType>; - using FoldedComparatorType = EnumStoreFoldedComparatorT<EntryType>; + using FoldedComparatorType = std::conditional_t<std::is_same_v<DataType, const char *>, + EnumStoreFoldedStringComparator, + ComparatorType>; using EnumStoreType = EnumStoreT<EntryType>; using EntryRef = datastore::EntryRef; using generation_t = vespalib::GenerationHandler::generation_t; - private: UniqueStoreType _store; IEnumStoreDictionary& _dict; @@ -110,6 +87,10 @@ private: return _store.get_allocator().get_wrapped(idx); } + static bool has_string_type() { + return std::is_same_v<DataType, const char *>; + } + ssize_t load_unique_values_internal(const void* src, size_t available, IndexVector& idx); ssize_t load_unique_value(const void* src, size_t available, Index& idx); @@ -231,6 +212,22 @@ public: return BatchUpdater(*this); } + ComparatorType make_comparator() const { + return ComparatorType(_store.get_data_store()); + } + + ComparatorType make_comparator(const DataType& fallback_value) const { + return ComparatorType(_store.get_data_store(), fallback_value); + } + + FoldedComparatorType make_folded_comparator() const { + return FoldedComparatorType(_store.get_data_store()); + } + + FoldedComparatorType make_folded_comparator(const DataType& fallback_value, bool prefix = false) const { + return FoldedComparatorType(_store.get_data_store(), fallback_value, prefix); + } + // TODO: Change to sending enum indexes as const array ref. void writeValues(BufferWriter& writer, vespalib::ConstArrayRef<Index> idxs) const override; bool foldedChange(const Index &idx1, const Index &idx2) const override; diff --git a/searchlib/src/vespa/searchlib/attribute/enumstore.hpp b/searchlib/src/vespa/searchlib/attribute/enumstore.hpp index ee970a07eef..dc66adab5ce 100644 --- a/searchlib/src/vespa/searchlib/attribute/enumstore.hpp +++ b/searchlib/src/vespa/searchlib/attribute/enumstore.hpp @@ -65,14 +65,18 @@ EnumStoreT<EntryType>::load_unique_value(const void* src, size_t available, Inde idx = _store.get_allocator().allocate(*value); if (prev_idx.valid()) { - assert(ComparatorType::compare(getValue(prev_idx), *value) < 0); + auto cmp = make_comparator(*value); + assert(cmp(prev_idx, Index())); } return sizeof(DataType); } template <typename EntryType> EnumStoreT<EntryType>::EnumStoreT(bool has_postings) - : _store(make_enum_store_dictionary(*this, has_postings, EntryType::hasFold() ? std::make_unique<FoldedComparatorType>(*this) : std::unique_ptr<datastore::EntryComparator>())), + : _store(make_enum_store_dictionary(*this, has_postings, + (has_string_type() ? + std::make_unique<FoldedComparatorType>(_store.get_data_store()) : + std::unique_ptr<datastore::EntryComparator>()))), _dict(static_cast<IEnumStoreDictionary&>(_store.get_dictionary())), _cached_values_memory_usage(), _cached_values_address_space_usage(0, 0, (1ull << 32)) @@ -142,16 +146,16 @@ template <class EntryType> bool EnumStoreT<EntryType>::foldedChange(const Index &idx1, const Index &idx2) const { - int cmpres = FoldedComparatorType::compareFolded(getValue(idx1), getValue(idx2)); - assert(cmpres <= 0); - return cmpres < 0; + auto cmp = make_folded_comparator(); + assert(!cmp(idx2, idx1)); + return cmp(idx1, idx2); } template <typename EntryType> bool EnumStoreT<EntryType>::findEnum(DataType value, IEnumStore::EnumHandle &e) const { - ComparatorType cmp(*this, value); + auto cmp = make_comparator(value); Index idx; if (_dict.findFrozenIndex(cmp, idx)) { e = idx.ref(); @@ -164,7 +168,7 @@ template <typename EntryType> std::vector<IEnumStore::EnumHandle> EnumStoreT<EntryType>::findFoldedEnums(DataType value) const { - FoldedComparatorType cmp(*this, value); + auto cmp = make_folded_comparator(value); return _dict.findMatchingEnums(cmp); } @@ -172,7 +176,7 @@ template <typename EntryType> bool EnumStoreT<EntryType>::findIndex(DataType value, Index &idx) const { - ComparatorType cmp(*this, value); + auto cmp = make_comparator(value); return _dict.findIndex(cmp, idx); } @@ -180,7 +184,7 @@ template <typename EntryType> void EnumStoreT<EntryType>::freeUnusedEnums() { - ComparatorType cmp(*this); + auto cmp = make_comparator(); _dict.freeUnusedEnums(cmp); } @@ -188,7 +192,7 @@ template <typename EntryType> void EnumStoreT<EntryType>::freeUnusedEnums(const IndexSet& toRemove) { - ComparatorType cmp(*this); + auto cmp = make_comparator(); _dict.freeUnusedEnums(toRemove, cmp); } @@ -196,7 +200,7 @@ template <typename EntryType> void EnumStoreT<EntryType>::addEnum(DataType value, Index& newIdx) { - ComparatorType cmp(*this, value); + auto cmp = make_comparator(value); auto add_result = _dict.add(cmp, [this, &value]() -> EntryRef { return _store.get_allocator().allocate(value); }); newIdx = add_result.ref(); } diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp index 27744e6d4b3..fb44b318f30 100644 --- a/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp @@ -27,10 +27,10 @@ MultiValueNumericPostingAttribute<B, M>::applyValueChanges(const DocIndices& doc { using PostingChangeComputer = PostingChangeComputerT<WeightedIndex, PostingMap>; EnumStore & enumStore = this->getEnumStore(); - ComparatorType compare(enumStore); + auto comp = enumStore.make_comparator(); EnumIndexMapper mapper; - PostingMap changePost(PostingChangeComputer::compute(this->getMultiValueMapping(), docIndices, compare, mapper)); + PostingMap changePost(PostingChangeComputer::compute(this->getMultiValueMapping(), docIndices, comp, mapper)); this->updatePostings(changePost); MultiValueNumericEnumAttribute<B, M>::applyValueChanges(docIndices, updater); } @@ -93,7 +93,7 @@ MultiValueNumericPostingAttribute<B, M>::DocumentWeightAttributeAdapter::lookup( char *end = nullptr; int64_t int_term = strtoll(term.c_str(), &end, 10); if (*end == '\0') { - ComparatorType comp(self._enumStore, int_term); + auto comp = self._enumStore.make_comparator(int_term); dictItr.lower_bound(frozenDictionary.getRoot(), EnumIndex(), comp); if (dictItr.valid() && !comp(EnumIndex(), dictItr.getKey())) { diff --git a/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp index 7602a71a691..a435c94d8f6 100644 --- a/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp @@ -119,14 +119,14 @@ StringTemplSearchContext(QueryTermSimpleUP qTerm, const AttrType & toBeSearched) this->_plsc = static_cast<attribute::IPostingListSearchContext *>(this); if (this->valid()) { if (this->isPrefix()) { - FoldedComparatorType comp(enumStore, queryTerm()->getTerm(), true); + auto comp = enumStore.make_folded_comparator(queryTerm()->getTerm(), true); lookupRange(comp, comp); } else if (this->isRegex()) { vespalib::string prefix(vespalib::Regexp::get_prefix(this->queryTerm()->getTerm())); - FoldedComparatorType comp(enumStore, prefix.c_str(), true); + auto comp = enumStore.make_folded_comparator(prefix.c_str(), true); lookupRange(comp, comp); } else { - FoldedComparatorType comp(enumStore, queryTerm()->getTerm()); + auto comp = enumStore.make_folded_comparator(queryTerm()->getTerm()); lookupTerm(comp); } } diff --git a/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp index 154bbb91809..0e75ea8e061 100644 --- a/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp @@ -44,7 +44,7 @@ applyValueChanges(const DocIndices& docIndices, EnumStoreBatchUpdater &updater) using PostingChangeComputer = PostingChangeComputerT<WeightedIndex, PostingMap>; EnumStore &enumStore(this->getEnumStore()); Dictionary &dict(enumStore.getPostingDictionary()); - FoldedComparatorType compare(enumStore); + auto compare = enumStore.make_folded_comparator(); StringEnumIndexMapper mapper(dict); PostingMap changePost(PostingChangeComputer::compute(this->getMultiValueMapping(), docIndices, compare, mapper)); @@ -105,7 +105,7 @@ MultiValueStringPostingAttributeT<B, T>::DocumentWeightAttributeAdapter::lookup( const Dictionary &dictionary = self._enumStore.getPostingDictionary(); const FrozenDictionary frozenDictionary(dictionary.getFrozenView()); DictionaryConstIterator dictItr(btree::BTreeNode::Ref(), dictionary.getAllocator()); - FoldedComparatorType comp(self._enumStore, term.c_str()); + auto comp = self._enumStore.make_folded_comparator(term.c_str()); dictItr.lower_bound(frozenDictionary.getRoot(), EnumIndex(), comp); if (dictItr.valid() && !comp(EnumIndex(), dictItr.getKey())) { diff --git a/searchlib/src/vespa/searchlib/attribute/postinglistattribute.cpp b/searchlib/src/vespa/searchlib/attribute/postinglistattribute.cpp index ce32d458445..079901053a3 100644 --- a/searchlib/src/vespa/searchlib/attribute/postinglistattribute.cpp +++ b/searchlib/src/vespa/searchlib/attribute/postinglistattribute.cpp @@ -232,7 +232,7 @@ handle_load_posting_lists(LoadedVector& loaded) LoadedValueType prev = value.getValue(); for (size_t i(0), m(loaded.size()); i < m; i++, loaded.next()) { value = loaded.read(); - if (FoldedComparatorType::compareFolded(prev, value.getValue()) == 0) { + if (FoldedComparatorType::equal(prev, value.getValue())) { // for single value attributes loaded[numDocs] is used // for default value but we don't want to add an // invalid docId to the posting list. @@ -286,9 +286,8 @@ void PostingListAttributeSubBase<P, LoadedVector, LoadedValueType, EnumStoreType>:: updatePostings(PostingMap &changePost) { - FoldedComparatorType cmpa(_es); - - updatePostings(changePost, cmpa); + auto cmp = _es.make_folded_comparator(); + updatePostings(changePost, cmp); } @@ -297,10 +296,9 @@ template <typename P, typename LoadedVector, typename LoadedValueType, void PostingListAttributeSubBase<P, LoadedVector, LoadedValueType, EnumStoreType>:: clearPostings(attribute::IAttributeVector::EnumHandle eidx, - uint32_t fromLid, - uint32_t toLid) + uint32_t fromLid, uint32_t toLid) { - FoldedComparatorType cmp(_es); + auto cmp = _es.make_folded_comparator(); clearPostings(eidx, fromLid, toLid, cmp); } diff --git a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h index a274528c92b..fdaf338b229 100644 --- a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h +++ b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h @@ -283,14 +283,14 @@ StringPostingSearchContext(QueryTermSimpleUP qTerm, bool useBitVector, const Att if (this->valid()) { if (this->isPrefix()) { - FoldedComparatorType comp(_enumStore, this->queryTerm()->getTerm(), true); + auto comp = _enumStore.make_folded_comparator(this->queryTerm()->getTerm(), true); this->lookupRange(comp, comp); } else if (this->isRegex()) { vespalib::string prefix(Regexp::get_prefix(this->queryTerm()->getTerm())); - FoldedComparatorType comp(_enumStore, prefix.c_str(), true); + auto comp = _enumStore.make_folded_comparator(prefix.c_str(), true); this->lookupRange(comp, comp); } else { - FoldedComparatorType comp(_enumStore, this->queryTerm()->getTerm()); + auto comp = _enumStore.make_folded_comparator(this->queryTerm()->getTerm()); this->lookupTerm(comp); } if (this->_uniqueValues == 1u) { @@ -313,7 +313,7 @@ NumericPostingSearchContext(QueryTermSimpleUP qTerm, const Params & params_in, c this->_PLSTC = 8; if (valid()) { if (_low == _high) { - ComparatorType comp(_enumStore, _low); + auto comp = _enumStore.make_comparator(_low); this->lookupTerm(comp); } else if (_low < _high) { bool shouldApplyRangeLimit = (params().diversityAttribute() == nullptr) && @@ -338,8 +338,8 @@ getIterators(bool shouldApplyRangeLimit) bool isUnsigned = _toBeSearched.getInternalBasicType().isUnsigned(); search::Range<BaseType> capped = this->template cappedRange<BaseType>(isFloat, isUnsigned); - ComparatorType compLow(_enumStore, capped.lower()); - ComparatorType compHigh(_enumStore, capped.upper()); + auto compLow = _enumStore.make_comparator(capped.lower()); + auto compHigh = _enumStore.make_comparator(capped.upper()); this->lookupRange(compLow, compHigh); if (shouldApplyRangeLimit) { diff --git a/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp index 8afb0418b68..6c377e411b2 100644 --- a/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp @@ -79,7 +79,7 @@ SingleValueNumericPostingAttribute<B>::applyValueChanges(EnumStoreBatchUpdater& { EnumStore & enumStore = this->getEnumStore(); Dictionary & dict = enumStore.getPostingDictionary(); - ComparatorType cmpa(enumStore); + auto cmp = enumStore.make_comparator(); PostingMap changePost; // used to make sure several arithmetic operations on the same document in a single commit works @@ -102,7 +102,7 @@ SingleValueNumericPostingAttribute<B>::applyValueChanges(EnumStoreBatchUpdater& T oldValue = enumStore.getValue(oldIdx); T newValue = this->applyArithmetic(oldValue, change); - auto addItr = dict.find(EnumIndex(), ComparatorType(enumStore, newValue)); + auto addItr = dict.find(EnumIndex(), enumStore.make_comparator(newValue)); EnumIndex newIdx = addItr.getKey(); currEnumIndices[change._doc] = newIdx; } @@ -113,7 +113,7 @@ SingleValueNumericPostingAttribute<B>::applyValueChanges(EnumStoreBatchUpdater& } } - makePostingChange(&cmpa, currEnumIndices, changePost); + makePostingChange(&cmp, currEnumIndices, changePost); this->updatePostings(changePost); SingleValueNumericEnumAttribute<B>::applyValueChanges(updater); diff --git a/searchlib/src/vespa/searchlib/attribute/singlestringattribute.hpp b/searchlib/src/vespa/searchlib/attribute/singlestringattribute.hpp index 05914cfee14..ba9ea24df69 100644 --- a/searchlib/src/vespa/searchlib/attribute/singlestringattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/singlestringattribute.hpp @@ -55,14 +55,14 @@ SingleValueStringAttributeT<B>::StringTemplSearchContext::StringTemplSearchConte this->_plsc = static_cast<attribute::IPostingListSearchContext *>(this); if (this->valid()) { if (this->isPrefix()) { - FoldedComparatorType comp(enumStore, queryTerm()->getTerm(), true); + auto comp = enumStore.make_folded_comparator(queryTerm()->getTerm(), true); lookupRange(comp, comp); } else if (this->isRegex()) { vespalib::string prefix(vespalib::Regexp::get_prefix(this->queryTerm()->getTerm())); - FoldedComparatorType comp(enumStore, prefix.c_str(), true); + auto comp = enumStore.make_folded_comparator(prefix.c_str(), true); lookupRange(comp, comp); } else { - FoldedComparatorType comp(enumStore, queryTerm()->getTerm()); + auto comp = enumStore.make_folded_comparator(queryTerm()->getTerm()); lookupTerm(comp); } } diff --git a/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp index ed76a8eca14..9639b05931c 100644 --- a/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp @@ -79,7 +79,7 @@ SingleValueStringPostingAttributeT<B>::applyValueChanges(EnumStoreBatchUpdater& { EnumStore & enumStore = this->getEnumStore(); Dictionary & dict = enumStore.getPostingDictionary(); - FoldedComparatorType cmpa(enumStore); + auto cmp = enumStore.make_folded_comparator(); PostingMap changePost; // used to make sure several arithmetic operations on the same document in a single commit works @@ -103,7 +103,7 @@ SingleValueStringPostingAttributeT<B>::applyValueChanges(EnumStoreBatchUpdater& } } - makePostingChange(&cmpa, dict, currEnumIndices, changePost); + makePostingChange(&cmp, dict, currEnumIndices, changePost); this->updatePostings(changePost); |