summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--searchcore/src/tests/proton/docsummary/docsummary.cpp61
-rw-r--r--searchcore/src/tests/proton/docsummary/summary.cfg2
-rw-r--r--searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp41
-rw-r--r--searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp17
-rw-r--r--searchcore/src/vespa/searchcore/proton/docsummary/summaryfieldconverter.cpp11
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp52
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/docsumfieldwriter.cpp2
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/docsumformat.cpp1
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp2
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/resultclass.h1
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp3
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h2
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/resultpacker.cpp12
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/resultpacker.h8
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/urlresult.cpp1
15 files changed, 149 insertions, 67 deletions
diff --git a/searchcore/src/tests/proton/docsummary/docsummary.cpp b/searchcore/src/tests/proton/docsummary/docsummary.cpp
index a0b947e11f8..d0705e7b538 100644
--- a/searchcore/src/tests/proton/docsummary/docsummary.cpp
+++ b/searchcore/src/tests/proton/docsummary/docsummary.cpp
@@ -26,6 +26,8 @@
#include <vespa/searchcore/proton/common/hw_info.h>
#include <vespa/vespalib/data/slime/slime.h>
#include <vespa/config/helper/configgetter.hpp>
+#include <vespa/vespalib/tensor/serialization/typed_binary_format.h>
+#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/log/log.h>
LOG_SETUP("docsummary_test");
@@ -300,10 +302,18 @@ private:
uint32_t id,
uint32_t resultClassID);
+ void
+ assertTensor(const Tensor::UP &exp,
+ const std::string &fieldName,
+ const DocsumReply &reply,
+ uint32_t id,
+ uint32_t resultClassID);
+
bool
assertSlime(const std::string &exp,
const DocsumReply &reply,
- uint32_t id);
+ uint32_t id,
+ bool relaxed = false);
void
requireThatAdapterHandlesAllFieldTypes();
@@ -400,8 +410,26 @@ Test::assertString(const std::string & exp, const std::string & fieldName,
}
+void
+Test::assertTensor(const Tensor::UP & exp, const std::string & fieldName,
+ const DocsumReply & reply,
+ uint32_t id, uint32_t resultClassID)
+{
+ GeneralResultPtr res = getResult(reply, id, resultClassID);
+ const void *data = res->GetEntry(fieldName.c_str())->_stringval;
+ size_t len = res->GetEntry(fieldName.c_str())->_stringlen;
+ EXPECT_EQUAL(exp.get() == nullptr, len == 0u);
+ if (exp) {
+ vespalib::nbostream serialized(data, len);
+ Tensor::UP tensor = vespalib::tensor::TypedBinaryFormat::deserialize(serialized);
+ EXPECT_TRUE(tensor.get() != nullptr);
+ EXPECT_EQUAL(*exp, *tensor);
+ }
+}
+
+
bool
-Test::assertSlime(const std::string &exp, const DocsumReply &reply, uint32_t id)
+Test::assertSlime(const std::string &exp, const DocsumReply &reply, uint32_t id, bool relaxed)
{
const DocsumReply::Docsum & docsum = reply.docsums[id];
uint32_t classId;
@@ -414,6 +442,14 @@ Test::assertSlime(const std::string &exp, const DocsumReply &reply, uint32_t id)
size_t decodeRes = vespalib::slime::BinaryFormat::decode(serialized,
slime);
ASSERT_EQUAL(decodeRes, serialized.size);
+ if (relaxed) {
+ vespalib::slime::SimpleBuffer buf;
+ vespalib::slime::JsonFormat::encode(slime, buf, false);
+ vespalib::Slime tmpSlime;
+ size_t used = vespalib::slime::JsonFormat::decode(buf.get(), tmpSlime);
+ EXPECT_EQUAL(buf.get().size, used);
+ slime = std::move(tmpSlime);
+ }
vespalib::Slime expSlime;
size_t used = vespalib::slime::JsonFormat::decode(exp, expSlime);
EXPECT_EQUAL(exp.size(), used);
@@ -726,7 +762,7 @@ Test::requireThatAttributesAreUsed()
endElement().
endField().
startAttributeField("bj").
- addTensor(createTensor({ {{}, 3} }, { "x", "y"})).
+ addTensor(createTensor({ {{{"x","f"},{"y","g"}}, 3} }, { "x", "y"})).
endField().
endDocument(),
2);
@@ -755,9 +791,8 @@ Test::requireThatAttributesAreUsed()
*rep, 0, rclass));
EXPECT_TRUE(assertString("[[\"quux\",7],[\"qux\",6]]", "bi",
*rep, 0, rclass));
- EXPECT_TRUE(assertString("{\"dimensions\":[\"x\",\"y\"],"
- "\"cells\":[{\"address\":{},\"value\":3}]}",
- "bj", *rep, 0, rclass));
+ TEST_DO(assertTensor(createTensor({ {{{"x","f"},{"y","g"}}, 3} }, { "x", "y"}),
+ "bj", *rep, 0, rclass));
// empty doc
EXPECT_TRUE(search::attribute::isUndefined<int32_t>
@@ -771,7 +806,7 @@ Test::requireThatAttributesAreUsed()
EXPECT_TRUE(assertString("[]", "bg", *rep, 1, rclass));
EXPECT_TRUE(assertString("[]", "bh", *rep, 1, rclass));
EXPECT_TRUE(assertString("[]", "bi", *rep, 1, rclass));
- EXPECT_TRUE(assertString("", "bj", *rep, 1, rclass));
+ TEST_DO(assertTensor(Tensor::UP(), "bj", *rep, 1, rclass));
proton::IAttributeManager::SP attributeManager =
dc._ddb->getReadySubDB()->getAttributeManager();
@@ -785,14 +820,13 @@ Test::requireThatAttributesAreUsed()
attributeFieldWriter.
execute("bj",
[&]() { bjTensorAttr->setTensor(3,
- *createTensor({ {{}, 4} }, { "x"}));
+ *createTensor({ {{{"x", "a"},{"y", "b"}}, 4} }, { "x"}));
bjTensorAttr->commit(); });
attributeFieldWriter.sync();
DocsumReply::UP rep2 = dc._ddb->getDocsums(req);
- EXPECT_TRUE(assertString("{\"dimensions\":[\"x\",\"y\"],"
- "\"cells\":[{\"address\":{},\"value\":4}]}",
- "bj", *rep2, 1, rclass));
+ TEST_DO(assertTensor(createTensor({ {{{"x","a"},{"y","b"}}, 4} }, { "x", "y"}),
+ "bj", *rep2, 1, rclass));
DocsumRequest req3;
req3.resultClassName = "class3";
@@ -802,9 +836,8 @@ Test::requireThatAttributesAreUsed()
EXPECT_TRUE(assertSlime("{bd:[],be:[],bf:[],bg:[],"
"bh:[],bi:[],"
- "bj:{dimensions:['x','y'],"
- "cells:[{address:{},value:4.0}]}}",
- *rep3, 0));
+ "bj:'0x01020178017901016101624010000000000000'}",
+ *rep3, 0, true));
}
diff --git a/searchcore/src/tests/proton/docsummary/summary.cfg b/searchcore/src/tests/proton/docsummary/summary.cfg
index 52f300ae3e0..33fd90f4c82 100644
--- a/searchcore/src/tests/proton/docsummary/summary.cfg
+++ b/searchcore/src/tests/proton/docsummary/summary.cfg
@@ -85,7 +85,7 @@ classes[3].fields[7].type "jsonstring"
classes[3].fields[8].name "bi"
classes[3].fields[8].type "jsonstring"
classes[3].fields[9].name "bj"
-classes[3].fields[9].type "jsonstring"
+classes[3].fields[9].type "tensor"
classes[4].name "class4"
classes[4].id 4
classes[4].fields[1]
diff --git a/searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp b/searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp
index e9496093cfe..27a50c9c57f 100644
--- a/searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp
+++ b/searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp
@@ -150,6 +150,7 @@ class Test : public vespalib::TestApp {
void checkString(const string &str, const FieldValue *value);
void checkData(const search::RawBuf &data, const FieldValue *value);
+ void checkTensor(const Tensor::UP &tensor, const FieldValue *value);
template <unsigned int N>
void checkArray(const char *(&str)[N], const FieldValue *value);
void setSummaryField(const string &name);
@@ -170,7 +171,7 @@ class Test : public vespalib::TestApp {
void requireThatSearchDataTypeUsesDefaultDataTypes();
void requireThatLinguisticsAnnotationUsesDefaultDataTypes();
void requireThatPredicateIsPrinted();
- void requireThatTensorIsPrinted();
+ void requireThatTensorIsNotConverted();
const DocumentType &getDocType() const { return *_documentType; }
Document makeDocument();
StringFieldValue annotateTerm(const string &term);
@@ -245,7 +246,7 @@ Test::Main()
TEST_CALL(requireThatSearchDataTypeUsesDefaultDataTypes());
TEST_CALL(requireThatLinguisticsAnnotationUsesDefaultDataTypes());
TEST_CALL(requireThatPredicateIsPrinted());
- TEST_CALL(requireThatTensorIsPrinted());
+ TEST_CALL(requireThatTensorIsNotConverted());
TEST_DONE();
}
@@ -430,6 +431,17 @@ void Test::checkData(const search::RawBuf &buf, const FieldValue *value) {
EXPECT_TRUE(memcmp(buf.GetDrainPos(), got.first, got.second) == 0);
}
+void Test::checkTensor(const Tensor::UP &tensor, const FieldValue *value) {
+ ASSERT_TRUE(value);
+ const TensorFieldValue *s = dynamic_cast<const TensorFieldValue *>(value);
+ ASSERT_TRUE(s);
+ const Tensor::UP &tvalue = s->getAsTensorPtr();
+ EXPECT_EQUAL(tensor.get() != nullptr, tvalue.get() != nullptr);
+ if (tensor) {
+ EXPECT_EQUAL(*tensor, *tvalue);
+ }
+}
+
template <unsigned int N>
void Test::checkArray(const char *(&str)[N], const FieldValue *value) {
ASSERT_TRUE(value);
@@ -649,7 +661,7 @@ createTensor(const TensorCells &cells, const TensorDimensions &dimensions) {
}
void
-Test::requireThatTensorIsPrinted()
+Test::requireThatTensorIsNotConverted()
{
TensorFieldValue tensorFieldValue;
tensorFieldValue = createTensor({ {{{"x", "4"}, {"y", "5"}}, 7} },
@@ -658,30 +670,17 @@ Test::requireThatTensorIsPrinted()
doc.setRepo(*_documentRepo);
doc.setValue("tensor", tensorFieldValue);
- FieldBlock expect1("{ dimensions: [ 'x', 'y' ], cells: ["
- "{ address: { x:'4', y:'5' }, value: 7.0 }"
- "] }");
-
- TEST_CALL(checkString(expect1.json,
+ TEST_CALL(checkTensor(createTensor({ {{{"x", "4"}, {"y", "5"}}, 7} },
+ {"x", "y"}),
SFC::convertSummaryField(false,
*doc.getValue("tensor"),
- false).get()));
- TEST_CALL(checkData(expect1.binary,
- SFC::convertSummaryField(false,
- *doc.getValue("tensor"),
- true).get()));
+ true).get()));
doc.setValue("tensor", TensorFieldValue());
- FieldBlock expect2("{ }");
-
- TEST_CALL(checkString(expect2.json,
+ TEST_CALL(checkTensor(Tensor::UP(),
SFC::convertSummaryField(false,
*doc.getValue("tensor"),
- false).get()));
- TEST_CALL(checkData(expect2.binary,
- SFC::convertSummaryField(false,
- *doc.getValue("tensor"),
- true).get()));
+ true).get()));
}
} // namespace
diff --git a/searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp b/searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp
index 855126bd064..4f61873b938 100644
--- a/searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp
+++ b/searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp
@@ -3,11 +3,16 @@
#include "documentstoreadapter.h"
#include "summaryfieldconverter.h"
#include <vespa/document/fieldvalue/stringfieldvalue.h>
+#include <vespa/vespalib/tensor/tensor.h>
+#include <vespa/vespalib/tensor/serialization/typed_binary_format.h>
+#include <vespa/vespalib/objects/nbostream.h>
+#include <vespa/document/fieldvalue/tensorfieldvalue.h>
#include <vespa/log/log.h>
LOG_SETUP(".proton.docsummary.documentstoreadapter");
using namespace document;
using namespace search::docsummary;
+using vespalib::tensor::Tensor;
namespace proton {
@@ -76,6 +81,18 @@ DocumentStoreAdapter::writeField(const FieldValue &value, ResType type)
std::pair<const char *, size_t> buf = value.getAsRaw();
return _resultPacker.AddLongData(buf.first, buf.second);
}
+ case RES_TENSOR:
+ {
+ vespalib::nbostream serialized;
+ if (value.getClass().inherits(TensorFieldValue::classId)) {
+ const TensorFieldValue &tvalue = static_cast<const TensorFieldValue &>(value);
+ const std::unique_ptr<Tensor> &tensor = tvalue.getAsTensorPtr();
+ if (tensor) {
+ vespalib::tensor::TypedBinaryFormat::serialize(serialized, *tensor);
+ }
+ }
+ return _resultPacker.AddSerializedTensor(serialized.peek(), serialized.size());
+ }
default:
LOG(warning,
"Unknown docsum field type: %s. Add empty field",
diff --git a/searchcore/src/vespa/searchcore/proton/docsummary/summaryfieldconverter.cpp b/searchcore/src/vespa/searchcore/proton/docsummary/summaryfieldconverter.cpp
index 0c4d739be79..c74442bd72b 100644
--- a/searchcore/src/vespa/searchcore/proton/docsummary/summaryfieldconverter.cpp
+++ b/searchcore/src/vespa/searchcore/proton/docsummary/summaryfieldconverter.cpp
@@ -42,6 +42,8 @@
#include <vespa/vespalib/data/slime/binary_format.h>
#include <vespa/vespalib/data/slime/json_format.h>
#include <vespa/vespalib/tensor/serialization/slime_binary_format.h>
+#include <vespa/vespalib/tensor/serialization/typed_binary_format.h>
+#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/searchlib/util/slime_output_raw_buf_adapter.h>
#include <vespa/vespalib/util/exceptions.h>
@@ -472,7 +474,7 @@ class SummaryFieldValueConverter : protected ConstFieldValueVisitor
}
virtual void visit(const TensorFieldValue &value) override {
- _field_value = _structuredFieldConverter.convert(value);
+ visitPrimitive(value);
}
public:
@@ -632,12 +634,11 @@ class SlimeFiller : public ConstFieldValueVisitor {
virtual void visit(const TensorFieldValue &value) override {
const auto &tensor = value.getAsTensorPtr();
+ vespalib::nbostream s;
if (tensor) {
- vespalib::tensor::SlimeBinaryFormat::serialize(_inserter, *tensor);
- } else {
- // No tensor value => empty object
- _inserter.insertObject();
+ vespalib::tensor::TypedBinaryFormat::serialize(s, *tensor);
}
+ _inserter.insertData(vespalib::slime::Memory(s.peek(), s.size()));
}
public:
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp
index b0704b2d148..cb8a3dc7680 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp
+++ b/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp
@@ -8,7 +8,8 @@
#include "attributedfw.h"
#include "docsumstate.h"
#include <vespa/vespalib/tensor/tensor.h>
-#include <vespa/vespalib/tensor/serialization/slime_binary_format.h>
+#include <vespa/vespalib/tensor/serialization/typed_binary_format.h>
+#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/data/slime/slime.h>
#include <vespa/log/log.h>
@@ -44,7 +45,13 @@ ResType inferType(const IAttributeVector & vec) {
} else if (vec.isFloatingPointType()) {
retval = (fw == sizeof(float)) ? RES_FLOAT : RES_DOUBLE;
} else {
- retval = RES_STRING;
+ BasicType::Type t = vec.getBasicType();
+ switch (t) {
+ case BasicType::TENSOR:
+ retval = RES_TENSOR;
+ default:
+ retval = RES_STRING;
+ }
}
}
}
@@ -133,34 +140,27 @@ SingleAttrDFW::WriteField(uint32_t docid,
target->append(s, slen);
return (sizeof(slen) + slen);
break; }
- case RES_JSONSTRING: {
+ case RES_TENSOR: {
+ vespalib::nbostream str;
BasicType::Type t = v.getBasicType();
switch (t) {
case BasicType::TENSOR: {
const tensor::TensorAttribute &tv =
static_cast<const tensor::TensorAttribute &>(v);
const auto tensor = tv.getTensor(docid);
- vespalib::string str;
if (tensor) {
- auto slime =
- vespalib::tensor::SlimeBinaryFormat::serialize(*tensor);
- vespalib::slime::SimpleBuffer buf;
- vespalib::slime::JsonFormat::encode(*slime, buf, true);
- str = buf.get().make_string();
- } else {
- // No tensor value => empty object
- str = "";
+ vespalib::tensor::TypedBinaryFormat::serialize(str, *tensor);
}
- uint32_t slen = str.size();
- target->append(&slen, sizeof(slen));
- target->append(str.c_str(), slen);
- return (sizeof(slen) + slen);
}
default:
break;
- };
+ }
+ uint32_t slen = str.size();
+ target->append(&slen, sizeof(slen));
+ target->append(str.peek(), slen);
+ return (sizeof(slen) + slen);
}
- /* FALLTHROUGH */
+ case RES_JSONSTRING:
case RES_XMLSTRING:
case RES_FEATUREDATA:
case RES_LONG_STRING:
@@ -222,7 +222,7 @@ SingleAttrDFW::insertField(uint32_t docid,
target.insertLong(val);
break;
}
- case RES_JSONSTRING: {
+ case RES_TENSOR: {
BasicType::Type t = v.getBasicType();
switch (t) {
case BasicType::TENSOR: {
@@ -230,17 +230,17 @@ SingleAttrDFW::insertField(uint32_t docid,
static_cast<const tensor::TensorAttribute &>(v);
const auto tensor = tv.getTensor(docid);
if (tensor) {
- vespalib::tensor::SlimeBinaryFormat::serialize(target, *tensor);
- } else {
- // No tensor value => no object
+ vespalib::nbostream str;
+ vespalib::tensor::TypedBinaryFormat::serialize(str, *tensor);
+ target.insertData(vespalib::slime::Memory(str.peek(), str.size()));
}
- return;
}
default:
- break;
- };
+ ;
+ }
}
- /* FALLTHROUGH */
+ break;
+ case RES_JSONSTRING:
case RES_XMLSTRING:
case RES_FEATUREDATA:
case RES_LONG_STRING:
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumfieldwriter.cpp b/searchsummary/src/vespa/searchsummary/docsummary/docsumfieldwriter.cpp
index be188e9a871..446ca347bff 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/docsumfieldwriter.cpp
+++ b/searchsummary/src/vespa/searchsummary/docsummary/docsumfieldwriter.cpp
@@ -164,6 +164,7 @@ CopyDFW::insertField(uint32_t /*docid*/,
target.insertString(value);
break; }
+ case RES_TENSOR:
case RES_LONG_DATA:
case RES_DATA: {
uint32_t len;
@@ -259,6 +260,7 @@ CopyDFW::WriteField(uint32_t docid,
break; }
+ case RES_TENSOR:
case RES_LONG_DATA: {
uint32_t flen = entry->_len;
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumformat.cpp b/searchsummary/src/vespa/searchsummary/docsummary/docsumformat.cpp
index a837fca3bdb..27b20f8b1bd 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/docsumformat.cpp
+++ b/searchsummary/src/vespa/searchsummary/docsummary/docsumformat.cpp
@@ -97,6 +97,7 @@ DocsumFormat::addEmpty(ResType type, search::RawBuf &target)
case RES_LONG_DATA:
case RES_XMLSTRING:
case RES_JSONSTRING:
+ case RES_TENSOR:
case RES_FEATUREDATA:
return addLongData(target, "", 0);
}
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp b/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp
index f790d38e70e..4273c89d7f5 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp
+++ b/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp
@@ -151,6 +151,7 @@ DynamicDocsumWriter::RepackDocsum(GeneralResult *gres,
written += slen;
break; }
+ case RES_TENSOR:
case RES_LONG_DATA: {
uint32_t flen = entry->_len;
uint32_t dlen = entry->_get_length();
@@ -304,6 +305,7 @@ static void convertEntry(GetDocsumsState *state,
inserter.insertString(Memory(ptr, len));
break;
case RES_DATA:
+ case RES_TENSOR:
case RES_LONG_DATA:
entry->_resolve_field(&ptr, &len, &state->_docSumFieldSpace);
inserter.insertData(Memory(ptr, len));
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultclass.h b/searchsummary/src/vespa/searchsummary/docsummary/resultclass.h
index e35408a796c..58a245a364a 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/resultclass.h
+++ b/searchsummary/src/vespa/searchsummary/docsummary/resultclass.h
@@ -31,6 +31,7 @@ enum ResType {
RES_LONG_DATA,
RES_XMLSTRING,
RES_JSONSTRING,
+ RES_TENSOR,
RES_FEATUREDATA
};
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp b/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp
index a08b0d11d5e..aa3029b9535 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp
+++ b/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp
@@ -55,6 +55,7 @@ ResultConfig::GetResTypeName(ResType type)
case RES_LONG_DATA: return "longdata";
case RES_XMLSTRING: return "xmlstring";
case RES_JSONSTRING: return "jsonstring";
+ case RES_TENSOR: return "tensor";
case RES_FEATUREDATA: return "featuredata";
}
return "unknown-type";
@@ -172,6 +173,8 @@ ResultConfig::ReadConfig(const vespa::config::search::SummaryConfig &cfg, const
rc = resClass->AddConfigEntry(fieldname, RES_XMLSTRING);
} else if (strcmp(fieldtype, "jsonstring") == 0) {
rc = resClass->AddConfigEntry(fieldname, RES_JSONSTRING);
+ } else if (strcmp(fieldtype, "tensor") == 0) {
+ rc = resClass->AddConfigEntry(fieldname, RES_TENSOR);
} else if (strcmp(fieldtype, "featuredata") == 0) {
rc = resClass->AddConfigEntry(fieldname, RES_FEATUREDATA);
} else { // FAIL: unknown field type
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h b/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h
index 7082a5636cc..4ae1b14e486 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h
+++ b/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h
@@ -164,6 +164,8 @@ public:
case RES_DATA:
case RES_LONG_DATA:
return (b == RES_DATA || b == RES_LONG_DATA);
+ case RES_TENSOR:
+ return (b == RES_TENSOR);
case RES_FEATUREDATA:
return (b == RES_FEATUREDATA);
}
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultpacker.cpp b/searchsummary/src/vespa/searchsummary/docsummary/resultpacker.cpp
index 83d504f2429..bda2f5c1b74 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/resultpacker.cpp
+++ b/searchsummary/src/vespa/searchsummary/docsummary/resultpacker.cpp
@@ -121,6 +121,7 @@ ResultPacker::AddEmpty()
case RES_JSONSTRING:
case RES_FEATUREDATA:
case RES_LONG_STRING: return AddLongString(NULL, 0);
+ case RES_TENSOR: return AddSerializedTensor(NULL, 0);
case RES_LONG_DATA: return AddLongData(NULL, 0);
}
}
@@ -251,6 +252,17 @@ ResultPacker::AddLongData(const char *buf, uint32_t buflen)
bool
+ResultPacker::AddSerializedTensor(const char *buf, uint32_t buflen)
+{
+ if (CheckEntry(RES_TENSOR)) {
+ _buf.append(&buflen, sizeof(buflen));
+ _buf.append(buf, buflen);
+ }
+ return !_error;
+}
+
+
+bool
ResultPacker::GetDocsumBlob(const char **buf, uint32_t *buflen)
{
if (!_error &&
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultpacker.h b/searchsummary/src/vespa/searchsummary/docsummary/resultpacker.h
index 8280ebe0980..634084fea6a 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/resultpacker.h
+++ b/searchsummary/src/vespa/searchsummary/docsummary/resultpacker.h
@@ -230,6 +230,14 @@ public:
**/
bool AddLongData(const char *buf, uint32_t buflen);
+ /*
+ * Add a 'tensor' field to the docsum blob we are currently creating.
+ *
+ * @return true(ok)/false(error).
+ * @param buf pointer to serialized tensor to add.
+ * @param buflen length of serialized tensor to add.
+ **/
+ bool AddSerializedTensor(const char *buf, uint32_t buflen);
/**
* Obtain a pointer to, and the length of, the created docsum
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/urlresult.cpp b/searchsummary/src/vespa/searchsummary/docsummary/urlresult.cpp
index 92ebe07d457..47cc0cf3a33 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/urlresult.cpp
+++ b/searchsummary/src/vespa/searchsummary/docsummary/urlresult.cpp
@@ -419,6 +419,7 @@ GeneralResult::unpack(const char *buf, const size_t buflen)
break;
}
+ case RES_TENSOR:
case RES_LONG_DATA: {
uint32_t ldlen;