summaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorGeir Storli <geirst@verizonmedia.com>2019-09-09 12:22:58 +0000
committerGeir Storli <geirst@verizonmedia.com>2019-09-09 13:02:17 +0000
commitf6af721145f1609bca2274970acbf314983fdc10 (patch)
tree9c5fa37608abc0c0f57293c753c0dc85ba320921 /searchlib
parentdd25c2a3c4c16ba96eda61e996f5347f1f8eaa9c (diff)
Reduce code duplication by letting enum store comparators inherit unique store comparators.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/tests/attribute/comparator/comparator_test.cpp45
-rw-r--r--searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumcomparator.cpp101
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumcomparator.h211
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumstore.cpp3
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumstore.h57
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumstore.hpp26
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp4
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglistattribute.cpp12
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h12
-rw-r--r--searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/singlestringattribute.hpp6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp4
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);