diff options
Diffstat (limited to 'searchlib/src')
26 files changed, 397 insertions, 103 deletions
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/BoolResultNode.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/BoolResultNode.java new file mode 100644 index 00000000000..c850c6f2c3a --- /dev/null +++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/BoolResultNode.java @@ -0,0 +1,95 @@ +// Copyright 2019 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.searchlib.expression; + +import com.yahoo.vespa.objects.Deserializer; +import com.yahoo.vespa.objects.ObjectVisitor; +import com.yahoo.vespa.objects.Serializer; + +import java.nio.ByteBuffer; + +public class BoolResultNode extends ResultNode { + public static final int classId = registerClass(0x4000 + 146, BoolResultNode.class); + private boolean value = false; + + public BoolResultNode() { + } + + public BoolResultNode(boolean value) { + this.value = value; + } + /** + * Sets the value of this result. + * + * @param value The value to set. + * @return This, to allow chaining. + */ + public BoolResultNode setValue(boolean value) { + this.value = value; + return this; + } + + public boolean getValue() { return value; } + + @Override + protected int onGetClassId() { + return classId; + } + + @Override + protected void onSerialize(Serializer buf) { + byte v = (byte)(value ? 1 : 0); + buf.putByte(null, v ); + } + + @Override + protected void onDeserialize(Deserializer buf) { + value = buf.getByte(null) != 0; + } + + @Override + public long getInteger() { + return value ? 1 : 0; + } + + @Override + public double getFloat() { + return value ? 1.0 : 0.0; + } + + @Override + public String getString() { + return String.valueOf(value); + } + + @Override + public byte[] getRaw() { + return ByteBuffer.allocate(8).putLong(getInteger()).array(); + } + + @Override + public void negate() { + value = ! value; + } + + + @Override + protected int onCmp(ResultNode rhs) { + return Long.compare(getInteger(), rhs.getInteger()); + } + + @Override + public int hashCode() { + return super.hashCode() + (int)getInteger(); + } + + @Override + public void visitMembers(ObjectVisitor visitor) { + super.visitMembers(visitor); + visitor.visit("value", value); + } + + @Override + public void set(ResultNode rhs) { + value = rhs.getInteger() > 0; + } +} diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/BoolResultNodeVector.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/BoolResultNodeVector.java new file mode 100644 index 00000000000..b8d31be8346 --- /dev/null +++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/BoolResultNodeVector.java @@ -0,0 +1,69 @@ +// Copyright 2019 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.searchlib.expression; + +import com.yahoo.vespa.objects.Deserializer; +import com.yahoo.vespa.objects.Serializer; + +import java.util.ArrayList; + +public class BoolResultNodeVector extends ResultNodeVector { + public static final int classId = registerClass(0x4000 + 147, BoolResultNodeVector.class); + private ArrayList<BoolResultNode> vector = new ArrayList<>(); + + public BoolResultNodeVector() {} + public BoolResultNodeVector add(BoolResultNode v) { + vector.add(v); + return this; + } + + public ArrayList<BoolResultNode> getVector() { + return vector; + } + @Override + public ResultNodeVector add(ResultNode r) { + return add((BoolResultNode)r); + } + + @Override + protected int onGetClassId() { + return classId; + } + + @Override + protected void onSerialize(Serializer buf) { + super.onSerialize(buf); + buf.putInt(null, vector.size()); + for (BoolResultNode node : vector) { + node.serialize(buf); + } + } + + @Override + protected void onDeserialize(Deserializer buf) { + super.onDeserialize(buf); + int sz = buf.getInt(null); + vector = new ArrayList<>(); + for (int i = 0; i < sz; i++) { + BoolResultNode node = new BoolResultNode(); + node.deserialize(buf); + vector.add(node); + } + } + + @Override + protected int onCmp(ResultNode rhs) { + if (classId != rhs.getClassId()) { + return (classId - rhs.getClassId()); + } + BoolResultNodeVector b = (BoolResultNodeVector)rhs; + int minLength = vector.size(); + if (b.vector.size() < minLength) { + minLength = b.vector.size(); + } + int diff = 0; + for (int i = 0; (diff == 0) && (i < minLength); i++) { + diff = vector.get(i).compareTo(b.vector.get(i)); + } + return (diff == 0) ? (vector.size() - b.vector.size()) : diff; + } +} diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java index 6fa2ae61f77..1144b01f638 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java @@ -50,6 +50,7 @@ public class ForceLoad { "Int32ResultNode", "Int16ResultNode", "Int8ResultNode", + "BoolResultNode", "ModuloFunctionNode", "IntegerResultNodeVector", "Int32ResultNodeVector", @@ -58,6 +59,7 @@ public class ForceLoad { "FloatResultNodeVector", "StringResultNodeVector", "RawResultNodeVector", + "BoolResultNodeVector", "MultiplyFunctionNode", "IntegerBucketResultNode", "FloatBucketResultNode", diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/Int8ResultNode.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/Int8ResultNode.java index 88920323703..f240a2d5ef7 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/expression/Int8ResultNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/Int8ResultNode.java @@ -18,9 +18,7 @@ public class Int8ResultNode extends NumericResultNode { public static final int classId = registerClass(0x4000 + 104, Int8ResultNode.class); private byte value = 0; - @SuppressWarnings("UnusedDeclaration") public Int8ResultNode() { - // used by deserializer } /** diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/Int8ResultNodeVector.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/Int8ResultNodeVector.java index 33734c15ff1..edae250defe 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/expression/Int8ResultNodeVector.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/Int8ResultNodeVector.java @@ -15,7 +15,7 @@ import java.util.ArrayList; public class Int8ResultNodeVector extends ResultNodeVector { public static final int classId = registerClass(0x4000 + 116, Int8ResultNodeVector.class); - private ArrayList<Int8ResultNode> vector = new ArrayList<Int8ResultNode>(); + private ArrayList<Int8ResultNode> vector = new ArrayList<>(); public Int8ResultNodeVector() { @@ -53,7 +53,7 @@ public class Int8ResultNodeVector extends ResultNodeVector { protected void onDeserialize(Deserializer buf) { super.onDeserialize(buf); int sz = buf.getInt(null); - vector = new ArrayList<Int8ResultNode>(); + vector = new ArrayList<>(); for (int i = 0; i < sz; i++) { Int8ResultNode node = new Int8ResultNode((byte)0); node.deserialize(buf); diff --git a/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerResultNodeTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerResultNodeTestCase.java index 4e079ba2adb..bb2cd640c8f 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerResultNodeTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerResultNodeTestCase.java @@ -33,7 +33,7 @@ public class IntegerResultNodeTestCase extends ResultNodeTest { assertThat(new Int16ResultNode().getClassId(), is(Int16ResultNode.classId)); assertThat(new Int32ResultNode().getClassId(), is(Int32ResultNode.classId)); assertThat(new IntegerResultNode().getClassId(), is(IntegerResultNode.classId)); - + assertThat(new BoolResultNode().getClassId(), is(BoolResultNode.classId)); } @Test @@ -80,6 +80,18 @@ public class IntegerResultNodeTestCase extends ResultNodeTest { } @Test + public void testBool() { + BoolResultNode node = new BoolResultNode(); + assertEquals(0, node.getInteger()); + assertEquals(0.0, node.getFloat(), 0.000000000001); + assertEquals("false", node.getString()); + node.setValue(true); + assertEquals(1, node.getInteger()); + assertEquals(1.0, node.getFloat(), 0.000000000001); + assertEquals("true", node.getString()); + } + + @Test public void testInt8() { Int8ResultNode node = new Int8ResultNode(); node.setValue((byte) 5); diff --git a/searchlib/src/test/java/com/yahoo/searchlib/expression/ResultNodeVectorTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/expression/ResultNodeVectorTestCase.java index 2f43ad6843b..2fc1771ece0 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/expression/ResultNodeVectorTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/expression/ResultNodeVectorTestCase.java @@ -23,10 +23,17 @@ public class ResultNodeVectorTestCase extends ResultNodeTest { assertThat(new Int16ResultNodeVector().getClassId(), is(Int16ResultNodeVector.classId)); assertThat(new Int8ResultNodeVector().getClassId(), is(Int8ResultNodeVector.classId)); assertThat(new FloatResultNodeVector().getClassId(), is(FloatResultNodeVector.classId)); + assertThat(new BoolResultNodeVector().getClassId(), is(BoolResultNodeVector.classId)); } @Test public void testVectorAdd() { + BoolResultNodeVector b = new BoolResultNodeVector(); + b.add(new BoolResultNode(true)); + b.add(new BoolResultNode(false)); + b.add((ResultNode)new BoolResultNode(false)); + assertThat(b.getVector().size(), is(3)); + Int8ResultNodeVector i8 = new Int8ResultNodeVector(); i8.add(new Int8ResultNode((byte)9)); i8.add(new Int8ResultNode((byte)2)); @@ -157,11 +164,12 @@ public class ResultNodeVectorTestCase extends ResultNodeTest { @Test public void testSerialize() throws InstantiationException, IllegalAccessException { - assertCorrectSerialization(new FloatResultNodeVector().add(new FloatResultNode(1.1)).add(new FloatResultNode(3.3)), new FloatResultNodeVector()); - assertCorrectSerialization(new IntegerResultNodeVector().add(new IntegerResultNode(1)).add(new IntegerResultNode(3)), new IntegerResultNodeVector()); - assertCorrectSerialization(new Int16ResultNodeVector().add(new Int16ResultNode((short) 1)).add(new Int16ResultNode((short) 3)), new Int16ResultNodeVector()); - assertCorrectSerialization(new Int8ResultNodeVector().add(new Int8ResultNode((byte) 1)).add(new Int8ResultNode((byte) 3)), new Int8ResultNodeVector()); - assertCorrectSerialization(new StringResultNodeVector().add(new StringResultNode("foo")).add(new StringResultNode("bar")), new StringResultNodeVector()); - assertCorrectSerialization(new RawResultNodeVector().add(new RawResultNode(new byte[]{6, 9})).add(new RawResultNode(new byte[]{9, 6})), new RawResultNodeVector()); + assertCorrectSerialization(new FloatResultNodeVector().add(new FloatResultNode(1.1)).add(new FloatResultNode(3.3)), new FloatResultNodeVector()); + assertCorrectSerialization(new IntegerResultNodeVector().add(new IntegerResultNode(1)).add(new IntegerResultNode(3)), new IntegerResultNodeVector()); + assertCorrectSerialization(new Int16ResultNodeVector().add(new Int16ResultNode((short) 1)).add(new Int16ResultNode((short) 3)), new Int16ResultNodeVector()); + assertCorrectSerialization(new Int8ResultNodeVector().add(new Int8ResultNode((byte) 1)).add(new Int8ResultNode((byte) 3)), new Int8ResultNodeVector()); + assertCorrectSerialization(new StringResultNodeVector().add(new StringResultNode("foo")).add(new StringResultNode("bar")), new StringResultNodeVector()); + assertCorrectSerialization(new RawResultNodeVector().add(new RawResultNode(new byte[]{6, 9})).add(new RawResultNode(new byte[]{9, 6})), new RawResultNodeVector()); + assertCorrectSerialization(new BoolResultNodeVector().add(new BoolResultNode(true)).add(new BoolResultNode(false)), new BoolResultNodeVector()); } } diff --git a/searchlib/src/tests/aggregator/perdocexpr.cpp b/searchlib/src/tests/aggregator/perdocexpr.cpp index 25bbd16de07..66d2e48194d 100644 --- a/searchlib/src/tests/aggregator/perdocexpr.cpp +++ b/searchlib/src/tests/aggregator/perdocexpr.cpp @@ -4,6 +4,7 @@ #include <vespa/searchlib/aggregation/expressioncountaggregationresult.h> #include <vespa/searchlib/aggregation/perdocexpression.h> #include <vespa/searchlib/attribute/extendableattributes.h> +#include <vespa/searchlib/attribute/singleboolattribute.h> #include <vespa/vespalib/objects/objectdumper.h> #include <vespa/vespalib/testkit/testapp.h> #include <vespa/document/base/testdocman.h> @@ -1534,12 +1535,37 @@ AttributeGuard createInt8Attribute() { return attr1; } +AttributeGuard createBoolAttribute() { + SingleBoolAttribute *selectAttr1(new SingleBoolAttribute("selectAttr1", search::GrowStrategy())); + DocId docId(0); + selectAttr1->addDoc(docId); + selectAttr1->setBit(docId, true); + selectAttr1->addDoc(docId); + selectAttr1->setBit(docId, false); + selectAttr1->addDoc(docId); + selectAttr1->addDoc(docId); + selectAttr1->setBit(docId, true); + selectAttr1->addDoc(docId); + selectAttr1->setBit(docId, true); + + + AttributeVector::SP spSelectAttr1(selectAttr1); + AttributeGuard attr1( spSelectAttr1 ); + return attr1; +} + TEST("testIntegerTypes") { - EXPECT_EQUAL(AttributeNode(*createInt8Attribute()).prepare(false) + EXPECT_EQUAL(AttributeNode(*createBoolAttribute()).prepare(false) .getResult().getClass().id(), + uint32_t(BoolResultNode::classId)); + EXPECT_EQUAL(AttributeNode(*createBoolAttribute()) + .prepare(true).getResult().getClass().id(), + uint32_t(BoolResultNode::classId)); + EXPECT_EQUAL(AttributeNode(*createInt8Attribute()).prepare(false) + .getResult().getClass().id(), uint32_t(Int64ResultNode::classId)); EXPECT_EQUAL(AttributeNode(*createInt8Attribute()) - .prepare(true).getResult().getClass().id(), + .prepare(true).getResult().getClass().id(), uint32_t(Int8ResultNode::classId)); EXPECT_EQUAL(AttributeNode(*createInt16Attribute()) .prepare(false).getResult().getClass().id(), diff --git a/searchlib/src/vespa/searchlib/attribute/singleboolattribute.h b/searchlib/src/vespa/searchlib/attribute/singleboolattribute.h index c10940574e6..789948838cb 100644 --- a/searchlib/src/vespa/searchlib/attribute/singleboolattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/singleboolattribute.h @@ -89,6 +89,13 @@ public: return getFast(doc); } const BitVector & getBitVector() const { return _bv; } + void setBit(DocId doc, bool value) { + if (value) { + _bv.setBit(doc); + } else { + _bv.clearBit(doc); + } + } protected: bool findEnum(int8_t, EnumHandle &) const override { return false; diff --git a/searchlib/src/vespa/searchlib/common/identifiable.h b/searchlib/src/vespa/searchlib/common/identifiable.h index 35e49b5cddf..adab458378b 100644 --- a/searchlib/src/vespa/searchlib/common/identifiable.h +++ b/searchlib/src/vespa/searchlib/common/identifiable.h @@ -149,6 +149,9 @@ #define CID_search_expression_NormalizeSubjectFunctionNode SEARCHLIB_CID(143) #define CID_search_expression_DebugWaitFunctionNode SEARCHLIB_CID(144) #define CID_search_expression_AttributeMapLookupNode SEARCHLIB_CID(145) +#define CID_search_expression_BoolResultNode SEARCHLIB_CID(146) +#define CID_search_expression_BoolResultNodeVector SEARCHLIB_CID(147) + #define CID_search_QueryNode SEARCHLIB_CID(150) #define CID_search_Query SEARCHLIB_CID(151) diff --git a/searchlib/src/vespa/searchlib/datastore/CMakeLists.txt b/searchlib/src/vespa/searchlib/datastore/CMakeLists.txt index 0698c57246a..5af7bd21d78 100644 --- a/searchlib/src/vespa/searchlib/datastore/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/datastore/CMakeLists.txt @@ -6,5 +6,6 @@ vespa_add_library(searchlib_datastore OBJECT bufferstate.cpp datastore.cpp datastorebase.cpp + entryref.cpp DEPENDS ) diff --git a/searchlib/src/vespa/searchlib/datastore/entryref.cpp b/searchlib/src/vespa/searchlib/datastore/entryref.cpp new file mode 100644 index 00000000000..f7224191d1b --- /dev/null +++ b/searchlib/src/vespa/searchlib/datastore/entryref.cpp @@ -0,0 +1,17 @@ +// Copyright 2019 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "entryref.hpp" + +namespace search::datastore { + +template EntryRefT<24u, 8u>::EntryRefT(uint64_t, uint32_t); +template EntryRefT<31u, 1u>::EntryRefT(uint64_t, uint32_t); +template EntryRefT<22u,10u>::EntryRefT(uint64_t, uint32_t); +template EntryRefT<19u,13u>::EntryRefT(uint64_t, uint32_t); +template EntryRefT<18u, 6u>::EntryRefT(uint64_t, uint32_t); +template EntryRefT<15u,17u>::EntryRefT(uint64_t, uint32_t); +template EntryRefT<10u,22u>::EntryRefT(uint64_t, uint32_t); +template EntryRefT<10u,10u>::EntryRefT(uint64_t, uint32_t); +template EntryRefT< 3u, 2u>::EntryRefT(uint64_t, uint32_t); + +} diff --git a/searchlib/src/vespa/searchlib/datastore/entryref.h b/searchlib/src/vespa/searchlib/datastore/entryref.h index f4dec5dbef3..457ffac4e26 100644 --- a/searchlib/src/vespa/searchlib/datastore/entryref.h +++ b/searchlib/src/vespa/searchlib/datastore/entryref.h @@ -3,7 +3,6 @@ #pragma once #include <cstdint> -#include <vespa/vespalib/util/assert.h> namespace search::datastore { @@ -28,12 +27,7 @@ template <uint32_t OffsetBits, uint32_t BufferBits = 32u - OffsetBits> class EntryRefT : public EntryRef { public: EntryRefT() : EntryRef() {} - EntryRefT(uint64_t offset_, uint32_t bufferId_) : - EntryRef((offset_ << BufferBits) + bufferId_) - { - ASSERT_ONCE_OR_LOG(offset_ < offsetSize(), "EntryRefT.offset_overflow", 10000); - ASSERT_ONCE_OR_LOG(bufferId_ < numBuffers(), "EntryRefT.bufferId_overflow", 10000); - } + EntryRefT(uint64_t offset_, uint32_t bufferId_); EntryRefT(const EntryRef & ref_) : EntryRef(ref_.ref()) {} uint32_t hash() const { return offset() + (bufferId() << OffsetBits); } uint64_t offset() const { return _ref >> BufferBits; } diff --git a/searchlib/src/vespa/searchlib/datastore/entryref.hpp b/searchlib/src/vespa/searchlib/datastore/entryref.hpp new file mode 100644 index 00000000000..a7bb9f9b3ef --- /dev/null +++ b/searchlib/src/vespa/searchlib/datastore/entryref.hpp @@ -0,0 +1,18 @@ +// Copyright 2019 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "entryref.h" +#include <vespa/vespalib/util/assert.h> + +namespace search::datastore { + +template <uint32_t OffsetBits, uint32_t BufferBits> +EntryRefT<OffsetBits, BufferBits>::EntryRefT(uint64_t offset_, uint32_t bufferId_) : + EntryRef((offset_ << BufferBits) + bufferId_) +{ + ASSERT_ONCE_OR_LOG(offset_ < offsetSize(), "EntryRefT.offset_overflow", 10000); + ASSERT_ONCE_OR_LOG(bufferId_ < numBuffers(), "EntryRefT.bufferId_overflow", 10000); +} + +} diff --git a/searchlib/src/vespa/searchlib/expression/attributenode.cpp b/searchlib/src/vespa/searchlib/expression/attributenode.cpp index 704000b7a04..94b24808e74 100644 --- a/searchlib/src/vespa/searchlib/expression/attributenode.cpp +++ b/searchlib/src/vespa/searchlib/expression/attributenode.cpp @@ -140,7 +140,10 @@ void AttributeNode::onPrepare(bool preserveAccurateTypes) BasicType::Type basicType = attribute->getBasicType(); if (attribute->isIntegerType()) { if (_hasMultiValue) { - if (preserveAccurateTypes) { + if (basicType == BasicType::BOOL) { + setResultType(std::make_unique<BoolResultNodeVector>()); + _handler = std::make_unique<IntegerHandler<BoolResultNodeVector>>(updateResult()); + } else if (preserveAccurateTypes) { switch (basicType) { case BasicType::INT8: setResultType(std::make_unique<Int8ResultNodeVector>()); @@ -167,7 +170,9 @@ void AttributeNode::onPrepare(bool preserveAccurateTypes) _handler = std::make_unique<IntegerHandler<IntegerResultNodeVector>>(updateResult()); } } else { - if (preserveAccurateTypes) { + if (basicType == BasicType::BOOL) { + setResultType(std::make_unique<BoolResultNode>()); + } else if (preserveAccurateTypes) { switch (basicType) { case BasicType::INT8: setResultType(std::make_unique<Int8ResultNode>()); diff --git a/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp b/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp index b0884d51db9..9ca49107079 100644 --- a/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp +++ b/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp @@ -10,8 +10,7 @@ #include <vespa/log/log.h> LOG_SETUP(".searchlib.documentfieldnode"); -namespace search { -namespace expression { +namespace search::expression { using namespace vespalib; using namespace document; @@ -23,9 +22,7 @@ IMPLEMENT_EXPRESSIONNODE(GetDocIdNamespaceSpecificFunctionNode, DocumentAccessor const vespalib::string DocumentAccessorNode::_S_docId("documentid"); -DocumentFieldNode::~DocumentFieldNode() -{ -} +DocumentFieldNode::~DocumentFieldNode() = default; DocumentFieldNode::DocumentFieldNode(const DocumentFieldNode & rhs) : DocumentAccessorNode(rhs), @@ -67,6 +64,8 @@ deduceResultNode(vespalib::stringref fieldName, const FieldValue & fv, bool pres } } else if (cInfo.inherits(FloatFieldValue::classId) || cInfo.inherits(DoubleFieldValue::classId)) { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new FloatResultNodeVector()) : static_cast<ResultNode *>(new FloatResultNode())); + } else if (cInfo.inherits(BoolFieldValue::classId)) { + value.reset(nestedMultiValue ? static_cast<ResultNode *>(new BoolResultNodeVector()) : static_cast<ResultNode *>(new BoolResultNode())); } else if (cInfo.inherits(StringFieldValue::classId)) { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new StringResultNodeVector()) : static_cast<ResultNode *>(new StringResultNode())); } else if (cInfo.inherits(RawFieldValue::classId)) { @@ -83,6 +82,8 @@ deduceResultNode(vespalib::stringref fieldName, const FieldValue & fv, bool pres const Identifiable::RuntimeClass & rInfo = value->getClass(); if (rInfo.inherits(ResultNodeVector::classId)) { //Already multivalue, so we are good to go. + } else if (rInfo.inherits(BoolResultNode::classId)) { + value.reset(new BoolResultNodeVector()); } else if (rInfo.inherits(Int8ResultNode::classId)) { value.reset(new Int8ResultNodeVector()); } else if (rInfo.inherits(Int16ResultNode::classId)) { @@ -339,7 +340,6 @@ GetYMUMChecksumFunctionNode::visitMembers(vespalib::ObjectVisitor &visitor) cons } } -} // this function was added by ../../forcelink.sh void forcelink_file_searchlib_expression_documentfieldnode() {} diff --git a/searchlib/src/vespa/searchlib/expression/documentfieldnode.h b/searchlib/src/vespa/searchlib/expression/documentfieldnode.h index beb658f7524..d681cdb8c0a 100644 --- a/searchlib/src/vespa/searchlib/expression/documentfieldnode.h +++ b/searchlib/src/vespa/searchlib/expression/documentfieldnode.h @@ -6,8 +6,7 @@ #include "resultvector.h" #include <vespa/document/fieldvalue/iteratorhandler.h> -namespace search { -namespace expression { +namespace search::expression { class DefaultValue final : public ResultNode { @@ -69,13 +68,12 @@ private: bool onExecute() const override; void onDoc(const document::Document & doc) override; void onDocType(const document::DocumentType & docType) override; - document::FieldPath _fieldPath; - mutable ResultNode::CP _value; + document::FieldPath _fieldPath; + mutable ResultNode::CP _value; mutable std::unique_ptr<Handler> _handler; - vespalib::string _fieldName; - const document::Document * _doc; + vespalib::string _fieldName; + const document::Document * _doc; }; } -} diff --git a/searchlib/src/vespa/searchlib/expression/expressiontree.cpp b/searchlib/src/vespa/searchlib/expression/expressiontree.cpp index ee673d087f0..9fd7caf02f5 100644 --- a/searchlib/src/vespa/searchlib/expression/expressiontree.cpp +++ b/searchlib/src/vespa/searchlib/expression/expressiontree.cpp @@ -7,8 +7,7 @@ #include "arrayatlookupfunctionnode.h" #include "attributenode.h" -namespace search { -namespace expression { +namespace search::expression { using vespalib::Serializer; using vespalib::Deserializer; @@ -224,7 +223,6 @@ operator >> (Deserializer & is, ExpressionTree & et) } } -} // this function was added by ../../forcelink.sh void forcelink_file_searchlib_expression_expressiontree() {} diff --git a/searchlib/src/vespa/searchlib/expression/integerresultnode.h b/searchlib/src/vespa/searchlib/expression/integerresultnode.h index ada513484fd..994c153a353 100644 --- a/searchlib/src/vespa/searchlib/expression/integerresultnode.h +++ b/searchlib/src/vespa/searchlib/expression/integerresultnode.h @@ -5,8 +5,7 @@ #include <vespa/vespalib/util/sort.h> #include <limits> -namespace search { -namespace expression { +namespace search::expression { class BucketResultNode; @@ -88,6 +87,17 @@ private: T _value; }; +class BoolResultNode : public IntegerResultNodeT<bool> +{ +private: + using Base = IntegerResultNodeT<bool>; +public: + DECLARE_RESULTNODE(BoolResultNode); + BoolResultNode(bool v=false) : Base(v) { } +private: + ConstBufferRef onGetString(size_t index, BufferRef buf) const override; +}; + class Int8ResultNode : public IntegerResultNodeT<int8_t> { private: @@ -133,5 +143,3 @@ private: }; } -} - diff --git a/searchlib/src/vespa/searchlib/expression/numericfunctionnode.cpp b/searchlib/src/vespa/searchlib/expression/numericfunctionnode.cpp index aa871cc165a..eea179f67ff 100644 --- a/searchlib/src/vespa/searchlib/expression/numericfunctionnode.cpp +++ b/searchlib/src/vespa/searchlib/expression/numericfunctionnode.cpp @@ -5,8 +5,8 @@ namespace search::expression { IMPLEMENT_ABSTRACT_EXPRESSIONNODE(NumericFunctionNode, MultiArgFunctionNode); -NumericFunctionNode::NumericFunctionNode() : _handler() { } -NumericFunctionNode::~NumericFunctionNode() {} +NumericFunctionNode::NumericFunctionNode() = default; +NumericFunctionNode::~NumericFunctionNode() = default; NumericFunctionNode::NumericFunctionNode(const NumericFunctionNode & rhs) : MultiArgFunctionNode(rhs), diff --git a/searchlib/src/vespa/searchlib/expression/numericfunctionnode.h b/searchlib/src/vespa/searchlib/expression/numericfunctionnode.h index 0d056883789..2306d9c1028 100644 --- a/searchlib/src/vespa/searchlib/expression/numericfunctionnode.h +++ b/searchlib/src/vespa/searchlib/expression/numericfunctionnode.h @@ -4,8 +4,7 @@ #include "multiargfunctionnode.h" #include "resultvector.h" -namespace search { -namespace expression { +namespace search::expression { class NumericFunctionNode : public MultiArgFunctionNode { @@ -174,4 +173,3 @@ private: }; } -} diff --git a/searchlib/src/vespa/searchlib/expression/resultnode.h b/searchlib/src/vespa/searchlib/expression/resultnode.h index 839bb96ceaa..55f08e9455c 100644 --- a/searchlib/src/vespa/searchlib/expression/resultnode.h +++ b/searchlib/src/vespa/searchlib/expression/resultnode.h @@ -5,8 +5,7 @@ #include "serializer.h" #include <vespa/vespalib/util/buffer.h> -namespace search { -namespace expression { +namespace search::expression { class BucketResultNode; @@ -124,4 +123,3 @@ public: }; } -} diff --git a/searchlib/src/vespa/searchlib/expression/resultnodes.cpp b/searchlib/src/vespa/searchlib/expression/resultnodes.cpp index a8a27f89d82..8e34babd92a 100644 --- a/searchlib/src/vespa/searchlib/expression/resultnodes.cpp +++ b/searchlib/src/vespa/searchlib/expression/resultnodes.cpp @@ -12,8 +12,7 @@ #include <vespa/vespalib/objects/serializer.hpp> #include <vespa/vespalib/objects/deserializer.hpp> -namespace search { -namespace expression { +namespace search::expression { using vespalib::nbo; using vespalib::Serializer; @@ -31,6 +30,7 @@ IMPLEMENT_RESULTNODE(StringResultNode, SingleResultNode); IMPLEMENT_RESULTNODE(NullResultNode, SingleResultNode); IMPLEMENT_RESULTNODE(PositiveInfinityResultNode, SingleResultNode); IMPLEMENT_RESULTNODE(RawResultNode, SingleResultNode); +IMPLEMENT_RESULTNODE(BoolResultNode, IntegerResultNode); IMPLEMENT_RESULTNODE(Int8ResultNode, IntegerResultNode); IMPLEMENT_RESULTNODE(Int16ResultNode, IntegerResultNode); IMPLEMENT_RESULTNODE(Int32ResultNode, IntegerResultNode); @@ -38,13 +38,9 @@ IMPLEMENT_RESULTNODE(Int64ResultNode, IntegerResultNode); IMPLEMENT_RESULTNODE(EnumResultNode, IntegerResultNode); IMPLEMENT_RESULTNODE(FloatResultNode, NumericResultNode); -void ResultNode::sort() -{ -} +void ResultNode::sort() {} -void ResultNode::reverse() -{ -} +void ResultNode::reverse() {} void ResultNode::negate() { @@ -85,19 +81,22 @@ FloatResultNode::visitMembers(vespalib::ObjectVisitor &visitor) const visit(visitor, "value", _value); } -ResultNode::ConstBufferRef FloatResultNode::onGetString(size_t index, ResultNode::BufferRef buf) const +ResultNode::ConstBufferRef +FloatResultNode::onGetString(size_t index, ResultNode::BufferRef buf) const { (void) index; int numWritten = std::min(buf.size(), (size_t)std::max(0, snprintf(buf.str(), buf.size(), "%g", _value))); return ConstBufferRef(buf.str(), numWritten); } -bool FloatResultNode::isNan() const +bool +FloatResultNode::isNan() const { return std::isnan(_value); } -int FloatResultNode::onCmp(const Identifiable & b) const +int +FloatResultNode::onCmp(const Identifiable & b) const { const FloatResultNode & rhs(static_cast<const FloatResultNode &>(b)); if (isNan()) { @@ -150,13 +149,15 @@ int PositiveInfinityResultNode::onCmp(const Identifiable & b) const int64_t StringResultNode::onGetInteger(size_t index) const { (void) index; return strtoll(_value.c_str(), NULL, 0); } double StringResultNode::onGetFloat(size_t index) const { (void) index; return vespalib::locale::c::strtod(_value.c_str(), NULL); } -Serializer & StringResultNode::onSerialize(Serializer & os) const +Serializer & +StringResultNode::onSerialize(Serializer & os) const { os << _value; return os; } -int StringResultNode::onCmp(const Identifiable & b) const +int +StringResultNode::onCmp(const Identifiable & b) const { if (b.inherits(PositiveInfinityResultNode::classId)) { return -1; @@ -171,14 +172,16 @@ int StringResultNode::onCmp(const Identifiable & b) const } } -Deserializer & StringResultNode::onDeserialize(Deserializer & is) +Deserializer & +StringResultNode::onDeserialize(Deserializer & is) { is >> _value; return is; } -void RawResultNode::add(const ResultNode & b) +void +RawResultNode::add(const ResultNode & b) { char buf[32]; ConstBufferRef s(b.getString(BufferRef(buf, sizeof(buf)))); @@ -196,7 +199,8 @@ void RawResultNode::add(const ResultNode & b) } -void RawResultNode::min(const ResultNode & b) +void +RawResultNode::min(const ResultNode & b) { char buf[32]; ConstBufferRef s(b.getString(BufferRef(buf, sizeof(buf)))); @@ -206,7 +210,8 @@ void RawResultNode::min(const ResultNode & b) } } -void RawResultNode::max(const ResultNode & b) +void +RawResultNode::max(const ResultNode & b) { char buf[32]; ConstBufferRef s(b.getString(BufferRef(buf, sizeof(buf)))); @@ -216,14 +221,16 @@ void RawResultNode::max(const ResultNode & b) } } -void RawResultNode::negate() +void +RawResultNode::negate() { for (size_t i(0); i < _value.size(); i++) { _value[i] = - _value[i]; } } -void StringResultNode::add(const ResultNode & b) +void +StringResultNode::add(const ResultNode & b) { char buf[32]; ConstBufferRef s(b.getString(BufferRef(buf, sizeof(buf)))); @@ -238,7 +245,8 @@ void StringResultNode::add(const ResultNode & b) } } -void StringResultNode::min(const ResultNode & b) +void +StringResultNode::min(const ResultNode & b) { char buf[32]; ConstBufferRef s(b.getString(BufferRef(buf, sizeof(buf)))); @@ -248,7 +256,8 @@ void StringResultNode::min(const ResultNode & b) } } -void StringResultNode::max(const ResultNode & b) +void +StringResultNode::max(const ResultNode & b) { char buf[32]; ConstBufferRef s(b.getString(BufferRef(buf, sizeof(buf)))); @@ -258,7 +267,8 @@ void StringResultNode::max(const ResultNode & b) } } -void StringResultNode::negate() +void +StringResultNode::negate() { for (size_t i(0); i < _value.length(); i++) { _value[i] = - _value[i]; @@ -271,9 +281,14 @@ StringResultNode::visitMembers(vespalib::ObjectVisitor &visitor) const visit(visitor, "value", _value); } -ResultNode::ConstBufferRef StringResultNode::onGetString(size_t index, ResultNode::BufferRef ) const { (void) index; return ConstBufferRef(_value.c_str(), _value.size()); } +ResultNode::ConstBufferRef +StringResultNode::onGetString(size_t index, ResultNode::BufferRef ) const { + (void) index; + return ConstBufferRef(_value.c_str(), _value.size()); +} -void StringResultNode::set(const ResultNode & rhs) +void +StringResultNode::set(const ResultNode & rhs) { char buf[32]; ConstBufferRef b(rhs.getString(BufferRef(buf, sizeof(buf)))); @@ -310,13 +325,15 @@ size_t hashBuf(const void *s, size_t sz) size_t StringResultNode::hash() const { return hashBuf(_value.c_str(), _value.size()); } -size_t StringResultNode::hash(const void * buf) const +size_t +StringResultNode::hash(const void * buf) const { const vespalib::string & s = *static_cast<const vespalib::string *>(buf); return hashBuf(s.c_str(), s.size()); } -int64_t RawResultNode::onGetInteger(size_t index) const +int64_t +RawResultNode::onGetInteger(size_t index) const { (void) index; union { @@ -367,19 +384,22 @@ int RawResultNode::onCmp(const Identifiable & b) const size_t RawResultNode::hash() const { return hashBuf(&_value[0], _value.size()); } -size_t RawResultNode::hash(const void * buf) const +size_t +RawResultNode::hash(const void * buf) const { const std::vector<uint8_t> & s = *static_cast<const std::vector<uint8_t> *>(buf); return hashBuf(&s[0], s.size()); } -Deserializer & RawResultNode::onDeserialize(Deserializer & is) +Deserializer & +RawResultNode::onDeserialize(Deserializer & is) { is >> _value; return is; } -ResultDeserializer & RawResultNode::onDeserializeResult(ResultDeserializer & is) +ResultDeserializer & +RawResultNode::onDeserializeResult(ResultDeserializer & is) { return is.getResult(getClass(), *this); } @@ -390,13 +410,15 @@ RawResultNode::visitMembers(vespalib::ObjectVisitor &visitor) const visit(visitor, "value", _value); } -void RawResultNode::set(const ResultNode & rhs) +void +RawResultNode::set(const ResultNode & rhs) { char buf[32]; ConstBufferRef b(rhs.getString(BufferRef(buf, sizeof(buf)))); setBuffer(b.data(), b.size()); } -void RawResultNode::setBuffer(const void *buf, size_t sz) +void +RawResultNode::setBuffer(const void *buf, size_t sz) { _value.resize(sz + 1); memcpy(&_value[0], buf, sz); @@ -404,37 +426,49 @@ void RawResultNode::setBuffer(const void *buf, size_t sz) _value.resize(sz); } -ResultNode::ConstBufferRef RawResultNode::onGetString(size_t index, BufferRef ) const { (void) index; return ConstBufferRef(&_value[0], _value.size()); } +namespace { + const vespalib::string TRUE = "true"; + const vespalib::string FALSE = "false"; +} -ResultNode::ConstBufferRef EnumResultNode::onGetString(size_t index, BufferRef buf) const { - (void) index; +ResultNode::ConstBufferRef +RawResultNode::onGetString(size_t, BufferRef ) const { + return ConstBufferRef(&_value[0], _value.size()); +} + +ResultNode::ConstBufferRef +EnumResultNode::onGetString(size_t, BufferRef buf) const { int numWritten(std::min(buf.size(), (size_t)std::max(0, snprintf(buf.str(), buf.size(), "%ld", getValue())))); return ConstBufferRef(buf.str(), numWritten); } -ResultNode::ConstBufferRef Int8ResultNode::onGetString(size_t index, BufferRef buf) const { - (void) index; +ResultNode::ConstBufferRef +BoolResultNode::onGetString(size_t, BufferRef) const { + return getValue() ? ConstBufferRef(TRUE.data(), TRUE.size()) : ConstBufferRef(FALSE.data(), FALSE.size()); +} + +ResultNode::ConstBufferRef +Int8ResultNode::onGetString(size_t, BufferRef buf) const { int numWritten(std::min(buf.size(), (size_t)std::max(0, snprintf(buf.str(), buf.size(), "%d", getValue())))); return ConstBufferRef(buf.str(), numWritten); } -ResultNode::ConstBufferRef Int16ResultNode::onGetString(size_t index, BufferRef buf) const { - (void) index; +ResultNode::ConstBufferRef +Int16ResultNode::onGetString(size_t, BufferRef buf) const { int numWritten(std::min(buf.size(), (size_t)std::max(0, snprintf(buf.str(), buf.size(), "%d", getValue())))); return ConstBufferRef(buf.str(), numWritten); } -ResultNode::ConstBufferRef Int32ResultNode::onGetString(size_t index, BufferRef buf) const { - (void) index; +ResultNode::ConstBufferRef +Int32ResultNode::onGetString(size_t, BufferRef buf) const { int numWritten(std::min(buf.size(), (size_t)std::max(0, snprintf(buf.str(), buf.size(), "%d", getValue())))); return ConstBufferRef(buf.str(), numWritten); } -ResultNode::ConstBufferRef Int64ResultNode::onGetString(size_t index, BufferRef buf) const { - (void) index; +ResultNode::ConstBufferRef +Int64ResultNode::onGetString(size_t, BufferRef buf) const { int numWritten(std::min(buf.size(), (size_t)std::max(0, snprintf(buf.str(), buf.size(), "%ld", getValue())))); return ConstBufferRef(buf.str(), numWritten); } } -} diff --git a/searchlib/src/vespa/searchlib/expression/resultvector.cpp b/searchlib/src/vespa/searchlib/expression/resultvector.cpp index af30ae87fa0..f1aed219965 100644 --- a/searchlib/src/vespa/searchlib/expression/resultvector.cpp +++ b/searchlib/src/vespa/searchlib/expression/resultvector.cpp @@ -2,10 +2,10 @@ #include "resultvector.h" -namespace search { -namespace expression { +namespace search::expression { IMPLEMENT_ABSTRACT_EXPRESSIONNODE(ResultNodeVector, ResultNode); +IMPLEMENT_RESULTNODE(BoolResultNodeVector, ResultNodeVector); IMPLEMENT_RESULTNODE(Int8ResultNodeVector, ResultNodeVector); IMPLEMENT_RESULTNODE(Int16ResultNodeVector, ResultNodeVector); IMPLEMENT_RESULTNODE(Int32ResultNodeVector, ResultNodeVector); @@ -55,7 +55,6 @@ ResultNodeVector::onDeserializeResult(ResultDeserializer & is) } } -} // this function was added by ../../forcelink.sh void forcelink_file_searchlib_expression_resultvector() {} diff --git a/searchlib/src/vespa/searchlib/expression/resultvector.h b/searchlib/src/vespa/searchlib/expression/resultvector.h index 7969c4f88fa..cd29178f24f 100644 --- a/searchlib/src/vespa/searchlib/expression/resultvector.h +++ b/searchlib/src/vespa/searchlib/expression/resultvector.h @@ -13,8 +13,7 @@ #include <vespa/vespalib/objects/visit.hpp> #include <algorithm> -namespace search { -namespace expression { +namespace search::expression { class ResultNodeVector : public ResultNode { @@ -304,6 +303,15 @@ public: }; +class BoolResultNodeVector : public NumericResultNodeVectorT<BoolResultNode> +{ +public: + BoolResultNodeVector() { } + DECLARE_RESULTNODE(BoolResultNodeVector); + + const IntegerBucketResultNode& getNullBucket() const override { return IntegerBucketResultNode::getNull(); } +}; + class Int8ResultNodeVector : public NumericResultNodeVectorT<Int8ResultNode> { public: @@ -426,7 +434,4 @@ private: std::vector<ResultNode::CP> _v; }; - } -} - diff --git a/searchlib/src/vespa/searchlib/util/sigbushandler.cpp b/searchlib/src/vespa/searchlib/util/sigbushandler.cpp index 9de3f16be67..7356baab131 100644 --- a/searchlib/src/vespa/searchlib/util/sigbushandler.cpp +++ b/searchlib/src/vespa/searchlib/util/sigbushandler.cpp @@ -97,7 +97,7 @@ SigBusHandler::handle(int sig, siginfo_t *si, void *ucv) do { // Protect against multiple threads. TryLockGuard guard; - if (!guard.gotLock()) { + if (!guard.gotLock() || _fired) { raced = true; break; } @@ -121,18 +121,19 @@ SigBusHandler::handle(int sig, siginfo_t *si, void *ucv) sleep(5); return; } - untrap(); // Further bus errors will trigger core dump if (_unwind != nullptr) { // Unit test is using siglongjmp based unwinding sigjmp_buf *unwind = _unwind; _unwind = nullptr; + untrap(); // Further bus errors will trigger core dump siglongjmp(*unwind, 1); } else { // Normal case, sleep 3 seconds (i.e. allow main thread to detect // issue and notify cluster controller) before returning and // likely core dumping. sleep(3); + untrap(); // Further bus errors will trigger core dump } } |