summaryrefslogtreecommitdiffstats
path: root/searchcore
diff options
context:
space:
mode:
authorGeir Storli <geirstorli@yahoo.no>2017-03-29 09:39:35 +0200
committerGitHub <noreply@github.com>2017-03-29 09:39:35 +0200
commitc9adfe2b0d35a9b02cf696e52b2764bd14250c9f (patch)
treead45bf6aa86a5c0db1d244ead31daa7f35ca010b /searchcore
parent8eb463eecb16219f30915dca88aa2d0ddf101876 (diff)
parentf652d55b1058a8bdd0ae8ecda6f330561ea91bb3 (diff)
Merge pull request #2075 from yahoo/toregge/flush-populated-attributes-to-disk
Flush populated attributes to disk as part of reprocessing.
Diffstat (limited to 'searchcore')
-rw-r--r--searchcore/CMakeLists.txt1
-rw-r--r--searchcore/src/tests/proton/attribute/attribute_initializer/CMakeLists.txt9
-rw-r--r--searchcore/src/tests/proton/attribute/attribute_initializer/DESC1
-rw-r--r--searchcore/src/tests/proton/attribute/attribute_initializer/FILES1
-rw-r--r--searchcore/src/tests/proton/attribute/attribute_initializer/attribute_initializer_test.cpp182
-rw-r--r--searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp61
-rw-r--r--searchcore/src/tests/proton/attribute/attribute_populator/attribute_populator_test.cpp4
-rw-r--r--searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp27
-rw-r--r--searchcore/src/tests/proton/reprocessing/document_reprocessing_handler/document_reprocessing_handler_test.cpp1
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.cpp116
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.h15
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.cpp19
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.h7
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp33
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp35
-rw-r--r--searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.cpp2
-rw-r--r--searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.h1
-rw-r--r--searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.cpp11
-rw-r--r--searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.h6
-rw-r--r--searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp18
-rw-r--r--searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.h3
-rw-r--r--searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.cpp8
-rw-r--r--searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.h1
-rw-r--r--searchcore/src/vespa/searchcore/proton/reprocessing/i_reprocessing_reader.h1
-rw-r--r--searchcore/src/vespa/searchcore/proton/reprocessing/reprocess_documents_task.cpp1
-rw-r--r--searchcore/src/vespa/searchcore/proton/server/fast_access_doc_subdb_configurer.cpp2
-rw-r--r--searchcore/src/vespa/searchcore/proton/server/searchable_doc_subdb_configurer.cpp7
27 files changed, 483 insertions, 90 deletions
diff --git a/searchcore/CMakeLists.txt b/searchcore/CMakeLists.txt
index 7c96a567f55..d7edca0ac35 100644
--- a/searchcore/CMakeLists.txt
+++ b/searchcore/CMakeLists.txt
@@ -62,6 +62,7 @@ vespa_define_module(
src/tests/grouping
src/tests/proton/attribute
src/tests/proton/attribute/attribute_directory
+ src/tests/proton/attribute/attribute_initializer
src/tests/proton/attribute/attribute_manager
src/tests/proton/attribute/attribute_populator
src/tests/proton/attribute/attribute_usage_filter
diff --git a/searchcore/src/tests/proton/attribute/attribute_initializer/CMakeLists.txt b/searchcore/src/tests/proton/attribute/attribute_initializer/CMakeLists.txt
new file mode 100644
index 00000000000..ad1383f6247
--- /dev/null
+++ b/searchcore/src/tests/proton/attribute/attribute_initializer/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(searchcore_attribute_initializer_test_app TEST
+ SOURCES
+ attribute_initializer_test.cpp
+ DEPENDS
+ searchcore_attribute
+ searchcore_pcommon
+)
+vespa_add_test(NAME searchcore_attribute_initializer_test_app COMMAND searchcore_attribute_initializer_test_app)
diff --git a/searchcore/src/tests/proton/attribute/attribute_initializer/DESC b/searchcore/src/tests/proton/attribute/attribute_initializer/DESC
new file mode 100644
index 00000000000..d7e2c61d85d
--- /dev/null
+++ b/searchcore/src/tests/proton/attribute/attribute_initializer/DESC
@@ -0,0 +1 @@
+attribute initializer test. Take a look at attribute_initializer_test.cpp for details.
diff --git a/searchcore/src/tests/proton/attribute/attribute_initializer/FILES b/searchcore/src/tests/proton/attribute/attribute_initializer/FILES
new file mode 100644
index 00000000000..cedbcb0155b
--- /dev/null
+++ b/searchcore/src/tests/proton/attribute/attribute_initializer/FILES
@@ -0,0 +1 @@
+attribute_initializer_test.cpp
diff --git a/searchcore/src/tests/proton/attribute/attribute_initializer/attribute_initializer_test.cpp b/searchcore/src/tests/proton/attribute/attribute_initializer/attribute_initializer_test.cpp
new file mode 100644
index 00000000000..37ef21fb700
--- /dev/null
+++ b/searchcore/src/tests/proton/attribute/attribute_initializer/attribute_initializer_test.cpp
@@ -0,0 +1,182 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("attribute_initializer_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/stllike/string.h>
+#include <vespa/searchcore/proton/test/directory_handler.h>
+#include <vespa/searchlib/attribute/attributefactory.h>
+#include <vespa/searchcore/proton/test/attribute_utils.h>
+#include <vespa/searchcore/proton/attribute/attributedisklayout.h>
+#include <vespa/searchcore/proton/attribute/attribute_directory.h>
+#include <vespa/searchcore/proton/attribute/attribute_factory.h>
+#include <vespa/searchcore/proton/attribute/attribute_initializer.h>
+
+using search::attribute::Config;
+using search::attribute::BasicType;
+using search::attribute::CollectionType;
+using search::SerialNum;
+
+const vespalib::string test_dir = "test_output";
+
+namespace proton
+{
+
+namespace {
+
+const Config int32_sv(BasicType::Type::INT32);
+const Config int16_sv(BasicType::Type::INT16);
+const Config int32_array(BasicType::Type::INT32, CollectionType::Type::ARRAY);
+const Config predicate(BasicType::Type::PREDICATE);
+
+Config getPredicateWithArity(uint32_t arity)
+{
+ Config ret(predicate);
+ search::attribute::PredicateParams predicateParams;
+ predicateParams.setArity(arity);
+ ret.setPredicateParams(predicateParams);
+ return ret;
+}
+
+Config getTensor(const vespalib::string &spec)
+{
+ Config ret(BasicType::Type::TENSOR);
+ ret.setTensorType(vespalib::eval::ValueType::from_spec(spec));
+ return ret;
+}
+
+void
+saveAttr(const vespalib::string &name, const Config &cfg, SerialNum serialNum, SerialNum createSerialNum)
+{
+ auto diskLayout = AttributeDiskLayout::create(test_dir);
+ auto dir = diskLayout->createAttributeDir(name);
+ auto writer = dir->getWriter();
+ writer->createInvalidSnapshot(serialNum);
+ auto snapshotdir = writer->getSnapshotDir(serialNum);
+ vespalib::mkdir(snapshotdir);
+ auto av = search::AttributeFactory::createAttribute(snapshotdir + "/" + name, cfg);
+ av->setCreateSerialNum(createSerialNum);
+ av->addReservedDoc();
+ uint32_t docId;
+ av->addDoc(docId);
+ assert(docId == 1u);
+ av->clearDoc(docId);
+ av->save();
+ writer->markValidSnapshot(serialNum);
+}
+
+}
+
+struct Fixture
+{
+ test::DirectoryHandler _dirHandler;
+ std::shared_ptr<AttributeDiskLayout> _diskLayout;
+ AttributeFactory _factory;
+ Fixture();
+ ~Fixture();
+ std::unique_ptr<AttributeInitializer> createInitializer(const vespalib::string &name, const Config &cfg, SerialNum serialNum);
+};
+
+Fixture::Fixture()
+ : _dirHandler(test_dir),
+ _diskLayout(AttributeDiskLayout::create(test_dir)),
+ _factory()
+{
+}
+
+Fixture::~Fixture() {}
+
+std::unique_ptr<AttributeInitializer>
+Fixture::createInitializer(const vespalib::string &name, const Config &cfg, SerialNum serialNum)
+{
+ return std::make_unique<AttributeInitializer>(_diskLayout->createAttributeDir(name), "test.subdb", cfg, serialNum, _factory);
+}
+
+TEST("require that integer attribute can be initialized")
+{
+ saveAttr("a", int32_sv, 10, 2);
+ Fixture f;
+ auto av = f.createInitializer("a", int32_sv, 5)->init();
+ EXPECT_EQUAL(2, av->getCreateSerialNum());
+ EXPECT_EQUAL(2, av->getNumDocs());
+}
+
+TEST("require that mismatching base type is not loaded")
+{
+ saveAttr("a", int32_sv, 10, 2);
+ Fixture f;
+ auto av = f.createInitializer("a", int16_sv, 5)->init();
+ EXPECT_EQUAL(5, av->getCreateSerialNum());
+ EXPECT_EQUAL(1, av->getNumDocs());
+}
+
+TEST("require that mismatching collection type is not loaded")
+{
+ saveAttr("a", int32_sv, 10, 2);
+ Fixture f;
+ auto av = f.createInitializer("a", int32_array, 5)->init();
+ EXPECT_EQUAL(5, av->getCreateSerialNum());
+ EXPECT_EQUAL(1, av->getNumDocs());
+}
+
+TEST("require that predicate attributes can be initialized")
+{
+ saveAttr("a", predicate, 10, 2);
+ Fixture f;
+ auto av = f.createInitializer("a", predicate, 5)->init();
+ EXPECT_EQUAL(2, av->getCreateSerialNum());
+ EXPECT_EQUAL(2, av->getNumDocs());
+}
+
+TEST("require that predicate attributes will not be initialized with future-created attribute")
+{
+ saveAttr("a", predicate, 10, 8);
+ Fixture f;
+ auto av = f.createInitializer("a", predicate, 5)->init();
+ EXPECT_EQUAL(5, av->getCreateSerialNum());
+ EXPECT_EQUAL(1, av->getNumDocs());
+}
+
+TEST("require that predicate attributes will not be initialized with mismatching type")
+{
+ saveAttr("a", predicate, 10, 2);
+ Fixture f;
+ auto av = f.createInitializer("a", getPredicateWithArity(4), 5)->init();
+ EXPECT_EQUAL(5, av->getCreateSerialNum());
+ EXPECT_EQUAL(1, av->getNumDocs());
+}
+
+TEST("require that tensor attribute can be initialized")
+{
+ saveAttr("a", getTensor("tensor(x[10])"), 10, 2);
+ Fixture f;
+ auto av = f.createInitializer("a", getTensor("tensor(x[10])"), 5)->init();
+ EXPECT_EQUAL(2, av->getCreateSerialNum());
+ EXPECT_EQUAL(2, av->getNumDocs());
+}
+
+TEST("require that tensor attributes will not be initialized with future-created attribute")
+{
+ saveAttr("a", getTensor("tensor(x[10])"), 10, 8);
+ Fixture f;
+ auto av = f.createInitializer("a", getTensor("tensor(x[10])"), 5)->init();
+ EXPECT_EQUAL(5, av->getCreateSerialNum());
+ EXPECT_EQUAL(1, av->getNumDocs());
+}
+
+TEST("require that tensor attributes will not be initialized with mismatching type")
+{
+ saveAttr("a", getTensor("tensor(x[10])"), 10, 2);
+ Fixture f;
+ auto av = f.createInitializer("a", getTensor("tensor(x[11])"), 5)->init();
+ EXPECT_EQUAL(5, av->getCreateSerialNum());
+ EXPECT_EQUAL(1, av->getNumDocs());
+}
+
+}
+
+TEST_MAIN()
+{
+ vespalib::rmdir(test_dir, true);
+ TEST_RUN_ALL();
+}
diff --git a/searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp b/searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp
index a030c65954d..7232f997b0e 100644
--- a/searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp
+++ b/searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp
@@ -61,6 +61,7 @@ using search::predicate::PredicateIndex;
using search::predicate::PredicateTreeAnnotations;
using vespa::config::search::AttributesConfig;
using vespa::config::search::AttributesConfigBuilder;
+using vespalib::eval::ValueType;
typedef search::attribute::Config AVConfig;
typedef proton::AttributeCollectionSpec::Attribute AttrSpec;
@@ -111,6 +112,19 @@ fillAttribute(const AttributeVector::SP &attr, uint32_t from, uint32_t to, int64
test::AttributeUtils::fillAttribute(attr, from, to, value, lastSyncToken);
}
+search::SerialNum getCreateSerialNum(const AttributeGuard::UP &guard)
+{
+ if (!guard || !guard->valid()) {
+ return 0;
+ } else {
+ return (*guard)->getCreateSerialNum();
+ }
+}
+
+void assertCreateSerialNum(const AttributeManager &am, const vespalib::string &name, search::SerialNum expCreateSerialNum) {
+ EXPECT_EQUAL(expCreateSerialNum, getCreateSerialNum(am.getAttribute(name)));
+}
+
struct ImportedAttributesRepoBuilder {
ImportedAttributesRepo::UP _repo;
ImportedAttributesRepoBuilder() : _repo(std::make_unique<ImportedAttributesRepo>()) {}
@@ -740,6 +754,53 @@ TEST_F("require that imported attributes are exposed via attribute context toget
EXPECT_EQUAL("imported", all[1]->getName());
}
+TEST_F("require that attribute vector of wrong type is dropped", BaseFixture)
+{
+ AVConfig generic_tensor(BasicType::TENSOR);
+ generic_tensor.setTensorType(ValueType::tensor_type({}));
+ AVConfig dense_tensor(BasicType::TENSOR);
+ dense_tensor.setTensorType(ValueType::from_spec("tensor(x[10])"));
+ AVConfig predicate(BasicType::PREDICATE);
+ using PredicateParams = search::attribute::PredicateParams;
+ PredicateParams predicateParams;
+ predicateParams.setArity(2);
+ predicate.setPredicateParams(predicateParams);
+ AVConfig predicate2(BasicType::PREDICATE);
+ PredicateParams predicateParams2;
+ predicateParams2.setArity(4);
+ predicate2.setPredicateParams(predicateParams2);
+
+ auto am1(std::make_shared<proton::AttributeManager>
+ (test_dir, "test.subdb", TuneFileAttributes(),
+ f._fileHeaderContext, f._attributeFieldWriter, f._hwInfo));
+ am1->addAttribute("a1", INT32_SINGLE, 1);
+ am1->addAttribute("a2", INT32_SINGLE, 2);
+ am1->addAttribute("a3", generic_tensor, 3);
+ am1->addAttribute("a4", generic_tensor, 4);
+ am1->addAttribute("a5", predicate, 5);
+ am1->addAttribute("a6", predicate, 6);
+ AttrSpecList newSpec;
+ newSpec.push_back(AttrSpec("a1", INT32_SINGLE));
+ newSpec.push_back(AttrSpec("a2", INT32_ARRAY));
+ newSpec.push_back(AttrSpec("a3", generic_tensor));
+ newSpec.push_back(AttrSpec("a4", dense_tensor));
+ newSpec.push_back(AttrSpec("a5", predicate));
+ newSpec.push_back(AttrSpec("a6", predicate2));
+ SequentialAttributeManager am2(*am1, AttrMgrSpec(newSpec, 5, 20));
+ TEST_DO(assertCreateSerialNum(*am1, "a1", 1));
+ TEST_DO(assertCreateSerialNum(*am1, "a2", 2));
+ TEST_DO(assertCreateSerialNum(*am1, "a3", 3));
+ TEST_DO(assertCreateSerialNum(*am1, "a4", 4));
+ TEST_DO(assertCreateSerialNum(*am1, "a5", 5));
+ TEST_DO(assertCreateSerialNum(*am1, "a6", 6));
+ TEST_DO(assertCreateSerialNum(am2.mgr, "a1", 1));
+ TEST_DO(assertCreateSerialNum(am2.mgr, "a2", 20));
+ TEST_DO(assertCreateSerialNum(am2.mgr, "a3", 3));
+ TEST_DO(assertCreateSerialNum(am2.mgr, "a4", 20));
+ TEST_DO(assertCreateSerialNum(am2.mgr, "a5", 5));
+ TEST_DO(assertCreateSerialNum(am2.mgr, "a6", 20));
+}
+
TEST_MAIN()
{
vespalib::rmdir(test_dir, true);
diff --git a/searchcore/src/tests/proton/attribute/attribute_populator/attribute_populator_test.cpp b/searchcore/src/tests/proton/attribute/attribute_populator/attribute_populator_test.cpp
index e28dd24a454..19bfedfcd31 100644
--- a/searchcore/src/tests/proton/attribute/attribute_populator/attribute_populator_test.cpp
+++ b/searchcore/src/tests/proton/attribute/attribute_populator/attribute_populator_test.cpp
@@ -68,7 +68,7 @@ struct Fixture
_mgr(new AttributeManager(TEST_DIR, "test.subdb",
TuneFileAttributes(),
_fileHeader, _attributeFieldWriter, _hwInfo)),
- _pop(_mgr, 1, "test"),
+ _pop(_mgr, 1, "test", CREATE_SERIAL_NUM),
_ctx()
{
_mgr->addAttribute("a1", AVConfig(AVBasicType::INT32),
@@ -93,6 +93,8 @@ TEST_F("require that reprocess with document populates attribute", Fixture)
EXPECT_EQUAL(7u, attr->get()->getNumDocs());
EXPECT_EQUAL(44, attr->get()->getInt(6));
EXPECT_EQUAL(2u, attr->get()->getStatus().getLastSyncToken());
+ f._pop.done();
+ EXPECT_EQUAL(CREATE_SERIAL_NUM, attr->get()->getStatus().getLastSyncToken());
}
TEST_MAIN()
diff --git a/searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp b/searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp
index 36319ae77d5..f560030db97 100644
--- a/searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp
+++ b/searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp
@@ -5,12 +5,15 @@ LOG_SETUP("attribute_reprocessing_initializer_test");
#include <vespa/searchcore/proton/attribute/attribute_populator.h>
#include <vespa/searchcore/proton/attribute/attributemanager.h>
+#include <vespa/searchcore/proton/attribute/attributedisklayout.h>
+#include <vespa/searchcore/proton/attribute/attribute_directory.h>
#include <vespa/searchcore/proton/attribute/document_field_populator.h>
#include <vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.h>
#include <vespa/searchcore/proton/reprocessing/i_reprocessing_handler.h>
#include <vespa/searchcore/proton/test/attribute_utils.h>
#include <vespa/searchcore/proton/test/directory_handler.h>
#include <vespa/searchlib/index/dummyfileheadercontext.h>
+#include <vespa/searchlib/attribute/attributefactory.h>
#include <vespa/vespalib/test/insertion_operators.h>
#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/searchcore/proton/common/hw_info.h>
@@ -19,6 +22,8 @@ LOG_SETUP("attribute_reprocessing_initializer_test");
using namespace proton;
using namespace search;
using namespace search::index;
+using search::attribute::Config;
+using search::attribute::BasicType;
const vespalib::string TEST_DIR = "test_output";
const SerialNum INIT_SERIAL_NUM = 10;
@@ -118,10 +123,11 @@ struct Fixture
_handler()
{
}
+ ~Fixture() { }
void init() {
_initializer.reset(new AttributeReprocessingInitializer
(ARIConfig(_newCfg._mgr, _newCfg._schema, _newCfg._inspector),
- ARIConfig(_oldCfg._mgr, _oldCfg._schema, _oldCfg._inspector), "test"));
+ ARIConfig(_oldCfg._mgr, _oldCfg._schema, _oldCfg._inspector), "test", INIT_SERIAL_NUM));
_initializer->initialize(_handler);
}
Fixture &addOldConfig(const StringVector &fields,
@@ -249,6 +255,25 @@ TEST_F("require that predicate fields are not populated from attribute", Fixture
EXPECT_TRUE(f.assertFields({"c", "d"}));
}
+TEST("require that added attribute aspect with flushed attribute after interruptted reprocessing does not require attribute populate")
+{
+ {
+ auto diskLayout = AttributeDiskLayout::create(TEST_DIR);
+ auto dir = diskLayout->createAttributeDir("a");
+ auto writer = dir->getWriter();
+ writer->createInvalidSnapshot(INIT_SERIAL_NUM);
+ writer->markValidSnapshot(INIT_SERIAL_NUM);
+ auto snapshotdir = writer->getSnapshotDir(INIT_SERIAL_NUM);
+ vespalib::mkdir(snapshotdir);
+ auto av = AttributeFactory::createAttribute(snapshotdir + "/a",
+ Config(BasicType::STRING));
+ av->save();
+ }
+ Fixture f;
+ f.addOldConfig({"a"}, {}).addNewConfig({"a"}, {"a"}).init();
+ EXPECT_TRUE(f.assertAttributes({}));
+}
+
TEST_MAIN()
{
TEST_RUN_ALL();
diff --git a/searchcore/src/tests/proton/reprocessing/document_reprocessing_handler/document_reprocessing_handler_test.cpp b/searchcore/src/tests/proton/reprocessing/document_reprocessing_handler/document_reprocessing_handler_test.cpp
index 483c1c3b977..1848ad8fc74 100644
--- a/searchcore/src/tests/proton/reprocessing/document_reprocessing_handler/document_reprocessing_handler_test.cpp
+++ b/searchcore/src/tests/proton/reprocessing/document_reprocessing_handler/document_reprocessing_handler_test.cpp
@@ -23,6 +23,7 @@ struct MyProcessor : public ReprocessingType
_lid = lid;
_docId = doc.getId();
}
+ virtual void done() { }
};
typedef MyProcessor<IReprocessingReader, const Document &> MyReader;
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.cpp
index 1b998646a25..7a23db1a071 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.cpp
+++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.cpp
@@ -7,64 +7,86 @@
#include <vespa/vespalib/data/fileheader.h>
#include <vespa/vespalib/io/fileutil.h>
#include <vespa/searchlib/util/fileutil.h>
+#include <vespa/searchlib/attribute/attribute_header.h>
#include <vespa/fastos/file.h>
#include <vespa/log/log.h>
LOG_SETUP(".proton.attribute.attribute_initializer");
+using search::attribute::BasicType;
using search::attribute::Config;
using search::AttributeVector;
using search::IndexMetaInfo;
namespace proton {
-typedef AttributeInitializer::AttributeHeader AttributeHeader;
+using search::attribute::AttributeHeader;
namespace {
-const vespalib::string dataTypeTag = "datatype";
-const vespalib::string collectionTypeTag = "collectiontype";
-const vespalib::string createSerialNumTag = "createSerialNum";
+vespalib::string
+extraPredicateType(const search::attribute::PersistentPredicateParams &params)
+{
+ vespalib::asciistream os;
+ os << "arity=" << params.arity();
+ os << ",lower_bound=" << params.lower_bound();
+ os << ",upper_bound=" << params.upper_bound();
+ return os.str();
+}
-uint64_t
-extractCreateSerialNum(const vespalib::GenericHeader &header)
+vespalib::string
+extraType(const Config &cfg)
{
- if (header.hasTag(createSerialNumTag)) {
- return header.getTag(createSerialNumTag).asInteger();
- } else {
- return 0u;
+ if (cfg.basicType().type() == BasicType::Type::TENSOR) {
+ return cfg.tensorType().to_spec();
+ }
+ if (cfg.basicType().type() == BasicType::Type::PREDICATE) {
+ return extraPredicateType(cfg.predicateParams());
+ }
+ return "";
+}
+
+vespalib::string
+extraType(const AttributeHeader &header)
+{
+ if (header.getBasicType().type() == BasicType::Type::TENSOR) {
+ return header.getTensorType().to_spec();
+ }
+ if (header.getBasicType().type() == BasicType::Type::PREDICATE) {
+ return extraPredicateType(header.getPredicateParams());
}
+ return "";
}
bool
-extractHeaderTypeOK(const vespalib::GenericHeader &header, const Config &cfg)
+headerTypeOK(const AttributeHeader &header, const Config &cfg)
{
- return header.hasTag(dataTypeTag) &&
- header.hasTag(collectionTypeTag) &&
- header.getTag(dataTypeTag).asString() ==
- cfg.basicType().asString() &&
- header.getTag(collectionTypeTag).asString() ==
- cfg.collectionType().asString();
+ if ((header.getBasicType().type() != cfg.basicType().type()) ||
+ (header.getCollectionType().type() != cfg.collectionType().type())) {
+ return false;
+ }
+ if (cfg.basicType().type() == BasicType::Type::TENSOR) {
+ if (header.getTensorType() != cfg.tensorType()) {
+ return false;
+ }
+ }
+ if (cfg.basicType().type() == BasicType::PREDICATE) {
+ if (header.getPredicateParamsSet()) {
+ if (!(header.getPredicateParams() == cfg.predicateParams())) {
+ return false;
+ }
+ }
+ }
+ return true;
}
AttributeHeader
-extractHeader(const AttributeVector::SP &attr,
- const vespalib::string &attrFileName)
+extractHeader(const vespalib::string &attrFileName)
{
-
auto df = search::FileUtil::openFile(attrFileName + ".dat");
vespalib::FileHeader datHeader;
datHeader.readFile(*df);
- AttributeHeader retval;
- retval._createSerialNum = extractCreateSerialNum(datHeader);
- retval._headerTypeOK = extractHeaderTypeOK(datHeader, attr->getConfig());
- if (datHeader.hasTag(dataTypeTag)) {
- retval._btString = datHeader.getTag(dataTypeTag).asString();
- }
- if (datHeader.hasTag(collectionTypeTag)) {
- retval._ctString = datHeader.getTag(collectionTypeTag).asString();
- }
- return retval;
+ return AttributeHeader::extractTags(datHeader);
}
void
@@ -73,9 +95,9 @@ logAttributeTooNew(const AttributeVector::SP &attr,
uint64_t serialNum)
{
LOG(info, "Attribute vector '%s' is too new (%" PRIu64 " > %" PRIu64 ")",
- attr->getBaseFileName().c_str(),
- header._createSerialNum,
- serialNum);
+ attr->getBaseFileName().c_str(),
+ header.getCreateSerialNum(),
+ serialNum);
}
void
@@ -83,26 +105,20 @@ logAttributeWrongType(const AttributeVector::SP &attr,
const AttributeHeader &header)
{
const Config &cfg(attr->getConfig());
- LOG(info, "Attribute vector '%s' is of wrong type (expected %s/%s, got %s/%s)",
+ vespalib::string extraCfgType = extraType(cfg);
+ vespalib::string extraHeaderType = extraType(header);
+ LOG(info, "Attribute vector '%s' is of wrong type (expected %s/%s/%s, got %s/%s/%s)",
attr->getBaseFileName().c_str(),
cfg.basicType().asString(),
cfg.collectionType().asString(),
- header._btString.c_str(),
- header._ctString.c_str());
-}
-
+ extraCfgType.c_str(),
+ header.getBasicType().asString(),
+ header.getCollectionType().asString(),
+ extraHeaderType.c_str());
}
-AttributeInitializer::AttributeHeader::AttributeHeader()
- : _createSerialNum(0),
- _headerTypeOK(false),
- _btString("unknown"),
- _ctString("unknown")
-{
}
-AttributeInitializer::AttributeHeader::~AttributeHeader() {}
-
AttributeVector::SP
AttributeInitializer::tryLoadAttribute() const
{
@@ -110,8 +126,8 @@ AttributeInitializer::tryLoadAttribute() const
vespalib::string attrFileName = _attrDir->getAttributeFileName(serialNum);
AttributeVector::SP attr = _factory.create(attrFileName, _cfg);
if (serialNum != 0) {
- AttributeHeader header = extractHeader(attr, attrFileName);
- if (header._createSerialNum > _currentSerialNum || !header._headerTypeOK) {
+ AttributeHeader header = extractHeader(attrFileName);
+ if (header.getCreateSerialNum() > _currentSerialNum || !headerTypeOK(header, attr->getConfig())) {
setupEmptyAttribute(attr, serialNum, header);
return attr;
}
@@ -150,10 +166,10 @@ AttributeInitializer::setupEmptyAttribute(AttributeVector::SP &attr,
search::SerialNum serialNum,
const AttributeHeader &header) const
{
- if (header._createSerialNum > _currentSerialNum) {
+ if (header.getCreateSerialNum() > _currentSerialNum) {
logAttributeTooNew(attr, header, _currentSerialNum);
}
- if (!header._headerTypeOK) {
+ if (!headerTypeOK(header, attr->getConfig())) {
logAttributeWrongType(attr, header);
}
LOG(info, "Returning empty attribute vector for '%s'",
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.h b/searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.h
index d396c663710..8643fd4c7df 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.h
+++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_initializer.h
@@ -6,6 +6,9 @@
#include <vespa/searchlib/attribute/attributevector.h>
#include <vespa/vespalib/stllike/string.h>
#include <vespa/searchlib/common/serialnum.h>
+#include <vespa/searchcommon/attribute/persistent_predicate_params.h>
+
+namespace search { namespace attribute { class AttributeHeader; } }
namespace proton {
@@ -19,16 +22,6 @@ class AttributeInitializer
public:
typedef std::unique_ptr<AttributeInitializer> UP;
- struct AttributeHeader
- {
- uint64_t _createSerialNum;
- bool _headerTypeOK;
- vespalib::string _btString;
- vespalib::string _ctString;
- AttributeHeader();
- ~AttributeHeader();
- };
-
private:
std::shared_ptr<AttributeDirectory> _attrDir;
const vespalib::string _documentSubDbName;
@@ -43,7 +36,7 @@ private:
void setupEmptyAttribute(search::AttributeVector::SP &attr,
search::SerialNum serialNum,
- const AttributeHeader &header) const;
+ const search::attribute::AttributeHeader &header) const;
search::AttributeVector::SP createAndSetupEmptyAttribute() const;
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.cpp
index 226a79b6d49..dadf5d41912 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.cpp
+++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.cpp
@@ -15,6 +15,7 @@ namespace proton {
search::SerialNum
AttributePopulator::nextSerialNum()
{
+ assert(_currSerialNum <= _configSerialNum);
return _currSerialNum++;
}
@@ -32,10 +33,12 @@ AttributePopulator::getNames() const
AttributePopulator::AttributePopulator(const proton::IAttributeManager::SP &mgr,
search::SerialNum initSerialNum,
- const vespalib::string &subDbName)
+ const vespalib::string &subDbName,
+ search::SerialNum configSerialNum)
: _writer(mgr),
_initSerialNum(initSerialNum),
_currSerialNum(initSerialNum),
+ _configSerialNum(configSerialNum),
_subDbName(subDbName)
{
if (LOG_WOULD_LOG(event)) {
@@ -58,4 +61,18 @@ AttributePopulator::handleExisting(uint32_t lid, const document::Document &doc)
_writer.put(serialNum, doc, lid, true, std::shared_ptr<IDestructorCallback>());
}
+void
+AttributePopulator::done()
+{
+ auto mgr = _writer.getAttributeManager();
+ auto flushTargets = mgr->getFlushTargets();
+ for (const auto &flushTarget : flushTargets) {
+ assert(flushTarget->getFlushedSerialNum() < _configSerialNum);
+ auto task = flushTarget->initFlush(_configSerialNum);
+ assert(task);
+ task->run();
+ assert(flushTarget->getFlushedSerialNum() == _configSerialNum);
+ }
+}
+
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.h b/searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.h
index b6c53af6bac..e918499fb5b 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.h
+++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_populator.h
@@ -16,6 +16,7 @@ private:
AttributeWriter _writer;
search::SerialNum _initSerialNum;
search::SerialNum _currSerialNum;
+ search::SerialNum _configSerialNum;
vespalib::string _subDbName;
search::SerialNum nextSerialNum();
@@ -27,13 +28,15 @@ public:
AttributePopulator(const proton::IAttributeManager::SP &mgr,
search::SerialNum initSerialNum,
- const vespalib::string &subDbName);
+ const vespalib::string &subDbName,
+ search::SerialNum configSerialNum);
~AttributePopulator();
const IAttributeWriter &getWriter() const { return _writer; }
// Implements IReprocessingReader
- virtual void handleExisting(uint32_t lid, const document::Document &doc);
+ virtual void handleExisting(uint32_t lid, const document::Document &doc) override;
+ virtual void done() override;
};
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp
index 6ddd018c179..fa4f9258e36 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp
+++ b/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp
@@ -27,9 +27,40 @@ using search::attribute::IAttributeContext;
using search::attribute::IAttributeVector;
using search::common::FileHeaderContext;
using search::index::Schema;
+using search::attribute::BasicType;
namespace proton {
+namespace {
+
+bool matchingTypes(const AttributeVector::SP &av, const search::attribute::Config &newConfig) {
+ if (av) {
+ const auto &oldConfig = av->getConfig();
+ if ((oldConfig.basicType() != newConfig.basicType()) ||
+ (oldConfig.collectionType() != newConfig.collectionType())) {
+ return false;
+ }
+ if (newConfig.basicType().type() == BasicType::TENSOR) {
+ if (oldConfig.tensorType() != newConfig.tensorType()) {
+ return false;
+ }
+ }
+ if (newConfig.basicType().type() == BasicType::PREDICATE) {
+ using Params = search::attribute::PersistentPredicateParams;
+ const Params &oldParams = oldConfig.predicateParams();
+ const Params &newParams = newConfig.predicateParams();
+ if (!(oldParams == newParams)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+}
+
AttributeVector::SP
AttributeManager::internalAddAttribute(const vespalib::string &name,
const Config &cfg,
@@ -86,7 +117,7 @@ AttributeManager::transferExistingAttributes(const AttributeManager &currMgr,
{
for (const auto &aspec : newSpec.getAttributes()) {
AttributeVector::SP av = currMgr.findAttribute(aspec.getName());
- if (av.get() != NULL) { // transfer attribute
+ if (matchingTypes(av, aspec.getConfig())) { // transfer attribute
LOG(debug, "Transferring attribute vector '%s' with %u docs and serial number %lu from current manager",
av->getName().c_str(), av->getNumDocs(), av->getStatus().getLastSyncToken());
addAttribute(av);
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp b/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp
index d6540331345..2610f243612 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp
+++ b/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp
@@ -6,9 +6,30 @@
#include <vespa/vespalib/util/exceptions.h>
using search::AttributeGuard;
+using searchcorespi::IFlushTarget;
namespace proton {
+namespace {
+
+const vespalib::string FLUSH_TARGET_NAME_PREFIX("attribute.");
+
+bool isAttributeFlushTarget(const IFlushTarget::SP &flushTarget) {
+ const vespalib::string &targetName = flushTarget->getName();
+ if ((flushTarget->getType() != IFlushTarget::Type::SYNC) ||
+ (flushTarget->getComponent() != IFlushTarget::Component::ATTRIBUTE)) {
+ return false;
+ }
+ return (targetName.substr(0, FLUSH_TARGET_NAME_PREFIX.size()) == FLUSH_TARGET_NAME_PREFIX);
+}
+
+vespalib::string attributeFlushTargetAttributeName(const IFlushTarget::SP &flushTarget) {
+ const vespalib::string &targetName = flushTarget->getName();
+ return targetName.substr(FLUSH_TARGET_NAME_PREFIX.size());
+}
+
+}
+
bool
FilterAttributeManager::acceptAttribute(const vespalib::string &name) const
{
@@ -43,10 +64,22 @@ IAttributeManager::SP
FilterAttributeManager::create(const AttributeCollectionSpec &) const {
throw vespalib::IllegalArgumentException("Not implemented");
}
+
std::vector<searchcorespi::IFlushTarget::SP>
FilterAttributeManager::getFlushTargets() const {
- throw vespalib::IllegalArgumentException("Not implemented");
+ std::vector<searchcorespi::IFlushTarget::SP> completeList = _mgr->getFlushTargets();
+ std::vector<searchcorespi::IFlushTarget::SP> list;
+ list.reserve(completeList.size());
+ for (const auto &flushTarget : completeList) {
+ if (isAttributeFlushTarget(flushTarget)) {
+ if (acceptAttribute(attributeFlushTargetAttributeName(flushTarget))) {
+ list.push_back(flushTarget);
+ }
+ }
+ }
+ return list;
}
+
search::SerialNum
FilterAttributeManager::getOldestFlushedSerialNumber() const {
throw vespalib::IllegalArgumentException("Not implemented");
diff --git a/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.cpp b/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.cpp
index 5fc4dceea7a..209d2cf07f3 100644
--- a/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.cpp
+++ b/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.cpp
@@ -235,7 +235,7 @@ DocumentMetaStore::onInitSave()
{
GenerationHandler::Guard guard(getGuard());
return std::make_unique<DocumentMetaStoreSaver>
- (std::move(guard), createSaveTargetConfig(),
+ (std::move(guard), createAttributeHeader(),
_gidToLidMap.getFrozenView().begin(), _metaDataStore);
}
diff --git a/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.h b/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.h
index 789706503cf..200535c7ae5 100644
--- a/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.h
+++ b/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastore.h
@@ -12,7 +12,6 @@
#include "raw_document_meta_data.h"
#include <vespa/searchcore/proton/bucketdb/bucket_db_owner.h>
#include <vespa/searchcore/proton/common/subdbtype.h>
-#include <vespa/searchlib/attribute/iattributesavetarget.h>
#include <vespa/searchlib/common/rcuvector.h>
#include <vespa/searchlib/attribute/singlesmallnumericattribute.h>
#include <vespa/searchlib/queryeval/blueprint.h>
diff --git a/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.cpp b/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.cpp
index ce7869e848e..4ca5d07d090 100644
--- a/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.cpp
+++ b/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.cpp
@@ -3,6 +3,7 @@
#include "documentmetastoresaver.h"
#include <vespa/searchlib/util/bufferwriter.h>
#include "document_meta_store_versions.h"
+#include <vespa/searchlib/attribute/iattributesavetarget.h>
using vespalib::GenerationHandler;
using search::IAttributeSaveTarget;
@@ -67,15 +68,15 @@ public:
DocumentMetaStoreSaver::
DocumentMetaStoreSaver(vespalib::GenerationHandler::Guard &&guard,
- const search::IAttributeSaveTarget::Config &cfg,
- const GidIterator &gidIterator,
- const MetaDataStore &metaDataStore)
- : AttributeSaver(std::move(guard), cfg),
+ const search::attribute::AttributeHeader &header,
+ const GidIterator &gidIterator,
+ const MetaDataStore &metaDataStore)
+ : AttributeSaver(std::move(guard), header),
_gidIterator(gidIterator),
_metaDataStore(metaDataStore),
_writeDocSize(true)
{
- if (cfg.getVersion() == documentmetastore::NO_DOCUMENT_SIZE_TRACKING_VERSION) {
+ if (header.getVersion() == documentmetastore::NO_DOCUMENT_SIZE_TRACKING_VERSION) {
_writeDocSize = false;
}
}
diff --git a/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.h b/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.h
index ddec7032faa..9a8aba5387f 100644
--- a/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.h
+++ b/searchcore/src/vespa/searchcore/proton/documentmetastore/documentmetastoresaver.h
@@ -35,9 +35,9 @@ private:
virtual bool onSave(search::IAttributeSaveTarget &saveTarget) override;
public:
DocumentMetaStoreSaver(vespalib::GenerationHandler::Guard &&guard,
- const search::IAttributeSaveTarget::Config &cfg,
- const GidIterator &gidIterator,
- const MetaDataStore &metaDataStore);
+ const search::attribute::AttributeHeader &header,
+ const GidIterator &gidIterator,
+ const MetaDataStore &metaDataStore);
virtual ~DocumentMetaStoreSaver();
};
diff --git a/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp b/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp
index d1cb05292c1..64587f03883 100644
--- a/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp
+++ b/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp
@@ -36,7 +36,8 @@ bool fastPartialUpdateAttribute(const schema::DataType &attrType) {
FilterAttributeManager::AttributeSet
getAttributeSetToPopulate(const ARIConfig &newCfg,
- const ARIConfig &oldCfg)
+ const ARIConfig &oldCfg,
+ search::SerialNum serialNum)
{
FilterAttributeManager::AttributeSet attrsToPopulate;
std::vector<AttributeGuard> attrList;
@@ -45,7 +46,8 @@ getAttributeSetToPopulate(const ARIConfig &newCfg,
const vespalib::string &name = guard->getName();
bool inOldAttrMgr = oldCfg.getAttrMgr()->getAttribute(name)->valid();
bool inOldSchema = oldCfg.getInspector()->hasField(name);
- bool populateAttribute = !inOldAttrMgr && inOldSchema;
+ search::SerialNum flushedSerialNum = newCfg.getAttrMgr()->getFlushedSerialNum(name);
+ bool populateAttribute = !inOldAttrMgr && inOldSchema && (flushedSerialNum < serialNum);
LOG(debug, "getAttributeSetToPopulate(): name='%s', inOldAttrMgr=%s, inOldSchema=%s, populate=%s",
name.c_str(), toStr(inOldAttrMgr), toStr(inOldSchema), toStr(populateAttribute));
if (populateAttribute) {
@@ -58,15 +60,16 @@ getAttributeSetToPopulate(const ARIConfig &newCfg,
IReprocessingReader::SP
getAttributesToPopulate(const ARIConfig &newCfg,
const ARIConfig &oldCfg,
- const vespalib::string &subDbName)
+ const vespalib::string &subDbName,
+ search::SerialNum serialNum)
{
FilterAttributeManager::AttributeSet attrsToPopulate =
- getAttributeSetToPopulate(newCfg, oldCfg);
+ getAttributeSetToPopulate(newCfg, oldCfg, serialNum);
if (!attrsToPopulate.empty()) {
return IReprocessingReader::SP(new AttributePopulator
(IAttributeManager::SP(new FilterAttributeManager
(attrsToPopulate, newCfg.getAttrMgr())),
- ATTRIBUTE_INIT_SERIAL, subDbName));
+ ATTRIBUTE_INIT_SERIAL, subDbName, serialNum));
}
return IReprocessingReader::SP();
}
@@ -119,8 +122,9 @@ getFieldsToPopulate(const ARIConfig &newCfg,
AttributeReprocessingInitializer::
AttributeReprocessingInitializer(const Config &newCfg,
const Config &oldCfg,
- const vespalib::string &subDbName)
- : _attrsToPopulate(getAttributesToPopulate(newCfg, oldCfg, subDbName)),
+ const vespalib::string &subDbName,
+ search::SerialNum serialNum)
+ : _attrsToPopulate(getAttributesToPopulate(newCfg, oldCfg, subDbName, serialNum)),
_fieldsToPopulate(getFieldsToPopulate(newCfg, oldCfg, subDbName))
{
}
diff --git a/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.h b/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.h
index f1837a6dbcb..bb2b4de4897 100644
--- a/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.h
+++ b/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.h
@@ -46,7 +46,8 @@ private:
public:
AttributeReprocessingInitializer(const Config &newCfg,
const Config &oldCfg,
- const vespalib::string &subDbName);
+ const vespalib::string &subDbName,
+ search::SerialNum serialNum);
// Implements IReprocessingInitializer
virtual bool hasReprocessors() const;
diff --git a/searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.cpp b/searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.cpp
index 4da9bdf76d9..ff538ea8c68 100644
--- a/searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.cpp
+++ b/searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.cpp
@@ -45,4 +45,12 @@ DocumentReprocessingHandler::visit(uint32_t lid)
(void) lid;
}
+void
+DocumentReprocessingHandler::done()
+{
+ for (const auto &reader : _readers) {
+ reader->done();
+ }
+}
+
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.h b/searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.h
index 32e472beaa0..f950e3b61a9 100644
--- a/searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.h
+++ b/searchcore/src/vespa/searchcore/proton/reprocessing/document_reprocessing_handler.h
@@ -70,6 +70,7 @@ public:
virtual void visit(uint32_t lid);
+ void done();
};
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/reprocessing/i_reprocessing_reader.h b/searchcore/src/vespa/searchcore/proton/reprocessing/i_reprocessing_reader.h
index e265befe257..f8c800f6e2e 100644
--- a/searchcore/src/vespa/searchcore/proton/reprocessing/i_reprocessing_reader.h
+++ b/searchcore/src/vespa/searchcore/proton/reprocessing/i_reprocessing_reader.h
@@ -20,6 +20,7 @@ struct IReprocessingReader
* Handle the given existing document.
*/
virtual void handleExisting(uint32_t lid, const document::Document &doc) = 0;
+ virtual void done() = 0;
};
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/reprocessing/reprocess_documents_task.cpp b/searchcore/src/vespa/searchcore/proton/reprocessing/reprocess_documents_task.cpp
index 9084c3d8e63..59b3966454a 100644
--- a/searchcore/src/vespa/searchcore/proton/reprocessing/reprocess_documents_task.cpp
+++ b/searchcore/src/vespa/searchcore/proton/reprocessing/reprocess_documents_task.cpp
@@ -53,6 +53,7 @@ ReprocessDocumentsTask::run()
*this,
*_docTypeRepo);
}
+ _handler.done();
ts = fastos::ClockSystem::now();
int64_t elapsedTime = ts.ms() - _startTime;
EventLogger::reprocessDocumentsComplete(_subDbName,
diff --git a/searchcore/src/vespa/searchcore/proton/server/fast_access_doc_subdb_configurer.cpp b/searchcore/src/vespa/searchcore/proton/server/fast_access_doc_subdb_configurer.cpp
index 2698ffdda69..5f77400d7fd 100644
--- a/searchcore/src/vespa/searchcore/proton/server/fast_access_doc_subdb_configurer.cpp
+++ b/searchcore/src/vespa/searchcore/proton/server/fast_access_doc_subdb_configurer.cpp
@@ -64,7 +64,7 @@ FastAccessDocSubDBConfigurer::reconfigure(const DocumentDBConfig &newConfig,
IDocumentTypeInspector::SP(new DocumentTypeInspector(*newDocType))),
ARIConfig(oldView->getAttributeWriter()->getAttributeManager(), *oldConfig.getSchemaSP(),
IDocumentTypeInspector::SP(new DocumentTypeInspector(*oldDocType))),
- _subDbName));
+ _subDbName, attrSpec.getCurrentSerialNum()));
}
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/server/searchable_doc_subdb_configurer.cpp b/searchcore/src/vespa/searchcore/proton/server/searchable_doc_subdb_configurer.cpp
index 202efae5397..c6b3a86239c 100644
--- a/searchcore/src/vespa/searchcore/proton/server/searchable_doc_subdb_configurer.cpp
+++ b/searchcore/src/vespa/searchcore/proton/server/searchable_doc_subdb_configurer.cpp
@@ -164,7 +164,8 @@ createAttributeReprocessingInitializer(const DocumentDBConfig &newConfig,
const IAttributeManager::SP &newAttrMgr,
const DocumentDBConfig &oldConfig,
const IAttributeManager::SP &oldAttrMgr,
- const vespalib::string &subDbName)
+ const vespalib::string &subDbName,
+ search::SerialNum serialNum)
{
const document::DocumentType *newDocType = newConfig.getDocumentType();
const document::DocumentType *oldDocType = oldConfig.getDocumentType();
@@ -175,7 +176,7 @@ createAttributeReprocessingInitializer(const DocumentDBConfig &newConfig,
IDocumentTypeInspector::SP(new DocumentTypeInspector(*newDocType))),
ARIConfig(oldAttrMgr, *oldConfig.getSchemaSP(),
IDocumentTypeInspector::SP(new DocumentTypeInspector(*oldDocType))),
- subDbName));
+ subDbName, serialNum));
}
}
@@ -216,7 +217,7 @@ SearchableDocSubDBConfigurer::reconfigure(const DocumentDBConfig &newConfig,
attrWriter = newAttrWriter;
shouldFeedViewChange = true;
initializer.reset(createAttributeReprocessingInitializer(newConfig, newAttrMgr,
- oldConfig, oldAttrMgr, _subDbName).release());
+ oldConfig, oldAttrMgr, _subDbName, attrSpec.getCurrentSerialNum()).release());
}
ISummaryManager::ISummarySetup::SP sumSetup =